diff --git a/packages/cli/lang/en.json b/packages/cli/lang/en.json index 4ee0cedc6e..0e32cb952e 100644 --- a/packages/cli/lang/en.json +++ b/packages/cli/lang/en.json @@ -92,7 +92,9 @@ "commands_codegen_options_m": "Path to the Polywrap manifest file (default: {default})", "commands_codegen_options_o": "Output directory for custom generated types (default: 'types/')", "commands_codegen_options_o_path": "path", + "commands_codegen_options_b": "Uri for custom bindgen wrap (must implement wrap-abi-bindgen interface; see https://github.com/polywrap/wrap-abi-bindgen)", "commands_codegen_success": "Types were generated successfully", + "commands_codegen_invalid_uri": "Invalid WRAP URI format: {uri}.", "commands_codegen_project_load_error": "Failed to load project, please make sure {manifestPath} is a valid Project manifest", "commands_codegen_options_publish": "Output path for the built schema and manifest (default: {default})", "commands_create_description": "Create New Projects", diff --git a/packages/cli/lang/es.json b/packages/cli/lang/es.json index 4ee0cedc6e..0e32cb952e 100644 --- a/packages/cli/lang/es.json +++ b/packages/cli/lang/es.json @@ -92,7 +92,9 @@ "commands_codegen_options_m": "Path to the Polywrap manifest file (default: {default})", "commands_codegen_options_o": "Output directory for custom generated types (default: 'types/')", "commands_codegen_options_o_path": "path", + "commands_codegen_options_b": "Uri for custom bindgen wrap (must implement wrap-abi-bindgen interface; see https://github.com/polywrap/wrap-abi-bindgen)", "commands_codegen_success": "Types were generated successfully", + "commands_codegen_invalid_uri": "Invalid WRAP URI format: {uri}.", "commands_codegen_project_load_error": "Failed to load project, please make sure {manifestPath} is a valid Project manifest", "commands_codegen_options_publish": "Output path for the built schema and manifest (default: {default})", "commands_create_description": "Create New Projects", diff --git a/packages/cli/src/__tests__/e2e/p2/codegen.spec.ts b/packages/cli/src/__tests__/e2e/p2/codegen.spec.ts index 060b9611d4..ba388daa40 100644 --- a/packages/cli/src/__tests__/e2e/p2/codegen.spec.ts +++ b/packages/cli/src/__tests__/e2e/p2/codegen.spec.ts @@ -16,6 +16,9 @@ Options: (default: polywrap.yaml | polywrap.yml) -g, --codegen-dir Output directory for the generated code (default: ./src/wrap) + -b, --bindgen Uri for custom bindgen wrap (must + implement wrap-abi-bindgen interface; see + https://github.com/polywrap/wrap-abi-bindgen) -s, --script Path to a custom generation script (JavaScript | TypeScript) -c, --client-config Add custom configuration to the @@ -188,4 +191,23 @@ describe("e2e tests for codegen command", () => { rimraf.sync(`${getTestCaseDir(1)}/types`); }); + + it("Should successfully generate types with custom bindgen wrap", async () => { + rimraf.sync(`${getTestCaseDir(0)}/types`); + + const { exitCode: code, stdout: output, stderr: error } = await Commands.codegen({ + bindgen: "https://github.com/polywrap/wrap-abi-bindgen/tree/wrap-0.1/implementations/wrap-rust" + }, { + cwd: getTestCaseDir(0), + cli: polywrapCli, + }); + + expect(code).toEqual(0); + expect(error).toBe(""); + expect(clearStyle(output)).toContain( + `🔥 Types were generated successfully 🔥` + ); + + rimraf.sync(`${getTestCaseDir(0)}/types`); + }); }); diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index c13365018e..5b457c3766 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -28,6 +28,7 @@ import { } from "../lib/build-strategies"; import { DEFAULT_CODEGEN_DIR } from "../lib/defaults"; import { watchProject } from "../lib/watchProject"; +import { parseUriOption } from "../lib/option-parsers/uri"; import { PolywrapClient } from "@polywrap/client-js"; import { PolywrapManifest } from "@polywrap/polywrap-manifest-types-js"; @@ -46,6 +47,7 @@ const supportedProjectTypes = [ export interface BuildCommandOptions extends BaseCommandOptions { manifestFile: string; outputDir: string; + bindgen: string | false; clientConfig: string | false; wrapperEnvs: string | false; noCodegen: boolean; @@ -72,6 +74,7 @@ export const build: Command = { default: defaultOutputDir, })}` ) + .option(`-b, --bindgen `, `${intlMsg.commands_codegen_options_b()}`) .option( `-c, --client-config <${intlMsg.commands_common_options_configPath()}>`, `${intlMsg.commands_common_options_config()}` @@ -112,6 +115,7 @@ export const build: Command = { clientConfig: options.clientConfig || false, wrapperEnvs: options.wrapperEnvs || false, outputDir: parseDirOption(options.outputDir, defaultOutputDir), + bindgen: options.bindgen || false, noCodegen: !options.codegen || false, codegenDir: parseDirOptionNoDefault(options.codegenDir), strategy: options.strategy || defaultStrategy, @@ -167,6 +171,7 @@ async function run(options: Required) { clientConfig, wrapperEnvs, outputDir, + bindgen, strategy, noCodegen, codegenDir, @@ -176,7 +181,7 @@ async function run(options: Required) { } = options; const logger = createLogger({ verbose, quiet, logFile }); - + const bindgenUri = parseUriOption(bindgen); const envs = await parseWrapperEnvsOption(wrapperEnvs); const configBuilder = await parseClientConfigOption(clientConfig); @@ -243,6 +248,7 @@ async function run(options: Required) { project, schemaComposer, codegenDirAbs: codegenDir || undefined, + bindgenUri, }); const codegenSuccess = await codeGenerator.generate(); diff --git a/packages/cli/src/commands/codegen.ts b/packages/cli/src/commands/codegen.ts index 3968cdbf65..e2d4e739f6 100644 --- a/packages/cli/src/commands/codegen.ts +++ b/packages/cli/src/commands/codegen.ts @@ -18,6 +18,7 @@ import { import { ScriptCodegenerator } from "../lib/codegen/ScriptCodeGenerator"; import { DEFAULT_CODEGEN_DIR } from "../lib/defaults"; import { watchProject } from "../lib/watchProject"; +import { parseUriOption } from "../lib/option-parsers/uri"; import { PolywrapClient } from "@polywrap/client-js"; @@ -27,6 +28,7 @@ const defaultManifestStr = defaultPolywrapManifestFiles.join(" | "); export interface CodegenCommandOptions extends BaseCommandOptions { manifestFile: string; codegenDir: string | false; + bindgen: string | false; script: string | false; clientConfig: string | false; wrapperEnvs: string | false; @@ -51,6 +53,7 @@ export const codegen: Command = { default: DEFAULT_CODEGEN_DIR, })}` ) + .option(`-b, --bindgen `, `${intlMsg.commands_codegen_options_b()}`) .option( `-s, --script <${pathStr}>`, `${intlMsg.commands_codegen_options_s()}` @@ -77,6 +80,7 @@ export const codegen: Command = { defaultProjectManifestFiles ), codegenDir: parseDirOptionNoDefault(options.codegenDir), + bindgen: options.bindgen || false, script: parseCodegenScriptOption(options.script), clientConfig: options.clientConfig || false, wrapperEnvs: options.wrapperEnvs || false, @@ -95,6 +99,7 @@ async function run(options: Required) { clientConfig, wrapperEnvs, codegenDir, + bindgen, script, verbose, quiet, @@ -102,7 +107,7 @@ async function run(options: Required) { watch, } = options; const logger = createLogger({ verbose, quiet, logFile }); - + const bindgenUri = parseUriOption(bindgen); const envs = await parseWrapperEnvsOption(wrapperEnvs); const configBuilder = await parseClientConfigOption(clientConfig); @@ -142,6 +147,7 @@ async function run(options: Required) { codegenDirAbs: codegenDir || undefined, schemaComposer, project, + bindgenUri, }); const execute = async (): Promise => { diff --git a/packages/cli/src/lib/codegen/CodeGenerator.ts b/packages/cli/src/lib/codegen/CodeGenerator.ts index 46a16e8bf8..1aee32cde4 100644 --- a/packages/cli/src/lib/codegen/CodeGenerator.ts +++ b/packages/cli/src/lib/codegen/CodeGenerator.ts @@ -21,11 +21,13 @@ import { CodegenOverrides, tryGetCodegenOverrides } from "./CodegenOverrides"; import path from "path"; import { BindLanguage } from "@polywrap/schema-bind"; import { writeDirectorySync } from "@polywrap/os-js"; +import { Uri } from "@polywrap/core-js"; export interface CodeGeneratorConfig { project: Project; schemaComposer: SchemaComposer; codegenDirAbs?: string; + bindgenUri?: Uri; } export class CodeGenerator { @@ -89,6 +91,7 @@ export class CodeGenerator { const binding = await this._config.project.generateSchemaBindings( abi, codegenDir, + this._config.bindgenUri?.toString(), bindConfig ); diff --git a/packages/cli/src/lib/option-parsers/uri.ts b/packages/cli/src/lib/option-parsers/uri.ts new file mode 100644 index 0000000000..2986d34d4a --- /dev/null +++ b/packages/cli/src/lib/option-parsers/uri.ts @@ -0,0 +1,17 @@ +import { intlMsg } from "../intl"; + +import { Uri } from "@polywrap/core-js"; + +export function parseUriOption( + uri: string | undefined | false +): Uri | undefined { + if (uri) { + try { + return Uri.from(uri); + } catch { + console.error(intlMsg.commands_codegen_invalid_uri({ uri })); + process.exit(1); + } + } + return undefined; +} diff --git a/packages/cli/src/lib/project/AppProject.ts b/packages/cli/src/lib/project/AppProject.ts index 371786057a..1e6dd30efe 100644 --- a/packages/cli/src/lib/project/AppProject.ts +++ b/packages/cli/src/lib/project/AppProject.ts @@ -113,7 +113,8 @@ export class AppProject extends Project { public async generateSchemaBindings( abi: WrapAbi, - generationSubPath?: string + generationSubPath?: string, + bindgenUri?: string ): Promise { const bindLanguage = appManifestLanguageToBindLanguage( await this.getManifestLanguage() @@ -128,7 +129,7 @@ export class AppProject extends Project { }, outputDirAbs: await this.getGenerationDirectory(generationSubPath), }; - return bindSchema(options); + return bindSchema(options, bindgenUri); } private _getGenerationDirectory( diff --git a/packages/cli/src/lib/project/PluginProject.ts b/packages/cli/src/lib/project/PluginProject.ts index 9da9a5d046..583f5d9046 100644 --- a/packages/cli/src/lib/project/PluginProject.ts +++ b/packages/cli/src/lib/project/PluginProject.ts @@ -117,7 +117,8 @@ export class PluginProject extends Project { public async generateSchemaBindings( abi: WrapAbi, - generationSubPath?: string + generationSubPath?: string, + bindgenUri?: string ): Promise { const moduleDirectory = await this.getGenerationDirectory( generationSubPath @@ -141,7 +142,7 @@ export class PluginProject extends Project { outputDirAbs: moduleDirectory, }; - return bindSchema(options); + return bindSchema(options, bindgenUri); } private _getGenerationDirectory( diff --git a/packages/cli/src/lib/project/PolywrapProject.ts b/packages/cli/src/lib/project/PolywrapProject.ts index bd0f3ef337..a15688aa8e 100644 --- a/packages/cli/src/lib/project/PolywrapProject.ts +++ b/packages/cli/src/lib/project/PolywrapProject.ts @@ -153,6 +153,7 @@ export class PolywrapProject extends Project { public async generateSchemaBindings( abi: WrapAbi, generationSubPath?: string, + bindgenUri?: string, bindConfig?: Record ): Promise { const codegenDirectory = await this.getGenerationDirectory( @@ -178,7 +179,7 @@ export class PolywrapProject extends Project { config: bindConfig, }; - return bindSchema(options); + return bindSchema(options, bindgenUri); } /// Polywrap Build Manifest (polywrap.build.yaml) diff --git a/packages/cli/src/lib/project/Project.ts b/packages/cli/src/lib/project/Project.ts index 03cc4b7b24..8fc8903153 100644 --- a/packages/cli/src/lib/project/Project.ts +++ b/packages/cli/src/lib/project/Project.ts @@ -73,6 +73,7 @@ export abstract class Project { public abstract generateSchemaBindings( abi: Abi, generationSubPath?: string, + bindgenUri?: string, bindConfig?: Record ): Promise; diff --git a/packages/schema/bind/src/index.ts b/packages/schema/bind/src/index.ts index 422198454a..8826be6c4c 100644 --- a/packages/schema/bind/src/index.ts +++ b/packages/schema/bind/src/index.ts @@ -1,5 +1,6 @@ import { BindOptions, BindOutput } from "./types"; import { getGenerateBindingFn } from "./bindings"; +import * as WrapBindgen from "./bindings/wrap-bindgen"; import Mustache from "mustache"; @@ -9,6 +10,12 @@ Mustache.escape = (value) => value; export * from "./types"; export * from "./bindings"; -export async function bindSchema(options: BindOptions): Promise { - return await getGenerateBindingFn(options.bindLanguage)(options); +export async function bindSchema( + options: BindOptions, + uri?: string +): Promise { + if (uri) { + return WrapBindgen.getGenerateBindingFn(uri)(options); + } + return getGenerateBindingFn(options.bindLanguage)(options); } diff --git a/yarn.lock b/yarn.lock index 23fd596643..039c66d460 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4450,9 +4450,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.4.431: - version "1.4.461" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz#6b14af66042732bf883ab63a4d82cac8f35eb252" - integrity sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ== + version "1.4.462" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.462.tgz#4faf5072bb5f55269d35ca9dc7475e7bf91b1ac3" + integrity sha512-ux2LqN9JKRBDKXMT+78jtiBLPiXf+rLtYlsrOg5Qn7uv6Cbg7+9JyIalE3wcqkOdB2wPCUYNWAuL7suKRMHe9w== elliptic@6.5.4: version "6.5.4"