@ingenyus/swarm-wasp 1.0.3 → 1.2.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.
Files changed (51) hide show
  1. package/README.md +14 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/common/index.d.ts +1 -0
  4. package/dist/common/index.d.ts.map +1 -1
  5. package/dist/common/index.js +81 -0
  6. package/dist/common/wasp-compatibility.d.ts +10 -0
  7. package/dist/common/wasp-compatibility.d.ts.map +1 -0
  8. package/dist/common/wasp-compatibility.js +82 -0
  9. package/dist/generators/action/action-generator.d.ts.map +1 -1
  10. package/dist/generators/action/action-generator.js +102 -13
  11. package/dist/generators/action/index.js +102 -13
  12. package/dist/generators/action/schema.js +7 -0
  13. package/dist/generators/api/api-generator.d.ts.map +1 -1
  14. package/dist/generators/api/api-generator.js +104 -15
  15. package/dist/generators/api/index.js +104 -15
  16. package/dist/generators/api/schema.js +7 -0
  17. package/dist/generators/api-namespace/api-namespace-generator.d.ts.map +1 -1
  18. package/dist/generators/api-namespace/api-namespace-generator.js +104 -15
  19. package/dist/generators/api-namespace/index.js +104 -15
  20. package/dist/generators/api-namespace/schema.js +7 -0
  21. package/dist/generators/base/component-generator.base.js +101 -13
  22. package/dist/generators/base/index.js +101 -13
  23. package/dist/generators/base/operation-generator.base.js +101 -13
  24. package/dist/generators/base/wasp-generator.base.d.ts +5 -0
  25. package/dist/generators/base/wasp-generator.base.d.ts.map +1 -1
  26. package/dist/generators/base/wasp-generator.base.js +93 -6
  27. package/dist/generators/config/index.js +11 -4
  28. package/dist/generators/config/wasp-config-generator.js +11 -4
  29. package/dist/generators/crud/crud-generator.d.ts.map +1 -1
  30. package/dist/generators/crud/crud-generator.js +102 -13
  31. package/dist/generators/crud/index.js +102 -13
  32. package/dist/generators/crud/schema.js +7 -0
  33. package/dist/generators/feature/feature-generator.d.ts.map +1 -1
  34. package/dist/generators/feature/feature-generator.js +98 -10
  35. package/dist/generators/feature/index.js +98 -10
  36. package/dist/generators/feature/schema.js +7 -0
  37. package/dist/generators/index.js +112 -17
  38. package/dist/generators/job/index.js +102 -13
  39. package/dist/generators/job/job-generator.d.ts.map +1 -1
  40. package/dist/generators/job/job-generator.js +102 -13
  41. package/dist/generators/job/schema.js +7 -0
  42. package/dist/generators/query/index.js +102 -13
  43. package/dist/generators/query/query-generator.d.ts.map +1 -1
  44. package/dist/generators/query/query-generator.js +102 -13
  45. package/dist/generators/query/schema.js +7 -0
  46. package/dist/generators/route/index.js +102 -13
  47. package/dist/generators/route/route-generator.d.ts.map +1 -1
  48. package/dist/generators/route/route-generator.js +102 -13
  49. package/dist/generators/route/schema.js +7 -0
  50. package/dist/index.js +120 -25
  51. package/package.json +11 -6
@@ -224,22 +224,102 @@ var TemplateUtility = class {
224
224
  }
225
225
  };
226
226
 
