@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/generators/api-namespace/api-namespace-generator.ts
|
|
2
2
|
import { toCamelCase } from "@ingenyus/swarm";
|
|
3
|
-
import
|
|
3
|
+
import path8 from "path";
|
|
4
4
|
|
|
5
5
|
// src/common/constants.ts
|
|
6
6
|
var PLUGIN_NAME = "wasp";
|
|
@@ -222,22 +222,102 @@ var TemplateUtility = class {
|
|
|
222
222
|
}
|
|
223
223
|
};
|
|
224
224
|
|
|
225
|
+
// src/common/wasp-compatibility.ts
|
|
226
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
227
|
+
import { execSync } from "child_process";
|
|
228
|
+
import path4 from "path";
|
|
229
|
+
import { fileURLToPath } from "url";
|
|
230
|
+
import * as semver from "semver";
|
|
231
|
+
var cachedSupportedRange = null;
|
|
232
|
+
function getWaspSupportedRange() {
|
|
233
|
+
if (cachedSupportedRange) {
|
|
234
|
+
return cachedSupportedRange;
|
|
235
|
+
}
|
|
236
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
237
|
+
const currentDir = path4.dirname(currentFile);
|
|
238
|
+
const result = findPackageJson(currentDir, {
|
|
239
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
240
|
+
});
|
|
241
|
+
if (!result) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
const swarm = result.packageJson.swarm;
|
|
247
|
+
const waspRange = swarm?.wasp;
|
|
248
|
+
if (!waspRange) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`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" }).`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
cachedSupportedRange = waspRange;
|
|
254
|
+
return cachedSupportedRange;
|
|
255
|
+
}
|
|
256
|
+
function getInstalledWaspVersion(logger) {
|
|
257
|
+
try {
|
|
258
|
+
const output = execSync("wasp version", {
|
|
259
|
+
encoding: "utf8",
|
|
260
|
+
stdio: "pipe"
|
|
261
|
+
});
|
|
262
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
263
|
+
if (!firstLine) {
|
|
264
|
+
logger.error(
|
|
265
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
266
|
+
);
|
|
267
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
268
|
+
}
|
|
269
|
+
if (!semver.valid(firstLine)) {
|
|
270
|
+
logger.error(
|
|
271
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
272
|
+
);
|
|
273
|
+
throw new Error("Invalid Wasp version format");
|
|
274
|
+
}
|
|
275
|
+
return firstLine;
|
|
276
|
+
} catch (error) {
|
|
277
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
278
|
+
logger.error(
|
|
279
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
280
|
+
);
|
|
281
|
+
throw new Error("Wasp CLI not found");
|
|
282
|
+
}
|
|
283
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function isTestEnvironment() {
|
|
287
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
288
|
+
}
|
|
289
|
+
function assertWaspCompatible(logger) {
|
|
290
|
+
if (isTestEnvironment()) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
const version = getInstalledWaspVersion(logger);
|
|
294
|
+
const supportedRange = getWaspSupportedRange();
|
|
295
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
296
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
297
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
298
|
+
logger.error(
|
|
299
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
300
|
+
);
|
|
301
|
+
throw new Error("Incompatible Wasp version");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
225
305
|
// src/generators/base/component-generator.base.ts
|
|
226
306
|
import {
|
|
227
307
|
hasHelperMethodCall,
|
|
228
308
|
toKebabCase as toKebabCase2
|
|
229
309
|
} from "@ingenyus/swarm";
|
|
230
|
-
import
|
|
310
|
+
import path7 from "path";
|
|
231
311
|
|
|
232
312
|
// src/generators/feature/feature-generator.ts
|
|
233
313
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
234
|
-
import
|
|
314
|
+
import path6 from "path";
|
|
235
315
|
|
|
236
316
|
// src/generators/base/wasp-generator.base.ts
|
|
237
317
|
import {
|
|
238
318
|
GeneratorBase,
|
|
239
|
-
|
|
240
|
-
|
|
319
|
+
TemplateResolver,
|
|
320
|
+
getConfigManager
|
|
241
321
|
} from "@ingenyus/swarm";
|
|
242
322
|
|
|
243
323
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -246,14 +326,14 @@ import {
|
|
|
246
326
|
handleFatalError,
|
|
247
327
|
parseHelperMethodDefinition
|
|
248
328
|
} from "@ingenyus/swarm";
|
|
249
|
-
import
|
|
329
|
+
import path5 from "path";
|
|
250
330
|
var WaspConfigGenerator = class {
|
|
251
331
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
252
332
|
this.logger = logger;
|
|
253
333
|
this.fileSystem = fileSystem;
|
|
254
334
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
255
335
|
}
|
|
256
|
-
path =
|
|
336
|
+
path = path5;
|
|
257
337
|
templateUtility;
|
|
258
338
|
/**
|
|
259
339
|
* Gets the template path for feature config templates.
|
|
@@ -282,7 +362,7 @@ var WaspConfigGenerator = class {
|
|
|
282
362
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
283
363
|
return;
|
|
284
364
|
}
|
|
285
|
-
const configFilePath =
|
|
365
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
286
366
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
287
367
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
288
368
|
return;
|
|
@@ -298,7 +378,7 @@ var WaspConfigGenerator = class {
|
|
|
298
378
|
*/
|
|
299
379
|
update(featurePath, declaration) {
|
|
300
380
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
301
|
-
const configFilePath =
|
|
381
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
302
382
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
303
383
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
304
384
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -694,6 +774,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
694
774
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
695
775
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
696
776
|
}
|
|
777
|
+
/**
|
|
778
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
779
|
+
* Should be called at the start of generator execution.
|
|
780
|
+
*/
|
|
781
|
+
ensureWaspCompatible() {
|
|
782
|
+
assertWaspCompatible(this.logger);
|
|
783
|
+
}
|
|
697
784
|
async loadConfig() {
|
|
698
785
|
if (this.configLoaded) return;
|
|
699
786
|
const configManager = getConfigManager();
|
|
@@ -810,21 +897,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
810
897
|
* @param target - The target path of the generated directory
|
|
811
898
|
*/
|
|
812
899
|
async generate(args) {
|
|
900
|
+
this.ensureWaspCompatible();
|
|
813
901
|
const { target } = args;
|
|
814
902
|
const segments = validateFeaturePath(target);
|
|
815
903
|
const normalisedPath = normaliseFeaturePath(target);
|
|
816
|
-
const sourceRoot =
|
|
904
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
817
905
|
if (segments.length > 1) {
|
|
818
906
|
const parentPath = segments.slice(0, -1).join("/");
|
|
819
907
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
820
|
-
const parentFeatureDir =
|
|
908
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
821
909
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
822
910
|
handleFatalError2(
|
|
823
911
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
824
912
|
);
|
|
825
913
|
}
|
|
826
914
|
}
|
|
827
|
-
const featureDir =
|
|
915
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
828
916
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
829
917
|
this.configGenerator.generate(normalisedPath);
|
|
830
918
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -859,7 +947,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
859
947
|
const currentPath = pathSegments.join("/");
|
|
860
948
|
const featureName = pathSegments[pathSegments.length - 1];
|
|
861
949
|
const featureDir = getFeatureDir(this.fileSystem, currentPath);
|
|
862
|
-
const configPath =
|
|
950
|
+
const configPath = path7.join(featureDir, `feature.wasp.ts`);
|
|
863
951
|
if (this.fileSystem.existsSync(configPath)) {
|
|
864
952
|
return configPath;
|
|
865
953
|
}
|
|
@@ -931,7 +1019,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
931
1019
|
const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
|
|
932
1020
|
const typeKey = type.toLowerCase();
|
|
933
1021
|
const typeDirectory = TYPE_DIRECTORIES[typeKey];
|
|
934
|
-
const targetDirectory =
|
|
1022
|
+
const targetDirectory = path7.join(featureDir, typeDirectory);
|
|
935
1023
|
const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
|
|
936
1024
|
return { targetDirectory, importDirectory };
|
|
937
1025
|
}
|
|
@@ -1010,12 +1098,13 @@ var ApiNamespaceGenerator = class extends ComponentGeneratorBase {
|
|
|
1010
1098
|
this.componentType,
|
|
1011
1099
|
namespaceName,
|
|
1012
1100
|
async () => {
|
|
1101
|
+
this.ensureWaspCompatible();
|
|
1013
1102
|
const configPath = this.validateFeatureConfig(feature);
|
|
1014
1103
|
const {
|
|
1015
1104
|
targetDirectory: apiTargetDirectory,
|
|
1016
1105
|
importDirectory: apiImportDirectory
|
|
1017
1106
|
} = this.ensureTargetDirectory(feature, "api");
|
|
1018
|
-
const middlewareTargetDirectory =
|
|
1107
|
+
const middlewareTargetDirectory = path8.join(
|
|
1019
1108
|
apiTargetDirectory,
|
|
1020
1109
|
"middleware"
|
|
1021
1110
|
);
|
|
@@ -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/api-namespace/schema.ts
|
|
108
115
|
var baseSchema = z2.object({
|
|
109
116
|
feature: commonSchemas.feature,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
hasHelperMethodCall,
|
|
4
4
|
toKebabCase as toKebabCase2
|
|
5
5
|
} from "@ingenyus/swarm";
|
|
6
|
-
import
|
|
6
|
+
import path7 from "path";
|
|
7
7
|
|
|
8
8
|
// src/common/constants.ts
|
|
9
9
|
var PLUGIN_NAME = "wasp";
|
|
@@ -216,15 +216,95 @@ var TemplateUtility = class {
|
|
|
216
216
|
}
|
|
217
217
|
};
|
|
218
218
|
|
|
219
|
+
// src/common/wasp-compatibility.ts
|
|
220
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
221
|
+
import { execSync } from "child_process";
|
|
222
|
+
import path4 from "path";
|
|
223
|
+
import { fileURLToPath } from "url";
|
|
224
|
+
import * as semver from "semver";
|
|
225
|
+
var cachedSupportedRange = null;
|
|
226
|
+
function getWaspSupportedRange() {
|
|
227
|
+
if (cachedSupportedRange) {
|
|
228
|
+
return cachedSupportedRange;
|
|
229
|
+
}
|
|
230
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
231
|
+
const currentDir = path4.dirname(currentFile);
|
|
232
|
+
const result = findPackageJson(currentDir, {
|
|
233
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
234
|
+
});
|
|
235
|
+
if (!result) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
const swarm = result.packageJson.swarm;
|
|
241
|
+
const waspRange = swarm?.wasp;
|
|
242
|
+
if (!waspRange) {
|
|
243
|
+
throw new Error(
|
|
244
|
+
`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" }).`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
cachedSupportedRange = waspRange;
|
|
248
|
+
return cachedSupportedRange;
|
|
249
|
+
}
|
|
250
|
+
function getInstalledWaspVersion(logger) {
|
|
251
|
+
try {
|
|
252
|
+
const output = execSync("wasp version", {
|
|
253
|
+
encoding: "utf8",
|
|
254
|
+
stdio: "pipe"
|
|
255
|
+
});
|
|
256
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
257
|
+
if (!firstLine) {
|
|
258
|
+
logger.error(
|
|
259
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
260
|
+
);
|
|
261
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
262
|
+
}
|
|
263
|
+
if (!semver.valid(firstLine)) {
|
|
264
|
+
logger.error(
|
|
265
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
266
|
+
);
|
|
267
|
+
throw new Error("Invalid Wasp version format");
|
|
268
|
+
}
|
|
269
|
+
return firstLine;
|
|
270
|
+
} catch (error) {
|
|
271
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
272
|
+
logger.error(
|
|
273
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
274
|
+
);
|
|
275
|
+
throw new Error("Wasp CLI not found");
|
|
276
|
+
}
|
|
277
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function isTestEnvironment() {
|
|
281
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
282
|
+
}
|
|
283
|
+
function assertWaspCompatible(logger) {
|
|
284
|
+
if (isTestEnvironment()) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const version = getInstalledWaspVersion(logger);
|
|
288
|
+
const supportedRange = getWaspSupportedRange();
|
|
289
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
290
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
291
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
292
|
+
logger.error(
|
|
293
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
294
|
+
);
|
|
295
|
+
throw new Error("Incompatible Wasp version");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
219
299
|
// src/generators/feature/feature-generator.ts
|
|
220
300
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
221
|
-
import
|
|
301
|
+
import path6 from "path";
|
|
222
302
|
|
|
223
303
|
// src/generators/base/wasp-generator.base.ts
|
|
224
304
|
import {
|
|
225
305
|
GeneratorBase,
|
|
226
|
-
|
|
227
|
-
|
|
306
|
+
TemplateResolver,
|
|
307
|
+
getConfigManager
|
|
228
308
|
} from "@ingenyus/swarm";
|
|
229
309
|
|
|
230
310
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -233,14 +313,14 @@ import {
|
|
|
233
313
|
handleFatalError,
|
|
234
314
|
parseHelperMethodDefinition
|
|
235
315
|
} from "@ingenyus/swarm";
|
|
236
|
-
import
|
|
316
|
+
import path5 from "path";
|
|
237
317
|
var WaspConfigGenerator = class {
|
|
238
318
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
239
319
|
this.logger = logger;
|
|
240
320
|
this.fileSystem = fileSystem;
|
|
241
321
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
242
322
|
}
|
|
243
|
-
path =
|
|
323
|
+
path = path5;
|
|
244
324
|
templateUtility;
|
|
245
325
|
/**
|
|
246
326
|
* Gets the template path for feature config templates.
|
|
@@ -269,7 +349,7 @@ var WaspConfigGenerator = class {
|
|
|
269
349
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
270
350
|
return;
|
|
271
351
|
}
|
|
272
|
-
const configFilePath =
|
|
352
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
273
353
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
274
354
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
275
355
|
return;
|
|
@@ -285,7 +365,7 @@ var WaspConfigGenerator = class {
|
|
|
285
365
|
*/
|
|
286
366
|
update(featurePath, declaration) {
|
|
287
367
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
288
|
-
const configFilePath =
|
|
368
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
289
369
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
290
370
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
291
371
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -681,6 +761,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
681
761
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
682
762
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
683
763
|
}
|
|
764
|
+
/**
|
|
765
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
766
|
+
* Should be called at the start of generator execution.
|
|
767
|
+
*/
|
|
768
|
+
ensureWaspCompatible() {
|
|
769
|
+
assertWaspCompatible(this.logger);
|
|
770
|
+
}
|
|
684
771
|
async loadConfig() {
|
|
685
772
|
if (this.configLoaded) return;
|
|
686
773
|
const configManager = getConfigManager();
|
|
@@ -797,21 +884,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
797
884
|
* @param target - The target path of the generated directory
|
|
798
885
|
*/
|
|
799
886
|
async generate(args) {
|
|
887
|
+
this.ensureWaspCompatible();
|
|
800
888
|
const { target } = args;
|
|
801
889
|
const segments = validateFeaturePath(target);
|
|
802
890
|
const normalisedPath = normaliseFeaturePath(target);
|
|
803
|
-
const sourceRoot =
|
|
891
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
804
892
|
if (segments.length > 1) {
|
|
805
893
|
const parentPath = segments.slice(0, -1).join("/");
|
|
806
894
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
807
|
-
const parentFeatureDir =
|
|
895
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
808
896
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
809
897
|
handleFatalError2(
|
|
810
898
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
811
899
|
);
|
|
812
900
|
}
|
|
813
901
|
}
|
|
814
|
-
const featureDir =
|
|
902
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
815
903
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
816
904
|
this.configGenerator.generate(normalisedPath);
|
|
817
905
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -846,7 +934,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
846
934
|
const currentPath = pathSegments.join("/");
|
|
847
935
|
const featureName = pathSegments[pathSegments.length - 1];
|
|
848
936
|
const featureDir = getFeatureDir(this.fileSystem, currentPath);
|
|
849
|
-
const configPath =
|
|
937
|
+
const configPath = path7.join(featureDir, `feature.wasp.ts`);
|
|
850
938
|
if (this.fileSystem.existsSync(configPath)) {
|
|
851
939
|
return configPath;
|
|
852
940
|
}
|
|
@@ -918,7 +1006,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
918
1006
|
const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
|
|
919
1007
|
const typeKey = type.toLowerCase();
|
|
920
1008
|
const typeDirectory = TYPE_DIRECTORIES[typeKey];
|
|
921
|
-
const targetDirectory =
|
|
1009
|
+
const targetDirectory = path7.join(featureDir, typeDirectory);
|
|
922
1010
|
const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
|
|
923
1011
|
return { targetDirectory, importDirectory };
|
|
924
1012
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
hasHelperMethodCall,
|
|
4
4
|
toKebabCase as toKebabCase2
|
|
5
5
|
} from "@ingenyus/swarm";
|
|
6
|
-
import
|
|
6
|
+
import path7 from "path";
|
|
7
7
|
|
|
8
8
|
// src/common/constants.ts
|
|
9
9
|
var PLUGIN_NAME = "wasp";
|
|
@@ -365,15 +365,95 @@ var TemplateUtility = class {
|
|
|
365
365
|
}
|
|
366
366
|
};
|
|
367
367
|
|
|
368
|
+
// src/common/wasp-compatibility.ts
|
|
369
|
+
import { findPackageJson, getVersion } from "@ingenyus/swarm";
|
|
370
|
+
import { execSync } from "child_process";
|
|
371
|
+
import path4 from "path";
|
|
372
|
+
import { fileURLToPath } from "url";
|
|
373
|
+
import * as semver from "semver";
|
|
374
|
+
var cachedSupportedRange = null;
|
|
375
|
+
function getWaspSupportedRange() {
|
|
376
|
+
if (cachedSupportedRange) {
|
|
377
|
+
return cachedSupportedRange;
|
|
378
|
+
}
|
|
379
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
380
|
+
const currentDir = path4.dirname(currentFile);
|
|
381
|
+
const result = findPackageJson(currentDir, {
|
|
382
|
+
packageName: "@ingenyus/swarm-wasp"
|
|
383
|
+
});
|
|
384
|
+
if (!result) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
"Unable to find package.json for @ingenyus/swarm-wasp. Wasp supported version range must be specified in swarm.wasp field."
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
const swarm = result.packageJson.swarm;
|
|
390
|
+
const waspRange = swarm?.wasp;
|
|
391
|
+
if (!waspRange) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
`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" }).`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
cachedSupportedRange = waspRange;
|
|
397
|
+
return cachedSupportedRange;
|
|
398
|
+
}
|
|
399
|
+
function getInstalledWaspVersion(logger) {
|
|
400
|
+
try {
|
|
401
|
+
const output = execSync("wasp version", {
|
|
402
|
+
encoding: "utf8",
|
|
403
|
+
stdio: "pipe"
|
|
404
|
+
});
|
|
405
|
+
const firstLine = output.split("\n")[0]?.trim();
|
|
406
|
+
if (!firstLine) {
|
|
407
|
+
logger.error(
|
|
408
|
+
"Unable to parse Wasp version from command output. Expected version number on first line."
|
|
409
|
+
);
|
|
410
|
+
throw new Error("Unable to parse Wasp version from command output");
|
|
411
|
+
}
|
|
412
|
+
if (!semver.valid(firstLine)) {
|
|
413
|
+
logger.error(
|
|
414
|
+
`Invalid Wasp version format: "${firstLine}". Expected a valid semver version (e.g., "0.18.2").`
|
|
415
|
+
);
|
|
416
|
+
throw new Error("Invalid Wasp version format");
|
|
417
|
+
}
|
|
418
|
+
return firstLine;
|
|
419
|
+
} catch (error) {
|
|
420
|
+
if (error.code === "ENOENT" || error.message?.includes("wasp")) {
|
|
421
|
+
logger.error(
|
|
422
|
+
"Wasp CLI not found. Install using: curl -sSL https://get.wasp.sh/installer.sh | sh -s"
|
|
423
|
+
);
|
|
424
|
+
throw new Error("Wasp CLI not found");
|
|
425
|
+
}
|
|
426
|
+
throw new Error("Unable to determine installed Wasp version");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
function isTestEnvironment() {
|
|
430
|
+
return process.env.NODE_ENV === "test" || process.env.VITEST === "true" || typeof process.env.VITEST !== "undefined";
|
|
431
|
+
}
|
|
432
|
+
function assertWaspCompatible(logger) {
|
|
433
|
+
if (isTestEnvironment()) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const version = getInstalledWaspVersion(logger);
|
|
437
|
+
const supportedRange = getWaspSupportedRange();
|
|
438
|
+
if (!semver.satisfies(version, supportedRange)) {
|
|
439
|
+
const startDir = path4.dirname(fileURLToPath(import.meta.url));
|
|
440
|
+
const packageVersion = getVersion("@ingenyus/swarm-wasp", startDir);
|
|
441
|
+
logger.error(
|
|
442
|
+
`Incompatible Wasp version detected: ${version}. @ingenyus/swarm-wasp@${packageVersion} supports Wasp ${supportedRange}.`
|
|
443
|
+
);
|
|
444
|
+
throw new Error("Incompatible Wasp version");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
368
448
|
// src/generators/feature/feature-generator.ts
|
|
369
449
|
import { handleFatalError as handleFatalError2 } from "@ingenyus/swarm";
|
|
370
|
-
import
|
|
450
|
+
import path6 from "path";
|
|
371
451
|
|
|
372
452
|
// src/generators/base/wasp-generator.base.ts
|
|
373
453
|
import {
|
|
374
454
|
GeneratorBase,
|
|
375
|
-
|
|
376
|
-
|
|
455
|
+
TemplateResolver,
|
|
456
|
+
getConfigManager
|
|
377
457
|
} from "@ingenyus/swarm";
|
|
378
458
|
|
|
379
459
|
// src/generators/config/wasp-config-generator.ts
|
|
@@ -382,14 +462,14 @@ import {
|
|
|
382
462
|
handleFatalError,
|
|
383
463
|
parseHelperMethodDefinition
|
|
384
464
|
} from "@ingenyus/swarm";
|
|
385
|
-
import
|
|
465
|
+
import path5 from "path";
|
|
386
466
|
var WaspConfigGenerator = class {
|
|
387
467
|
constructor(logger = getCLILogger(), fileSystem = realFileSystem) {
|
|
388
468
|
this.logger = logger;
|
|
389
469
|
this.fileSystem = fileSystem;
|
|
390
470
|
this.templateUtility = new TemplateUtility(fileSystem);
|
|
391
471
|
}
|
|
392
|
-
path =
|
|
472
|
+
path = path5;
|
|
393
473
|
templateUtility;
|
|
394
474
|
/**
|
|
395
475
|
* Gets the template path for feature config templates.
|
|
@@ -418,7 +498,7 @@ var WaspConfigGenerator = class {
|
|
|
418
498
|
this.logger.error(`Template not found: ${templatePath}`);
|
|
419
499
|
return;
|
|
420
500
|
}
|
|
421
|
-
const configFilePath =
|
|
501
|
+
const configFilePath = path5.join(featureDir, `feature.wasp.ts`);
|
|
422
502
|
if (this.fileSystem.existsSync(configFilePath)) {
|
|
423
503
|
this.logger.warn(`Feature config already exists: ${configFilePath}`);
|
|
424
504
|
return;
|
|
@@ -434,7 +514,7 @@ var WaspConfigGenerator = class {
|
|
|
434
514
|
*/
|
|
435
515
|
update(featurePath, declaration) {
|
|
436
516
|
const configDir = getFeatureDir(this.fileSystem, featurePath);
|
|
437
|
-
const configFilePath =
|
|
517
|
+
const configFilePath = path5.join(configDir, `feature.wasp.ts`);
|
|
438
518
|
if (!this.fileSystem.existsSync(configFilePath)) {
|
|
439
519
|
const templatePath = this.getTemplatePath("feature.wasp.eta");
|
|
440
520
|
if (!this.fileSystem.existsSync(templatePath)) {
|
|
@@ -830,6 +910,13 @@ var WaspGeneratorBase = class extends GeneratorBase {
|
|
|
830
910
|
this.templateUtility = new TemplateUtility(this.fileSystem);
|
|
831
911
|
this.templateResolver = new TemplateResolver(this.fileSystem);
|
|
832
912
|
}
|
|
913
|
+
/**
|
|
914
|
+
* Ensures that the installed Wasp version is compatible with this package.
|
|
915
|
+
* Should be called at the start of generator execution.
|
|
916
|
+
*/
|
|
917
|
+
ensureWaspCompatible() {
|
|
918
|
+
assertWaspCompatible(this.logger);
|
|
919
|
+
}
|
|
833
920
|
async loadConfig() {
|
|
834
921
|
if (this.configLoaded) return;
|
|
835
922
|
const configManager = getConfigManager();
|
|
@@ -946,21 +1033,22 @@ var FeatureGenerator = class extends WaspGeneratorBase {
|
|
|
946
1033
|
* @param target - The target path of the generated directory
|
|
947
1034
|
*/
|
|
948
1035
|
async generate(args) {
|
|
1036
|
+
this.ensureWaspCompatible();
|
|
949
1037
|
const { target } = args;
|
|
950
1038
|
const segments = validateFeaturePath(target);
|
|
951
1039
|
const normalisedPath = normaliseFeaturePath(target);
|
|
952
|
-
const sourceRoot =
|
|
1040
|
+
const sourceRoot = path6.join(findWaspRoot(this.fileSystem), "src");
|
|
953
1041
|
if (segments.length > 1) {
|
|
954
1042
|
const parentPath = segments.slice(0, -1).join("/");
|
|
955
1043
|
const parentNormalisedPath = normaliseFeaturePath(parentPath);
|
|
956
|
-
const parentFeatureDir =
|
|
1044
|
+
const parentFeatureDir = path6.join(sourceRoot, parentNormalisedPath);
|
|
957
1045
|
if (!this.fileSystem.existsSync(parentFeatureDir)) {
|
|
958
1046
|
handleFatalError2(
|
|
959
1047
|
`Parent feature '${parentPath}' does not exist. Please create it first.`
|
|
960
1048
|
);
|
|
961
1049
|
}
|
|
962
1050
|
}
|
|
963
|
-
const featureDir =
|
|
1051
|
+
const featureDir = path6.join(sourceRoot, normalisedPath);
|
|
964
1052
|
this.fileSystem.mkdirSync(featureDir, { recursive: true });
|
|
965
1053
|
this.configGenerator.generate(normalisedPath);
|
|
966
1054
|
this.logger.success(`Generated feature: ${normalisedPath}`);
|
|
@@ -995,7 +1083,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
995
1083
|
const currentPath = pathSegments.join("/");
|
|
996
1084
|
const featureName = pathSegments[pathSegments.length - 1];
|
|
997
1085
|
const featureDir = getFeatureDir(this.fileSystem, currentPath);
|
|
998
|
-
const configPath =
|
|
1086
|
+
const configPath = path7.join(featureDir, `feature.wasp.ts`);
|
|
999
1087
|
if (this.fileSystem.existsSync(configPath)) {
|
|
1000
1088
|
return configPath;
|
|
1001
1089
|
}
|
|
@@ -1067,7 +1155,7 @@ var ComponentGeneratorBase = class extends WaspGeneratorBase {
|
|
|
1067
1155
|
const featureDir = getFeatureDir(this.fileSystem, normalisedPath);
|
|
1068
1156
|
const typeKey = type.toLowerCase();
|
|
1069
1157
|
const typeDirectory = TYPE_DIRECTORIES[typeKey];
|
|
1070
|
-
const targetDirectory =
|
|
1158
|
+
const targetDirectory = path7.join(featureDir, typeDirectory);
|
|
1071
1159
|
const importDirectory = `@src/${normalisedPath}/${typeDirectory}`;
|
|
1072
1160
|
return { targetDirectory, importDirectory };
|
|
1073
1161
|
}
|