@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
|
@@ -366,22 +366,102 @@ var TemplateUtility = class {
|
|
|
366
366
|
}
|
|
367
367
|
};
|
|
368
368
|
|
|
369
|
+
// src/common/wasp-compatibility.ts
|
|
370
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
371
|
+
import { execSync } from "child_process";
|
|
372
|
+
import path4 from "path";
|
|
373
|
+
import { fileURLToPath } from "url";
|
|
374
|
+
import * as semver from "semver";
|
|
375
|
+
var cachedSupportedRange = null;
|
|
376
|
+
function getWaspSupportedRange() {
|
|
377
|
+
if (cachedSupportedRange) {
|
|
378
|
+
return cachedSupportedRange;
|
|
379
|
+
}
|
|
380
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
381
|
+
const currentDir = path4.dirname(currentFile);
|
|
382
|
+
const result = findPackageJson(currentDir, {
|
|
383
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
384
|
+
});
|
|
385
|
+
if (!result) {
|
|
386
|
+
throw new Error(
|
|
387
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
const swarm = result.packageJson.swarm;
|
|
391
|
+
const waspRange = swarm?.wasp;
|
|
392
|
+
if (!waspRange) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`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" }).`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
cachedSupportedRange = waspRange;
|
|
398
|
+
return cachedSupportedRange;
|
|
399
|
+
}
|
|
400
|
+
function getInstalledWaspVersion(logger) {
|
|
401
|
+
try {
|
|
402
|
+
const output = execSync("wasp version", {
|
|
403
|
+
encoding: "utf8",
|
|
404
|
+
stdio: "pipe"
|
|
405
|
+
});
|
|
406
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
407
|
+
if (!firstLine) {
|
|
408
|
+
logger.error(
|
|
409
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
410
|
+
);
|
|
411
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
412
|
+
}
|
|
413
|
+
if (!semver.valid(firstLine)) {
|
|
414
|
+
logger.error(
|
|
415
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
416
|
+
);
|
|
417
|
+
throw new Error("Invalid Wasp version format");
|
|
418
|
+
}
|
|
419
|
+
return firstLine;
|
|
420
|
+
} catch (error) {
|
|
421
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
422
|
+
logger.error(
|
|
423
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
424
|
+
);
|
|
425
|
+
throw new Error("Wasp CLI not found");
|
|
426
|
+
}
|
|
427
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function isTestEnvironment() {
|
|
431
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
432
|
+
}
|
|
433
|
+
function assertWaspCompatible(logger) {
|
|
434
|
+
if (isTestEnvironment()) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const version = getInstalledWaspVersion(logger);
|
|
438
|
+
const supportedRange = getWaspSupportedRange();
|
|
439
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
440
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
441
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
442
|
+
logger.error(
|
|
443
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
444
|
+
);
|
|
445
|
+
throw new Error("Incompatible Wasp version");
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
369
449
|
// src/generators/base/component-generator.base.ts
|
|
370
450
|
import {
|
|
371
451
|
hasHelperMethodCall,
|
|
372
452
|
toKebabCase as toKebabCase2
|
|
373
453
|
} from "@ingenyus/swarm";
|
|
374
|
-
import
|
|
454
|
+
import path7 from "path";
|
|
375
455
|
|
|
376
456
|
// src/generators/feature/feature-generator.ts
|
|
377
457
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
378
|
-
import
|
|
458
|
+
import path6 from "path";
|
|
379
459
|
|
|
380
460
|
// src/generators/base/wasp-generator.base.ts
|
|
381
461
|
import {
|
|
382
462
|
GeneratorBase,
|
|
383
|
-
|
|
384
|
-
|
|
463
|
+
TemplateResolver,
|
|
464
|
+
getConfigManager
|
|
385
465
|
} from "@ingenyus/swarm";
|
|
386
466
|
|
|
387
467
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -390,14 +470,14 @@ import {
|
|
|
390
470
|
handleFatalError,
|
|
391
471
|
parseHelperMethodDefinition
|
|
392
472
|
} from "@ingenyus/swarm";
|
|
393
|
-
import
|
|
473
|
+
import path5 from "path";
|
|
394
474
|
var WaspConfigGenerator = class {
|
|
395
475
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
396
476
|
this.logger = logger;
|
|
397
477
|
this.fileSystem = fileSystem;
|
|
398
478
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
399
479
|
}
|
|
400
|
-
path =
|
|
480
|
+
path = path5;
|
|
401
481
|
templateUtility;
|
|
402
482
|
/**
|
|
403
483
|
* Gets the template path for feature config templates.
|
|
@@ -426,7 +506,7 @@ var WaspConfigGenerator = class {
|
|
|
426
506
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
427
507
|
return;
|
|
428
508
|
}
|
|
429
|
-
const configFilePath =
|
|
509
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
430
510
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
431
511
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
432
512
|
return;
|
|
@@ -442,7 +522,7 @@ var WaspConfigGenerator = class {
|
|
|
442
522
|
*/
|
|
443
523
|
update(featurePath, declaration) {
|
|
444
524
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
445
|
-
const configFilePath =
|
|
525
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
446
526
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
447
527
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
448
528
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -838,6 +918,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
838
918
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
839
919
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
840
920
|
}
|
|
921
|
+
/**
|
|
922
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
923
|
+
* Should be called at the start of generator execution.
|
|
924
|
+
*/
|
|
925
|
+
ensureWaspCompatible() {
|
|
926
|
+
assertWaspCompatible(this.logger);
|
|
927
|
+
}
|
|
841
928
|
async loadConfig() {
|
|
842
929
|
if (this.configLoaded) return;
|
|
843
930
|
const configManager = getConfigManager();
|
|
@@ -954,21 +1041,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
954
1041
|
* @param target - The target path of the generated directory
|
|
955
1042
|
*/
|
|
956
1043
|
async generate(args) {
|
|
1044
|
+
this.ensureWaspCompatible();
|
|
957
1045
|
const { target } = args;
|
|
958
1046
|
const segments = validateFeaturePath(target);
|
|
959
1047
|
const normalisedPath = normaliseFeaturePath(target);
|
|
960
|
-
const sourceRoot =
|
|
1048
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
961
1049
|
if (segments.length > 1) {
|
|
962
1050
|
const parentPath = segments.slice(0, -1).join("/");
|
|
963
1051
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
964
|
-
const parentFeatureDir =
|
|
1052
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
965
1053
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
966
1054
|
handleFatalError2(
|
|
967
1055
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
968
1056
|
);
|
|
969
1057
|
}
|
|
970
1058
|
}
|
|
971
|
-
const featureDir =
|
|
1059
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
972
1060
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
973
1061
|
this.configGenerator.generate(normalisedPath);
|
|
974
1062
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -1003,7 +1091,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
1003
1091
|
const currentPath = pathSegments.join("/");
|
|
1004
1092
|
const featureName = pathSegments[pathSegments.length - 1];
|
|
1005
1093
|
const featureDir = getFeatureDir(this.fileSystem, currentPath);
|
|
1006
|
-
const configPath =
|
|
1094
|
+
const configPath = path7.join(featureDir, `feature.wasp.ts`);
|
|
1007
1095
|
if (this.fileSystem.existsSync(configPath)) {
|
|
1008
1096
|
return configPath;
|
|
1009
1097
|
}
|
|
@@ -1075,7 +1163,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
1075
1163
|
const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
|
|
1076
1164
|
const typeKey = type.toLowerCase();
|
|
1077
1165
|
const typeDirectory = TYPE_DIRECTORIES[typeKey];
|
|
1078
|
-
const targetDirectory =
|
|
1166
|
+
const targetDirectory = path7.join(featureDir, typeDirectory);
|
|
1079
1167
|
const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
|
|
1080
1168
|
return { targetDirectory, importDirectory };
|
|
1081
1169
|
}
|
|
@@ -12,6 +12,11 @@ export declare abstract class WaspGeneratorBase<S extends StandardSchemaV1> exte
|
|
|
12
12
|
private configLoaded;
|
|
13
13
|
protected readonly pluginName: "wasp";
|
|
14
14
|
constructor(services: GeneratorServices);
|
|
15
|
+
/**
|
|
16
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
17
|
+
* Should be called at the start of generator execution.
|
|
18
|
+
*/
|
|
19
|
+
protected ensureWaspCompatible(): void;
|
|
15
20
|
private loadConfig;
|
|
16
21
|
protected getCustomTemplateDir(): Promise<string | undefined>;
|
|
17
22
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasp-generator.base.d.ts","sourceRoot":"","sources":["../../../src/generators/base/wasp-generator.base.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"wasp-generator.base.d.ts","sourceRoot":"","sources":["../../../src/generators/base/wasp-generator.base.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAEjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,eAAe,EAEhB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEhD;;GAEG;AACH,8BAAsB,iBAAiB,CACrC,CAAC,SAAS,gBAAgB,CAC1B,SAAQ,aAAa,CAAC,CAAC,CAAC;IACxB,SAAS,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAC/C,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC;IAC3C,SAAS,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;IAC7C,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,YAAY,CAAS;IAG7B,SAAS,CAAC,QAAQ,CAAC,UAAU,SAAe;gBAEhC,QAAQ,EAAE,iBAAiB;IAUvC;;;OAGG;IACH,SAAS,CAAC,oBAAoB,IAAI,IAAI;YAIxB,UAAU;cASR,oBAAoB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAMnE;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAEvE;;OAEG;cACa,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwBtE;;OAEG;cACa,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,OAAO,CAAC;IAiBnB;;;OAGG;IACH,SAAS,CAAC,cAAc,CACtB,MAAM,EAAE,OAAO,EACf,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO;IAQV;;OAEG;IACH,SAAS,CAAC,eAAe,CACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,OAAO;IAUV;;OAEG;IACH,SAAS,CAAC,SAAS,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,GAClB,IAAI;CAMR"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/generators/base/wasp-generator.base.ts
|
|
2
2
|
import {
|
|
3
3
|
GeneratorBase,
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
TemplateResolver,
|
|
5
|
+
getConfigManager
|
|
6
6
|
} from "@ingenyus/swarm";
|
|
7
7
|
|
|
8
8
|
// src/common/constants.ts
|
|
@@ -132,20 +132,100 @@ var TemplateUtility = class {
|
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
+
// src/common/wasp-compatibility.ts
|
|
136
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
137
|
+
import { execSync } from "child_process";
|
|
138
|
+
import path4 from "path";
|
|
139
|
+
import { fileURLToPath } from "url";
|
|
140
|
+
import * as semver from "semver";
|
|
141
|
+
var cachedSupportedRange = null;
|
|
142
|
+
function getWaspSupportedRange() {
|
|
143
|
+
if (cachedSupportedRange) {
|
|
144
|
+
return cachedSupportedRange;
|
|
145
|
+
}
|
|
146
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
147
|
+
const currentDir = path4.dirname(currentFile);
|
|
148
|
+
const result = findPackageJson(currentDir, {
|
|
149
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
150
|
+
});
|
|
151
|
+
if (!result) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const swarm = result.packageJson.swarm;
|
|
157
|
+
const waspRange = swarm?.wasp;
|
|
158
|
+
if (!waspRange) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`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" }).`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
cachedSupportedRange = waspRange;
|
|
164
|
+
return cachedSupportedRange;
|
|
165
|
+
}
|
|
166
|
+
function getInstalledWaspVersion(logger) {
|
|
167
|
+
try {
|
|
168
|
+
const output = execSync("wasp version", {
|
|
169
|
+
encoding: "utf8",
|
|
170
|
+
stdio: "pipe"
|
|
171
|
+
});
|
|
172
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
173
|
+
if (!firstLine) {
|
|
174
|
+
logger.error(
|
|
175
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
176
|
+
);
|
|
177
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
178
|
+
}
|
|
179
|
+
if (!semver.valid(firstLine)) {
|
|
180
|
+
logger.error(
|
|
181
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
182
|
+
);
|
|
183
|
+
throw new Error("Invalid Wasp version format");
|
|
184
|
+
}
|
|
185
|
+
return firstLine;
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
188
|
+
logger.error(
|
|
189
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
190
|
+
);
|
|
191
|
+
throw new Error("Wasp CLI not found");
|
|
192
|
+
}
|
|
193
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function isTestEnvironment() {
|
|
197
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
198
|
+
}
|
|
199
|
+
function assertWaspCompatible(logger) {
|
|
200
|
+
if (isTestEnvironment()) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const version = getInstalledWaspVersion(logger);
|
|
204
|
+
const supportedRange = getWaspSupportedRange();
|
|
205
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
206
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
207
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
208
|
+
logger.error(
|
|
209
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
210
|
+
);
|
|
211
|
+
throw new Error("Incompatible Wasp version");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
135
215
|
// src/generators/config/wasp-config-generator.ts
|
|
136
216
|
import {
|
|
137
217
|
getCLILogger,
|
|
138
218
|
handleFatalError,
|
|
139
219
|
parseHelperMethodDefinition
|
|
140
220
|
} from "@ingenyus/swarm";
|
|
141
|
-
import
|
|
221
|
+
import path5 from "path";
|
|
142
222
|
var WaspConfigGenerator = class {
|
|
143
223
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
144
224
|
this.logger = logger;
|
|
145
225
|
this.fileSystem = fileSystem;
|
|
146
226
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
147
227
|
}
|
|
148
|
-
path =
|
|
228
|
+
path = path5;
|
|
149
229
|
templateUtility;
|
|
150
230
|
/**
|
|
151
231
|
* Gets the template path for feature config templates.
|
|
@@ -174,7 +254,7 @@ var WaspConfigGenerator = class {
|
|
|
174
254
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
175
255
|
return;
|
|
176
256
|
}
|
|
177
|
-
const configFilePath =
|
|
257
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
178
258
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
179
259
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
180
260
|
return;
|
|
@@ -190,7 +270,7 @@ var WaspConfigGenerator = class {
|
|
|
190
270
|
*/
|
|
191
271
|
update(featurePath, declaration) {
|
|
192
272
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
193
|
-
const configFilePath =
|
|
273
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
194
274
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
195
275
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
196
276
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -586,6 +666,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
586
666
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
587
667
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
588
668
|
}
|
|
669
|
+
/**
|
|
670
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
671
|
+
* Should be called at the start of generator execution.
|
|
672
|
+
*/
|
|
673
|
+
ensureWaspCompatible() {
|
|
674
|
+
assertWaspCompatible(this.logger);
|
|
675
|
+
}
|
|
589
676
|
async loadConfig() {
|
|
590
677
|
if (this.configLoaded) return;
|
|
591
678
|
const configManager = getConfigManager();
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleFatalError,
|
|
5
5
|
parseHelperMethodDefinition
|
|
6
6
|
} from "@ingenyus/swarm";
|
|
7
|
-
import
|
|
7
|
+
import path5 from "path";
|
|
8
8
|
|
|
9
9
|
// src/common/filesystem.ts
|
|
10
10
|
import { toPascalCase } from "@ingenyus/swarm";
|
|
@@ -130,6 +130,13 @@ var TemplateUtility = class {
|
|
|
130
130
|
}
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
// src/common/wasp-compatibility.ts
|
|
134
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
135
|
+
import { execSync } from "child_process";
|
|
136
|
+
import path4 from "path";
|
|
137
|
+
import { fileURLToPath } from "url";
|
|
138
|
+
import * as semver from "semver";
|
|
139
|
+
|
|
133
140
|
// src/generators/config/wasp-config-generator.ts
|
|
134
141
|
var WaspConfigGenerator = class {
|
|
135
142
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
@@ -137,7 +144,7 @@ var WaspConfigGenerator = class {
|
|
|
137
144
|
this.fileSystem = fileSystem;
|
|
138
145
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
139
146
|
}
|
|
140
|
-
path =
|
|
147
|
+
path = path5;
|
|
141
148
|
templateUtility;
|
|
142
149
|
/**
|
|
143
150
|
* Gets the template path for feature config templates.
|
|
@@ -166,7 +173,7 @@ var WaspConfigGenerator = class {
|
|
|
166
173
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
167
174
|
return;
|
|
168
175
|
}
|
|
169
|
-
const configFilePath =
|
|
176
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
170
177
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
171
178
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
172
179
|
return;
|
|
@@ -182,7 +189,7 @@ var WaspConfigGenerator = class {
|
|
|
182
189
|
*/
|
|
183
190
|
update(featurePath, declaration) {
|
|
184
191
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
185
|
-
const configFilePath =
|
|
192
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
186
193
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
187
194
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
188
195
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
handleFatalError,
|
|
5
5
|
parseHelperMethodDefinition
|
|
6
6
|
} from "@ingenyus/swarm";
|
|
7
|
-
import
|
|
7
|
+
import path5 from "path";
|
|
8
8
|
|
|
9
9
|
// src/common/filesystem.ts
|
|
10
10
|
import { toPascalCase } from "@ingenyus/swarm";
|
|
@@ -130,6 +130,13 @@ var TemplateUtility = class {
|
|
|
130
130
|
}
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
// src/common/wasp-compatibility.ts
|
|
134
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
135
|
+
import { execSync } from "child_process";
|
|
136
|
+
import path4 from "path";
|
|
137
|
+
import { fileURLToPath } from "url";
|
|
138
|
+
import * as semver from "semver";
|
|
139
|
+
|
|
133
140
|
// src/generators/config/wasp-config-generator.ts
|
|
134
141
|
var WaspConfigGenerator = class {
|
|
135
142
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
@@ -137,7 +144,7 @@ var WaspConfigGenerator = class {
|
|
|
137
144
|
this.fileSystem = fileSystem;
|
|
138
145
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
139
146
|
}
|
|
140
|
-
path =
|
|
147
|
+
path = path5;
|
|
141
148
|
templateUtility;
|
|
142
149
|
/**
|
|
143
150
|
* Gets the template path for feature config templates.
|
|
@@ -166,7 +173,7 @@ var WaspConfigGenerator = class {
|
|
|
166
173
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
167
174
|
return;
|
|
168
175
|
}
|
|
169
|
-
const configFilePath =
|
|
176
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
170
177
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
171
178
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
172
179
|
return;
|
|
@@ -182,7 +189,7 @@ var WaspConfigGenerator = class {
|
|
|
182
189
|
*/
|
|
183
190
|
update(featurePath, declaration) {
|
|
184
191
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
185
|
-
const configFilePath =
|
|
192
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
186
193
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
187
194
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
188
195
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crud-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/crud/crud-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAEjB,GAAG,EAGJ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EAKb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAUlC,qBAAa,aAAc,SAAQ,sBAAsB,CACvD,OAAO,MAAM,EACb,OAAO,YAAY,CAAC,IAAI,CACzB;IACC,SAAS,KAAK,aAAa,WAE1B;IAED,WAAW,SAAqC;IAChD,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAIjC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"crud-generator.d.ts","sourceRoot":"","sources":["../../../src/generators/crud/crud-generator.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAEjB,GAAG,EAGJ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,YAAY,EAKb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAUlC,qBAAa,aAAc,SAAQ,sBAAsB,CACvD,OAAO,MAAM,EACb,OAAO,YAAY,CAAC,IAAI,CACzB;IACC,SAAS,KAAK,aAAa,WAE1B;IAED,WAAW,SAAqC;IAChD,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;qCAAU;gBAEJ,QAAQ,EAAE,iBAAiB;IAIjC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;YAyCzC,gBAAgB;IA8B9B;;OAEG;IACH,OAAO,CAAC,mBAAmB;YAsBb,gBAAgB;IAoB9B,OAAO,CAAC,eAAe;IA+BvB;;OAEG;YACW,iBAAiB;IA4B/B;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,MAAM;CAoB3E"}
|
|
@@ -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,
|