@ic-reactor/codegen 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # @ic-reactor/codegen
2
+
3
+ > shared code generation pipeline and utilities for IC Reactor.
4
+
5
+ This package contains the core machinery for generating TypeScript declarations, reactor instances, and client managers from Candid files. It is primarily used by:
6
+
7
+ - **`@ic-reactor/cli`**: For manual/CLI-based generation
8
+ - **`@ic-reactor/vite-plugin`**: For automatic build-time generation
9
+
10
+ ## API
11
+
12
+ The main entry point is the `runCanisterPipeline` function, which orchestrates the generation process.
13
+
14
+ ```typescript
15
+ import { runCanisterPipeline } from "@ic-reactor/codegen"
16
+
17
+ await runCanisterPipeline({
18
+ canisterConfig: {
19
+ name: "backend",
20
+ didFile: "./backend.did",
21
+ },
22
+ projectRoot: process.cwd(),
23
+ globalConfig: {
24
+ outDir: "src/declarations",
25
+ clientManagerPath: "../../clients",
26
+ },
27
+ })
28
+ ```
29
+
30
+ ## Generators
31
+
32
+ You can also use individual generators if you need more granular control:
33
+
34
+ - **`generateDeclarations`**: Generates `.js` (factory), `.d.ts` (types), and `.did` copy.
35
+ - **`generateReactorFile`**: Generates the `index.ts` file with `DisplayReactor` and hooks.
36
+ - **`generateClientFile`**: Generates a `ClientManager` boilerplate file.
37
+
38
+ ## Utilities
39
+
40
+ - **`parseDIDFile`**: Parses a `.did` file and extracts method signatures.
41
+ - **`toPascalCase` / `toCamelCase`**: Naming helpers.
42
+
43
+ ## License
44
+
45
+ MIT
package/dist/index.cjs CHANGED
@@ -31,45 +31,38 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  declarationsExist: () => declarationsExist,
34
+ extractMethods: () => extractMethods,
34
35
  generateClientFile: () => generateClientFile,
35
36
  generateDeclarations: () => generateDeclarations,
36
37
  generateReactorFile: () => generateReactorFile,
37
38
  getReactorName: () => getReactorName,
38
39
  getServiceTypeName: () => getServiceTypeName,
40
+ parseDIDFile: () => parseDIDFile,
41
+ runCanisterPipeline: () => runCanisterPipeline,
39
42
  toPascalCase: () => toPascalCase
40
43
  });
41
44
  module.exports = __toCommonJS(index_exports);
42
45
 
43
- // src/naming.ts
44
- var import_change_case = require("change-case");
45
- function toPascalCase(str) {
46
- return (0, import_change_case.pascalCase)(str);
47
- }
48
- function toCamelCase(str) {
49
- return (0, import_change_case.camelCase)(str);
50
- }
51
- function getReactorName(canisterName) {
52
- return `${toCamelCase(canisterName)}Reactor`;
53
- }
54
- function getServiceTypeName(canisterName) {
55
- return `${toPascalCase(canisterName)}Service`;
56
- }
46
+ // src/pipeline.ts
47
+ var import_node_fs2 = __toESM(require("fs"), 1);
48
+ var import_node_path3 = __toESM(require("path"), 1);
57
49
 
58
- // src/bindgen.ts
50
+ // src/generators/declarations.ts
59
51
  var import_parser = require("@ic-reactor/parser");
60
52
  var import_node_path = __toESM(require("path"), 1);
61
53
  var import_node_fs = __toESM(require("fs"), 1);
