Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 40 additions & 91 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@dfinity/identity": "^2.3.0",
"@dfinity/principal": "^2.3.0",
"@junobuild/admin": "^0.1.6",
"@junobuild/cli-tools": "^0.1.4",
"@junobuild/cli-tools": "^0.1.6",
"@junobuild/config-loader": "^0.2.0",
"@junobuild/core": "^0.1.9",
"@junobuild/did-tools": "^0.2.0",
Expand Down
22 changes: 21 additions & 1 deletion scripts/esbuild.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import {config} from 'dotenv';
import esbuild from 'esbuild';
import {existsSync, mkdirSync, writeFileSync} from 'node:fs';
import {existsSync, mkdirSync, readFileSync, writeFileSync} from 'node:fs';
import {join} from 'node:path';

config({
path: process.env.NODE_ENV === 'development' ? `.env.development` : `.env.production`
});

export const PACKAGE_JSON = 'package.json';

const readPackageJson = () => {
const packageJson = join(process.cwd(), PACKAGE_JSON);
const json = readFileSync(packageJson, 'utf8');
const {peerDependencies, devDependencies} = JSON.parse(json);
return {
peerDependencies: peerDependencies ?? {},
devDependencies: devDependencies ?? devDependencies
};
};

const {peerDependencies, devDependencies} = readPackageJson();

export const externalDependencies = [
...Object.keys(peerDependencies),
...Object.keys(devDependencies)
];

