@ingenyus/swarm-wasp 0.2.0 → 0.2.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.
Files changed (47) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/common/index.d.ts +0 -1
  3. package/dist/common/index.d.ts.map +1 -1
  4. package/dist/common/index.js +9 -34
  5. package/dist/generators/action/action-generator.js +50 -58
  6. package/dist/generators/action/index.js +50 -58
  7. package/dist/generators/action/schema.js +1 -5
  8. package/dist/generators/api/api-generator.js +51 -59
  9. package/dist/generators/api/index.js +51 -59
  10. package/dist/generators/api/schema.js +1 -5
  11. package/dist/generators/api-namespace/api-namespace-generator.js +51 -59
  12. package/dist/generators/api-namespace/index.js +51 -59
  13. package/dist/generators/api-namespace/schema.js +1 -5
  14. package/dist/generators/base/component-generator.base.d.ts +4 -7
  15. package/dist/generators/base/component-generator.base.d.ts.map +1 -1
  16. package/dist/generators/base/component-generator.base.js +49 -57
  17. package/dist/generators/base/index.js +50 -58
  18. package/dist/generators/base/operation-generator.base.js +50 -58
  19. package/dist/generators/base/wasp-generator.base.d.ts +3 -5
  20. package/dist/generators/base/wasp-generator.base.d.ts.map +1 -1
  21. package/dist/generators/base/wasp-generator.base.js +22 -26
  22. package/dist/generators/config/index.js +12 -16
  23. package/dist/generators/config/wasp-config-generator.js +12 -16
  24. package/dist/generators/crud/crud-generator.js +50 -58
  25. package/dist/generators/crud/index.js +50 -58
  26. package/dist/generators/crud/schema.js +1 -5
  27. package/dist/generators/feature/feature-generator.d.ts +2 -4
  28. package/dist/generators/feature/feature-generator.d.ts.map +1 -1
  29. package/dist/generators/feature/feature-generator.js +32 -42
  30. package/dist/generators/feature/index.js +32 -42
  31. package/dist/generators/feature/schema.js +1 -5
  32. package/dist/generators/index.js +54 -62
  33. package/dist/generators/job/index.js +49 -57
  34. package/dist/generators/job/job-generator.js +49 -57
  35. package/dist/generators/job/schema.js +1 -5
  36. package/dist/generators/query/index.js +50 -58
  37. package/dist/generators/query/query-generator.js +50 -58
  38. package/dist/generators/query/schema.js +1 -5
  39. package/dist/generators/route/index.js +49 -57
  40. package/dist/generators/route/route-generator.js +49 -57
  41. package/dist/generators/route/schema.js +1 -5
  42. package/dist/index.js +60 -90
  43. package/dist/plugins/wasp.d.ts.map +1 -1
  44. package/package.json +2 -2
  45. package/dist/common/plugin.d.ts +0 -2
  46. package/dist/common/plugin.d.ts.map +0 -1
  47. package/dist/common/plugin.js +0 -41
