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