diff --git a/.gitignore b/.gitignore index eb979909..ef9f96bc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ _brisa **/out/* **/out-*/* **/dist/* +**/build-utils/create-deno-json/deno.json **/.temp-test-files/* packages/brisa/index.js packages/brisa/out diff --git a/packages/brisa/src/build-utils/README.md b/packages/brisa/src/build-utils/README.md new file mode 100644 index 00000000..077f958b --- /dev/null +++ b/packages/brisa/src/build-utils/README.md @@ -0,0 +1,5 @@ +# Brisa build utils + +This folder is made to move all the `utils` we currently have that are related to the building of the brisa here so that it is easier to maintain and understand. + +We are going to do this migration gradually, so as not to break anything, if you want to contribute to this task, it will be very well received. diff --git a/packages/brisa/src/build-utils/create-deno-json/index.test.ts b/packages/brisa/src/build-utils/create-deno-json/index.test.ts new file mode 100644 index 00000000..f19c92bc --- /dev/null +++ b/packages/brisa/src/build-utils/create-deno-json/index.test.ts @@ -0,0 +1,103 @@ +import { describe, it, expect, beforeEach, afterEach } from 'bun:test'; +import fs from 'node:fs'; +import path from 'node:path'; +import { createDenoJSON } from '.'; + +describe('createDenoJSON', () => { + beforeEach(() => { + globalThis.mockConstants = { + BUILD_DIR: import.meta.dirname, + ROOT_DIR: import.meta.dirname, + SRC_DIR: import.meta.dirname, + }; + }); + + afterEach(() => { + delete globalThis.mockConstants; + fs.rmSync(path.join(import.meta.dirname, 'deno.json')); + }); + + it('should create the default deno.json file when no existing one', () => { + createDenoJSON(); + expect( + JSON.parse( + fs.readFileSync(path.join(import.meta.dirname, 'deno.json'), 'utf-8'), + ), + ).toEqual({ + imports: { + 'fs/promises': 'node:fs/promises', + path: 'node:path', + }, + permissions: { + read: true, + write: true, + run: 'inherit', + }, + }); + }); + + it('should merge with the existing deno.json file in the root directory', () => { + // Ensure is not taking src dir + globalThis.mockConstants!.SRC_DIR = path.join(import.meta.dirname, 'src'); + fs.writeFileSync( + path.join(import.meta.dirname, 'deno.json'), + JSON.stringify({ + permissions: { + read: false, + }, + }), + ); + createDenoJSON(); + expect( + JSON.parse( + fs.readFileSync(path.join(import.meta.dirname, 'deno.json'), 'utf-8'), + ), + ).toEqual({ + imports: { + 'fs/promises': 'node:fs/promises', + path: 'node:path', + }, + permissions: { + read: false, + write: true, + run: 'inherit', + }, + }); + }); + + it('should merge with the existing deno.json file in the src directory', () => { + // Ensure is taking src dir + globalThis.mockConstants!.ROOT_DIR = path.join( + import.meta.dirname, + 'not-exist', + ); + + fs.writeFileSync( + path.join(import.meta.dirname, 'deno.json'), + JSON.stringify({ + imports: { + cluster: 'node:cluster', + }, + foo: 'bar', + }), + ); + createDenoJSON(); + expect( + JSON.parse( + fs.readFileSync(path.join(import.meta.dirname, 'deno.json'), 'utf-8'), + ), + ).toEqual({ + foo: 'bar', + imports: { + 'fs/promises': 'node:fs/promises', + path: 'node:path', + cluster: 'node:cluster', + }, + permissions: { + read: true, + write: true, + run: 'inherit', + }, + }); + }); +}); diff --git a/packages/brisa/src/build-utils/create-deno-json/index.ts b/packages/brisa/src/build-utils/create-deno-json/index.ts new file mode 100644 index 00000000..c66611c1 --- /dev/null +++ b/packages/brisa/src/build-utils/create-deno-json/index.ts @@ -0,0 +1,63 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { getConstants } from '@/constants'; + +export function createDenoJSON() { + const { BUILD_DIR } = getConstants(); + const denoJSON = getDenoJSON(); + fs.writeFileSync( + path.join(BUILD_DIR, 'deno.json'), + JSON.stringify(denoJSON, null, 2), + ); +} + +function getDenoJSON() { + const { ROOT_DIR, SRC_DIR } = getConstants(); + const defaultDenoJSON = { + imports: { + 'fs/promises': 'node:fs/promises', + path: 'node:path', + }, + permissions: { + read: true, + write: true, + run: 'inherit', + }, + }; + + if (fs.existsSync(path.join(ROOT_DIR, 'deno.json'))) { + const denoJSON = JSON.parse( + fs.readFileSync(path.join(ROOT_DIR, 'deno.json'), 'utf-8'), + ); + return { + ...denoJSON, + imports: { + ...defaultDenoJSON.imports, + ...denoJSON.imports, + }, + permissions: { + ...defaultDenoJSON.permissions, + ...denoJSON.permissions, + }, + }; + } + + if (fs.existsSync(path.join(SRC_DIR, 'deno.json'))) { + const denoJSON = JSON.parse( + fs.readFileSync(path.join(SRC_DIR, 'deno.json'), 'utf-8'), + ); + return { + ...denoJSON, + imports: { + ...defaultDenoJSON.imports, + ...denoJSON.imports, + }, + permissions: { + ...defaultDenoJSON.permissions, + ...denoJSON.permissions, + }, + }; + } + + return defaultDenoJSON; +} diff --git a/packages/brisa/src/cli/build.test.ts b/packages/brisa/src/cli/build.test.ts index cc885054..49cc2787 100644 --- a/packages/brisa/src/cli/build.test.ts +++ b/packages/brisa/src/cli/build.test.ts @@ -325,5 +325,125 @@ describe('cli', () => { await build(); expect(mockLog).not.toHaveBeenCalled(); }); + + it('should NOT create deno.json when output is "bun" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'bun', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "node" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'bun', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "static" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'static', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "ios" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'ios', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "android" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'android', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "desktop" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'desktop', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should NOT create deno.json when output is "deno" in development', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'deno', + }, + IS_PRODUCTION: false, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeFalse(); + }); + + it('should create deno.json when output is "deno" in production', async () => { + globalThis.mockConstants = { + ...(getConstants() ?? {}), + BUILD_DIR, + BRISA_DIR, + CONFIG: { + output: 'deno', + }, + IS_PRODUCTION: true, + }; + + await build(); + expect(fs.existsSync(path.join(BUILD_DIR, 'deno.json'))).toBeTrue(); + }); }); }); diff --git a/packages/brisa/src/cli/build.ts b/packages/brisa/src/cli/build.ts index d662652b..d0dc1e5a 100644 --- a/packages/brisa/src/cli/build.ts +++ b/packages/brisa/src/cli/build.ts @@ -7,6 +7,7 @@ import { logTable, generateStaticExport } from './build-utils'; import compileBrisaInternalsToDoBuildPortable from '@/utils/compile-serve-internals-into-build'; import { log } from '@/utils/log/log-build'; import runtimeVersion from '@/utils/runtime-version'; +import { createDenoJSON } from '@/build-utils/create-deno-json'; const outputText = { bun: 'Bun.js Web Service App', @@ -128,6 +129,10 @@ export default async function build() { await compileBrisaInternalsToDoBuildPortable(); + if (IS_PRODUCTION && CONFIG.output === 'deno') { + createDenoJSON(); + } + if (IS_PRODUCTION && CONFIG.outputAdapter) { log(LOG_PREFIX.WAIT, `Adapting output to ${CONFIG.outputAdapter.name}...`); await CONFIG.outputAdapter.adapt(constants, generated);