@@ -40,13 +40,13 @@ var CONFIG_TYPES = {
40
40
 
41
41
  // src/generators/base/component-generator.base.ts
42
42
  import {
43
+ GeneratorRuntime,
43
44
  hasHelperMethodCall,
44
- logger as singletonLogger4,
45
45
  toCamelCase,
46
46
  toKebabCase as toKebabCase2,
47
47
  validateFeaturePath as validateFeaturePath3
48
48
  } from "@ingenyus/swarm";
49
- import path7 from "path";
49
+ import path6 from "path";
50
50
 
51
51
  // src/common/filesystem.ts
52
52
  import { toPascalCase, validateFeaturePath } from "@ingenyus/swarm";
@@ -119,19 +119,15 @@ function getFeatureImportPath(featurePath) {
119
119
  return segments.join("/");
120
120
  }
121
121
 
122
- // src/common/plugin.ts
123
- import path2 from "path";
124
- import { fileURLToPath } from "url";
125
-
126
122
  // src/common/prisma.ts
127
123
  import {
128
124
  getSchema
129
125
  } from "@mrleebo/prisma-ast";
130
126
  import fs2 from "fs";
131
- import path3 from "path";
127
+ import path2 from "path";
132
128
  async function getEntityMetadata(modelName) {
133
129
  try {
134
- const schemaPath = path3.join(process.cwd(), "schema.prisma");
130
+ const schemaPath = path2.join(process.cwd(), "schema.prisma");
135
131
  const schemaContent = fs2.readFileSync(schemaPath, "utf8");
136
132
  const schema3 = getSchema(schemaContent);
137
133
  const model = schema3.list?.find(
@@ -306,7 +302,7 @@ var commonSchemas = {
306
302
  // src/common/templates.ts
307
303
  import { toKebabCase } from "@ingenyus/swarm";
308
304
  import { Eta } from "eta";
309
- import path4 from "path";
305
+ import path3 from "path";
310
306
  var TemplateUtility = class {
311
307
  constructor(fileSystem) {
312
308
  this.fileSystem = fileSystem;
@@ -314,14 +310,14 @@ var TemplateUtility = class {
314
310
  processTemplate(templatePath, replacements) {
315
311
  const declarations = Object.keys(replacements).map((key) => `${key}=it.${key}`).join(", ");
316
312
  const functionHeader = declarations ? `const ${declarations};` : void 0;
317
- const templateDir = path4.dirname(templatePath);
313
+ const templateDir = path3.dirname(templatePath);
318
314
  const eta = new Eta({
319
315
  autoTrim: false,
320
316
  autoEscape: false,
321
317
  views: templateDir,
322
318
  functionHeader
323
319
  });
324
- const templateName = path4.basename(templatePath).replace(/\.eta$/, "");
320
+ const templateName = path3.basename(templatePath).replace(/\.eta$/, "");
325
321
  if (this.fileSystem.existsSync(templatePath)) {
326
322
  return eta.render(templateName, replacements);
327
323
  } else {
@@ -339,11 +335,11 @@ var TemplateUtility = class {
339
335
  resolveTemplatePath(relativePath, generatorName, currentFileUrl) {
340
336
  const generatorDirName = toKebabCase(generatorName);
341
337
  const currentFilePath = new URL(currentFileUrl).pathname;
342
- const currentFileDir = path4.dirname(currentFilePath);
343
- const currentFileName = path4.basename(currentFilePath);
338
+ const currentFileDir = path3.dirname(currentFilePath);
339
+ const currentFileName = path3.basename(currentFilePath);
344
340
  const isInstalledPackage = currentFileDir.includes("node_modules") && currentFileDir.endsWith("/dist") && currentFileName === "index.js";
345
- const startDir = isInstalledPackage ? currentFileDir : path4.dirname(path4.dirname(currentFileDir));
346
- return path4.join(
341
+ const startDir = isInstalledPackage ? currentFileDir : path3.dirname(path3.dirname(currentFileDir));
342
+ return path3.join(
347
343
  startDir,
348
344
  "generators",
349
345
  generatorDirName,
@@ -354,17 +350,12 @@ var TemplateUtility = class {
354
350
  };
355
351
 
356
352
  // src/generators/feature/feature-generator.ts
357
- import {
358
- handleFatalError as handleFatalError2,
359
- logger as singletonLogger3,
360
- validateFeaturePath as validateFeaturePath2
361
- } from "@ingenyus/swarm";
362
- import path6 from "path";
353
+ import { handleFatalError as handleFatalError2, validateFeaturePath as validateFeaturePath2 } from "@ingenyus/swarm";
354
+ import path5 from "path";
363
355
 
364
356
  // src/generators/base/wasp-generator.base.ts
365
357
  import {
366
358
  GeneratorBase,
367
- logger as singletonLogger2,
368
359
  SwarmConfigManager,
369
360
  TemplateResolver
370
361
  } from "@ingenyus/swarm";
@@ -375,14 +366,14 @@ import {
375
366
  parseHelperMethodDefinition,
376
367
  logger as singletonLogger
377
368
  } from "@ingenyus/swarm";
378
- import path5 from "path";
369
+ import path4 from "path";
379
370
  var WaspConfigGenerator = class {
380
371
  constructor(logger = singletonLogger, fileSystem = realFileSystem) {
381
372
  this.logger = logger;
382
373
  this.fileSystem = fileSystem;
383
374
  this.templateUtility = new TemplateUtility(fileSystem);
384
375
  }
385
- path = path5;
376
+ path = path4;
386
377
  templateUtility;
387
378
  /**
388
379
  * Gets the template path for feature config templates.
@@ -411,7 +402,7 @@ var WaspConfigGenerator = class {
411
402
  this.logger.error(`Template not found: ${templatePath}`);
412
403
  return;
413
404
  }
414
- const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
405
+ const configFilePath = path4.join(featureDir, `feature.wasp.ts`);
415
406
  if (this.fileSystem.existsSync(configFilePath)) {
416
407
  this.logger.warn(`Feature config already exists: ${configFilePath}`);
417
408
  return;
@@ -427,7 +418,7 @@ var WaspConfigGenerator = class {
427
418
  */
428
419
  update(featurePath, declaration) {
429
420
  const configDir = getFeatureDir(this.fileSystem, featurePath);
430
- const configFilePath = path5.join(configDir, `feature.wasp.ts`);
421
+ const configFilePath = path4.join(configDir, `feature.wasp.ts`);
431
422
  if (!this.fileSystem.existsSync(configFilePath)) {
432
423
  const templatePath = this.getTemplatePath("feature.wasp.eta");
433
424
  if (!this.fileSystem.existsSync(templatePath)) {
@@ -807,14 +798,6 @@ var WaspConfigGenerator = class {
807
798
 
808
799
  // src/generators/base/wasp-generator.base.ts
809
800
  var WaspGeneratorBase = class extends GeneratorBase {
810
- constructor(fileSystem = realFileSystem, logger = singletonLogger2) {
811
- super(fileSystem, logger);
812
- this.fileSystem = fileSystem;
813
- this.logger = logger;
814
- this.configGenerator = new WaspConfigGenerator(logger, fileSystem);
815
- this.templateUtility = new TemplateUtility(fileSystem);
816
- this.templateResolver = new TemplateResolver(fileSystem);
817
- }
818
801
  configGenerator;
819
802
  templateUtility;
820
803
  templateResolver;
@@ -822,6 +805,15 @@ var WaspGeneratorBase = class extends GeneratorBase {
822
805
  configLoaded = false;
823
806
  // Plugin name from swarm.config.json
824
807
  pluginName = PLUGIN_NAME;
808
+ constructor() {
809
+ super();
810
+ this.configGenerator = new WaspConfigGenerator(
811
+ this.logger,
812
+ this.fileSystem
813
+ );
814
+ this.templateUtility = new TemplateUtility(this.fileSystem);
815
+ this.templateResolver = new TemplateResolver(this.fileSystem);
816
+ }
825
817
  async loadSwarmConfig() {
826
818
  if (this.configLoaded) return;
827
819
  const configManager = new SwarmConfigManager();
@@ -872,7 +864,7 @@ var WaspGeneratorBase = class extends GeneratorBase {
872
864
  }
873
865
  /**
874
866
  * Generic existence check with force flag handling
875
- * Consolidates the pattern used in both file and config checks
867
+ * Consolidates the pattern used in both file and config existence checks
876
868
  */
877
869
  checkExistence(exists, itemDescription, force, errorMessage) {
878
870
  if (exists && !force) {
@@ -912,16 +904,14 @@ var schema = z2.object({
912
904
 
913
905
  // src/generators/feature/feature-generator.ts
914
906
  var FeatureGenerator = class extends WaspGeneratorBase {
915
- constructor(logger = singletonLogger3, fileSystem = realFileSystem) {
916
- super(fileSystem, logger);
917
- this.logger = logger;
918
- this.fileSystem = fileSystem;
919
- this.name = "feature";
920
- this.description = "Generates a feature directory containing a Wasp configuration file";
921
- }
922
907
  name;
923
908
  description;
924
909
  schema = schema;
910
+ constructor() {
911
+ super();
912
+ this.name = "feature";
913
+ this.description = "Generates a feature directory containing a Wasp configuration file";
914
+ }
925
915
  getDefaultTemplatePath(templateName) {
926
916
  return this.templateUtility.resolveTemplatePath(
927
917
  templateName,
@@ -937,18 +927,18 @@ var FeatureGenerator = class extends WaspGeneratorBase {
937
927
  const { target } = args;
938
928
  const segments = validateFeaturePath2(target);
939
929
  const normalisedPath = normaliseFeaturePath(target);
940
- const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
930
+ const sourceRoot = path5.join(findWaspRoot(this.fileSystem), "src");
941
931
  if (segments.length > 1) {
942
932
  const parentPath = segments.slice(0, -1).join("/");
943
933
  const parentNormalisedPath = normaliseFeaturePath(parentPath);
944
- const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
934
+ const parentFeatureDir = path5.join(sourceRoot, parentNormalisedPath);
945
935
  if (!this.fileSystem.existsSync(parentFeatureDir)) {
946
936
  handleFatalError2(
947
937
  `Parent feature '${parentPath}' does not exist. Please create it first.`
948
938
  );
949
939
  }
950
940
  }
951
- const featureDir = path6.join(sourceRoot, normalisedPath);
941
+ const featureDir = path5.join(sourceRoot, normalisedPath);
952
942
  this.fileSystem.mkdirSync(featureDir, { recursive: true });
953
943
  this.configGenerator.generate(normalisedPath);
954
944
  this.logger.success(`Generated feature: ${normalisedPath}`);
@@ -957,13 +947,6 @@ var FeatureGenerator = class extends WaspGeneratorBase {
957
947
 
958
948
  // src/generators/base/component-generator.base.ts
959
949
  var ComponentGeneratorBase = class extends WaspGeneratorBase {
960
- constructor(logger = singletonLogger4, fileSystem = realFileSystem, featureDirectoryGenerator = new FeatureGenerator(logger, fileSystem)) {
961
- super(fileSystem, logger);
962
- this.logger = logger;
963
- this.fileSystem = fileSystem;
964
- this.featureDirectoryGenerator = featureDirectoryGenerator;
965
- this.featureDirectoryGenerator = featureDirectoryGenerator;
966
- }
967
950
  getDefaultTemplatePath(templateName) {
968
951
  return this.templateUtility.resolveTemplatePath(
969
952
  templateName,
@@ -971,6 +954,17 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
971
954
  import.meta.url
972
955
  );
973
956
  }
957
+ featureDirectoryGenerator;
958
+ constructor() {
959
+ super();
960
+ const runtime = GeneratorRuntime.current();
961
+ if (runtime.featureGeneratorFactory) {
962
+ const factoryResult = runtime.featureGeneratorFactory(runtime);
963
+ this.featureDirectoryGenerator = factoryResult;
964
+ } else {
965
+ this.featureDirectoryGenerator = new FeatureGenerator();
966
+ }
967
+ }
974
968
  get name() {
975
969
  return toKebabCase2(this.componentType);
976
970
  }
@@ -985,7 +979,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
985
979
  const currentPath = pathSegments.join("/");
986
980
  const featureName = pathSegments[pathSegments.length - 1];
987
981
  const featureDir = getFeatureDir(this.fileSystem, currentPath);
988
- const configPath = path7.join(featureDir, `feature.wasp.ts`);
982
+ const configPath = path6.join(featureDir, `feature.wasp.ts`);
989
983
  if (this.fileSystem.existsSync(configPath)) {
990
984
  return configPath;
991
985
  }
@@ -1047,18 +1041,17 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1047
1041
  }
1048
1042
  /**
1049
1043
  * Gets the appropriate directory for a feature based on its path.
1050
- * @param fileSystem - The filesystem abstraction
1051
1044
  * @param featurePath - The full feature path
1052
1045
  * @param type - The type of file being generated
1053
1046
  * @returns The target directory and import path
1054
1047
  */
1055
- getFeatureTargetDir(fileSystem, featurePath, type) {
1048
+ getFeatureTargetDir(featurePath, type) {
1056
1049
  validateFeaturePath3(featurePath);
1057
1050
  const normalisedPath = normaliseFeaturePath(featurePath);
1058
- const featureDir = getFeatureDir(fileSystem, normalisedPath);
1051
+ const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
1059
1052
  const typeKey = type.toLowerCase();
1060
1053
  const typeDirectory = TYPE_DIRECTORIES[typeKey];
1061
- const targetDirectory = path7.join(featureDir, typeDirectory);
1054
+ const targetDirectory = path6.join(featureDir, typeDirectory);
1062
1055
  const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
1063
1056
  return { targetDirectory, importDirectory };
1064
1057
  }
@@ -1067,7 +1060,6 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1067
1060
  */
1068
1061
  ensureTargetDirectory(featurePath, type) {
1069
1062
  const { targetDirectory, importDirectory } = this.getFeatureTargetDir(
1070
- this.fileSystem,
1071
1063
  featurePath,
1072
1064
  type
1073
1065
  );
@@ -24,16 +24,12 @@ var realFileSystem = {
24
24
  statSync: fs.statSync
25
25
  };
26
26
 
27
- // src/common/plugin.ts
28
- import path from "path";
29
- import { fileURLToPath } from "url";
30
-
31
27
  // src/common/prisma.ts
32
28
  import {
33
29
  getSchema
34
30
  } from "@mrleebo/prisma-ast";
35
31
  import fs2 from "fs";
36
- import path2 from "path";
32
+ import path from "path";
37
33
 
38
34
  // src/common/schemas.ts
39
35
  import { commandRegistry } from "@ingenyus/swarm";
@@ -90,16 +90,12 @@ function getRouteNameFromPath(routePath) {
90
90
  return `${toPascalCase(cleanSegment)}Page`;
91
91
  }
92
92
 
93
- // src/common/plugin.ts
94
- import path2 from "path";
95
- import { fileURLToPath } from "url";
96
-
97
93
  // src/common/prisma.ts
98
94
  import {
99
95
  getSchema
100
96
  } from "@mrleebo/prisma-ast";
101
97
  import fs2 from "fs";
102
- import path3 from "path";
98
+ import path2 from "path";
103
99
 
104
100
  // src/common/schemas.ts
105
101
  import { commandRegistry } from "@ingenyus/swarm";
@@ -156,7 +152,7 @@ var commonSchemas = {
156
152
  // src/common/templates.ts
157
153
  import { toKebabCase } from "@ingenyus/swarm";
158
154
  import { Eta } from "eta";
159
- import path4 from "path";
155
+ import path3 from "path";
160
156
  var TemplateUtility = class {
161
157
  constructor(fileSystem) {
162
158
  this.fileSystem = fileSystem;
@@ -164,14 +160,14 @@ var TemplateUtility = class {
164
160
  processTemplate(templatePath, replacements) {
165
161
  const declarations = Object.keys(replacements).map((key) => `${key}=it.${key}`).join(", ");
166
162
  const functionHeader = declarations ? `const ${declarations};` : void 0;
167
- const templateDir = path4.dirname(templatePath);
163
+ const templateDir = path3.dirname(templatePath);
168
164
  const eta = new Eta({
169
165
  autoTrim: false,
170
166
  autoEscape: false,
171
167
  views: templateDir,
172
168
  functionHeader
173
169
  });
174
- const templateName = path4.basename(templatePath).replace(/\.eta$/, "");
170
+ const templateName = path3.basename(templatePath).replace(/\.eta$/, "");
175
171
  if (this.fileSystem.existsSync(templatePath)) {
176
172
  return eta.render(templateName, replacements);
177
173
  } else {
@@ -189,11 +185,11 @@ var TemplateUtility = class {
189
185
  resolveTemplatePath(relativePath, generatorName, currentFileUrl) {
190
186
  const generatorDirName = toKebabCase(generatorName);
191
187
  const currentFilePath = new URL(currentFileUrl).pathname;
192
- const currentFileDir = path4.dirname(currentFilePath);
193
- const currentFileName = path4.basename(currentFilePath);
188
+ const currentFileDir = path3.dirname(currentFilePath);
189
+ const currentFileName = path3.basename(currentFilePath);
194
190
  const isInstalledPackage = currentFileDir.includes("node_modules") && currentFileDir.endsWith("/dist") && currentFileName === "index.js";
195
- const startDir = isInstalledPackage ? currentFileDir : path4.dirname(path4.dirname(currentFileDir));
196
- return path4.join(
191
+ const startDir = isInstalledPackage ? currentFileDir : path3.dirname(path3.dirname(currentFileDir));
192
+ return path3.join(
197
193
  startDir,
198
194
  "generators",
199
195
  generatorDirName,
@@ -205,26 +201,21 @@ var TemplateUtility = class {
205
201
 
206
202
  // src/generators/base/component-generator.base.ts
207
203
  import {
204
+ GeneratorRuntime,
208
205
  hasHelperMethodCall,
209
- logger as singletonLogger4,
210
206
  toCamelCase,
211
207
  toKebabCase as toKebabCase2,
212
208
  validateFeaturePath as validateFeaturePath3
213
209
  } from "@ingenyus/swarm";
214
- import path7 from "path";
210
+ import path6 from "path";
215
211
 
216
212
  // src/generators/feature/feature-generator.ts
217
- import {
218
- handleFatalError as handleFatalError2,
219
- logger as singletonLogger3,
220
- validateFeaturePath as validateFeaturePath2
221
- } from "@ingenyus/swarm";
222
- import path6 from "path";
213
+ import { handleFatalError as handleFatalError2, validateFeaturePath as validateFeaturePath2 } from "@ingenyus/swarm";
214
+ import path5 from "path";
223
215
 
224
216
  // src/generators/base/wasp-generator.base.ts
225
217
  import {
226
218
  GeneratorBase,
227
- logger as singletonLogger2,
228
219
  SwarmConfigManager,
229
220
  TemplateResolver
230
221
  } from "@ingenyus/swarm";
@@ -235,14 +226,14 @@ import {
235
226
  parseHelperMethodDefinition,
236
227
  logger as singletonLogger
237
228
  } from "@ingenyus/swarm";
238
- import path5 from "path";
229
+ import path4 from "path";
239
230
  var WaspConfigGenerator = class {
240
231
  constructor(logger = singletonLogger, fileSystem = realFileSystem) {
241
232
  this.logger = logger;
242
233
  this.fileSystem = fileSystem;
243
234
  this.templateUtility = new TemplateUtility(fileSystem);
244
235
  }
245
- path = path5;
236
+ path = path4;
246
237
  templateUtility;
247
238
  /**
248
239
  * Gets the template path for feature config templates.
@@ -271,7 +262,7 @@ var WaspConfigGenerator = class {
271
262
  this.logger.error(`Template not found: ${templatePath}`);
272
263
  return;
273
264
  }
274
- const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
265
+ const configFilePath = path4.join(featureDir, `feature.wasp.ts`);
275
266
  if (this.fileSystem.existsSync(configFilePath)) {
276
267
  this.logger.warn(`Feature config already exists: ${configFilePath}`);
277
268
  return;
@@ -287,7 +278,7 @@ var WaspConfigGenerator = class {
287
278
  */
288
279
  update(featurePath, declaration) {
289
280
  const configDir = getFeatureDir(this.fileSystem, featurePath);
290
- const configFilePath = path5.join(configDir, `feature.wasp.ts`);
281
+ const configFilePath = path4.join(configDir, `feature.wasp.ts`);
291
282
  if (!this.fileSystem.existsSync(configFilePath)) {
292
283
  const templatePath = this.getTemplatePath("feature.wasp.eta");
293
284
  if (!this.fileSystem.existsSync(templatePath)) {
@@ -667,14 +658,6 @@ var WaspConfigGenerator = class {
667
658
 
668
659
  // src/generators/base/wasp-generator.base.ts
669
660
  var WaspGeneratorBase = class extends GeneratorBase {
670
- constructor(fileSystem = realFileSystem, logger = singletonLogger2) {
671
- super(fileSystem, logger);
672
- this.fileSystem = fileSystem;
673
- this.logger = logger;
674
- this.configGenerator = new WaspConfigGenerator(logger, fileSystem);
675
- this.templateUtility = new TemplateUtility(fileSystem);
676
- this.templateResolver = new TemplateResolver(fileSystem);
677
- }
678
661
  configGenerator;
679
662
  templateUtility;
680
663
  templateResolver;
@@ -682,6 +665,15 @@ var WaspGeneratorBase = class extends GeneratorBase {
682
665
  configLoaded = false;
683
666
  // Plugin name from swarm.config.json
684
667
  pluginName = PLUGIN_NAME;
668
+ constructor() {
669
+ super();
670
+ this.configGenerator = new WaspConfigGenerator(
671
+ this.logger,
672
+ this.fileSystem
673
+ );
674
+ this.templateUtility = new TemplateUtility(this.fileSystem);
675
+ this.templateResolver = new TemplateResolver(this.fileSystem);
676
+ }
685
677
  async loadSwarmConfig() {
686
678
  if (this.configLoaded) return;
687
679
  const configManager = new SwarmConfigManager();
@@ -732,7 +724,7 @@ var WaspGeneratorBase = class extends GeneratorBase {
732
724
  }
733
725
  /**
734
726
  * Generic existence check with force flag handling
735
- * Consolidates the pattern used in both file and config checks
727
+ * Consolidates the pattern used in both file and config existence checks
736
728
  */
737
729
  checkExistence(exists, itemDescription, force, errorMessage) {
738
730
  if (exists && !force) {
@@ -772,16 +764,14 @@ var schema = z2.object({
772
764
 
773
765
  // src/generators/feature/feature-generator.ts
774
766
  var FeatureGenerator = class extends WaspGeneratorBase {
775
- constructor(logger = singletonLogger3, fileSystem = realFileSystem) {
776
- super(fileSystem, logger);
777
- this.logger = logger;
778
- this.fileSystem = fileSystem;
779
- this.name = "feature";
780
- this.description = "Generates a feature directory containing a Wasp configuration file";
781
- }
782
767
  name;
783
768
  description;
784
769
  schema = schema;
770
+ constructor() {
771
+ super();
772
+ this.name = "feature";
773
+ this.description = "Generates a feature directory containing a Wasp configuration file";
774
+ }
785
775
  getDefaultTemplatePath(templateName) {
786
776
  return this.templateUtility.resolveTemplatePath(
787
777
  templateName,
@@ -797,18 +787,18 @@ var FeatureGenerator = class extends WaspGeneratorBase {
797
787
  const { target } = args;
798
788
  const segments = validateFeaturePath2(target);
799
789
  const normalisedPath = normaliseFeaturePath(target);
800
- const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
790
+ const sourceRoot = path5.join(findWaspRoot(this.fileSystem), "src");
801
791
  if (segments.length > 1) {
802
792
  const parentPath = segments.slice(0, -1).join("/");
803
793
  const parentNormalisedPath = normaliseFeaturePath(parentPath);
804
- const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
794
+ const parentFeatureDir = path5.join(sourceRoot, parentNormalisedPath);
805
795
  if (!this.fileSystem.existsSync(parentFeatureDir)) {
806
796
  handleFatalError2(
807
797
  `Parent feature '${parentPath}' does not exist. Please create it first.`
808
798
  );
809
799
  }
810
800
  }
811
- const featureDir = path6.join(sourceRoot, normalisedPath);
801
+ const featureDir = path5.join(sourceRoot, normalisedPath);
812
802
  this.fileSystem.mkdirSync(featureDir, { recursive: true });
813
803
  this.configGenerator.generate(normalisedPath);
814
804
  this.logger.success(`Generated feature: ${normalisedPath}`);
@@ -817,13 +807,6 @@ var FeatureGenerator = class extends WaspGeneratorBase {
817
807
 
818
808
  // src/generators/base/component-generator.base.ts
819
809
  var ComponentGeneratorBase = class extends WaspGeneratorBase {
820
- constructor(logger = singletonLogger4, fileSystem = realFileSystem, featureDirectoryGenerator = new FeatureGenerator(logger, fileSystem)) {
821
- super(fileSystem, logger);
822
- this.logger = logger;
823
- this.fileSystem = fileSystem;
824
- this.featureDirectoryGenerator = featureDirectoryGenerator;
825
- this.featureDirectoryGenerator = featureDirectoryGenerator;
826
- }
827
810
  getDefaultTemplatePath(templateName) {
828
811
  return this.templateUtility.resolveTemplatePath(
829
812
  templateName,
@@ -831,6 +814,17 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
831
814
  import.meta.url
832
815
  );
833
816
  }
817
+ featureDirectoryGenerator;
818
+ constructor() {
819
+ super();
820
+ const runtime = GeneratorRuntime.current();
821
+ if (runtime.featureGeneratorFactory) {
822
+ const factoryResult = runtime.featureGeneratorFactory(runtime);
823
+ this.featureDirectoryGenerator = factoryResult;
824
+ } else {
825
+ this.featureDirectoryGenerator = new FeatureGenerator();
826
+ }
827
+ }
834
828
  get name() {
835
829
  return toKebabCase2(this.componentType);
836
830
  }
@@ -845,7 +839,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
845
839
  const currentPath = pathSegments.join("/");
846
840
  const featureName = pathSegments[pathSegments.length - 1];
847
841
  const featureDir = getFeatureDir(this.fileSystem, currentPath);
848
- const configPath = path7.join(featureDir, `feature.wasp.ts`);
842
+ const configPath = path6.join(featureDir, `feature.wasp.ts`);
849
843
  if (this.fileSystem.existsSync(configPath)) {
850
844
  return configPath;
851
845
  }
@@ -907,18 +901,17 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
907
901
  }
908
902
  /**
909
903
  * Gets the appropriate directory for a feature based on its path.
910
- * @param fileSystem - The filesystem abstraction
911
904
  * @param featurePath - The full feature path
912
905
  * @param type - The type of file being generated
913
906
  * @returns The target directory and import path
914
907
  */
915
- getFeatureTargetDir(fileSystem, featurePath, type) {
908
+ getFeatureTargetDir(featurePath, type) {
916
909
  validateFeaturePath3(featurePath);
917
910
  const normalisedPath = normaliseFeaturePath(featurePath);
918
- const featureDir = getFeatureDir(fileSystem, normalisedPath);
911
+ const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
919
912
  const typeKey = type.toLowerCase();
920
913
  const typeDirectory = TYPE_DIRECTORIES[typeKey];
921
- const targetDirectory = path7.join(featureDir, typeDirectory);
914
+ const targetDirectory = path6.join(featureDir, typeDirectory);
922
915
  const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
923
916
  return { targetDirectory, importDirectory };
924
917
  }
@@ -927,7 +920,6 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
927
920
  */
928
921
  ensureTargetDirectory(featurePath, type) {
929
922
  const { targetDirectory, importDirectory } = this.getFeatureTargetDir(
930
- this.fileSystem,
931
923
  featurePath,
932
924
  type
933
925
  );