diff --git a/package-lock.json b/package-lock.json index b5bb71b..dec5b5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@dfinity/identity": "^1.0.1", "@dfinity/principal": "^1.0.1", "@junobuild/admin": "^0.0.46", + "@junobuild/cli-tools": "^0.0.3", "@junobuild/config": "^0.0.2", "@junobuild/core-peer": "^0.0.11", "@junobuild/utils": "^0.0.19", @@ -1430,6 +1431,20 @@ "semver": "7.*" } }, + "node_modules/@junobuild/cli-tools": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.0.3.tgz", + "integrity": "sha512-qwibz7KYEiguCb5Frw2i0DMPmibcKrLnr0EMZJ1rQaPN7kucVrAsB2fQfyADoiTyXXst9vFE9lLLNbI0Fv6o0Q==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/preset-typescript": "^7.23.3" + }, + "peerDependencies": { + "@junobuild/config": "^0.0.2", + "@junobuild/utils": "^0.0.19" + } + }, "node_modules/@junobuild/config": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-0.0.2.tgz", @@ -7553,6 +7568,16 @@ "integrity": "sha512-UjY/9X7NiVjBxh3zg0L+mCkaPnY0IkVPn3oDvTGeeQ8Bj5oxJo2bJbE94hCTEquK7nGv14NXj4+MGh1iFuc3mw==", "requires": {} }, + "@junobuild/cli-tools": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.0.3.tgz", + "integrity": "sha512-qwibz7KYEiguCb5Frw2i0DMPmibcKrLnr0EMZJ1rQaPN7kucVrAsB2fQfyADoiTyXXst9vFE9lLLNbI0Fv6o0Q==", + "requires": { + "@babel/core": "^7.23.9", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/preset-typescript": "^7.23.3" + } + }, "@junobuild/config": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/@junobuild/config/-/config-0.0.2.tgz", diff --git a/package.json b/package.json index da8d158..f01bb72 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@dfinity/identity": "^1.0.1", "@dfinity/principal": "^1.0.1", "@junobuild/admin": "^0.0.46", + "@junobuild/cli-tools": "^0.0.3", "@junobuild/config": "^0.0.2", "@junobuild/core-peer": "^0.0.11", "@junobuild/utils": "^0.0.19", diff --git a/src/configs/juno.config.ts b/src/configs/juno.config.ts index f49b984..4e23ea8 100644 --- a/src/configs/juno.config.ts +++ b/src/configs/juno.config.ts @@ -1,84 +1,29 @@ +import { + junoConfigExist as junoConfigExistTools, + junoConfigFile as junoConfigFileTools, + readJunoConfig as readJunoConfigTools, + type ConfigFilename +} from '@junobuild/cli-tools'; import type {JunoConfig, JunoConfigEnv, JunoConfigFnOrObject} from '@junobuild/config'; import {nonNullish} from '@junobuild/utils'; -import {existsSync} from 'node:fs'; -import {access, readFile, writeFile} from 'node:fs/promises'; -import {join} from 'node:path'; +import {writeFile} from 'node:fs/promises'; import { TEMPLATE_INIT_PATH, TEMPLATE_SATELLITE_CONFIG_FILENAME } from '../constants/config.constants'; -import {JUNO_CONFIG_FILENAME, JUNO_JSON} from '../constants/constants'; +import {JUNO_CONFIG_FILENAME} from '../constants/constants'; import {DEPLOY_DEFAULT_SOURCE} from '../constants/deploy.constants'; import type {ConfigType, JunoConfigWithSatelliteId} from '../types/config'; import {readTemplateFile} from '../utils/fs.utils'; -import {nodeRequire} from '../utils/node.utils'; + +const JUNO_CONFIG_FILE: {filename: ConfigFilename} = {filename: JUNO_CONFIG_FILENAME}; export const junoConfigExist = async (): Promise => { - try { - const {configPath} = junoConfigFile(); - await access(configPath); - return true; - } catch (err: unknown) { - if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') { - return false; - } else { - throw err; - } - } + return await junoConfigExistTools(JUNO_CONFIG_FILE); }; -export const junoConfigFile = (): {configPath: string; configType: ConfigType} => { - const junoTs = join(process.cwd(), `${JUNO_CONFIG_FILENAME}.ts`); - - if (existsSync(junoTs)) { - return { - configPath: junoTs, - configType: 'ts' - }; - } - - const junoJs = join(process.cwd(), `${JUNO_CONFIG_FILENAME}.js`); - - if (existsSync(junoJs)) { - return { - configPath: junoJs, - configType: 'js' - }; - } - - const junoMjs = join(process.cwd(), `${JUNO_CONFIG_FILENAME}.mjs`); - - if (existsSync(junoMjs)) { - return { - configPath: junoMjs, - configType: 'js' - }; - } - - const junoCjs = join(process.cwd(), `${JUNO_CONFIG_FILENAME}.cjs`); - - if (existsSync(junoCjs)) { - return { - configPath: junoCjs, - configType: 'js' - }; - } - - // Support for original juno.json file - const junoJsonDeprecated = join(process.cwd(), JUNO_JSON); - - if (existsSync(junoJsonDeprecated)) { - return { - configPath: junoJsonDeprecated, - configType: 'json' - }; - } - - return { - configPath: join(process.cwd(), `${JUNO_CONFIG_FILENAME}.json`), - configType: 'json' - }; -}; +export const junoConfigFile = (): {configPath: string; configType: ConfigType} => + junoConfigFileTools(JUNO_CONFIG_FILE); export const writeJunoConfig = async ({ config, @@ -117,23 +62,11 @@ export const writeJunoConfig = async ({ }; export const readJunoConfig = async (env: JunoConfigEnv): Promise => { - const {configPath, configType} = junoConfigFile(); - const config = (userConfig: JunoConfigFnOrObject): JunoConfig => typeof userConfig === 'function' ? userConfig(env) : userConfig; - switch (configType) { - case 'ts': { - const {default: userConfig} = nodeRequire(configPath); - return config(userConfig); - } - case 'js': { - const {default: userConfig} = await import(configPath); - return config(userConfig as JunoConfigFnOrObject); - } - default: { - const buffer = await readFile(configPath); - return JSON.parse(buffer.toString('utf-8')); - } - } + return await readJunoConfigTools({ + ...JUNO_CONFIG_FILE, + config + }); }; diff --git a/src/configs/juno.dev.config.ts b/src/configs/juno.dev.config.ts index e0ba50f..78c75d4 100644 --- a/src/configs/juno.dev.config.ts +++ b/src/configs/juno.dev.config.ts @@ -1,72 +1,16 @@ -import {existsSync} from 'node:fs'; -import {access} from 'node:fs/promises'; -import {join} from 'node:path'; -import {JUNO_DEV_CONFIG_FILENAME, JUNO_DEV_JSON} from '../constants/constants'; +import type {ConfigFilename} from '@junobuild/cli-tools'; +import { + junoConfigExist as junoConfigExistTools, + junoConfigFile as junoConfigFileTools +} from '@junobuild/cli-tools'; +import {JUNO_DEV_CONFIG_FILENAME} from '../constants/constants'; import type {ConfigType} from '../types/config'; +const JUNO_DEV_CONFIG_FILE: {filename: ConfigFilename} = {filename: JUNO_DEV_CONFIG_FILENAME}; + export const junoDevConfigExist = async (): Promise => { - try { - const {configPath} = junoDevConfigFile(); - await access(configPath); - return true; - } catch (err: unknown) { - if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') { - return false; - } else { - throw err; - } - } + return await junoConfigExistTools(JUNO_DEV_CONFIG_FILE); }; -export const junoDevConfigFile = (): {configPath: string; configType: ConfigType} => { - const junoTs = join(process.cwd(), `${JUNO_DEV_CONFIG_FILENAME}.ts`); - - if (existsSync(junoTs)) { - return { - configPath: junoTs, - configType: 'ts' - }; - } - - const junoJs = join(process.cwd(), `${JUNO_DEV_CONFIG_FILENAME}.js`); - - if (existsSync(junoJs)) { - return { - configPath: junoJs, - configType: 'js' - }; - } - - const junoMjs = join(process.cwd(), `${JUNO_DEV_CONFIG_FILENAME}.mjs`); - - if (existsSync(junoMjs)) { - return { - configPath: junoMjs, - configType: 'js' - }; - } - - const junoCjs = join(process.cwd(), `${JUNO_DEV_CONFIG_FILENAME}.cjs`); - - if (existsSync(junoCjs)) { - return { - configPath: junoCjs, - configType: 'js' - }; - } - - // Support for original juno.json file - const junoJsonDeprecated = join(process.cwd(), JUNO_DEV_JSON); - - if (existsSync(junoJsonDeprecated)) { - return { - configPath: junoJsonDeprecated, - configType: 'json' - }; - } - - return { - configPath: join(process.cwd(), `${JUNO_DEV_CONFIG_FILENAME}.json`), - configType: 'json' - }; -}; +export const junoDevConfigFile = (): {configPath: string; configType: ConfigType} => + junoConfigFileTools(JUNO_DEV_CONFIG_FILE); diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 6925de1..e6bf084 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -3,14 +3,6 @@ export const CLI_PROJECT_NAME = process.env.CLI_PROJECT_NAME; export const REDIRECT_URL = 'http://localhost:{port}'; export const JUNO_CONFIG_FILENAME = 'juno.config'; // .json | .js | .mjs | .cjs | .ts export const JUNO_DEV_CONFIG_FILENAME = 'juno.dev.config'; // .json | .js | .mjs | .cjs | .ts -/** - * @deprecated juno.json is deprecated but still supported. We are now using juno.config.xxx - */ -export const JUNO_JSON = 'juno.json'; -/** - * @deprecated juno.dev.json is deprecated but still supported. We are now using juno.dev.config.xxx - */ -export const JUNO_DEV_JSON = 'juno.dev.json'; export const DAPP_COLLECTION = '#dapp'; export const SATELLITE_WASM_NAME = 'satellite'; export const MISSION_CONTROL_WASM_NAME = 'mission_control'; diff --git a/src/utils/node.utils.ts b/src/utils/node.utils.ts deleted file mode 100644 index eb28028..0000000 --- a/src/utils/node.utils.ts +++ /dev/null @@ -1,73 +0,0 @@ -import {transformFileSync} from '@babel/core'; -import * as mod from '@babel/plugin-transform-modules-commonjs'; -import * as ts from '@babel/preset-typescript'; -import {defineConfig, type JunoConfig} from '@junobuild/config'; -import {readFileSync} from 'node:fs'; - -/** - * Adapted source from Stencil (https://github.com/ionic-team/stencil/blob/main/src/compiler/sys/node-require.ts) - */ -export const nodeRequire = (id: string): {default: T} => { - // ensure we cleared out node's internal require() cache for this file - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete require.cache[id]; - - // eslint-disable-next-line @typescript-eslint/no-var-requires - const Module = require('module'); - const originalLoad = Module._load; - - try { - // let's override node's require for a second - // don't worry, we'll revert this when we're done - // eslint-disable-next-line n/no-deprecated-api - require.extensions['.ts'] = (module: NodeJS.Module, fileName: string) => { - let sourceText = readFileSync(fileName, 'utf8'); - - if (fileName.endsWith('.ts')) { - // looks like we've got a typed config file - // let's transpile it to .js quick - sourceText = transformFileSync(fileName, { - presets: [ts.default], - plugins: [mod.default] - }).code; - } else { - // quick hack to turn a modern es module - // into and old school commonjs module - sourceText = sourceText.replace(/export\s+\w+\s+(\w+)/gm, 'exports.$1'); - } - - interface NodeModuleWithCompile extends NodeModule { - // eslint-disable-next-line @typescript-eslint/method-signature-style - _compile(code: string, filename: string): T; - } - - // we need to coerce because of the requirements for the arguments to - // this function. - (module as NodeModuleWithCompile)._compile(sourceText, fileName); - }; - - // We override defineConfig because the library is unknown in the module we are trying to load. - // This need to be a function and not an arrow function because of the "arguments" - Module._load = function (request: string): unknown { - if (request === '@junobuild/config') { - return { - defineConfig: (config: JunoConfig) => defineConfig(config) - }; - } - - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error - // @ts-ignore arguments are passed by NodeJS - return originalLoad.apply(this, arguments); - }; - - // let's do this! - return require(id); - } finally { - // all set, let's go ahead and reset the require back to the default - // eslint-disable-next-line n/no-deprecated-api - require.extensions['.ts'] = undefined; - - // Redo our hack - Module._load = originalLoad; - } -};