@fluojs/cli 1.0.0-beta.1 → 1.0.0-beta.2

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.
@@ -1,9 +1,11 @@
1
1
  import type { GeneratorFactory } from '../generator-types.js';
2
+ /** Module metadata array names that auto-registered generators are allowed to update. */
2
3
  export type ModuleArrayKey = 'controllers' | 'providers' | 'middleware';
3
4
  type ModuleRegistrationDescriptor = {
4
5
  arrayKey: ModuleArrayKey;
5
6
  classSuffix: string;
6
7
  };
8
+ /** Describes one built-in generator schematic and its CLI-facing metadata. */
7
9
  export type GeneratorManifestEntry = {
8
10
  aliases: readonly string[];
9
11
  description: string;
@@ -15,6 +17,244 @@ export type GeneratorManifestEntry = {
15
17
  schematic: string;
16
18
  wiringBehavior: 'auto-registered' | 'files-only';
17
19
  };
20
+ /** Describes a deterministic collection of generator schematics discoverable by the CLI. */
21
+ export type GeneratorCollection = {
22
+ description: string;
23
+ generators: readonly GeneratorManifestEntry[];
24
+ id: string;
25
+ source: 'built-in';
26
+ };
27
+ /** Option metadata shared by generate-command parsing, help output, docs, and tests. */
28
+ export declare const generatorOptionSchemas: readonly [{
29
+ readonly aliases: readonly ["-o"];
30
+ readonly description: "Write generated files under a specific source directory.";
31
+ readonly name: "--target-directory <path>";
32
+ readonly value: "path";
33
+ }, {
34
+ readonly aliases: readonly ["-f"];
35
+ readonly description: "Overwrite files that already exist.";
36
+ readonly name: "--force";
37
+ readonly value: "boolean";
38
+ }, {
39
+ readonly aliases: readonly [];
40
+ readonly description: "Preview planned writes, skips, and module wiring without touching files.";
41
+ readonly name: "--dry-run";
42
+ readonly value: "boolean";
43
+ }, {
44
+ readonly aliases: readonly ["-h"];
45
+ readonly description: "Show help for the generate command.";
46
+ readonly name: "--help";
47
+ readonly value: "boolean";
48
+ }];
49
+ /** The single generator collection shipped directly inside `@fluojs/cli`. */
50
+ export declare const builtInGeneratorCollection: {
51
+ readonly description: "The deterministic collection of generator schematics shipped by @fluojs/cli.";
52
+ readonly generators: readonly [{
53
+ readonly aliases: readonly ["co"];
54
+ readonly description: "Generate a controller (auto-registered in the module controllers array).";
55
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
56
+ readonly kind: "controller";
57
+ readonly moduleRegistration: {
58
+ readonly arrayKey: "controllers";
59
+ readonly classSuffix: "Controller";
60
+ };
61
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then add route handlers.";
62
+ readonly schematic: "controller";
63
+ readonly wiringBehavior: "auto-registered";
64
+ }, {
65
+ readonly aliases: readonly ["gu"];
66
+ readonly description: "Generate a guard (auto-registered as a provider in the module).";
67
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
68
+ readonly kind: "guard";
69
+ readonly moduleRegistration: {
70
+ readonly arrayKey: "providers";
71
+ readonly classSuffix: "Guard";
72
+ };
73
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then apply the guard to routes.";
74
+ readonly schematic: "guard";
75
+ readonly wiringBehavior: "auto-registered";
76
+ }, {
77
+ readonly aliases: readonly ["in"];
78
+ readonly description: "Generate an interceptor (auto-registered as a provider in the module).";
79
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
80
+ readonly kind: "interceptor";
81
+ readonly moduleRegistration: {
82
+ readonly arrayKey: "providers";
83
+ readonly classSuffix: "Interceptor";
84
+ };
85
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then bind the interceptor to routes.";
86
+ readonly schematic: "interceptor";
87
+ readonly wiringBehavior: "auto-registered";
88
+ }, {
89
+ readonly aliases: readonly ["mi"];
90
+ readonly description: "Generate a middleware (auto-registered in the module middleware array).";
91
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
92
+ readonly kind: "middleware";
93
+ readonly moduleRegistration: {
94
+ readonly arrayKey: "middleware";
95
+ readonly classSuffix: "Middleware";
96
+ };
97
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then configure route matching in forRoutes.";
98
+ readonly schematic: "middleware";
99
+ readonly wiringBehavior: "auto-registered";
100
+ }, {
101
+ readonly aliases: readonly ["mo"];
102
+ readonly description: "Generate a standalone module (import it in a parent module to activate).";
103
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
104
+ readonly kind: "module";
105
+ readonly nextStepHint: "Import the new module in a parent module's imports array, then run 'pnpm typecheck'.";
106
+ readonly schematic: "module";
107
+ readonly wiringBehavior: "files-only";
108
+ }, {
109
+ readonly aliases: readonly ["repo"];
110
+ readonly description: "Generate a persistence-agnostic repository (auto-registered as a provider).";
111
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
112
+ readonly kind: "repo";
113
+ readonly moduleRegistration: {
114
+ readonly arrayKey: "providers";
115
+ readonly classSuffix: "Repo";
116
+ };
117
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then add data-access methods to the repo stub.";
118
+ readonly registryAliases: readonly ["repository"];
119
+ readonly schematic: "repository";
120
+ readonly wiringBehavior: "auto-registered";
121
+ }, {
122
+ readonly aliases: readonly ["req"];
123
+ readonly description: "Generate a request DTO for route-level data binding and validation (files only — wire it into a controller manually).";
124
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
125
+ readonly kind: "request-dto";
126
+ readonly nextStepHint: "Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.";
127
+ readonly schematic: "request-dto";
128
+ readonly wiringBehavior: "files-only";
129
+ }, {
130
+ readonly aliases: readonly ["res"];
131
+ readonly description: "Generate a response DTO for typed response payloads (files only — use it as a controller return type).";
132
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
133
+ readonly kind: "response-dto";
134
+ readonly nextStepHint: "Import the DTO in a controller and use it as the return type for route handlers.";
135
+ readonly schematic: "response-dto";
136
+ readonly wiringBehavior: "files-only";
137
+ }, {
138
+ readonly aliases: readonly ["s"];
139
+ readonly description: "Generate a service (auto-registered as a provider in the module).";
140
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
141
+ readonly kind: "service";
142
+ readonly moduleRegistration: {
143
+ readonly arrayKey: "providers";
144
+ readonly classSuffix: "Service";
145
+ };
146
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then implement business logic.";
147
+ readonly schematic: "service";
148
+ readonly wiringBehavior: "auto-registered";
149
+ }];
150
+ readonly id: "@fluojs/cli/builtin";
151
+ readonly source: "built-in";
152
+ };
153
+ /** Deterministic list of generator collections currently discovered by `fluo generate`. */
154
+ export declare const generatorCollections: readonly [{
155
+ readonly description: "The deterministic collection of generator schematics shipped by @fluojs/cli.";
156
+ readonly generators: readonly [{
157
+ readonly aliases: readonly ["co"];
158
+ readonly description: "Generate a controller (auto-registered in the module controllers array).";
159
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
160
+ readonly kind: "controller";
161
+ readonly moduleRegistration: {
162
+ readonly arrayKey: "controllers";
163
+ readonly classSuffix: "Controller";
164
+ };
165
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then add route handlers.";
166
+ readonly schematic: "controller";
167
+ readonly wiringBehavior: "auto-registered";
168
+ }, {
169
+ readonly aliases: readonly ["gu"];
170
+ readonly description: "Generate a guard (auto-registered as a provider in the module).";
171
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
172
+ readonly kind: "guard";
173
+ readonly moduleRegistration: {
174
+ readonly arrayKey: "providers";
175
+ readonly classSuffix: "Guard";
176
+ };
177
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then apply the guard to routes.";
178
+ readonly schematic: "guard";
179
+ readonly wiringBehavior: "auto-registered";
180
+ }, {
181
+ readonly aliases: readonly ["in"];
182
+ readonly description: "Generate an interceptor (auto-registered as a provider in the module).";
183
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
184
+ readonly kind: "interceptor";
185
+ readonly moduleRegistration: {
186
+ readonly arrayKey: "providers";
187
+ readonly classSuffix: "Interceptor";
188
+ };
189
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then bind the interceptor to routes.";
190
+ readonly schematic: "interceptor";
191
+ readonly wiringBehavior: "auto-registered";
192
+ }, {
193
+ readonly aliases: readonly ["mi"];
194
+ readonly description: "Generate a middleware (auto-registered in the module middleware array).";
195
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
196
+ readonly kind: "middleware";
197
+ readonly moduleRegistration: {
198
+ readonly arrayKey: "middleware";
199
+ readonly classSuffix: "Middleware";
200
+ };
201
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then configure route matching in forRoutes.";
202
+ readonly schematic: "middleware";
203
+ readonly wiringBehavior: "auto-registered";
204
+ }, {
205
+ readonly aliases: readonly ["mo"];
206
+ readonly description: "Generate a standalone module (import it in a parent module to activate).";
207
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
208
+ readonly kind: "module";
209
+ readonly nextStepHint: "Import the new module in a parent module's imports array, then run 'pnpm typecheck'.";
210
+ readonly schematic: "module";
211
+ readonly wiringBehavior: "files-only";
212
+ }, {
213
+ readonly aliases: readonly ["repo"];
214
+ readonly description: "Generate a persistence-agnostic repository (auto-registered as a provider).";
215
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
216
+ readonly kind: "repo";
217
+ readonly moduleRegistration: {
218
+ readonly arrayKey: "providers";
219
+ readonly classSuffix: "Repo";
220
+ };
221
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then add data-access methods to the repo stub.";
222
+ readonly registryAliases: readonly ["repository"];
223
+ readonly schematic: "repository";
224
+ readonly wiringBehavior: "auto-registered";
225
+ }, {
226
+ readonly aliases: readonly ["req"];
227
+ readonly description: "Generate a request DTO for route-level data binding and validation (files only — wire it into a controller manually).";
228
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
229
+ readonly kind: "request-dto";
230
+ readonly nextStepHint: "Import the DTO in a controller and add it as a parameter with @FromBody or @FromQuery.";
231
+ readonly schematic: "request-dto";
232
+ readonly wiringBehavior: "files-only";
233
+ }, {
234
+ readonly aliases: readonly ["res"];
235
+ readonly description: "Generate a response DTO for typed response payloads (files only — use it as a controller return type).";
236
+ readonly factory: (name: string) => import("../generator-types.js").GeneratedFile[];
237
+ readonly kind: "response-dto";
238
+ readonly nextStepHint: "Import the DTO in a controller and use it as the return type for route handlers.";
239
+ readonly schematic: "response-dto";
240
+ readonly wiringBehavior: "files-only";
241
+ }, {
242
+ readonly aliases: readonly ["s"];
243
+ readonly description: "Generate a service (auto-registered as a provider in the module).";
244
+ readonly factory: (name: string, options: import("../generator-types.js").GenerateOptions | undefined) => import("../generator-types.js").GeneratedFile[];
245
+ readonly kind: "service";
246
+ readonly moduleRegistration: {
247
+ readonly arrayKey: "providers";
248
+ readonly classSuffix: "Service";
249
+ };
250
+ readonly nextStepHint: "Run 'pnpm typecheck' to verify module wiring, then implement business logic.";
251
+ readonly schematic: "service";
252
+ readonly wiringBehavior: "auto-registered";
253
+ }];
254
+ readonly id: "@fluojs/cli/builtin";
255
+ readonly source: "built-in";
256
+ }];
257
+ /** Built-in generator manifest used by CLI parsing, help output, and command execution. */
18
258
  export declare const generatorManifest: readonly [{
19
259
  readonly aliases: readonly ["co"];
20
260
  readonly description: "Generate a controller (auto-registered in the module controllers array).";
@@ -113,9 +353,36 @@ export declare const generatorManifest: readonly [{
113
353
  readonly schematic: "service";
114
354
  readonly wiringBehavior: "auto-registered";
115
355
  }];
356
+ /** Union of generator kind tokens accepted by the built-in generator manifest. */
116
357
  export type GeneratorKind = (typeof generatorManifest)[number]['kind'];
358
+ /** Exact manifest entry type for one built-in generator definition. */
117
359
  export type GeneratorDefinition = (typeof generatorManifest)[number];
360
+ /**
361
+ * Looks up one built-in generator definition by canonical kind.
362
+ *
363
+ * @param kind Canonical generator kind to resolve.
364
+ * @returns The matching built-in generator definition.
365
+ */
118
366
  export declare function findGeneratorDefinition(kind: GeneratorKind): GeneratorDefinition;
367
+ /**
368
+ * Lists generator collections that `fluo generate` discovers without loading external code.
369
+ *
370
+ * @returns The deterministic generator collection list.
371
+ */
372
+ export declare function listGeneratorCollections(): readonly GeneratorCollection[];
373
+ /**
374
+ * Lists generator definitions for a known collection.
375
+ *
376
+ * @param collectionId Collection identifier to read, defaulting to the built-in collection.
377
+ * @returns Generator definitions owned by the requested collection.
378
+ */
379
+ export declare function listGeneratorDefinitions(collectionId?: string): readonly GeneratorDefinition[];
380
+ /**
381
+ * Resolves a CLI token or alias to a canonical generator kind.
382
+ *
383
+ * @param value Raw CLI generator token or alias.
384
+ * @returns The canonical generator kind when the token is known, otherwise `undefined`.
385
+ */
119
386
  export declare function resolveGeneratorKind(value: string | undefined): GeneratorKind | undefined;
120
387
  export {};
121
388
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/generators/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAY9D,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAExE,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,4BAA4B,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,iBAAiB,GAAG,YAAY,CAAC;CAClD,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyFwB,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAcrE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,GAAG,mBAAmB,CAOhF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAMzF"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/generators/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,uBAAuB,CAAC;AAYrF,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAExE,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,4BAA4B,CAAC;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,iBAAiB,GAAG,YAAY,CAAC;CAClD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAC9C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;EAKkB,CAAC;AA6FtD,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKC,CAAC;AAEzC,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAiF,CAAC;AAEnH,2FAA2F;AAC3F,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAAwC,CAAC;AAEvE,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAcrE;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,aAAa,GAAG,mBAAmB,CAOhF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,SAAS,mBAAmB,EAAE,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,GAAE,MAAsC,GAAG,SAAS,mBAAmB,EAAE,CAO7H;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAMzF"}
@@ -7,7 +7,36 @@ import { generateRepoFiles } from './repository.js';
7
7
  import { generateRequestDtoFiles } from './request-dto.js';
8
8
  import { generateResponseDtoFiles } from './response-dto.js';
9
9
  import { generateServiceFiles } from './service.js';
10
- export const generatorManifest = [{
10
+
11
+ /** Module metadata array names that auto-registered generators are allowed to update. */
12
+
13
+ /** Describes one built-in generator schematic and its CLI-facing metadata. */
14
+
15
+ /** Describes a deterministic collection of generator schematics discoverable by the CLI. */
16
+
17
+ /** Option metadata shared by generate-command parsing, help output, docs, and tests. */
18
+ export const generatorOptionSchemas = [{
19
+ aliases: ['-o'],
20
+ description: 'Write generated files under a specific source directory.',
21
+ name: '--target-directory <path>',
22
+ value: 'path'
23
+ }, {
24
+ aliases: ['-f'],
25
+ description: 'Overwrite files that already exist.',
26
+ name: '--force',
27
+ value: 'boolean'
28
+ }, {
29
+ aliases: [],
30
+ description: 'Preview planned writes, skips, and module wiring without touching files.',
31
+ name: '--dry-run',
32
+ value: 'boolean'
33
+ }, {
34
+ aliases: ['-h'],
35
+ description: 'Show help for the generate command.',
36
+ name: '--help',
37
+ value: 'boolean'
38
+ }];
39
+ const builtInGeneratorDefinitions = [{
11
40
  aliases: ['co'],
12
41
  description: 'Generate a controller (auto-registered in the module controllers array).',
13
42
  factory: (name, options) => generateControllerFiles(name, options),
@@ -105,6 +134,25 @@ export const generatorManifest = [{
105
134
  schematic: 'service',
106
135
  wiringBehavior: 'auto-registered'
107
136
  }];
137
+
138
+ /** The single generator collection shipped directly inside `@fluojs/cli`. */
139
+ export const builtInGeneratorCollection = {
140
+ description: 'The deterministic collection of generator schematics shipped by @fluojs/cli.',
141
+ generators: builtInGeneratorDefinitions,
142
+ id: '@fluojs/cli/builtin',
143
+ source: 'built-in'
144
+ };
145
+
146
+ /** Deterministic list of generator collections currently discovered by `fluo generate`. */
147
+ export const generatorCollections = [builtInGeneratorCollection];
148
+
149
+ /** Built-in generator manifest used by CLI parsing, help output, and command execution. */
150
+ export const generatorManifest = builtInGeneratorCollection.generators;
151
+
152
+ /** Union of generator kind tokens accepted by the built-in generator manifest. */
153
+
154
+ /** Exact manifest entry type for one built-in generator definition. */
155
+
108
156
  const generatorByKind = new Map();
109
157
  const tokenToKind = new Map();
110
158
  for (const entry of generatorManifest) {
@@ -115,6 +163,13 @@ for (const entry of generatorManifest) {
115
163
  tokenToKind.set(alias, entry.kind);
116
164
  }
117
165
  }
166
+
167
+ /**
168
+ * Looks up one built-in generator definition by canonical kind.
169
+ *
170
+ * @param kind Canonical generator kind to resolve.
171
+ * @returns The matching built-in generator definition.
172
+ */
118
173
  export function findGeneratorDefinition(kind) {
119
174
  const entry = generatorByKind.get(kind);
120
175
  if (!entry) {
@@ -122,6 +177,36 @@ export function findGeneratorDefinition(kind) {
122
177
  }
123
178
  return entry;
124
179
  }
180
+
181
+ /**
182
+ * Lists generator collections that `fluo generate` discovers without loading external code.
183
+ *
184
+ * @returns The deterministic generator collection list.
185
+ */
186
+ export function listGeneratorCollections() {
187
+ return generatorCollections;
188
+ }
189
+
190
+ /**
191
+ * Lists generator definitions for a known collection.
192
+ *
193
+ * @param collectionId Collection identifier to read, defaulting to the built-in collection.
194
+ * @returns Generator definitions owned by the requested collection.
195
+ */
196
+ export function listGeneratorDefinitions(collectionId = builtInGeneratorCollection.id) {
197
+ const collection = generatorCollections.find(entry => entry.id === collectionId);
198
+ if (!collection) {
199
+ throw new Error(`Unknown generator collection: ${collectionId}`);
200
+ }
201
+ return collection.generators;
202
+ }
203
+
204
+ /**
205
+ * Resolves a CLI token or alias to a canonical generator kind.
206
+ *
207
+ * @param value Raw CLI generator token or alias.
208
+ * @returns The canonical generator kind when the token is known, otherwise `undefined`.
209
+ */
125
210
  export function resolveGeneratorKind(value) {
126
211
  if (!value) {
127
212
  return undefined;
@@ -20,6 +20,7 @@ export interface BootstrapPrompter {
20
20
  }
21
21
  /** Runtime overrides for resolving bootstrap answers in tests and editors. */
22
22
  export interface ResolveBootstrapAnswersOptions {
23
+ completionMessage?: string | ((answers: BootstrapAnswers) => string);
23
24
  interactive?: boolean;
24
25
  prompt?: BootstrapPrompter;
25
26
  stdin?: ReadableStream;
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/new/prompt.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnE,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,EAAE,cAAuB,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAQF,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,8BAA8B;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AA6OD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAIhB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,gBAAgB,CAgBlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/new/prompt.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnE,iEAAiE;AACjE,eAAO,MAAM,uBAAuB,EAAE,cAAuB,CAAC;AAI9D,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAQF,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,IAAI,IAAI,CAAC;IACf,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC7G,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,8BAA8B;IAC7C,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,MAAM,CAAC,CAAC;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAwPD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAIhB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,GACjB,gBAAgB,CAgBlB;AAED;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,8BAAmC,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CA0B3B"}
@@ -22,6 +22,12 @@ const STARTER_SHAPE_CHOICES = [{
22
22
 
23
23
  /** Runtime overrides for resolving bootstrap answers in tests and editors. */
24
24
 
25
+ function resolveCompletionMessage(completionMessage, answers) {
26
+ if (typeof completionMessage === 'function') {
27
+ return completionMessage(answers);
28
+ }
29
+ return completionMessage ?? `Project created! Run: cd ${answers.targetDirectory}`;
30
+ }
25
31
  function hasOwnValue(partial, key) {
26
32
  return partial[key] !== undefined;
27
33
  }
@@ -269,7 +275,7 @@ export async function collectBootstrapAnswers(partial, cwd, userAgent, options =
269
275
  }
270
276
  const answers = await resolveInteractiveBootstrapAnswers(partial, cwd, userAgent, prompt);
271
277
  if (isInteractiveShell) {
272
- clack.outro(`Project created! Run: cd ${answers.targetDirectory}`);
278
+ clack.outro(resolveCompletionMessage(options.completionMessage, answers));
273
279
  }
274
280
  return answers;
275
281
  } finally {
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AAijEnE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAuB,CAAC"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/new/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAkB,MAAM,YAAY,CAAC;AAmkEnE;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,gBAAgB,EACzB,aAAa,SAAkB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,6BAAuB,CAAC"}
@@ -26,6 +26,22 @@ const PUBLISHED_RUNTIME_DEPENDENCIES = {
26
26
  mqtt: '^5.0.0',
27
27
  nats: '^2.29.3'
28
28
  };
29
+ const PUBLISHED_INTERNAL_DEPENDENCIES = {
30
+ '@fluojs/cli': '^1.0.0-beta.2',
31
+ '@fluojs/config': '^1.0.0-beta.1',
32
+ '@fluojs/core': '^1.0.0-beta.1',
33
+ '@fluojs/di': '^1.0.0-beta.1',
34
+ '@fluojs/http': '^1.0.0-beta.1',
35
+ '@fluojs/microservices': '^1.0.0-beta.1',
36
+ '@fluojs/platform-bun': '^1.0.0-beta.1',
37
+ '@fluojs/platform-cloudflare-workers': '^1.0.0-beta.1',
38
+ '@fluojs/platform-deno': '^1.0.0-beta.1',
39
+ '@fluojs/platform-express': '^1.0.0-beta.1',
40
+ '@fluojs/platform-fastify': '^1.0.0-beta.2',
41
+ '@fluojs/platform-nodejs': '^1.0.0-beta.1',
42
+ '@fluojs/runtime': '^1.0.0-beta.1',
43
+ '@fluojs/testing': '^1.0.0-beta.1'
44
+ };
29
45
  function describeApplicationStarter(options) {
30
46
  if (options.runtime === 'bun') {
31
47
  return {
@@ -97,7 +113,7 @@ function writeTextFile(filePath, content) {
97
113
  writeFileSync(filePath, content, 'utf8');
98
114
  }
99
115
  function createDependencySpec(packageName, releaseVersion, packageSpecs) {
100
- return packageSpecs[packageName] ?? PUBLISHED_RUNTIME_DEPENDENCIES[packageName] ?? createPublishedInternalDependencySpec(releaseVersion);
116
+ return packageSpecs[packageName] ?? PUBLISHED_RUNTIME_DEPENDENCIES[packageName] ?? PUBLISHED_INTERNAL_DEPENDENCIES[packageName] ?? createPublishedInternalDependencySpec(releaseVersion);
101
117
  }
102
118
  function createPublishedInternalDependencySpec(version) {
103
119
  return `^${version}`;
@@ -1,10 +1,13 @@
1
1
  import type { GeneratorFactory } from './generator-types.js';
2
+ /** In-memory registry that maps generator tokens to factories and their owning collection. */
2
3
  export declare class GeneratorRegistry {
3
4
  private readonly registry;
4
- register(kind: string, factory: GeneratorFactory, description?: string): this;
5
+ register(kind: string, factory: GeneratorFactory, description?: string, collectionId?: string): this;
6
+ collectionId(kind: string): string | undefined;
5
7
  resolve(kind: string): GeneratorFactory | undefined;
6
8
  has(kind: string): boolean;
7
9
  kinds(): string[];
8
10
  }
11
+ /** Default generator registry populated from the deterministic built-in collection. */
9
12
  export declare const defaultRegistry: GeneratorRegistry;
10
13
  //# sourceMappingURL=registry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,sBAAsB,CAAC;AAIpF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IAErE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAK7E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAInD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,KAAK,IAAI,MAAM,EAAE;CAGlB;AAED,eAAO,MAAM,eAAe,mBAA0B,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,sBAAsB,CAAC;AAIpF,8FAA8F;AAC9F,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IAErE,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAKpG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI9C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAInD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,KAAK,IAAI,MAAM,EAAE;CAGlB;AAED,uFAAuF;AACvF,eAAO,MAAM,eAAe,mBAA0B,CAAC"}
package/dist/registry.js CHANGED
@@ -1,13 +1,19 @@
1
- import { generatorManifest } from './generators/manifest.js';
1
+ import { builtInGeneratorCollection, listGeneratorDefinitions } from './generators/manifest.js';
2
+
3
+ /** In-memory registry that maps generator tokens to factories and their owning collection. */
2
4
  export class GeneratorRegistry {
3
5
  registry = new Map();
4
- register(kind, factory, description) {
6
+ register(kind, factory, description, collectionId) {
5
7
  this.registry.set(kind, {
8
+ collectionId,
6
9
  factory,
7
10
  description
8
11
  });
9
12
  return this;
10
13
  }
14
+ collectionId(kind) {
15
+ return this.registry.get(kind)?.collectionId;
16
+ }
11
17
  resolve(kind) {
12
18
  return this.registry.get(kind)?.factory;
13
19
  }
@@ -18,13 +24,15 @@ export class GeneratorRegistry {
18
24
  return Array.from(this.registry.keys());
19
25
  }
20
26
  }
27
+
28
+ /** Default generator registry populated from the deterministic built-in collection. */
21
29
  export const defaultRegistry = new GeneratorRegistry();
22
- for (const entry of generatorManifest) {
23
- defaultRegistry.register(entry.kind, entry.factory, entry.description);
30
+ for (const entry of listGeneratorDefinitions()) {
31
+ defaultRegistry.register(entry.kind, entry.factory, entry.description, builtInGeneratorCollection.id);
24
32
  const registryAliases = 'registryAliases' in entry ? entry.registryAliases : undefined;
25
33
  if (registryAliases) {
26
34
  for (const alias of registryAliases) {
27
- defaultRegistry.register(alias, entry.factory, entry.description);
35
+ defaultRegistry.register(alias, entry.factory, entry.description, builtInGeneratorCollection.id);
28
36
  }
29
37
  }
30
38
  }
@@ -0,0 +1,50 @@
1
+ type CliStream = {
2
+ isTTY?: boolean;
3
+ write(message: string): unknown;
4
+ };
5
+ type CliReadableStream = {
6
+ isTTY?: boolean;
7
+ };
8
+ export type CliUpdateCheckResult = {
9
+ action: 'continue';
10
+ } | {
11
+ action: 'reran';
12
+ exitCode: number;
13
+ };
14
+ export type UpdateInstallCommand = {
15
+ args: string[];
16
+ command: string;
17
+ display: string;
18
+ };
19
+ export type UpdateCommandRuntime = {
20
+ env: NodeJS.ProcessEnv;
21
+ stderr: CliStream;
22
+ };
23
+ export type UpdatePrompter = {
24
+ confirm(message: string, defaultValue: boolean): Promise<boolean>;
25
+ };
26
+ export interface CliUpdateCheckRuntimeOptions {
27
+ cacheFile?: string;
28
+ cacheTtlMs?: number;
29
+ ci?: boolean;
30
+ currentVersion?: string;
31
+ env?: NodeJS.ProcessEnv;
32
+ fetchLatestVersion?: (packageName: string) => Promise<string | undefined>;
33
+ installPackage?: (installCommand: UpdateInstallCommand, runtime: UpdateCommandRuntime) => Promise<number>;
34
+ interactive?: boolean;
35
+ now?: () => Date;
36
+ packageName?: string;
37
+ prompt?: UpdatePrompter;
38
+ rerunCli?: (argv: string[], runtime: UpdateCommandRuntime) => Promise<number>;
39
+ skip?: boolean;
40
+ stderr?: CliStream;
41
+ stdin?: CliReadableStream;
42
+ stdout?: CliStream;
43
+ }
44
+ export declare function removeUpdateCheckFlags(argv: string[]): {
45
+ argv: string[];
46
+ skipUpdateCheck: boolean;
47
+ };
48
+ export declare function runCliUpdateCheck(argv: string[], options?: CliUpdateCheckRuntimeOptions): Promise<CliUpdateCheckResult>;
49
+ export {};
50
+ //# sourceMappingURL=update-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.d.ts","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAOA,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAcF,MAAM,MAAM,oBAAoB,GAC5B;IACE,MAAM,EAAE,UAAU,CAAC;CACpB,GACD;IACE,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEN,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,SAAS,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACnE,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC1E,cAAc,CAAC,EAAE,CAAC,cAAc,EAAE,oBAAoB,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1G,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AA0VD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAcnG;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,4BAAiC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgEjI"}