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
9 changes: 6 additions & 3 deletions src/constants/dev.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ export const SATELLITE_PROJECT_NAME = 'satellite';
export const SPUTNIK_PROJECT_NAME = 'sputnik';

export const DEVELOPER_PROJECT_SRC_PATH = join(process.cwd(), 'src');
export const DEVELOPER_PROJECT_SATELLITE_PATH = join(DEVELOPER_PROJECT_SRC_PATH, 'satellite');
export const DEVELOPER_PROJECT_SATELLITE_PATH = join(
DEVELOPER_PROJECT_SRC_PATH,
SATELLITE_PROJECT_NAME
);
export const DEVELOPER_PROJECT_SATELLITE_DECLARATIONS_PATH = join(
DEVELOPER_PROJECT_SRC_PATH,
'declarations',
'satellite'
SATELLITE_PROJECT_NAME
);

export const CARGO_TOML = 'Cargo.toml';
Expand All @@ -31,7 +34,7 @@ export const DEVELOPER_PROJECT_SATELLITE_INDEX_MJS = join(
const TEMPLATE_PATH = '../templates/eject';

export const RUST_TEMPLATE_PATH = join(TEMPLATE_PATH, 'rust');
export const RUST_TEMPLATE_SATELLITE_PATH = join(RUST_TEMPLATE_PATH, 'src', 'satellite');
export const RUST_TEMPLATE_SATELLITE_PATH = join(RUST_TEMPLATE_PATH, 'src', SATELLITE_PROJECT_NAME);

export const TS_TEMPLATE_PATH = join(TEMPLATE_PATH, 'typescript');
export const MJS_TEMPLATE_PATH = join(TEMPLATE_PATH, 'javascript');
Expand Down
63 changes: 30 additions & 33 deletions src/services/functions/build/build.rust.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {execute, formatBytes, gzipFile, spawn} from '@junobuild/cli-tools';
import {generateApi} from '@junobuild/did-tools';
import {red, yellow} from 'kleur';
import {existsSync} from 'node:fs';
import {copyFile, lstat, mkdir, readFile, rename, writeFile} from 'node:fs/promises';
import {copyFile, lstat, mkdir, readFile, rename, rm, writeFile} from 'node:fs/promises';
import {join, relative} from 'node:path';
import ora, {type Ora} from 'ora';
import {compare, minVersion, satisfies} from 'semver';
Expand All @@ -20,15 +20,16 @@ import {
} from '../../../constants/dev.constants';
import type {BuildArgs, BuildType} from '../../../types/build';
import {
checkBindgen,
checkCandidExtractor,
checkIcWasm,
checkJunoDidc,
checkWasi2ic
} from '../../../utils/build.rust.utils';
import {readSatelliteDid} from '../../../utils/did.utils';
import {checkRustVersion} from '../../../utils/env.utils';
import {formatTime} from '../../../utils/format.utils';
import {readPackageJson} from '../../../utils/pkg.utils';
import {detectPackageManager} from '../../../utils/pm.utils';
import {readEmulatorConfigAndCreateDeployTargetDir} from '../../emulator/_fs.services';
import {prepareJunoPkgForSatellite, prepareJunoPkgForSputnik} from './build.metadata.services';
import {dispatchEmulatorTouchSatellite} from './touch.services';
Expand All @@ -55,9 +56,9 @@ export const buildRust = async ({
return;
}

const {valid: validDidc} = await checkJunoDidc();
const {valid: validBindgen} = await checkBindgen();

if (!validDidc) {
if (!validBindgen) {
return;
}

Expand Down Expand Up @@ -216,40 +217,36 @@ const didc = async () => {
return;
}

const generate = async (type: 'js' | 'ts') => {
const output = satellitedIdl(type);
const pm = detectPackageManager();

await spawn({
command: 'junobuild-didc',
args: ['-i', SATELLITE_CUSTOM_DID_FILE, '-t', type, '-o', output]
});

const content = await readFile(output, 'utf-8');

// Depending on the `tsconfig`, the `factory.did.js` file might be validated.
// Cleaning the file prevents errors such as:
// TS7031: Binding element 'IDL' implicitly has an 'any' type.
const cleanJs = (content: string): string => {
const cleanFactory = content.replace(
/export const idlFactory = \({ IDL }\) => {/g,
`// @ts-expect-error
export const idlFactory = ({ IDL }) => {`
);
return cleanFactory.replace(
/export const init = \({ IDL }\) => {/g,
`// @ts-expect-error
export const init = ({ IDL }) => {`
);
};
const command = pm === 'npm' || isNullish(pm) ? 'npx' : pm;

const cleanedContent = type === 'js' ? cleanJs(content) : content;
// --actor-disabled: skip generating actor files, since we handle those ourselves
// --force: overwrite files. Required; otherwise, icp-bindgen would delete files at preprocess,
// which causes issues when multiple .did files are located in the same folder.
await spawn({
command,
args: [
'icp-bindgen',
'--did-file',
SATELLITE_CUSTOM_DID_FILE,
'--out-dir',
DEVELOPER_PROJECT_SATELLITE_DECLARATIONS_PATH,
'--actor-disabled',
'--force'
],
silentOut: true
});

await writeFile(output, `${AUTO_GENERATED}\n\n${cleanedContent}`);
};
// icp-bindgen generates the files in a `declarations` subfolder
// using a different suffix for JavaScript as the one we used to use.
// That's why we have to post-process the results.
const generatedFolder = join(DEVELOPER_PROJECT_SATELLITE_DECLARATIONS_PATH, 'declarations');

const promises = (['js', 'ts'] as Array<'js' | 'ts'>).map(generate);
await rename(join(generatedFolder, `${EXTENSION_DID_FILE_NAME}.d.ts`), satellitedIdl('ts'));
await rename(join(generatedFolder, `${EXTENSION_DID_FILE_NAME}.js`), satellitedIdl('js'));

await Promise.all(promises);
await rm(generatedFolder, {recursive: true, force: true});
};

const api = async () => {
Expand Down
30 changes: 18 additions & 12 deletions src/utils/build.rust.utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {isNullish} from '@dfinity/utils';
import {execute} from '@junobuild/cli-tools';
import {magenta, yellow} from 'kleur';
import {IC_WASM_MIN_VERSION} from '../constants/dev.constants';
import {checkCargoBinInstalled, checkIcWasmVersion} from './env.utils';
import {checkIcWasmVersion, checkToolInstalled} from './env.utils';
import {detectPackageManager} from './pm.utils';
import {confirmAndExit} from './prompt.utils';

export const checkIcWasm = async (): Promise<{valid: boolean}> => {
Expand All @@ -28,7 +30,7 @@ export const checkIcWasm = async (): Promise<{valid: boolean}> => {
};

export const checkCandidExtractor = async (): Promise<{valid: boolean}> => {
const {valid} = await checkCargoBinInstalled({
const {valid} = await checkToolInstalled({
command: 'candid-extractor',
args: ['--version']
});
Expand All @@ -53,10 +55,14 @@ export const checkCandidExtractor = async (): Promise<{valid: boolean}> => {
return {valid: true};
};

export const checkJunoDidc = async (): Promise<{valid: boolean}> => {
const {valid} = await checkCargoBinInstalled({
command: 'junobuild-didc',
args: ['--version']
export const checkBindgen = async (): Promise<{valid: boolean}> => {
const pm = detectPackageManager();

const command = pm === 'npm' || isNullish(pm) ? 'npx' : pm;

const {valid} = await checkToolInstalled({
command,
args: ['icp-bindgen', '--version']
});

if (valid === false) {
Expand All @@ -65,22 +71,22 @@ export const checkJunoDidc = async (): Promise<{valid: boolean}> => {

if (valid === 'error') {
await confirmAndExit(
`It seems that ${magenta(
'junobuild-didc'
)} is not installed. This is a useful tool for generating automatically JavaScript or TypeScript bindings. Would you like to install it?`
`${magenta(
'@icp-sdk/bindgen'
)} is not available. This tool is required to generate API bindings. Would you like to install it now?`
);

await execute({
command: 'cargo',
args: ['install', `junobuild-didc`]
command: pm ?? 'npm',
args: [pm === 'npm' ? 'i' : 'add', '@icp-sdk/bindgen', '-D']
});
}

return {valid: true};
};

export const checkWasi2ic = async (): Promise<{valid: boolean}> => {
const {valid} = await checkCargoBinInstalled({
const {valid} = await checkToolInstalled({
command: 'wasi2ic',
args: ['--version']
});
Expand Down
2 changes: 1 addition & 1 deletion src/utils/env.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const checkIcWasmVersion = async (): Promise<{valid: boolean | 'error'}>
return {valid: true};
};

export const checkCargoBinInstalled = async ({
export const checkToolInstalled = async ({
command,
args
}: {
Expand Down