62
54
  async function generateDeclarations(options) {
63
- const { didFile, outDir } = options;
55
+ const { didFile, outDir, canisterName } = options;
64
56
  if (!import_node_fs.default.existsSync(didFile)) {
65
57
  return {
66
58
  success: false,
67
59
  declarationsDir: "",
60
+ files: [],
68
61
  error: `DID file not found: ${didFile}`
69
62
  };
70
63
  }
71
64
  const declarationsDir = import_node_path.default.join(outDir, "declarations");
72
- const didFileName = import_node_path.default.basename(didFile);
65
+ const baseName = import_node_path.default.basename(didFile, ".did");
73
66
  try {
74
67
  const didContent = import_node_fs.default.readFileSync(didFile, "utf-8");
75
68
  if (!import_node_fs.default.existsSync(outDir)) {
@@ -81,73 +74,75 @@ async function generateDeclarations(options) {
81
74
  import_node_fs.default.mkdirSync(declarationsDir, { recursive: true });
82
75
  const jsContent = (0, import_parser.didToJs)(didContent);
83
76
  const tsContent = (0, import_parser.didToTs)(didContent);
84
- const baseName = didFileName.replace(/\.did$/, "");
85
- const jsPath = import_node_path.default.join(declarationsDir, baseName + ".js");
86
- const dtsPath = import_node_path.default.join(declarationsDir, baseName + ".d.ts");
87
- const didPath = import_node_path.default.join(declarationsDir, didFileName);
77
+ const jsPath = import_node_path.default.join(declarationsDir, `${baseName}.js`);
78
+ const dtsPath = import_node_path.default.join(declarationsDir, `${baseName}.d.ts`);
79
+ const didCopyPath = import_node_path.default.join(declarationsDir, `${baseName}.did`);
88
80
  import_node_fs.default.writeFileSync(jsPath, jsContent);
89
81
  import_node_fs.default.writeFileSync(dtsPath, tsContent);
90
- import_node_fs.default.writeFileSync(didPath, didContent);
82
+ import_node_fs.default.writeFileSync(didCopyPath, didContent);
91
83
  return {
92
84
  success: true,
93
- declarationsDir
85
+ declarationsDir,
86
+ files: [
87
+ { success: true, filePath: jsPath },
88
+ { success: true, filePath: dtsPath },
89
+ { success: true, filePath: didCopyPath }
90
+ ]
94
91
  };
95
92
  } catch (error) {
93
+ const message = error instanceof Error ? error.message : String(error);
96
94
  return {
97
95
  success: false,
98
96
  declarationsDir,
99
- error: error instanceof Error ? error.message : String(error)
97
+ files: [],
98
+ error: `[${canisterName}] Failed to generate declarations: ${message}`
100
99
  };
101
100
  }
102
101
  }
103
102
  function declarationsExist(outDir, canisterName) {
104
- const declarationsDir = import_node_path.default.join(outDir, "declarations");
105
- const didTsPath = import_node_path.default.join(declarationsDir, `${canisterName}.d.ts`);
106
- return import_node_fs.default.existsSync(didTsPath);
103
+ const dtsPath = import_node_path.default.join(outDir, "declarations", `${canisterName}.d.ts`);
104
+ return import_node_fs.default.existsSync(dtsPath);
107
105
  }
108
106
 
109
- // src/templates/reactor.ts
107
+ // src/generators/reactor.ts
110
108
  var import_node_path2 = __toESM(require("path"), 1);
109
+
110
+ // src/naming.ts
111
+ var import_change_case = require("change-case");
112
+ function toPascalCase(str) {
113
+ return (0, import_change_case.pascalCase)(str);
114
+ }
115
+ function toCamelCase(str) {
116
+ return (0, import_change_case.camelCase)(str);
117
+ }
118
+ function getReactorName(canisterName) {
119
+ return `${toCamelCase(canisterName)}Reactor`;
120
+ }
121
+ function getServiceTypeName(canisterName) {
122
+ return `${toPascalCase(canisterName)}Service`;
123
+ }
124
+
125
+ // src/generators/reactor.ts
111
126
  function generateReactorFile(options) {
112
- const pascalName = toPascalCase(options.canisterName);
113
- const reactorName = getReactorName(options.canisterName);
114
- const serviceName = getServiceTypeName(options.canisterName);
115
- const reactorType = "DisplayReactor";
116
- const didFileName = import_node_path2.default.basename(options.didFile);
117
- const baseName = didFileName.replace(/\.did$/, "");
127
+ const { canisterName, didFile, clientManagerPath = "../../clients" } = options;
128
+ const pascalName = toPascalCase(canisterName);
129
+ const reactorName = getReactorName(canisterName);
130
+ const serviceName = getServiceTypeName(canisterName);
131
+ const baseName = import_node_path2.default.basename(didFile, ".did");
118
132
  const declarationsPath = `./declarations/${baseName}`;
119
- const clientManagerPath = options.clientManagerPath ?? "../../clients";
120
- const vars = {
121
- canisterName: options.canisterName,
122
- pascalName,
123
- reactorName,
124
- serviceName,
125
- reactorType,
126
- clientManagerPath,
127
- declarationsPath
128
- };
129
- return generateStandardReactorFile(vars);
130
- }
131
- function generateStandardReactorFile(vars) {
132
- const {
133
- pascalName,
134
- reactorName,
135
- serviceName,
136
- reactorType,
137
- clientManagerPath,
138
- declarationsPath,
139
- canisterName
140
- } = vars;
141
- return `import { ${reactorType}, createActorHooks } from "@ic-reactor/react"
133
+ return `import { DisplayReactor, createActorHooks } from "@ic-reactor/react"
142
134
  import { clientManager } from "${clientManagerPath}"
143
135
  import { idlFactory, type _SERVICE } from "${declarationsPath}"
144
136
 
145
137
  export type ${serviceName} = _SERVICE
146
138
 
147
139
  /**
148
- * ${pascalName} Display Reactor
140
+ * ${pascalName} Reactor
141
+ *
142
+ * Auto-generated by @ic-reactor/codegen \u2014 do not edit.
143
+ * Re-run \`ic-reactor generate\` (or the Vite plugin) to regenerate.
149
144
  */
150
- export const ${reactorName} = new ${reactorType}<${serviceName}>({
145
+ export const ${reactorName} = new DisplayReactor<${serviceName}>({
151
146
  clientManager,
152
147
  idlFactory,
153
148
  name: "${canisterName}",
@@ -164,18 +159,123 @@ export const {
164
159
  `;
165
160
  }
166
161
 
167
- // src/templates/client.ts
162
+ // src/pipeline.ts
163
+ async function runCanisterPipeline(options) {
164
+ const { canisterConfig, projectRoot, globalConfig } = options;
165
+ const { name, didFile, clientManagerPath } = canisterConfig;
166
+ const files = [];
167
+ const resolvedDidFile = import_node_path3.default.isAbsolute(didFile) ? didFile : import_node_path3.default.resolve(projectRoot, didFile);
168
+ if (!import_node_fs2.default.existsSync(resolvedDidFile)) {
169
+ return {
170
+ canisterName: name,
171
+ success: false,
172
+ files: [],
173
+ error: `DID file not found: ${resolvedDidFile}`
174
+ };
175
+ }
176
+ const canisterOutDir = canisterConfig.outDir != null ? import_node_path3.default.isAbsolute(canisterConfig.outDir) ? canisterConfig.outDir : import_node_path3.default.resolve(projectRoot, canisterConfig.outDir) : import_node_path3.default.resolve(projectRoot, globalConfig.outDir, name);
177
+ const resolvedClientManagerPath = clientManagerPath ?? globalConfig.clientManagerPath ?? "../../clients";
178
+ try {
179
+ const declResult = await generateDeclarations({
180
+ didFile: resolvedDidFile,
181
+ outDir: canisterOutDir,
182
+ canisterName: name
183
+ });
184
+ if (!declResult.success) {
185
+ return {
186
+ canisterName: name,
187
+ success: false,
188
+ files,
189
+ error: declResult.error
190
+ };
191
+ }
192
+ files.push(...declResult.files);
193
+ } catch (err) {
194
+ return {
195
+ canisterName: name,
196
+ success: false,
197
+ files,
198
+ error: `Declarations step failed: ${err instanceof Error ? err.message : String(err)}`
199
+ };
200
+ }
201
+ const reactorPath = import_node_path3.default.join(canisterOutDir, "index.ts");
202
+ try {
203
+ const reactorContent = generateReactorFile({
204
+ canisterName: name,
205
+ didFile: resolvedDidFile,
206
+ clientManagerPath: resolvedClientManagerPath
207
+ });
208
+ import_node_fs2.default.mkdirSync(canisterOutDir, { recursive: true });
209
+ import_node_fs2.default.writeFileSync(reactorPath, reactorContent);
210
+ files.push({ success: true, filePath: reactorPath });
211
+ } catch (err) {
212
+ files.push({
213
+ success: false,
214
+ filePath: reactorPath,
215
+ error: `Reactor generation failed: ${err instanceof Error ? err.message : String(err)}`
216
+ });
217
+ return {
218
+ canisterName: name,
219
+ success: false,
220
+ files,
221
+ error: `Reactor step failed: ${err instanceof Error ? err.message : String(err)}`
222
+ };
223
+ }
224
+ return {
225
+ canisterName: name,
226
+ success: true,
227
+ files
228
+ };
229
+ }
230
+
231
+ // src/parser.ts
232
+ var import_parser2 = require("@ic-reactor/parser");
233
+ var import_node_fs3 = __toESM(require("fs"), 1);
234
+ function extractMethods(didContent) {
235
+ try {
236
+ const jsContent = (0, import_parser2.didToJs)(didContent);
237
+ const methods = [];
238
+ const serviceMatch = /IDL\.Service\(\{([\s\S]*?)\}\)/.exec(jsContent);
239
+ if (!serviceMatch) return methods;
240
+ const serviceBody = serviceMatch[1];
241
+ const methodRegex = /['"]([\w]+)['"]\s*:\s*IDL\.Func\(\s*\[(.*?)\],\s*\[.*?\],\s*\[(.*?)\]\)/g;
242
+ let match;
243
+ while ((match = methodRegex.exec(serviceBody)) !== null) {
244
+ const [, name, args, annotations] = match;
245
+ methods.push({
246
+ name,
247
+ type: annotations.includes("'query'") ? "query" : "mutation",
248
+ hasArgs: args.trim().length > 0
249
+ });
250
+ }
251
+ return methods;
252
+ } catch (error) {
253
+ const msg = error instanceof Error ? error.message : String(error);
254
+ throw new Error(`Failed to parse Candid: ${msg}`);
255
+ }
256
+ }
257
+ function parseDIDFile(didFilePath) {
258
+ if (!import_node_fs3.default.existsSync(didFilePath)) {
259
+ throw new Error(`DID file not found: ${didFilePath}`);
260
+ }
261
+ const content = import_node_fs3.default.readFileSync(didFilePath, "utf-8");
262
+ return extractMethods(content);
263
+ }
264
+
265
+ // src/generators/client.ts
168
266
  function generateClientFile(options = {}) {
169
267
  const { queryClientPath } = options;
170
- return `import { ClientManager } from "@ic-reactor/react"
171
- ${queryClientPath ? `import { queryClient } from "${queryClientPath}"` : `import { QueryClient } from "@tanstack/react-query"
268
+ const queryClientImport = queryClientPath ? `import { queryClient } from "${queryClientPath}"` : `import { QueryClient } from "@tanstack/react-query"
172
269
 
173
- export const queryClient = new QueryClient()`}
270
+ export const queryClient = new QueryClient()`;
271
+ return `import { ClientManager } from "@ic-reactor/react"
272
+ ${queryClientImport}
174
273
 
175
274
  /**
176
275
  * IC Reactor Client Manager
177
- *
178
- * Auto-generated by @ic-reactor/codegen
276
+ *
277
+ * Auto-generated by @ic-reactor/codegen \u2014 customize as needed.
278
+ * See: https://github.com/B3Pay/ic-reactor#client-manager
179
279
  */
180
280
  export const clientManager = new ClientManager({
181
281
  queryClient,
@@ -186,10 +286,13 @@ export const clientManager = new ClientManager({
186
286
  // Annotate the CommonJS export names for ESM import in node:
187
287
  0 && (module.exports = {
188
288
  declarationsExist,
289
+ extractMethods,
189
290
  generateClientFile,
190
291
  generateDeclarations,
191
292
  generateReactorFile,
192
293
  getReactorName,
193
294
  getServiceTypeName,
295
+ parseDIDFile,
296
+ runCanisterPipeline,
194
297
  toPascalCase
195
298
  });
package/dist/index.d.cts CHANGED
@@ -1,83 +1,249 @@
1
+ /**
2
+ * @ic-reactor/codegen — Core Types
3
+ *
4
+ * All shared types used across generators, pipeline, CLI, and vite-plugin.
5
+ */
6
+ /**
7
+ * Per-canister configuration.
8
+ * `name` is always required — it drives all naming in generators.
9
+ */
10
+ interface CanisterConfig {
11
+ /** Canister name (used for variable names, file names, etc.) */
12
+ name: string;
13
+ /** Path to the .did file (relative to project root, or absolute) */
14
+ didFile: string;
15
+ /** Override output dir for this specific canister */
16
+ outDir?: string;
17
+ /**
18
+ * Import path to the ClientManager (relative from the generated reactor file).
19
+ * Example: "../../clients" → `import { clientManager } from "../../clients"`
20
+ */
21
+ clientManagerPath?: string;
22
+ /** Optional fixed canister ID */
23
+ canisterId?: string;
24
+ }
25
+ /**
26
+ * Top-level codegen / CLI configuration (stored in `ic-reactor.json`).
27
+ */
28
+ interface CodegenConfig {
29
+ /** JSON Schema reference */
30
+ $schema?: string;
31
+ /**
32
+ * Default output directory for all canisters (relative to project root).
33
+ * Individual canisters can override via `CanisterConfig.outDir`.
34
+ */
35
+ outDir: string;
36
+ /**
37
+ * Default import path for the ClientManager (relative from generated files).
38
+ * Individual canisters can override via `CanisterConfig.clientManagerPath`.
39
+ */
40
+ clientManagerPath?: string;
41
+ /** Canister configurations, keyed by canister name */
42
+ canisters: Record<string, CanisterConfig>;
43
+ }
44
+ /**
45
+ * Result of a single file-writing generator step.
46
+ */
47
+ interface GeneratorResult {
48
+ success: boolean;
49
+ /** Absolute path of the file that was (or would have been) written */
50
+ filePath: string;
51
+ /** If true, skipped because the file already existed */
52
+ skipped?: boolean;
53
+ error?: string;
54
+ }
55
+
56
+ /**
57
+ * Codegen Pipeline
58
+ *
59
+ * Orchestrates all generators for a single canister.
60
+ * This is the primary entry point used by @ic-reactor/cli and @ic-reactor/vite-plugin.
61
+ *
62
+ * Pipeline steps (in order):
63
+ * 1. Resolve paths (didFile, outDir)
64
+ * 2. Generate declarations (JS + .d.ts + .did copy)
65
+ * 3. Generate reactor file (index.ts)
66
+ */
67
+
68
+ interface PipelineOptions {
69
+ /** Canister name and config */
70
+ canisterConfig: CanisterConfig;
71
+ /**
72
+ * Absolute path to the project root.
73
+ * Relative paths in `CanisterConfig` are resolved from here.
74
+ */
75
+ projectRoot: string;
76
+ /**
77
+ * Global codegen config (for fallback outDir and clientManagerPath).
78
+ */
79
+ globalConfig: Pick<CodegenConfig, "outDir" | "clientManagerPath">;
80
+ }
81
+ interface PipelineResult {
82
+ canisterName: string;
83
+ success: boolean;
84
+ /** All files the pipeline attempted to write */
85
+ files: GeneratorResult[];
86
+ error?: string;
87
+ }
88
+ /**
89
+ * Run the full codegen pipeline for a single canister.
90
+ *
91
+ * @returns PipelineResult with per-file details
92
+ */
93
+ declare function runCanisterPipeline(options: PipelineOptions): Promise<PipelineResult>;
94
+
1
95
  /**
2
96
  * Naming utilities for code generation
3
97
  *
4
- * Uses the `change-case` library for base transformations,
5
- * with domain-specific helpers for IC Reactor patterns.
98
+ * Pure functions that convert canister/method names to correctly cased
99
+ * identifiers used throughout generated code.
6
100
  */
7
101
  /**
8
- * Convert string to PascalCase
102
+ * Convert string to PascalCase.
9
103
  * @example toPascalCase("get_message") → "GetMessage"
10
104
  * @example toPascalCase("my-canister") → "MyCanister"
11
105
  */
12
106
  declare function toPascalCase(str: string): string;
13
107
  /**
14
- * Generate reactor variable name
108
+ * Generate the reactor variable name for a canister.
15
109
  * @example getReactorName("backend") → "backendReactor"
110
+ * @example getReactorName("my_canister") → "myCanisterReactor"
16
111
  */
17
112
  declare function getReactorName(canisterName: string): string;
18
113
  /**
19
- * Generate service type name
114
+ * Generate the service type name for a canister.
20
115
  * @example getServiceTypeName("backend") → "BackendService"
116
+ * @example getServiceTypeName("my_canister") → "MyCanisterService"
21
117
  */
22
118
  declare function getServiceTypeName(canisterName: string): string;
23
119
 
24
120
  /**
25
- * Bindgen utilities
121
+ * Candid Parser Utilities
122
+ *
123
+ * Parses Candid .did files to extract service method signatures.
124
+ * Used by the CLI for listing methods and by advanced generators.
125
+ */
126
+ type MethodType = "query" | "mutation";
127
+ interface MethodInfo {
128
+ /** Method name as it appears in the Candid service */
129
+ name: string;
130
+ /** "query" for read-only calls, "mutation" for update calls */
131
+ type: MethodType;
132
+ /** True if the method takes at least one argument */
133
+ hasArgs: boolean;
134
+ }
135
+ /**
136
+ * Extract method information from raw Candid source text.
26
137
  *
27
- * Generates TypeScript declarations from Candid files using @ic-reactor/parser.
138
+ * Compiles the Candid to JS and inspects the IDL.Service definition.
28
139
  */
29
- interface BindgenOptions {
30
- /** Path to the .did file */
140
+ declare function extractMethods(didContent: string): MethodInfo[];
141
+ /**
142
+ * Parse a .did file from disk and return its methods.
143
+ *
144
+ * @throws if the file does not exist or fails to parse
145
+ */
146
+ declare function parseDIDFile(didFilePath: string): MethodInfo[];
147
+
148
+ /**
149
+ * Declarations Generator
150
+ *
151
+ * Generates TypeScript declaration files (.js IDL factory + .d.ts types)
152
+ * from a Candid .did file using @ic-reactor/parser.
153
+ *
154
+ * Output structure:
155
+ * <outDir>/declarations/<name>.js — IDL factory
156
+ * <outDir>/declarations/<name>.d.ts — TypeScript types
157
+ * <outDir>/declarations/<name>.did — Copy of the source .did file
158
+ */
159
+
160
+ interface DeclarationsGeneratorOptions {
161
+ /** Absolute path to the .did file */
31
162
  didFile: string;
32
- /** Output directory for generated declarations */
163
+ /** Absolute path to the output directory (declarations/ will be created inside) */
33
164
  outDir: string;
34
- /** Canister name (used for naming) */
165
+ /** Canister name (used only for error messages) */
35
166
  canisterName: string;
36
167
  }
37
- interface BindgenResult {
168
+ interface DeclarationsGeneratorResult {
38
169
  success: boolean;
39
170
  declarationsDir: string;
171
+ files: GeneratorResult[];
40
172
  error?: string;
41
173
  }
42
174
  /**
43
- * Generate TypeScript declarations from a Candid file
175
+ * Generate TypeScript declarations from a Candid file.
44
176
  *
45
- * This creates:
46
- * - declarations/<canisterName>.js - IDL factory
47
- * - declarations/<canisterName>.d.ts - Types
177
+ * Always cleans and regenerates the declarations directory to ensure
178
+ * it's in sync with the source .did file.
48
179
  */
49
- declare function generateDeclarations(options: BindgenOptions): Promise<BindgenResult>;
180
+ declare function generateDeclarations(options: DeclarationsGeneratorOptions): Promise<DeclarationsGeneratorResult>;
50
181
  /**
51
- * Check if declarations already exist for a canister
182
+ * Check if declarations already exist for a canister.
52
183
  */
53
184
  declare function declarationsExist(outDir: string, canisterName: string): boolean;
54
185
 
55
186
  /**
56
- * Reactor file template generator
187
+ * Reactor File Generator
188
+ *
189
+ * Generates the main `index.ts` for a canister — a DisplayReactor instance
190
+ * plus the full set of typed hooks via `createActorHooks`.
191
+ *
192
+ * Generated output example (for canister "backend"):
57
193
  *
58
- * Generates the reactor instance file for a canister using DisplayReactor.
59
- * Standardizes the output to include typed hooks and clean imports.
194
+ * import { DisplayReactor, createActorHooks } from "@ic-reactor/react"
195
+ * import { clientManager } from "../../clients"
196
+ * import { idlFactory, type _SERVICE } from "./declarations/backend"
197
+ *
198
+ * export type BackendService = _SERVICE
199
+ *
200
+ * export const backendReactor = new DisplayReactor<BackendService>({ ... })
201
+ *
202
+ * export const {
203
+ * useActorQuery: useBackendQuery,
204
+ * ...
205
+ * } = createActorHooks(backendReactor)
60
206
  */
61
- type ReactorGeneratorOptions = {
207
+ interface ReactorGeneratorOptions {
208
+ /** Canister name (e.g. "backend") */
62
209
  canisterName: string;
210
+ /**
211
+ * Path to the .did file. Used to derive the declarations import path.
212
+ * Can be relative or absolute — only the basename is used.
213
+ */
63
214
  didFile: string;
215
+ /**
216
+ * Import path for the client manager, relative from the generated reactor file.
217
+ * Default: "../../clients"
218
+ */
64
219
  clientManagerPath?: string;
65
- };
220
+ }
66
221
  /**
67
- * Generate the reactor file content
222
+ * Generate the content of a canister's `index.ts` reactor file.
68
223
  */
69
224
  declare function generateReactorFile(options: ReactorGeneratorOptions): string;
70
225
 
71
226
  /**
72
227
  * Client Manager Generator
228
+ *
229
+ * Generates a central `clients.ts` file that creates a `ClientManager` instance.
230
+ * This file is shared across all canisters in a project.
231
+ *
232
+ * Users typically customize this file once to configure:
233
+ * - Custom host (local vs. mainnet)
234
+ * - Identity provider
235
+ * - Query client options
73
236
  */
74
237
  interface ClientGeneratorOptions {
75
- /** Optional path to an existing queryClient */
238
+ /**
239
+ * Import path to an existing `queryClient` instance.
240
+ * If omitted, a default `QueryClient` will be created.
241
+ */
76
242
  queryClientPath?: string;
77
243
  }
78
244
  /**
79
- * Generate a central client manager file
245
+ * Generate the content for a central client manager file (`clients.ts`).
80
246
  */
81
247
  declare function generateClientFile(options?: ClientGeneratorOptions): string;
82
248
 
83
- export { type BindgenOptions, type BindgenResult, type ClientGeneratorOptions, type ReactorGeneratorOptions, declarationsExist, generateClientFile, generateDeclarations, generateReactorFile, getReactorName, getServiceTypeName, toPascalCase };
249
+ export { type CanisterConfig, type ClientGeneratorOptions, type CodegenConfig, type DeclarationsGeneratorOptions, type DeclarationsGeneratorResult, type GeneratorResult, type MethodInfo, type MethodType, type PipelineOptions, type PipelineResult, type ReactorGeneratorOptions, declarationsExist, extractMethods, generateClientFile, generateDeclarations, generateReactorFile, getReactorName, getServiceTypeName, parseDIDFile, runCanisterPipeline, toPascalCase };