@wneng/create-keel 0.4.2 → 0.5.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/dist/index.js +74 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/standards/templates/tech-stack-server.md.eta +34 -2
- package/src/templates/contracts-base/files/dictionaries/event-types.yaml +16 -0
- package/src/templates/contracts-base/files/dictionaries/locales.yaml +12 -0
- package/src/templates/contracts-base/files/dictionaries/roles.yaml +12 -0
- package/src/templates/contracts-base/files/dictionaries/status.yaml +16 -0
- package/src/templates/contracts-base/files/errors/common-errors.yaml +40 -0
- package/src/templates/contracts-base/files/errors/server-errors.yaml +16 -0
- package/src/templates/contracts-base/files/events/audit-event.schema.json +47 -0
- package/src/templates/contracts-base/fragment.yaml +22 -10
- package/src/templates/contracts-rest/fragment.yaml +2 -1
- package/src/templates/contracts-rest-by-audience/files/_components-README.md +32 -0
- package/src/templates/contracts-rest-by-audience/files/_components-schemas.yaml +78 -0
- package/src/templates/contracts-rest-by-audience/files/admin-api.yaml +37 -0
- package/src/templates/contracts-rest-by-audience/files/agent-api.yaml +37 -0
- package/src/templates/contracts-rest-by-audience/files/user-api.yaml +33 -0
- package/src/templates/contracts-rest-by-audience/fragment.yaml +22 -0
- package/src/templates/contracts-rest-events/fragment.yaml +2 -1
- package/src/templates/contracts-rest-events-by-audience/files/_components-README.md +32 -0
- package/src/templates/contracts-rest-events-by-audience/files/_components-schemas.yaml +78 -0
- package/src/templates/contracts-rest-events-by-audience/files/admin-api.yaml +37 -0
- package/src/templates/contracts-rest-events-by-audience/files/agent-api.yaml +37 -0
- package/src/templates/contracts-rest-events-by-audience/files/asyncapi.yaml +8 -0
- package/src/templates/contracts-rest-events-by-audience/files/user-api.yaml +33 -0
- package/src/templates/contracts-rest-events-by-audience/fragment.yaml +25 -0
- package/src/templates/docs-skeleton/files/governance-contracts-layout.md +172 -0
- package/src/templates/docs-skeleton/fragment.yaml +3 -0
- package/src/templates/root-files/files/AGENTS.md +2 -0
- package/src/templates/contracts-base/files/dictionaries/domain-models.yaml +0 -3
- package/src/templates/contracts-base/files/dictionaries/enums.yaml +0 -3
- package/src/templates/contracts-base/files/errors/error-codes.yaml +0 -6
- package/src/templates/contracts-base/files/events-gitkeep +0 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/version.ts
|
|
4
|
-
var SCAFFOLDER_VERSION = "0.
|
|
4
|
+
var SCAFFOLDER_VERSION = "0.5.0";
|
|
5
5
|
|
|
6
6
|
// src/schema/options.ts
|
|
7
7
|
import Ajv from "ajv";
|
|
@@ -29,6 +29,7 @@ var AI_TOOLS = ["kiro", "cursor", "claude-code", "codex", "none"];
|
|
|
29
29
|
var LICENSE_KINDS = ["mit", "apache-2.0", "proprietary"];
|
|
30
30
|
var CI_PLATFORMS = ["gitee", "github"];
|
|
31
31
|
var ROLE_KINDS = ["design", "qa", "field", "data", "legal-security", "marketing"];
|
|
32
|
+
var OPENAPI_LAYOUTS = ["single", "by-audience"];
|
|
32
33
|
var PROJECT_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
33
34
|
var PROJECT_NAME_PATTERN_SOURCE = "^[a-z0-9][a-z0-9-]{0,62}$";
|
|
34
35
|
var OPTIONS_FIELD_ORDER = [
|
|
@@ -47,7 +48,8 @@ var OPTIONS_FIELD_ORDER = [
|
|
|
47
48
|
"ci",
|
|
48
49
|
"roles",
|
|
49
50
|
"multiApp",
|
|
50
|
-
"database"
|
|
51
|
+
"database",
|
|
52
|
+
"openapiLayout"
|
|
51
53
|
];
|
|
52
54
|
var OPTIONS_SCHEMA = {
|
|
53
55
|
$schema: "http://json-schema.org/draft-07/schema#",
|
|
@@ -71,7 +73,8 @@ var OPTIONS_SCHEMA = {
|
|
|
71
73
|
"ci",
|
|
72
74
|
"roles",
|
|
73
75
|
"multiApp",
|
|
74
|
-
"database"
|
|
76
|
+
"database",
|
|
77
|
+
"openapiLayout"
|
|
75
78
|
],
|
|
76
79
|
properties: {
|
|
77
80
|
projectName: {
|
|
@@ -96,7 +99,8 @@ var OPTIONS_SCHEMA = {
|
|
|
96
99
|
uniqueItems: true
|
|
97
100
|
},
|
|
98
101
|
multiApp: { type: "boolean" },
|
|
99
|
-
database: { type: "string", enum: [...DATABASE_KINDS] }
|
|
102
|
+
database: { type: "string", enum: [...DATABASE_KINDS] },
|
|
103
|
+
openapiLayout: { type: "string", enum: [...OPENAPI_LAYOUTS] }
|
|
100
104
|
},
|
|
101
105
|
// Cross-axis constraint: `backend === 'none'` requires `database === 'none'`.
|
|
102
106
|
// A non-'none' database without a backend would be a contradiction (no
|
|
@@ -452,6 +456,7 @@ function parseCreateArgs(args) {
|
|
|
452
456
|
let gitLfs;
|
|
453
457
|
let integrations;
|
|
454
458
|
let database;
|
|
459
|
+
let openapiLayout;
|
|
455
460
|
function takeEnum(flag, next, enumValues) {
|
|
456
461
|
if (next === void 0 || next.startsWith("--")) {
|
|
457
462
|
throw new UserInputError(
|
|
@@ -548,6 +553,11 @@ function parseCreateArgs(args) {
|
|
|
548
553
|
i += 1;
|
|
549
554
|
break;
|
|
550
555
|
}
|
|
556
|
+
case "--openapi-layout": {
|
|
557
|
+
openapiLayout = takeEnum("--openapi-layout", args[i + 1], OPENAPI_LAYOUTS);
|
|
558
|
+
i += 1;
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
551
561
|
case "--engineering-standards": {
|
|
552
562
|
const next = args[i + 1];
|
|
553
563
|
if (next === void 0 || next.startsWith("--")) {
|
|
@@ -673,7 +683,8 @@ function parseCreateArgs(args) {
|
|
|
673
683
|
...license !== void 0 ? { license } : {},
|
|
674
684
|
...gitLfs !== void 0 ? { gitLfs } : {},
|
|
675
685
|
...integrations !== void 0 ? { integrations } : {},
|
|
676
|
-
...database !== void 0 ? { database } : {}
|
|
686
|
+
...database !== void 0 ? { database } : {},
|
|
687
|
+
...openapiLayout !== void 0 ? { openapiLayout } : {}
|
|
677
688
|
};
|
|
678
689
|
if (sampleFeature && dryRun) {
|
|
679
690
|
throw new UserInputError(
|
|
@@ -762,6 +773,7 @@ function helpText() {
|
|
|
762
773
|
" --ai <kind> " + AI_TOOLS.join("|"),
|
|
763
774
|
" --license <kind> " + LICENSE_KINDS.join("|"),
|
|
764
775
|
" --database <kind> " + DATABASE_KINDS.join("|") + " (requires backend != none)",
|
|
776
|
+
" --openapi-layout <kind> " + OPENAPI_LAYOUTS.join("|") + " (default: single; ignored when contract has no OpenAPI)",
|
|
765
777
|
" --gitLfs Enable Git LFS in the generated project",
|
|
766
778
|
" --integrations Enable docs/06-\u96C6\u6210\u5BF9\u63A5/ at create time",
|
|
767
779
|
" -h, --help Show this help",
|
|
@@ -816,7 +828,8 @@ var OPTION_DEFAULTS = {
|
|
|
816
828
|
ci: "gitee",
|
|
817
829
|
roles: [],
|
|
818
830
|
multiApp: false,
|
|
819
|
-
database: "none"
|
|
831
|
+
database: "none",
|
|
832
|
+
openapiLayout: "single"
|
|
820
833
|
};
|
|
821
834
|
function buildDefaultOptions(projectName) {
|
|
822
835
|
return { projectName, ...OPTION_DEFAULTS };
|
|
@@ -853,7 +866,8 @@ var PARTIAL_OPTIONS_SCHEMA = {
|
|
|
853
866
|
uniqueItems: true
|
|
854
867
|
},
|
|
855
868
|
multiApp: { type: "boolean" },
|
|
856
|
-
database: { type: "string", enum: [...DATABASE_KINDS] }
|
|
869
|
+
database: { type: "string", enum: [...DATABASE_KINDS] },
|
|
870
|
+
openapiLayout: { type: "string", enum: [...OPENAPI_LAYOUTS] }
|
|
857
871
|
}
|
|
858
872
|
};
|
|
859
873
|
var ajv2 = new Ajv2({ allErrors: true, strict: true });
|
|
@@ -1051,6 +1065,25 @@ async function promptForOptions(input) {
|
|
|
1051
1065
|
report,
|
|
1052
1066
|
"contract"
|
|
1053
1067
|
);
|
|
1068
|
+
let openapiLayout;
|
|
1069
|
+
const contractHasOpenapi = contract === "rest" || contract === "rest+events";
|
|
1070
|
+
if (!contractHasOpenapi) {
|
|
1071
|
+
openapiLayout = "single";
|
|
1072
|
+
report("openapiLayout", openapiLayout, true);
|
|
1073
|
+
} else if (pre.openapiLayout !== void 0) {
|
|
1074
|
+
openapiLayout = pre.openapiLayout;
|
|
1075
|
+
report("openapiLayout", openapiLayout, false);
|
|
1076
|
+
} else {
|
|
1077
|
+
openapiLayout = await p.select(
|
|
1078
|
+
"OpenAPI \u6587\u4EF6\u5E03\u5C40",
|
|
1079
|
+
[
|
|
1080
|
+
{ value: "single", name: "single \u5355\u6587\u4EF6 contracts/openapi/api.yaml\uFF08\u5C0F\u9879\u76EE\uFF0C\u9ED8\u8BA4\uFF09" },
|
|
1081
|
+
{ value: "by-audience", name: "by-audience \u6309\u53D7\u4F17\u62C6 admin / user / agent + _components/schemas.yaml\uFF08\u591A\u56E2\u961F\u573A\u666F\uFF09" }
|
|
1082
|
+
],
|
|
1083
|
+
OPTION_DEFAULTS.openapiLayout
|
|
1084
|
+
);
|
|
1085
|
+
report("openapiLayout", openapiLayout, false);
|
|
1086
|
+
}
|
|
1054
1087
|
const ai = await chooseAxis(
|
|
1055
1088
|
p,
|
|
1056
1089
|
pre.ai,
|
|
@@ -1121,7 +1154,8 @@ async function promptForOptions(input) {
|
|
|
1121
1154
|
ci,
|
|
1122
1155
|
roles,
|
|
1123
1156
|
multiApp: OPTION_DEFAULTS.multiApp,
|
|
1124
|
-
database
|
|
1157
|
+
database,
|
|
1158
|
+
openapiLayout
|
|
1125
1159
|
};
|
|
1126
1160
|
}
|
|
1127
1161
|
async function chooseAxis(prompter, prefilled, question, domain, def, report, axisName) {
|
|
@@ -1173,7 +1207,8 @@ var APPLIES_WHEN_SCHEMA = {
|
|
|
1173
1207
|
integrations: { type: "boolean" },
|
|
1174
1208
|
ci: { type: "string", enum: [...CI_PLATFORMS] },
|
|
1175
1209
|
role: { type: "string", enum: [...ROLE_KINDS] },
|
|
1176
|
-
database: { type: "string", enum: [...DATABASE_KINDS] }
|
|
1210
|
+
database: { type: "string", enum: [...DATABASE_KINDS] },
|
|
1211
|
+
openapiLayout: { type: "string", enum: [...OPENAPI_LAYOUTS] }
|
|
1177
1212
|
}
|
|
1178
1213
|
};
|
|
1179
1214
|
var MANIFEST_SCHEMA = {
|
|
@@ -1645,6 +1680,9 @@ function assertMetadata(value) {
|
|
|
1645
1680
|
if (!("database" in opts)) {
|
|
1646
1681
|
opts.database = "none";
|
|
1647
1682
|
}
|
|
1683
|
+
if (!("openapiLayout" in opts)) {
|
|
1684
|
+
opts.openapiLayout = "single";
|
|
1685
|
+
}
|
|
1648
1686
|
}
|
|
1649
1687
|
if (!validateFn3(value)) {
|
|
1650
1688
|
throw new MetadataValidationError(collectIssues3());
|
|
@@ -2224,6 +2262,20 @@ function detectRuntimeManifests(options) {
|
|
|
2224
2262
|
}
|
|
2225
2263
|
|
|
2226
2264
|
// src/standards/plan.ts
|
|
2265
|
+
function defaultOrmConvention(options) {
|
|
2266
|
+
if (options.backend === "none" || options.database === "none") return "none";
|
|
2267
|
+
if (options.database === "elasticsearch") return "none";
|
|
2268
|
+
switch (options.backend) {
|
|
2269
|
+
case "java":
|
|
2270
|
+
return "mybatis-plus-only";
|
|
2271
|
+
case "node":
|
|
2272
|
+
return "knex-only";
|
|
2273
|
+
case "python":
|
|
2274
|
+
return "sqlalchemy-orm-only";
|
|
2275
|
+
case "go":
|
|
2276
|
+
return "none";
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2227
2279
|
async function buildStandardsPlan(input) {
|
|
2228
2280
|
const templatesRoot = input.templatesRoot ?? defaultStandardsTemplatesRoot();
|
|
2229
2281
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -2248,6 +2300,16 @@ async function buildStandardsPlan(input) {
|
|
|
2248
2300
|
if (input.tier === "standard" || input.tier === "full") {
|
|
2249
2301
|
for (const m of manifests) {
|
|
2250
2302
|
const fileBaseName = `tech-stack-${m.env}.md`;
|
|
2303
|
+
const standardsBase = {
|
|
2304
|
+
tier: input.tier,
|
|
2305
|
+
env: m.env,
|
|
2306
|
+
language: m.language,
|
|
2307
|
+
packageManager: m.packageManager,
|
|
2308
|
+
manifestPath: m.manifestPath,
|
|
2309
|
+
lastReviewed,
|
|
2310
|
+
multiApp: input.options.multiApp
|
|
2311
|
+
};
|
|
2312
|
+
const standards = m.env === "server" ? { ...standardsBase, ormConvention: defaultOrmConvention(input.options) } : standardsBase;
|
|
2251
2313
|
files.push(
|
|
2252
2314
|
await renderStandardsTemplate({
|
|
2253
2315
|
templatesRoot,
|
|
@@ -2257,21 +2319,7 @@ async function buildStandardsPlan(input) {
|
|
|
2257
2319
|
options: input.options,
|
|
2258
2320
|
scaffolderVersion: input.scaffolderVersion,
|
|
2259
2321
|
now,
|
|
2260
|
-
standards
|
|
2261
|
-
tier: input.tier,
|
|
2262
|
-
env: m.env,
|
|
2263
|
-
language: m.language,
|
|
2264
|
-
packageManager: m.packageManager,
|
|
2265
|
-
manifestPath: m.manifestPath,
|
|
2266
|
-
lastReviewed,
|
|
2267
|
-
multiApp: input.options.multiApp
|
|
2268
|
-
// Smuggle dependencies through standards context so the
|
|
2269
|
-
// template can iterate. We attach via Object.assign-style
|
|
2270
|
-
// cast because StandardsRenderContext does not declare it
|
|
2271
|
-
// (deps are only read by the tech-stack templates and the
|
|
2272
|
-
// shape varies per env, so keeping it untyped here is
|
|
2273
|
-
// acceptable).
|
|
2274
|
-
},
|
|
2322
|
+
standards,
|
|
2275
2323
|
extraStandardsFields: { dependencies: m.dependencies }
|
|
2276
2324
|
})
|
|
2277
2325
|
);
|
|
@@ -2531,7 +2579,8 @@ async function resolveOptions(input) {
|
|
|
2531
2579
|
...flags.gitLfs !== void 0 ? { gitLfs: flags.gitLfs } : {},
|
|
2532
2580
|
...flags.integrations !== void 0 ? { integrations: flags.integrations } : {},
|
|
2533
2581
|
...flags.multiApp !== void 0 ? { multiApp: flags.multiApp } : {},
|
|
2534
|
-
...flags.database !== void 0 ? { database: flags.database } : {}
|
|
2582
|
+
...flags.database !== void 0 ? { database: flags.database } : {},
|
|
2583
|
+
...flags.openapiLayout !== void 0 ? { openapiLayout: flags.openapiLayout } : {}
|
|
2535
2584
|
};
|
|
2536
2585
|
if (flags.yes) {
|
|
2537
2586
|
const full = { ...buildDefaultOptions(projectName), ...merged };
|