@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.
- package/README.md +14 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/common/index.d.ts +1 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/common/index.js +81 -0
- package/dist/common/wasp-compatibility.d.ts +10 -0
- package/dist/common/wasp-compatibility.d.ts.map +1 -0
- package/dist/common/wasp-compatibility.js +82 -0
- package/dist/generators/action/action-generator.d.ts.map +1 -1
- package/dist/generators/action/action-generator.js +102 -13
- package/dist/generators/action/index.js +102 -13
- package/dist/generators/action/schema.js +7 -0
- package/dist/generators/api/api-generator.d.ts.map +1 -1
- package/dist/generators/api/api-generator.js +104 -15
- package/dist/generators/api/index.js +104 -15
- package/dist/generators/api/schema.js +7 -0
- package/dist/generators/api-namespace/api-namespace-generator.d.ts.map +1 -1
- package/dist/generators/api-namespace/api-namespace-generator.js +104 -15
- package/dist/generators/api-namespace/index.js +104 -15
- package/dist/generators/api-namespace/schema.js +7 -0
- package/dist/generators/base/component-generator.base.js +101 -13
- package/dist/generators/base/index.js +101 -13
- package/dist/generators/base/operation-generator.base.js +101 -13
- package/dist/generators/base/wasp-generator.base.d.ts +5 -0
- package/dist/generators/base/wasp-generator.base.d.ts.map +1 -1
- package/dist/generators/base/wasp-generator.base.js +93 -6
- package/dist/generators/config/index.js +11 -4
- package/dist/generators/config/wasp-config-generator.js +11 -4
- package/dist/generators/crud/crud-generator.d.ts.map +1 -1
- package/dist/generators/crud/crud-generator.js +102 -13
- package/dist/generators/crud/index.js +102 -13
- package/dist/generators/crud/schema.js +7 -0
- package/dist/generators/feature/feature-generator.d.ts.map +1 -1
- package/dist/generators/feature/feature-generator.js +98 -10
- package/dist/generators/feature/index.js +98 -10
- package/dist/generators/feature/schema.js +7 -0
- package/dist/generators/index.js +112 -17
- package/dist/generators/job/index.js +102 -13
- package/dist/generators/job/job-generator.d.ts.map +1 -1
- package/dist/generators/job/job-generator.js +102 -13
- package/dist/generators/job/schema.js +7 -0
- package/dist/generators/query/index.js +102 -13
- package/dist/generators/query/query-generator.d.ts.map +1 -1
- package/dist/generators/query/query-generator.js +102 -13
- package/dist/generators/query/schema.js +7 -0
- package/dist/generators/route/index.js +102 -13
- package/dist/generators/route/route-generator.d.ts.map +1 -1
- package/dist/generators/route/route-generator.js +102 -13
- package/dist/generators/route/schema.js +7 -0
- package/dist/index.js +120 -25
- package/package.json +11 -6
|
@@ -381,22 +381,102 @@ var TemplateUtility = class {
|
|
|
381
381
|
}
|
|
382
382
|
};
|
|
383
383
|
|
|
384
|
+
// src/common/wasp-compatibility.ts
|
|
385
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
386
|
+
import { execSync } from "child_process";
|
|
387
|
+
import path4 from "path";
|
|
388
|
+
import { fileURLToPath } from "url";
|
|
389
|
+
import * as semver from "semver";
|
|
390
|
+
var cachedSupportedRange = null;
|
|
391
|
+
function getWaspSupportedRange() {
|
|
392
|
+
if (cachedSupportedRange) {
|
|
393
|
+
return cachedSupportedRange;
|
|
394
|
+
}
|
|
395
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
396
|
+
const currentDir = path4.dirname(currentFile);
|
|
397
|
+
const result = findPackageJson(currentDir, {
|
|
398
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
399
|
+
});
|
|
400
|
+
if (!result) {
|
|
401
|
+
throw new Error(
|
|
402
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
const swarm = result.packageJson.swarm;
|
|
406
|
+
const waspRange = swarm?.wasp;
|
|
407
|
+
if (!waspRange) {
|
|
408
|
+
throw new Error(
|
|
409
|
+
`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" }).`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
cachedSupportedRange = waspRange;
|
|
413
|
+
return cachedSupportedRange;
|
|
414
|
+
}
|
|
415
|
+
function getInstalledWaspVersion(logger) {
|
|
416
|
+
try {
|
|
417
|
+
const output = execSync("wasp version", {
|
|
418
|
+
encoding: "utf8",
|
|
419
|
+
stdio: "pipe"
|
|
420
|
+
});
|
|
421
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
422
|
+
if (!firstLine) {
|
|
423
|
+
logger.error(
|
|
424
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
425
|
+
);
|
|
426
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
427
|
+
}
|
|
428
|
+
if (!semver.valid(firstLine)) {
|
|
429
|
+
logger.error(
|
|
430
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
431
|
+
);
|
|
432
|
+
throw new Error("Invalid Wasp version format");
|
|
433
|
+
}
|
|
434
|
+
return firstLine;
|
|
435
|
+
} catch (error) {
|
|
436
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
437
|
+
logger.error(
|
|
438
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
439
|
+
);
|
|
440
|
+
throw new Error("Wasp CLI not found");
|
|
441
|
+
}
|
|
442
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
function isTestEnvironment() {
|
|
446
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
447
|
+
}
|
|
448
|
+
function assertWaspCompatible(logger) {
|
|
449
|
+
if (isTestEnvironment()) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const version = getInstalledWaspVersion(logger);
|
|
453
|
+
const supportedRange = getWaspSupportedRange();
|
|
454
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
455
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
456
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
457
|
+
logger.error(
|
|
458
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
459
|
+
);
|
|
460
|
+
throw new Error("Incompatible Wasp version");
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
384
464
|
// src/generators/base/component-generator.base.ts
|
|
385
465
|
import {
|
|
386
466
|
hasHelperMethodCall,
|
|
387
467
|
toKebabCase as toKebabCase2
|
|
388
468
|
} from "@ingenyus/swarm";
|
|
389
|
-
import
|
|
469
|
+
import path7 from "path";
|
|
390
470
|
|
|
391
471
|
// src/generators/feature/feature-generator.ts
|
|
392
472
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
393
|
-
import
|
|
473
|
+
import path6 from "path";
|
|
394
474
|
|
|
395
475
|
// src/generators/base/wasp-generator.base.ts
|
|
396
476
|
import {
|
|
397
477
|
GeneratorBase,
|
|
398
|
-
|
|
399
|
-
|
|
478
|
+
TemplateResolver,
|
|
479
|
+
getConfigManager
|
|
400
480
|
} from "@ingenyus/swarm";
|
|
401
481
|
|
|
402
482
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -405,14 +485,14 @@ import {
|
|
|
405
485
|
handleFatalError,
|
|
406
486
|
parseHelperMethodDefinition
|
|
407
487
|
} from "@ingenyus/swarm";
|
|
408
|
-
import
|
|
488
|
+
import path5 from "path";
|
|
409
489
|
var WaspConfigGenerator = class {
|
|
410
490
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
411
491
|
this.logger = logger;
|
|
412
492
|
this.fileSystem = fileSystem;
|
|
413
493
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
414
494
|
}
|
|
415
|
-
path =
|
|
495
|
+
path = path5;
|
|
416
496
|
templateUtility;
|
|
417
497
|
/**
|
|
418
498
|
* Gets the template path for feature config templates.
|
|
@@ -441,7 +521,7 @@ var WaspConfigGenerator = class {
|
|
|
441
521
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
442
522
|
return;
|
|
443
523
|
}
|
|
444
|
-
const configFilePath =
|
|
524
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
445
525
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
446
526
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
447
527
|
return;
|
|
@@ -457,7 +537,7 @@ var WaspConfigGenerator = class {
|
|
|
457
537
|
*/
|
|
458
538
|
update(featurePath, declaration) {
|
|
459
539
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
460
|
-
const configFilePath =
|
|
540
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
461
541
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
462
542
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
463
543
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -853,6 +933,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
853
933
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
854
934
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
855
935
|
}
|
|
936
|
+
/**
|
|
937
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
938
|
+
* Should be called at the start of generator execution.
|
|
939
|
+
*/
|
|
940
|
+
ensureWaspCompatible() {
|
|
941
|
+
assertWaspCompatible(this.logger);
|
|
942
|
+
}
|
|
856
943
|
async loadConfig() {
|
|
857
944
|
if (this.configLoaded) return;
|
|
858
945
|
const configManager = getConfigManager();
|
|
@@ -969,21 +1056,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
969
1056
|
* @param target - The target path of the generated directory
|
|
970
1057
|
*/
|
|
971
1058
|
async generate(args) {
|
|
1059
|
+
this.ensureWaspCompatible();
|
|
972
1060
|
const { target } = args;
|
|
973
1061
|
const segments = validateFeaturePath(target);
|
|
974
1062
|
const normalisedPath = normaliseFeaturePath(target);
|
|
975
|
-
const sourceRoot =
|
|
1063
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
976
1064
|
if (segments.length > 1) {
|
|
977
1065
|
const parentPath = segments.slice(0, -1).join("/");
|
|
978
1066
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
979
|
-
const parentFeatureDir =
|
|
1067
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
980
1068
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
981
1069
|
handleFatalError2(
|
|
982
1070
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
983
1071
|
);
|
|
984
1072
|
}
|
|
985
1073
|
}
|
|
986
|
-
const featureDir =
|
|
1074
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
987
1075
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
988
1076
|
this.configGenerator.generate(normalisedPath);
|
|
989
1077
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -1018,7 +1106,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
1018
1106
|
const currentPath = pathSegments.join("/");
|
|
1019
1107
|
const featureName = pathSegments[pathSegments.length - 1];
|
|
1020
1108
|
const featureDir = getFeatureDir(this.fileSystem, currentPath);
|
|
1021
|
-
const configPath =
|
|
1109
|
+
const configPath = path7.join(featureDir, `feature.wasp.ts`);
|
|
1022
1110
|
if (this.fileSystem.existsSync(configPath)) {
|
|
1023
1111
|
return configPath;
|
|
1024
1112
|
}
|
|
@@ -1090,7 +1178,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
1090
1178
|
const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
|
|
1091
1179
|
const typeKey = type.toLowerCase();
|
|
1092
1180
|
const typeDirectory = TYPE_DIRECTORIES[typeKey];
|
|
1093
|
-
const targetDirectory =
|
|
1181
|
+
const targetDirectory = path7.join(featureDir, typeDirectory);
|
|
1094
1182
|
const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
|
|
1095
1183
|
return { targetDirectory, importDirectory };
|
|
1096
1184
|
}
|
|
@@ -1472,6 +1560,7 @@ var CrudGenerator = class extends OperationGeneratorBase {
|
|
|
1472
1560
|
const crudName = name || toCamelCase(getPlural2(dataType));
|
|
1473
1561
|
const crudType = toPascalCase3(crudName);
|
|
1474
1562
|
return this.handleGeneratorError(this.componentType, crudName, async () => {
|
|
1563
|
+
this.ensureWaspCompatible();
|
|
1475
1564
|
const configPath = this.validateFeatureConfig(feature);
|
|
1476
1565
|
const { targetDirectory } = this.ensureTargetDirectory(
|
|
1477
1566
|
feature,
|
|
@@ -113,6 +113,13 @@ var commonFieldMetadata = {
|
|
|
113
113
|
import { toKebabCase } from "@ingenyus/swarm";
|
|
114
114
|
import { Eta } from "eta";
|
|
115
115
|
|
|
116
|
+
// src/common/wasp-compatibility.ts
|
|
117
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
118
|
+
import { execSync } from "child_process";
|
|
119
|
+
import path2 from "path";
|
|
120
|
+
import { fileURLToPath } from "url";
|
|
121
|
+
import * as semver from "semver";
|
|
122
|
+
|
|
116
123
|
// src/generators/crud/schema.ts
|
|
117
124
|
var validCrudOperations = Object.values(CRUD_OPERATIONS);
|
|
118
125
|
var publicOperations = getCrudOperationsArray();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/feature/feature-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAO3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,gBAAiB,SAAQ,iBAAiB,CAAC,OAAO,MAAM,CAAC;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAOvC,SAAS,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAQ9D;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"feature-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/feature/feature-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAO3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,qBAAa,gBAAiB,SAAQ,iBAAiB,CAAC,OAAO,MAAM,CAAC;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAOvC,SAAS,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAQ9D;;;OAGG;IACG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA2BxD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/generators/feature/feature-generator.ts
|
|
2
2
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
3
|
-
import
|
|
3
|
+
import path6 from "path";
|
|
4
4
|
|
|
5
5
|
// src/common/constants.ts
|
|
6
6
|
var PLUGIN_NAME = "wasp";
|
|
@@ -194,11 +194,91 @@ var TemplateUtility = class {
|
|
|
194
194
|
}
|
|
195
195
|
};
|
|
196
196
|
|
|
197
|
+
// src/common/wasp-compatibility.ts
|
|
198
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
199
|
+
import { execSync } from "child_process";
|
|
200
|
+
import path4 from "path";
|
|
201
|
+
import { fileURLToPath } from "url";
|
|
202
|
+
import * as semver from "semver";
|
|
203
|
+
var cachedSupportedRange = null;
|
|
204
|
+
function getWaspSupportedRange() {
|
|
205
|
+
if (cachedSupportedRange) {
|
|
206
|
+
return cachedSupportedRange;
|
|
207
|
+
}
|
|
208
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
209
|
+
const currentDir = path4.dirname(currentFile);
|
|
210
|
+
const result = findPackageJson(currentDir, {
|
|
211
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
212
|
+
});
|
|
213
|
+
if (!result) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const swarm = result.packageJson.swarm;
|
|
219
|
+
const waspRange = swarm?.wasp;
|
|
220
|
+
if (!waspRange) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`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" }).`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
cachedSupportedRange = waspRange;
|
|
226
|
+
return cachedSupportedRange;
|
|
227
|
+
}
|
|
228
|
+
function getInstalledWaspVersion(logger) {
|
|
229
|
+
try {
|
|
230
|
+
const output = execSync("wasp version", {
|
|
231
|
+
encoding: "utf8",
|
|
232
|
+
stdio: "pipe"
|
|
233
|
+
});
|
|
234
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
235
|
+
if (!firstLine) {
|
|
236
|
+
logger.error(
|
|
237
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
238
|
+
);
|
|
239
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
240
|
+
}
|
|
241
|
+
if (!semver.valid(firstLine)) {
|
|
242
|
+
logger.error(
|
|
243
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
244
|
+
);
|
|
245
|
+
throw new Error("Invalid Wasp version format");
|
|
246
|
+
}
|
|
247
|
+
return firstLine;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
250
|
+
logger.error(
|
|
251
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
252
|
+
);
|
|
253
|
+
throw new Error("Wasp CLI not found");
|
|
254
|
+
}
|
|
255
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function isTestEnvironment() {
|
|
259
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
260
|
+
}
|
|
261
|
+
function assertWaspCompatible(logger) {
|
|
262
|
+
if (isTestEnvironment()) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const version = getInstalledWaspVersion(logger);
|
|
266
|
+
const supportedRange = getWaspSupportedRange();
|
|
267
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
268
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
269
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
270
|
+
logger.error(
|
|
271
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
272
|
+
);
|
|
273
|
+
throw new Error("Incompatible Wasp version");
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
197
277
|
// src/generators/base/wasp-generator.base.ts
|
|
198
278
|
import {
|
|
199
279
|
GeneratorBase,
|
|
200
|
-
|
|
201
|
-
|
|
280
|
+
TemplateResolver,
|
|
281
|
+
getConfigManager
|
|
202
282
|
} from "@ingenyus/swarm";
|
|
203
283
|
|
|
204
284
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -207,14 +287,14 @@ import {
|
|
|
207
287
|
handleFatalError,
|
|
208
288
|
parseHelperMethodDefinition
|
|
209
289
|
} from "@ingenyus/swarm";
|
|
210
|
-
import
|
|
290
|
+
import path5 from "path";
|
|
211
291
|
var WaspConfigGenerator = class {
|
|
212
292
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
213
293
|
this.logger = logger;
|
|
214
294
|
this.fileSystem = fileSystem;
|
|
215
295
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
216
296
|
}
|
|
217
|
-
path =
|
|
297
|
+
path = path5;
|
|
218
298
|
templateUtility;
|
|
219
299
|
/**
|
|
220
300
|
* Gets the template path for feature config templates.
|
|
@@ -243,7 +323,7 @@ var WaspConfigGenerator = class {
|
|
|
243
323
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
244
324
|
return;
|
|
245
325
|
}
|
|
246
|
-
const configFilePath =
|
|
326
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
247
327
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
248
328
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
249
329
|
return;
|
|
@@ -259,7 +339,7 @@ var WaspConfigGenerator = class {
|
|
|
259
339
|
*/
|
|
260
340
|
update(featurePath, declaration) {
|
|
261
341
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
262
|
-
const configFilePath =
|
|
342
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
263
343
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
264
344
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
265
345
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -655,6 +735,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
655
735
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
656
736
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
657
737
|
}
|
|
738
|
+
/**
|
|
739
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
740
|
+
* Should be called at the start of generator execution.
|
|
741
|
+
*/
|
|
742
|
+
ensureWaspCompatible() {
|
|
743
|
+
assertWaspCompatible(this.logger);
|
|
744
|
+
}
|
|
658
745
|
async loadConfig() {
|
|
659
746
|
if (this.configLoaded) return;
|
|
660
747
|
const configManager = getConfigManager();
|
|
@@ -771,21 +858,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
771
858
|
* @param target - The target path of the generated directory
|
|
772
859
|
*/
|
|
773
860
|
async generate(args) {
|
|
861
|
+
this.ensureWaspCompatible();
|
|
774
862
|
const { target } = args;
|
|
775
863
|
const segments = validateFeaturePath(target);
|
|
776
864
|
const normalisedPath = normaliseFeaturePath(target);
|
|
777
|
-
const sourceRoot =
|
|
865
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
778
866
|
if (segments.length > 1) {
|
|
779
867
|
const parentPath = segments.slice(0, -1).join("/");
|
|
780
868
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
781
|
-
const parentFeatureDir =
|
|
869
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
782
870
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
783
871
|
handleFatalError2(
|
|
784
872
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
785
873
|
);
|
|
786
874
|
}
|
|
787
875
|
}
|
|
788
|
-
const featureDir =
|
|
876
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
789
877
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
790
878
|
this.configGenerator.generate(normalisedPath);
|
|
791
879
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/generators/feature/feature-generator.ts
|
|
2
2
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
3
|
-
import
|
|
3
|
+
import path6 from "path";
|
|
4
4
|
|
|
5
5
|
// src/common/constants.ts
|
|
6
6
|
var PLUGIN_NAME = "wasp";
|
|
@@ -194,11 +194,91 @@ var TemplateUtility = class {
|
|
|
194
194
|
}
|
|
195
195
|
};
|
|
196
196
|
|
|
197
|
+
// src/common/wasp-compatibility.ts
|
|
198
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
199
|
+
import { execSync } from "child_process";
|
|
200
|
+
import path4 from "path";
|
|
201
|
+
import { fileURLToPath } from "url";
|
|
202
|
+
import * as semver from "semver";
|
|
203
|
+
var cachedSupportedRange = null;
|
|
204
|
+
function getWaspSupportedRange() {
|
|
205
|
+
if (cachedSupportedRange) {
|
|
206
|
+
return cachedSupportedRange;
|
|
207
|
+
}
|
|
208
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
209
|
+
const currentDir = path4.dirname(currentFile);
|
|
210
|
+
const result = findPackageJson(currentDir, {
|
|
211
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
212
|
+
});
|
|
213
|
+
if (!result) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const swarm = result.packageJson.swarm;
|
|
219
|
+
const waspRange = swarm?.wasp;
|
|
220
|
+
if (!waspRange) {
|
|
221
|
+
throw new Error(
|
|
222
|
+
`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" }).`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
cachedSupportedRange = waspRange;
|
|
226
|
+
return cachedSupportedRange;
|
|
227
|
+
}
|
|
228
|
+
function getInstalledWaspVersion(logger) {
|
|
229
|
+
try {
|
|
230
|
+
const output = execSync("wasp version", {
|
|
231
|
+
encoding: "utf8",
|
|
232
|
+
stdio: "pipe"
|
|
233
|
+
});
|
|
234
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
235
|
+
if (!firstLine) {
|
|
236
|
+
logger.error(
|
|
237
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
238
|
+
);
|
|
239
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
240
|
+
}
|
|
241
|
+
if (!semver.valid(firstLine)) {
|
|
242
|
+
logger.error(
|
|
243
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
244
|
+
);
|
|
245
|
+
throw new Error("Invalid Wasp version format");
|
|
246
|
+
}
|
|
247
|
+
return firstLine;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
250
|
+
logger.error(
|
|
251
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
252
|
+
);
|
|
253
|
+
throw new Error("Wasp CLI not found");
|
|
254
|
+
}
|
|
255
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function isTestEnvironment() {
|
|
259
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
260
|
+
}
|
|
261
|
+
function assertWaspCompatible(logger) {
|
|
262
|
+
if (isTestEnvironment()) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const version = getInstalledWaspVersion(logger);
|
|
266
|
+
const supportedRange = getWaspSupportedRange();
|
|
267
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
268
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
269
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
270
|
+
logger.error(
|
|
271
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
272
|
+
);
|
|
273
|
+
throw new Error("Incompatible Wasp version");
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
197
277
|
// src/generators/base/wasp-generator.base.ts
|
|
198
278
|
import {
|
|
199
279
|
GeneratorBase,
|
|
200
|
-
|
|
201
|
-
|
|
280
|
+
TemplateResolver,
|
|
281
|
+
getConfigManager
|
|
202
282
|
} from "@ingenyus/swarm";
|
|
203
283
|
|
|
204
284
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -207,14 +287,14 @@ import {
|
|
|
207
287
|
handleFatalError,
|
|
208
288
|
parseHelperMethodDefinition
|
|
209
289
|
} from "@ingenyus/swarm";
|
|
210
|
-
import
|
|
290
|
+
import path5 from "path";
|
|
211
291
|
var WaspConfigGenerator = class {
|
|
212
292
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
213
293
|
this.logger = logger;
|
|
214
294
|
this.fileSystem = fileSystem;
|
|
215
295
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
216
296
|
}
|
|
217
|
-
path =
|
|
297
|
+
path = path5;
|
|
218
298
|
templateUtility;
|
|
219
299
|
/**
|
|
220
300
|
* Gets the template path for feature config templates.
|
|
@@ -243,7 +323,7 @@ var WaspConfigGenerator = class {
|
|
|
243
323
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
244
324
|
return;
|
|
245
325
|
}
|
|
246
|
-
const configFilePath =
|
|
326
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
247
327
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
248
328
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
249
329
|
return;
|
|
@@ -259,7 +339,7 @@ var WaspConfigGenerator = class {
|
|
|
259
339
|
*/
|
|
260
340
|
update(featurePath, declaration) {
|
|
261
341
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
262
|
-
const configFilePath =
|
|
342
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
263
343
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
264
344
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
265
345
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -655,6 +735,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
655
735
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
656
736
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
657
737
|
}
|
|
738
|
+
/**
|
|
739
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
740
|
+
* Should be called at the start of generator execution.
|
|
741
|
+
*/
|
|
742
|
+
ensureWaspCompatible() {
|
|
743
|
+
assertWaspCompatible(this.logger);
|
|
744
|
+
}
|
|
658
745
|
async loadConfig() {
|
|
659
746
|
if (this.configLoaded) return;
|
|
660
747
|
const configManager = getConfigManager();
|
|
@@ -771,21 +858,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
771
858
|
* @param target - The target path of the generated directory
|
|
772
859
|
*/
|
|
773
860
|
async generate(args) {
|
|
861
|
+
this.ensureWaspCompatible();
|
|
774
862
|
const { target } = args;
|
|
775
863
|
const segments = validateFeaturePath(target);
|
|
776
864
|
const normalisedPath = normaliseFeaturePath(target);
|
|
777
|
-
const sourceRoot =
|
|
865
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
778
866
|
if (segments.length > 1) {
|
|
779
867
|
const parentPath = segments.slice(0, -1).join("/");
|
|
780
868
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
781
|
-
const parentFeatureDir =
|
|
869
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
782
870
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
783
871
|
handleFatalError2(
|
|
784
872
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
785
873
|
);
|
|
786
874
|
}
|
|
787
875
|
}
|
|
788
|
-
const featureDir =
|
|
876
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
789
877
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
790
878
|
this.configGenerator.generate(normalisedPath);
|
|
791
879
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -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/feature/schema.ts
|
|
108
115
|
var baseSchema = z2.object({
|
|
109
116
|
target: commonSchemas.target
|