227
+ // src/common/wasp-compatibility.ts
228
+ import { findPackageJson, getVersion } from "@ingenyus/swarm";
229
+ import { execSync } from "child_process";
230
+ import path4 from "path";
231
+ import { fileURLToPath } from "url";
232
+ import * as semver from "semver";
233
+ var cachedSupportedRange = null;
234
+ function getWaspSupportedRange() {
235
+ if (cachedSupportedRange) {
236
+ return cachedSupportedRange;
237
+ }
238
+ const currentFile = fileURLToPath(import.meta.url);
239
+ const currentDir = path4.dirname(currentFile);
240
+ const result = findPackageJson(currentDir, {
241
+ packageName: "@ingenyus/swarm-wasp"
242
+ });
243
+ if (!result) {
244
+ throw new Error(
245
+ "Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
246
+ );
247
+ }
248
+ const swarm = result.packageJson.swarm;
249
+ const waspRange = swarm?.wasp;
250
+ if (!waspRange) {
251
+ throw new Error(
252
+ `Wasp supported version range not found in package.json. Please specify swarm.wasp field in @ingenyus/swarm-wasp package.json (e.g., "swarm": { "wasp": ">=0.18.0 <0.20.0" }).`
253
+ );
254
+ }
255
+ cachedSupportedRange = waspRange;
256
+ return cachedSupportedRange;
257
+ }
258
+ function getInstalledWaspVersion(logger) {
259
+ try {
260
+ const output = execSync("wasp version", {
261
+ encoding: "utf8",
262
+ stdio: "pipe"
263
+ });
264
+ const firstLine = output.split("\n")[0]?.trim();
265
+ if (!firstLine) {
266
+ logger.error(
267
+ "Unable to parse Wasp version from command output. Expected version number on first line."
268
+ );
269
+ throw new Error("Unable to parse Wasp version from command output");
270
+ }
271
+ if (!semver.valid(firstLine)) {
272
+ logger.error(
273
+ `Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
274
+ );
275
+ throw new Error("Invalid Wasp version format");
276
+ }
277
+ return firstLine;
278
+ } catch (error) {
279
+ if (error.code === "ENOENT" || error.message?.includes("wasp")) {
280
+ logger.error(
281
+ "Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
282
+ );
283
+ throw new Error("Wasp CLI not found");
284
+ }
285
+ throw new Error("Unable to determine installed Wasp version");
286
+ }
287
+ }
288
+ function isTestEnvironment() {
289
+ return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
290
+ }
291
+ function assertWaspCompatible(logger) {
292
+ if (isTestEnvironment()) {
293
+ return;
294
+ }
295
+ const version = getInstalledWaspVersion(logger);
296
+ const supportedRange = getWaspSupportedRange();
297
+ if (!semver.satisfies(version, supportedRange)) {
298
+ const startDir = path4.dirname(fileURLToPath(import.meta.url));
299
+ const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
300
+ logger.error(
301
+ `Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
302
+ );
303
+ throw new Error("Incompatible Wasp version");
304
+ }
305
+ }
306
+
227
307
  // src/generators/base/component-generator.base.ts
228
308
  import {
229
309
  hasHelperMethodCall,
230
310
  toKebabCase as toKebabCase2
231
311
  } from "@ingenyus/swarm";
232
- import path6 from "path";
312
+ import path7 from "path";
233
313
 
234
314
  // src/generators/feature/feature-generator.ts
235
315
  import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
236
- import path5 from "path";
316
+ import path6 from "path";
237
317
 
238
318
  // src/generators/base/wasp-generator.base.ts
239
319
  import {
240
320
  GeneratorBase,
241
- getConfigManager,
242
- TemplateResolver
321
+ TemplateResolver,
322
+ getConfigManager
243
323
  } from "@ingenyus/swarm";
244
324
 
245
325
  // src/generators/config/wasp-config-generator.ts
@@ -248,14 +328,14 @@ import {
248
328
  handleFatalError,
249
329
  parseHelperMethodDefinition
250
330
  } from "@ingenyus/swarm";
251
- import path4 from "path";
331
+ import path5 from "path";
252
332
  var WaspConfigGenerator = class {
253
333
  constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
254
334
  this.logger = logger;
255
335
  this.fileSystem = fileSystem;
256
336
  this.templateUtility = new TemplateUtility(fileSystem);
257
337
  }
258
- path = path4;
338
+ path = path5;
259
339
  templateUtility;
260
340
  /**
261
341
  * Gets the template path for feature config templates.
@@ -284,7 +364,7 @@ var WaspConfigGenerator = class {
284
364
  this.logger.error(`Template not found: ${templatePath}`);
285
365
  return;
286
366
  }
287
- const configFilePath = path4.join(featureDir, `feature.wasp.ts`);
367
+ const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
288
368
  if (this.fileSystem.existsSync(configFilePath)) {
289
369
  this.logger.warn(`Feature config already exists: ${configFilePath}`);
290
370
  return;
@@ -300,7 +380,7 @@ var WaspConfigGenerator = class {
300
380
  */
301
381
  update(featurePath, declaration) {
302
382
  const configDir = getFeatureDir(this.fileSystem, featurePath);
303
- const configFilePath = path4.join(configDir, `feature.wasp.ts`);
383
+ const configFilePath = path5.join(configDir, `feature.wasp.ts`);
304
384
  if (!this.fileSystem.existsSync(configFilePath)) {
305
385
  const templatePath = this.getTemplatePath("feature.wasp.eta");
306
386
  if (!this.fileSystem.existsSync(templatePath)) {
@@ -696,6 +776,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
696
776
  this.templateUtility = new TemplateUtility(this.fileSystem);
697
777
  this.templateResolver = new TemplateResolver(this.fileSystem);
698
778
  }
779
+ /**
780
+ * Ensures that the installed Wasp version is compatible with this package.
781
+ * Should be called at the start of generator execution.
782
+ */
783
+ ensureWaspCompatible() {
784
+ assertWaspCompatible(this.logger);
785
+ }
699
786
  async loadConfig() {
700
787
  if (this.configLoaded) return;
701
788
  const configManager = getConfigManager();
@@ -812,21 +899,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
812
899
  * @param target - The target path of the generated directory
813
900
  */
814
901
  async generate(args) {
902
+ this.ensureWaspCompatible();
815
903
  const { target } = args;
816
904
  const segments = validateFeaturePath(target);
817
905
  const normalisedPath = normaliseFeaturePath(target);
818
- const sourceRoot = path5.join(findWaspRoot(this.fileSystem), "src");
906
+ const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
819
907
  if (segments.length > 1) {
820
908
  const parentPath = segments.slice(0, -1).join("/");
821
909
  const parentNormalisedPath = normaliseFeaturePath(parentPath);
822
- const parentFeatureDir = path5.join(sourceRoot, parentNormalisedPath);
910
+ const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
823
911
  if (!this.fileSystem.existsSync(parentFeatureDir)) {
824
912
  handleFatalError2(
825
913
  `Parent feature '${parentPath}' does not exist. Please create it first.`
826
914
  );
827
915
  }
828
916
  }
829
- const featureDir = path5.join(sourceRoot, normalisedPath);
917
+ const featureDir = path6.join(sourceRoot, normalisedPath);
830
918
  this.fileSystem.mkdirSync(featureDir, { recursive: true });
831
919
  this.configGenerator.generate(normalisedPath);
832
920
  this.logger.success(`Generated feature: ${normalisedPath}`);
@@ -861,7 +949,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
861
949
  const currentPath = pathSegments.join("/");
862
950
  const featureName = pathSegments[pathSegments.length - 1];
863
951
  const featureDir = getFeatureDir(this.fileSystem, currentPath);
864
- const configPath = path6.join(featureDir, `feature.wasp.ts`);
952
+ const configPath = path7.join(featureDir, `feature.wasp.ts`);
865
953
  if (this.fileSystem.existsSync(configPath)) {
866
954
  return configPath;
867
955
  }
@@ -933,7 +1021,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
933
1021
  const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
934
1022
  const typeKey = type.toLowerCase();
935
1023
  const typeDirectory = TYPE_DIRECTORIES[typeKey];
936
- const targetDirectory = path6.join(featureDir, typeDirectory);
1024
+ const targetDirectory = path7.join(featureDir, typeDirectory);
937
1025
  const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
938
1026
  return { targetDirectory, importDirectory };
939
1027
  }
@@ -1078,6 +1166,7 @@ var JobGenerator = class extends ComponentGeneratorBase {
1078
1166
  async generate(args) {
1079
1167
  const jobName = toCamelCase(args.name);
1080
1168
  return this.handleGeneratorError(this.componentType, jobName, async () => {
1169
+ this.ensureWaspCompatible();
1081
1170
  const configPath = this.validateFeatureConfig(args.feature);
1082
1171
  const { targetDirectory } = this.ensureTargetDirectory(
1083
1172
  args.feature,
@@ -104,6 +104,13 @@ var commonFieldMetadata = {
104
104
  import { toKebabCase } from "@ingenyus/swarm";
105
105
  import { Eta } from "eta";
106
106
 
107
+ // src/common/wasp-compatibility.ts
108
+ import { findPackageJson, getVersion } from "@ingenyus/swarm";
109
+ import { execSync } from "child_process";
110
+ import path2 from "path";
111
+ import { fileURLToPath } from "url";
112
+ import * as semver from "semver";
113
+
107
114
  // src/generators/job/schema.ts
108
115
  var cronSchema = z2.string().optional().refine(
109
116
  (val) => {
@@ -372,22 +372,102 @@ var TemplateUtility = class {
372
372
  }
373
373
  };
374
374
 
375
+ // src/common/wasp-compatibility.ts
376
+ import { findPackageJson, getVersion } from "@ingenyus/swarm";
377
+ import { execSync } from "child_process";
378
+ import path4 from "path";
379
+ import { fileURLToPath } from "url";
380
+ import * as semver from "semver";
381
+ var cachedSupportedRange = null;
382
+ function getWaspSupportedRange() {
383
+ if (cachedSupportedRange) {
384
+ return cachedSupportedRange;
385
+ }
386
+ const currentFile = fileURLToPath(import.meta.url);
387
+ const currentDir = path4.dirname(currentFile);
388
+ const result = findPackageJson(currentDir, {
389
+ packageName: "@ingenyus/swarm-wasp"
390
+ });
391
+ if (!result) {
392
+ throw new Error(
393
+ "Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
394
+ );
395
+ }
396
+ const swarm = result.packageJson.swarm;
397
+ const waspRange = swarm?.wasp;
398
+ if (!waspRange) {
399
+ throw new Error(
400
+ `Wasp supported version range not found in package.json. Please specify swarm.wasp field in @ingenyus/swarm-wasp package.json (e.g., "swarm": { "wasp": ">=0.18.0 <0.20.0" }).`
401
+ );
402
+ }
403
+ cachedSupportedRange = waspRange;
404
+ return cachedSupportedRange;
405
+ }
406
+ function getInstalledWaspVersion(logger) {
407
+ try {
408
+ const output = execSync("wasp version", {
409
+ encoding: "utf8",
410
+ stdio: "pipe"
411
+ });
412
+ const firstLine = output.split("\n")[0]?.trim();
413
+ if (!firstLine) {
414
+ logger.error(
415
+ "Unable to parse Wasp version from command output. Expected version number on first line."
416
+ );
417
+ throw new Error("Unable to parse Wasp version from command output");
418
+ }
419
+ if (!semver.valid(firstLine)) {
420
+ logger.error(
421
+ `Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
422
+ );
423
+ throw new Error("Invalid Wasp version format");
424
+ }
425
+ return firstLine;
426
+ } catch (error) {
427
+ if (error.code === "ENOENT" || error.message?.includes("wasp")) {
428
+ logger.error(
429
+ "Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
430
+ );
431
+ throw new Error("Wasp CLI not found");
432
+ }
433
+ throw new Error("Unable to determine installed Wasp version");
434
+ }
435
+ }
436
+ function isTestEnvironment() {
437
+ return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
438
+ }
439
+ function assertWaspCompatible(logger) {
440
+ if (isTestEnvironment()) {
441
+ return;
442
+ }
443
+ const version = getInstalledWaspVersion(logger);
444
+ const supportedRange = getWaspSupportedRange();
445
+ if (!semver.satisfies(version, supportedRange)) {
446
+ const startDir = path4.dirname(fileURLToPath(import.meta.url));
447
+ const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
448
+ logger.error(
449
+ `Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
450
+ );
451
+ throw new Error("Incompatible Wasp version");
452
+ }
453
+ }
454
+
375
455
  // src/generators/base/component-generator.base.ts
376
456
  import {
377
457
  hasHelperMethodCall,
378
458
  toKebabCase as toKebabCase2
379
459
  } from "@ingenyus/swarm";
380
- import path6 from "path";
460
+ import path7 from "path";
381
461
 
382
462
  // src/generators/feature/feature-generator.ts
383
463
  import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
384
- import path5 from "path";
464
+ import path6 from "path";
385
465
 
386
466
  // src/generators/base/wasp-generator.base.ts
387
467
  import {
388
468
  GeneratorBase,
389
- getConfigManager,
390
- TemplateResolver
469
+ TemplateResolver,
470
+ getConfigManager
391
471
  } from "@ingenyus/swarm";
392
472
 
393
473
  // src/generators/config/wasp-config-generator.ts
@@ -396,14 +476,14 @@ import {
396
476
  handleFatalError,
397
477
  parseHelperMethodDefinition
398
478
  } from "@ingenyus/swarm";
399
- import path4 from "path";
479
+ import path5 from "path";
400
480
  var WaspConfigGenerator = class {
401
481
  constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
402
482
  this.logger = logger;
403
483
  this.fileSystem = fileSystem;
404
484
  this.templateUtility = new TemplateUtility(fileSystem);
405
485
  }
406
- path = path4;
486
+ path = path5;
407
487
  templateUtility;
408
488
  /**
409
489
  * Gets the template path for feature config templates.
@@ -432,7 +512,7 @@ var WaspConfigGenerator = class {
432
512
  this.logger.error(`Template not found: ${templatePath}`);
433
513
  return;
434
514
  }
435
- const configFilePath = path4.join(featureDir, `feature.wasp.ts`);
515
+ const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
436
516
  if (this.fileSystem.existsSync(configFilePath)) {
437
517
  this.logger.warn(`Feature config already exists: ${configFilePath}`);
438
518
  return;
@@ -448,7 +528,7 @@ var WaspConfigGenerator = class {
448
528
  */
449
529
  update(featurePath, declaration) {
450
530
  const configDir = getFeatureDir(this.fileSystem, featurePath);
451
- const configFilePath = path4.join(configDir, `feature.wasp.ts`);
531
+ const configFilePath = path5.join(configDir, `feature.wasp.ts`);
452
532
  if (!this.fileSystem.existsSync(configFilePath)) {
453
533
  const templatePath = this.getTemplatePath("feature.wasp.eta");
454
534
  if (!this.fileSystem.existsSync(templatePath)) {
@@ -844,6 +924,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
844
924
  this.templateUtility = new TemplateUtility(this.fileSystem);
845
925
  this.templateResolver = new TemplateResolver(this.fileSystem);
846
926
  }
927
+ /**
928
+ * Ensures that the installed Wasp version is compatible with this package.
929
+ * Should be called at the start of generator execution.
930
+ */
931
+ ensureWaspCompatible() {
932
+ assertWaspCompatible(this.logger);
933
+ }
847
934
  async loadConfig() {
848
935
  if (this.configLoaded) return;
849
936
  const configManager = getConfigManager();
@@ -960,21 +1047,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
960
1047
  * @param target - The target path of the generated directory
961
1048
  */
962
1049
  async generate(args) {
1050
+ this.ensureWaspCompatible();
963
1051
  const { target } = args;
964
1052
  const segments = validateFeaturePath(target);
965
1053
  const normalisedPath = normaliseFeaturePath(target);
966
- const sourceRoot = path5.join(findWaspRoot(this.fileSystem), "src");
1054
+ const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
967
1055
  if (segments.length > 1) {
968
1056
  const parentPath = segments.slice(0, -1).join("/");
969
1057
  const parentNormalisedPath = normaliseFeaturePath(parentPath);
970
- const parentFeatureDir = path5.join(sourceRoot, parentNormalisedPath);
1058
+ const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
971
1059
  if (!this.fileSystem.existsSync(parentFeatureDir)) {
972
1060
  handleFatalError2(
973
1061
  `Parent feature '${parentPath}' does not exist. Please create it first.`
974
1062
  );
975
1063
  }
976
1064
  }
977
- const featureDir = path5.join(sourceRoot, normalisedPath);
1065
+ const featureDir = path6.join(sourceRoot, normalisedPath);
978
1066
  this.fileSystem.mkdirSync(featureDir, { recursive: true });
979
1067
  this.configGenerator.generate(normalisedPath);
980
1068
  this.logger.success(`Generated feature: ${normalisedPath}`);
@@ -1009,7 +1097,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1009
1097
  const currentPath = pathSegments.join("/");
1010
1098
  const featureName = pathSegments[pathSegments.length - 1];
1011
1099
  const featureDir = getFeatureDir(this.fileSystem, currentPath);
1012
- const configPath = path6.join(featureDir, `feature.wasp.ts`);
1100
+ const configPath = path7.join(featureDir, `feature.wasp.ts`);
1013
1101
  if (this.fileSystem.existsSync(configPath)) {
1014
1102
  return configPath;
1015
1103
  }
@@ -1081,7 +1169,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1081
1169
  const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
1082
1170
  const typeKey = type.toLowerCase();
1083
1171
  const typeDirectory = TYPE_DIRECTORIES[typeKey];
1084
- const targetDirectory = path6.join(featureDir, typeDirectory);
1172
+ const targetDirectory = path7.join(featureDir, typeDirectory);
1085
1173
  const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
1086
1174
  return { targetDirectory, importDirectory };
1087
1175
  }
@@ -1447,6 +1535,7 @@ var QueryGenerator = class extends OperationGeneratorBase {
1447
1535
  this.componentType,
1448
1536
  operationName,
1449
1537
  async () => {
1538
+ this.ensureWaspCompatible();
1450
1539
  const configPath = this.validateFeatureConfig(feature);
1451
1540
  const { targetDirectory: operationsDir, importDirectory } = this.ensureTargetDirectory(feature, operationType);
1452
1541
  const importPath = `${importDirectory}/${operationName}`;
@@ -1 +1 @@
1
- {"version":3,"file":"query-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/query/query-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,cAAe,SAAQ,sBAAsB,CACxD,OAAO,MAAM,EACb,OAAO,YAAY,CAAC,KAAK,CAC1B;IACC,SAAS,KAAK,aAAa,YAE1B;IAED,WAAW,SAA4B;IACvC,MAAM;;;;;;;;;;;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAIjC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA0DxD"}
1
+ {"version":3,"file":"query-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/query/query-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,cAAe,SAAQ,sBAAsB,CACxD,OAAO,MAAM,EACb,OAAO,YAAY,CAAC,KAAK,CAC1B;IACC,SAAS,KAAK,aAAa,YAE1B;IAED,WAAW,SAA4B;IACvC,MAAM;;;;;;;;;;;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAIjC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA4DxD"}
@@ -372,22 +372,102 @@ var TemplateUtility = class {
372
372
  }
373
373
  };
374
374
 
375
+ // src/common/wasp-compatibility.ts
376
+ import { findPackageJson, getVersion } from "@ingenyus/swarm";
377
+ import { execSync } from "child_process";
378
+ import path4 from "path";
379
+ import { fileURLToPath } from "url";
380
+ import * as semver from "semver";
381
+ var cachedSupportedRange = null;
382
+ function getWaspSupportedRange() {
383
+ if (cachedSupportedRange) {
384
+ return cachedSupportedRange;
385
+ }
386
+ const currentFile = fileURLToPath(import.meta.url);
387
+ const currentDir = path4.dirname(currentFile);
388
+ const result = findPackageJson(currentDir, {
389
+ packageName: "@ingenyus/swarm-wasp"
390
+ });
391
+ if (!result) {
392
+ throw new Error(
393
+ "Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
394
+ );
395
+ }
396
+ const swarm = result.packageJson.swarm;
397
+ const waspRange = swarm?.wasp;
398
+ if (!waspRange) {
399
+ throw new Error(
400
+ `Wasp supported version range not found in package.json. Please specify swarm.wasp field in @ingenyus/swarm-wasp package.json (e.g., "swarm": { "wasp": ">=0.18.0 <0.20.0" }).`
401
+ );
402
+ }
403
+ cachedSupportedRange = waspRange;
404
+ return cachedSupportedRange;
405
+ }
406
+ function getInstalledWaspVersion(logger) {
407
+ try {
408
+ const output = execSync("wasp version", {
409
+ encoding: "utf8",
410
+ stdio: "pipe"
411
+ });
412
+ const firstLine = output.split("\n")[0]?.trim();
413
+ if (!firstLine) {
414
+ logger.error(
415
+ "Unable to parse Wasp version from command output. Expected version number on first line."
416
+ );
417
+ throw new Error("Unable to parse Wasp version from command output");
418
+ }
419
+ if (!semver.valid(firstLine)) {
420
+ logger.error(
421
+ `Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
422
+ );
423
+ throw new Error("Invalid Wasp version format");
424
+ }
425
+ return firstLine;
426
+ } catch (error) {
427
+ if (error.code === "ENOENT" || error.message?.includes("wasp")) {
428
+ logger.error(
429
+ "Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
430
+ );
431
+ throw new Error("Wasp CLI not found");
432
+ }
433
+ throw new Error("Unable to determine installed Wasp version");
434
+ }
435
+ }
436
+ function isTestEnvironment() {
437
+ return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
438
+ }
439
+ function assertWaspCompatible(logger) {
440
+ if (isTestEnvironment()) {
441
+ return;
442
+ }
443
+ const version = getInstalledWaspVersion(logger);
444
+ const supportedRange = getWaspSupportedRange();
445
+ if (!semver.satisfies(version, supportedRange)) {
446
+ const startDir = path4.dirname(fileURLToPath(import.meta.url));
447
+ const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
448
+ logger.error(
449
+ `Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
450
+ );
451
+ throw new Error("Incompatible Wasp version");
452
+ }
453
+ }
454
+
375
455
  // src/generators/base/component-generator.base.ts
376
456
  import {
377
457
  hasHelperMethodCall,
378
458
  toKebabCase as toKebabCase2
379
459
  } from "@ingenyus/swarm";
380
- import path6 from "path";
460
+ import path7 from "path";
381
461
 
382
462
  // src/generators/feature/feature-generator.ts
383
463
  import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
384
- import path5 from "path";
464
+ import path6 from "path";
385
465
 
386
466
  // src/generators/base/wasp-generator.base.ts
387
467
  import {
388
468
  GeneratorBase,
389
- getConfigManager,
390
- TemplateResolver
469
+ TemplateResolver,
470
+ getConfigManager
391
471
  } from "@ingenyus/swarm";
392
472
 
393
473
  // src/generators/config/wasp-config-generator.ts
@@ -396,14 +476,14 @@ import {
396
476
  handleFatalError,
397
477
  parseHelperMethodDefinition
398
478
  } from "@ingenyus/swarm";
399
- import path4 from "path";
479
+ import path5 from "path";
400
480
  var WaspConfigGenerator = class {
401
481
  constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
402
482
  this.logger = logger;
403
483
  this.fileSystem = fileSystem;
404
484
  this.templateUtility = new TemplateUtility(fileSystem);
405
485
  }
406
- path = path4;
486
+ path = path5;
407
487
  templateUtility;
408
488
  /**
409
489
  * Gets the template path for feature config templates.
@@ -432,7 +512,7 @@ var WaspConfigGenerator = class {
432
512
  this.logger.error(`Template not found: ${templatePath}`);
433
513
  return;
434
514
  }
435
- const configFilePath = path4.join(featureDir, `feature.wasp.ts`);
515
+ const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
436
516
  if (this.fileSystem.existsSync(configFilePath)) {
437
517
  this.logger.warn(`Feature config already exists: ${configFilePath}`);
438
518
  return;
@@ -448,7 +528,7 @@ var WaspConfigGenerator = class {
448
528
  */
449
529
  update(featurePath, declaration) {
450
530
  const configDir = getFeatureDir(this.fileSystem, featurePath);
451
- const configFilePath = path4.join(configDir, `feature.wasp.ts`);
531
+ const configFilePath = path5.join(configDir, `feature.wasp.ts`);
452
532
  if (!this.fileSystem.existsSync(configFilePath)) {
453
533
  const templatePath = this.getTemplatePath("feature.wasp.eta");
454
534
  if (!this.fileSystem.existsSync(templatePath)) {
@@ -844,6 +924,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
844
924
  this.templateUtility = new TemplateUtility(this.fileSystem);
845
925
  this.templateResolver = new TemplateResolver(this.fileSystem);
846
926
  }
927
+ /**
928
+ * Ensures that the installed Wasp version is compatible with this package.
929
+ * Should be called at the start of generator execution.
930
+ */
931
+ ensureWaspCompatible() {
932
+ assertWaspCompatible(this.logger);
933
+ }
847
934
  async loadConfig() {
848
935
  if (this.configLoaded) return;
849
936
  const configManager = getConfigManager();
@@ -960,21 +1047,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
960
1047
  * @param target - The target path of the generated directory
961
1048
  */
962
1049
  async generate(args) {
1050
+ this.ensureWaspCompatible();
963
1051
  const { target } = args;
964
1052
  const segments = validateFeaturePath(target);
965
1053
  const normalisedPath = normaliseFeaturePath(target);
966
- const sourceRoot = path5.join(findWaspRoot(this.fileSystem), "src");
1054
+ const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
967
1055
  if (segments.length > 1) {
968
1056
  const parentPath = segments.slice(0, -1).join("/");
969
1057
  const parentNormalisedPath = normaliseFeaturePath(parentPath);
970
- const parentFeatureDir = path5.join(sourceRoot, parentNormalisedPath);
1058
+ const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
971
1059
  if (!this.fileSystem.existsSync(parentFeatureDir)) {
972
1060
  handleFatalError2(
973
1061
  `Parent feature '${parentPath}' does not exist. Please create it first.`
974
1062
  );
975
1063
  }
976
1064
  }
977
- const featureDir = path5.join(sourceRoot, normalisedPath);
1065
+ const featureDir = path6.join(sourceRoot, normalisedPath);
978
1066
  this.fileSystem.mkdirSync(featureDir, { recursive: true });
979
1067
  this.configGenerator.generate(normalisedPath);
980
1068
  this.logger.success(`Generated feature: ${normalisedPath}`);
@@ -1009,7 +1097,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1009
1097
  const currentPath = pathSegments.join("/");
1010
1098
  const featureName = pathSegments[pathSegments.length - 1];
1011
1099
  const featureDir = getFeatureDir(this.fileSystem, currentPath);
1012
- const configPath = path6.join(featureDir, `feature.wasp.ts`);
1100
+ const configPath = path7.join(featureDir, `feature.wasp.ts`);
1013
1101
  if (this.fileSystem.existsSync(configPath)) {
1014
1102
  return configPath;
1015
1103
  }
@@ -1081,7 +1169,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
1081
1169
  const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
1082
1170
  const typeKey = type.toLowerCase();
1083
1171
  const typeDirectory = TYPE_DIRECTORIES[typeKey];
1084
- const targetDirectory = path6.join(featureDir, typeDirectory);
1172
+ const targetDirectory = path7.join(featureDir, typeDirectory);
1085
1173
  const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
1086
1174
  return { targetDirectory, importDirectory };
1087
1175
  }
@@ -1447,6 +1535,7 @@ var QueryGenerator = class extends OperationGeneratorBase {
1447
1535
  this.componentType,
1448
1536
  operationName,
1449
1537
  async () => {
1538
+ this.ensureWaspCompatible();
1450
1539
  const configPath = this.validateFeatureConfig(feature);
1451
1540
  const { targetDirectory: operationsDir, importDirectory } = this.ensureTargetDirectory(feature, operationType);
1452
1541
  const importPath = `${importDirectory}/${operationName}`;
@@ -111,6 +111,13 @@ var commonFieldMetadata = {
111
111
  import { toKebabCase } from "@ingenyus/swarm";
112
112
  import { Eta } from "eta";
113
113
 
114
+ // src/common/wasp-compatibility.ts
115
+ import { findPackageJson, getVersion } from "@ingenyus/swarm";
116
+ import { execSync } from "child_process";
117
+ import path2 from "path";
118
+ import { fileURLToPath } from "url";
119
+ import * as semver from "semver";
120
+
114
121
  // src/generators/query/schema.ts
115
122
  var validQueries = Object.values(QUERY_OPERATIONS);
116
123
  var querySchema = z2.string().min(1, "Query type is required").transform((val) => SchemaManager.findEnumValue(QUERY_OPERATIONS, val)).pipe(