const define = Object.entries(process.env).reduce(
(acc, [key, value]) => ({
...acc,
Expand All @@ -32,6 +51,7 @@ const script = await esbuild.build({
banner: {
js: "import { createRequire as topLevelCreateRequire } from 'module';\n const require = topLevelCreateRequire(import.meta.url);"
},
external: externalDependencies,
define
});

Expand Down
17 changes: 15 additions & 2 deletions src/commands/dev.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {red} from 'kleur';
import {logHelpDevBuild} from '../help/dev.build.help';
import {logHelpDev} from '../help/dev.help';
import {build} from '../services/build.services';
import {build} from '../services/build/build.services';
import {start, stop} from '../services/docker.services';
import {eject} from '../services/eject.services';

Expand All @@ -12,7 +13,7 @@ export const dev = async (args?: string[]) => {
await eject();
break;
case 'build':
await build();
await build(args);
break;
case 'start':
await start();
Expand All @@ -25,3 +26,15 @@ export const dev = async (args?: string[]) => {
logHelpDev();
}
};

export const helpDev = (args?: string[]) => {
const [subCommand] = args ?? [];

switch (subCommand) {
case 'build':
logHelpDevBuild(args);
break;
default:
logHelpDev(args);
}
};
15 changes: 15 additions & 0 deletions src/constants/dev.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,24 @@ export const DEVELOPER_PROJECT_SATELLITE_DECLARATIONS_PATH = join(
'satellite'
);

export const DEVELOPER_PROJECT_SATELLITE_CARGO_TOML = join(
DEVELOPER_PROJECT_SATELLITE_PATH,
'Cargo.toml'
);
export const DEVELOPER_PROJECT_SATELLITE_INDEX_TS = join(
DEVELOPER_PROJECT_SATELLITE_PATH,
'index.ts'
);
export const DEVELOPER_PROJECT_SATELLITE_INDEX_MJS = join(
DEVELOPER_PROJECT_SATELLITE_PATH,
'index.mjs'
);

export const TEMPLATE_PATH = '../templates/eject';
export const TEMPLATE_SATELLITE_PATH = join(TEMPLATE_PATH, 'src', 'satellite');

export const RUST_MIN_VERSION = '1.70.0';
export const IC_WASM_MIN_VERSION = '0.8.5';
export const DOCKER_MIN_VERSION = '24.0.0';

export const DEPLOY_LOCAL_REPLICA_PATH = join(process.cwd(), 'target', 'deploy');
38 changes: 38 additions & 0 deletions src/help/dev.build.help.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {cyan, green, magenta, yellow} from 'kleur';
import {helpOutput} from './common.help';
import {TITLE} from './help';

export const DEV_BUILD_DESCRIPTION = 'Build your serverless functions.';

export const helpDevBuild = `${magenta('build')} ${DEV_BUILD_DESCRIPTION}`;

const usage = `Usage: ${green('juno')} ${cyan('dev')} ${magenta('build')} ${yellow('[options]')}

Options:
${yellow('-l, --lang')} Specify the language for building the serverless functions: ${magenta('rust')}, ${magenta('typescript')} or ${magenta('javascript')}.
${yellow('-p, --path')} Path to the source to bundle.
${yellow('-h, --help')} Output usage information.

Notes:

- If no language is provided, the CLI attempts to determine the appropriate build.
- Language can be shortened to ${magenta('rs')} for Rust, ${magenta('ts')} for TypeScript and ${magenta('js')} for JavaScript.
- The path option maps to ${magenta('--manifest-path')} for Rust (Cargo) or to the source file for TypeScript and JavaScript (e.g. ${magenta('index.ts')} or ${magenta('index.mjs')}) .`;

const doc = `${DEV_BUILD_DESCRIPTION}

\`\`\`bash
${usage}
\`\`\`
`;

const help = `${TITLE}

${DEV_BUILD_DESCRIPTION}

${usage}
`;

export const logHelpDevBuild = (args?: string[]) => {
console.log(helpOutput(args) === 'doc' ? doc : help);
};
6 changes: 3 additions & 3 deletions src/help/dev.help.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {cyan, green, magenta} from 'kleur';
import {cyan, green, magenta, yellow} from 'kleur';
import {helpOutput} from './common.help';
import {helpDevBuild} from './dev.build.help';
import {TITLE} from './help';

export const DEV_DESCRIPTION =
'Handle development tasks like building serverless functions or running a local Internet Computer instance.';

const helpDevBuild = `${magenta('build')} Build your serverless functions.`;
const helpDevStart = `${magenta(
'start'
)} Start a local Internet Computer network in a container.`;

export const helpDevContinue = `${helpDevBuild}
${helpDevStart}`;

const usage = `Usage: ${green('juno')} ${cyan('dev')} ${magenta('<subcommand>')}
const usage = `Usage: ${green('juno')} ${cyan('dev')} ${magenta('<subcommand>')} ${yellow('[options]')}

Subcommands:
${helpDevBuild}
Expand Down
5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {login, logout} from './commands/auth';
import {clear} from './commands/clear';
import {config} from './commands/config';
import {deploy} from './commands/deploy';
import {dev} from './commands/dev';
import {dev, helpDev} from './commands/dev';
import {init} from './commands/init';
import {open} from './commands/open';
import {snapshot} from './commands/snapshot';
Expand All @@ -16,7 +16,6 @@ import {whoami} from './commands/whoami';
import {logHelpClear} from './help/clear.help';
import {logHelpConfig} from './help/config.help';
import {logHelpDeploy} from './help/deploy.help';
import {logHelpDev} from './help/dev.help';
import {help} from './help/help';
import {logHelpInit} from './help/init.help';
import {logHelpLogin} from './help/login.help';
Expand Down Expand Up @@ -81,7 +80,7 @@ export const run = async () => {
logHelpDeploy(args);
break;
case 'dev':
logHelpDev(args);
helpDev(args);
break;
case 'snapshot':
logHelpSnapshot(args);
Expand Down
64 changes: 64 additions & 0 deletions src/services/build/build.javascript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {buildEsm} from '@junobuild/cli-tools';
import {red, yellow} from 'kleur';
import {mkdir} from 'node:fs/promises';
import {join} from 'node:path';
import {
DEPLOY_LOCAL_REPLICA_PATH,
DEVELOPER_PROJECT_SATELLITE_PATH
} from '../../constants/dev.constants';

export const buildTypeScript = async ({path}: {path?: string | undefined} = {}) => {
await build({lang: 'ts', path});
};

export const buildJavaScript = async ({path}: {path?: string | undefined} = {}) => {
await build({lang: 'js', path});
};

const build = async ({lang, path}: {lang: 'ts' | 'js'; path?: string | undefined}) => {
// Create output target/deploy if it does not yet exist.
await mkdir(DEPLOY_LOCAL_REPLICA_PATH, {recursive: true});

const infile =
path ?? join(DEVELOPER_PROJECT_SATELLITE_PATH, lang === 'js' ? 'index.mjs' : 'index.ts');

const outfile = join(DEPLOY_LOCAL_REPLICA_PATH, 'index.mjs');

const {metafile, errors, warnings, version} = await buildEsm({
infile,
outfile
});

for (const {text} of warnings) {
console.log(`${yellow('[Warn]')} ${text}`);
}

for (const {text} of errors) {
console.log(`${red('[Error]')} ${text}`);
}

if (errors.length > 0) {
process.exit(1);
}

const entry = Object.entries(metafile.outputs);

if (entry.length === 0) {
console.log(red('Unexpected: No metafile resulting from the build was found.'));
process.exit(1);
}

const [key, {bytes}] = entry[0];

const unit = bytes >= 1000 ? 'megabyte' : 'kilobyte';

const formatter = new Intl.NumberFormat('en', {
style: 'unit',
unit
});

console.log(`✅ Build complete (esbuild ${version}).`);
console.log(
`➡️ ${key} (${formatter.format(bytes / (unit === 'megabyte' ? 1_000_000 : 1_000))})`
);
};
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
import {nonNullish} from '@dfinity/utils';
import {execute, gzipFile, spawn} from '@junobuild/cli-tools';
import {generateApi} from '@junobuild/did-tools';
import {green, grey, magenta, yellow} from 'kleur';
import {existsSync} from 'node:fs';
import {lstat, mkdir, readFile, rename, writeFile} from 'node:fs/promises';
import {join, relative} from 'node:path';
import ora, {type Ora} from 'ora';
import {detectJunoDevConfigType} from '../configs/juno.dev.config';
import {detectJunoDevConfigType} from '../../configs/juno.dev.config';
import {
DEPLOY_LOCAL_REPLICA_PATH,
DEVELOPER_PROJECT_SATELLITE_DECLARATIONS_PATH,
DEVELOPER_PROJECT_SATELLITE_PATH,
IC_WASM_MIN_VERSION
} from '../constants/dev.constants';
import {readSatelliteDid} from '../utils/did.utils';
import {checkCargoBinInstalled, checkIcWasmVersion, checkRustVersion} from '../utils/env.utils';
import {confirmAndExit} from '../utils/prompt.utils';
} from '../../constants/dev.constants';
import {readSatelliteDid} from '../../utils/did.utils';
import {checkCargoBinInstalled, checkIcWasmVersion, checkRustVersion} from '../../utils/env.utils';
import {confirmAndExit} from '../../utils/prompt.utils';

const CARGO_RELEASE_DIR = join(process.cwd(), 'target', 'wasm32-unknown-unknown', 'release');
const DEPLOY_DIR = join(process.cwd(), 'target', 'deploy');
const SATELLITE_OUTPUT = join(DEPLOY_DIR, 'satellite.wasm');
const SATELLITE_OUTPUT = join(DEPLOY_LOCAL_REPLICA_PATH, 'satellite.wasm');

export const build = async () => {
export const buildRust = async ({path}: {path?: string | undefined} = {}) => {
const {valid: validRust} = await checkRustVersion();

if (validRust === 'error' || !validRust) {
Expand All @@ -44,12 +45,13 @@ export const build = async () => {
return;
}

const defaultProjectArgs = ['-p', 'satellite'];

const args = [
'build',
'--target',
'wasm32-unknown-unknown',
'-p',
'satellite',
...(nonNullish(path) ? ['--manifest-path', path] : defaultProjectArgs),
'--release',
...(existsSync('Cargo.lock') ? ['--locked'] : [])
];
Expand Down Expand Up @@ -214,7 +216,7 @@ const api = async () => {
};

const icWasm = async () => {
await mkdir(DEPLOY_DIR, {recursive: true});
await mkdir(DEPLOY_LOCAL_REPLICA_PATH, {recursive: true});

// Remove unused functions and debug info.
await spawn({
Expand Down
Loading