@sixthsummit/ship-cli 0.0.0-stage → 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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +45 -2
- package/lib/bin.d.ts +3 -0
- package/lib/bin.d.ts.map +1 -0
- package/lib/bin.js +4 -0
- package/lib/bin.js.map +1 -0
- package/lib/contract.d.ts +27 -0
- package/lib/contract.d.ts.map +1 -0
- package/lib/contract.js +99 -0
- package/lib/contract.js.map +1 -0
- package/lib/create.d.ts +60 -0
- package/lib/create.d.ts.map +1 -0
- package/lib/create.js +212 -0
- package/lib/create.js.map +1 -0
- package/lib/forms.d.ts +10 -0
- package/lib/forms.d.ts.map +1 -0
- package/lib/forms.js +96 -0
- package/lib/forms.js.map +1 -0
- package/lib/graph.d.ts +195 -0
- package/lib/graph.d.ts.map +1 -0
- package/lib/graph.js +596 -0
- package/lib/graph.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +7 -0
- package/lib/index.js.map +1 -0
- package/lib/migration.d.ts +53 -0
- package/lib/migration.d.ts.map +1 -0
- package/lib/migration.js +303 -0
- package/lib/migration.js.map +1 -0
- package/lib/release-manifest.json +23 -0
- package/lib/ship-api.d.ts +38 -0
- package/lib/ship-api.d.ts.map +1 -0
- package/lib/ship-api.js +134 -0
- package/lib/ship-api.js.map +1 -0
- package/package.json +70 -3
- package/templates/operation/.github/pull_request_template.md +41 -0
- package/templates/operation/AGENTS.md +46 -0
- package/templates/operation/README.md +37 -0
- package/templates/operation/_gitignore +5 -0
- package/templates/operation/_gitmessage +12 -0
- package/templates/operation/biome.json +39 -0
- package/templates/operation/package.template.json +21 -0
- package/templates/operation/ship.config.ts +1 -0
- package/templates/operation/src/application.integration.test.ts +15 -0
- package/templates/operation/src/application.test.ts +16 -0
- package/templates/operation/src/application.ts +7 -0
- package/templates/operation/src/modules/system/health.operation.ts +34 -0
- package/templates/operation/src/modules/system/module.ts +10 -0
- package/templates/operation/src/server.ts +13 -0
- package/templates/operation/tsconfig.build.json +11 -0
- package/templates/operation/tsconfig.json +17 -0
- package/templates/operation/vitest.config.ts +20 -0
- package/templates/operation/vitest.integration.config.ts +8 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load an application, legacy route catalog, and disposition mapping from disk
|
|
3
|
+
* and enforce the migration's exactly-once route accounting invariant.
|
|
4
|
+
*
|
|
5
|
+
* @param {{cwd?: string, appPath?: string, catalogPath: string, mappingPath: string}} options
|
|
6
|
+
*/
|
|
7
|
+
export function checkRouteMigration(options: {
|
|
8
|
+
cwd?: string;
|
|
9
|
+
appPath?: string;
|
|
10
|
+
catalogPath: string;
|
|
11
|
+
mappingPath: string;
|
|
12
|
+
}): Promise<Readonly<{
|
|
13
|
+
command: "migrate-routes";
|
|
14
|
+
ok: true;
|
|
15
|
+
appId: string;
|
|
16
|
+
catalogRevision: any;
|
|
17
|
+
routes: number;
|
|
18
|
+
mapped: number;
|
|
19
|
+
removed: number;
|
|
20
|
+
catalog: string;
|
|
21
|
+
mapping: string;
|
|
22
|
+
}>>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate already-loaded migration data. This pure entrypoint is intended for
|
|
25
|
+
* tests and for consumers that generate the catalog in memory.
|
|
26
|
+
*
|
|
27
|
+
* Catalog shape:
|
|
28
|
+
* `{schemaVersion: 1, applicationId, revision, routes: [{id, method, path, source?}]}`
|
|
29
|
+
*
|
|
30
|
+
* Mapping shape:
|
|
31
|
+
* `{schemaVersion: 1, applicationId, catalogRevision, entries: [{legacyRouteId,
|
|
32
|
+
* operationId} | {legacyRouteId, removal: {decisionId, reason}}]}`
|
|
33
|
+
*
|
|
34
|
+
* @param {import("@sixthsummit/ship-core").CompiledApplication<string, readonly import("@sixthsummit/ship-core").AnyModule[]>} application
|
|
35
|
+
* @param {unknown} catalogDocument
|
|
36
|
+
* @param {unknown} mappingDocument
|
|
37
|
+
* @param {{catalogPath?: string, mappingPath?: string}} [options]
|
|
38
|
+
*/
|
|
39
|
+
export function validateRouteMigration(application: import("@sixthsummit/ship-core").CompiledApplication<string, readonly import("@sixthsummit/ship-core").AnyModule[]>, catalogDocument: unknown, mappingDocument: unknown, options?: {
|
|
40
|
+
catalogPath?: string;
|
|
41
|
+
mappingPath?: string;
|
|
42
|
+
}): Readonly<{
|
|
43
|
+
command: "migrate-routes";
|
|
44
|
+
ok: true;
|
|
45
|
+
appId: string;
|
|
46
|
+
catalogRevision: any;
|
|
47
|
+
routes: number;
|
|
48
|
+
mapped: number;
|
|
49
|
+
removed: number;
|
|
50
|
+
catalog: string;
|
|
51
|
+
mapping: string;
|
|
52
|
+
}>;
|
|
53
|
+
//# sourceMappingURL=migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.js"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,6CAFW;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC;;;;;;;;;;IAWpF;AAED;;;;;;;;;;;;;;;GAeG;AACH,oDALW,OAAO,wBAAwB,EAAE,mBAAmB,CAAC,MAAM,EAAE,SAAS,OAAO,wBAAwB,EAAE,SAAS,EAAE,CAAC,mBACnH,OAAO,mBACP,OAAO,YACP;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAC;;;;;;;;;;GAkCtD"}
|
package/lib/migration.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { GRAPH_CLI_EXIT, GraphCliError, loadApplication } from "./graph.js";
|
|
4
|
+
const HTTP_METHODS = new Set(["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]);
|
|
5
|
+
/**
|
|
6
|
+
* Load an application, legacy route catalog, and disposition mapping from disk
|
|
7
|
+
* and enforce the migration's exactly-once route accounting invariant.
|
|
8
|
+
*
|
|
9
|
+
* @param {{cwd?: string, appPath?: string, catalogPath: string, mappingPath: string}} options
|
|
10
|
+
*/
|
|
11
|
+
export async function checkRouteMigration(options) {
|
|
12
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
13
|
+
const catalogPath = resolve(cwd, options.catalogPath);
|
|
14
|
+
const mappingPath = resolve(cwd, options.mappingPath);
|
|
15
|
+
const application = await loadApplication({ cwd, appPath: options.appPath });
|
|
16
|
+
const catalog = await readJsonDocument(catalogPath, "catalog");
|
|
17
|
+
const mapping = await readJsonDocument(mappingPath, "mapping");
|
|
18
|
+
return validateRouteMigration(application, catalog, mapping, { catalogPath, mappingPath });
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate already-loaded migration data. This pure entrypoint is intended for
|
|
22
|
+
* tests and for consumers that generate the catalog in memory.
|
|
23
|
+
*
|
|
24
|
+
* Catalog shape:
|
|
25
|
+
* `{schemaVersion: 1, applicationId, revision, routes: [{id, method, path, source?}]}`
|
|
26
|
+
*
|
|
27
|
+
* Mapping shape:
|
|
28
|
+
* `{schemaVersion: 1, applicationId, catalogRevision, entries: [{legacyRouteId,
|
|
29
|
+
* operationId} | {legacyRouteId, removal: {decisionId, reason}}]}`
|
|
30
|
+
*
|
|
31
|
+
* @param {import("@sixthsummit/ship-core").CompiledApplication<string, readonly import("@sixthsummit/ship-core").AnyModule[]>} application
|
|
32
|
+
* @param {unknown} catalogDocument
|
|
33
|
+
* @param {unknown} mappingDocument
|
|
34
|
+
* @param {{catalogPath?: string, mappingPath?: string}} [options]
|
|
35
|
+
*/
|
|
36
|
+
export function validateRouteMigration(application, catalogDocument, mappingDocument, options = {}) {
|
|
37
|
+
const diagnostics = [];
|
|
38
|
+
const catalog = readCatalog(catalogDocument, diagnostics);
|
|
39
|
+
const mapping = readMapping(mappingDocument, diagnostics);
|
|
40
|
+
if (catalog && mapping) {
|
|
41
|
+
validateDocumentIdentity(application.id, catalog, mapping, diagnostics);
|
|
42
|
+
validateExactlyOnceMapping(application.graph, catalog, mapping, diagnostics);
|
|
43
|
+
}
|
|
44
|
+
if (diagnostics.length > 0) {
|
|
45
|
+
throw new GraphCliError(sortDiagnostics(diagnostics), GRAPH_CLI_EXIT.applicationInvalid);
|
|
46
|
+
}
|
|
47
|
+
const mapped = mapping.entries.filter((entry) => entry.operationId !== undefined).length;
|
|
48
|
+
const removed = mapping.entries.length - mapped;
|
|
49
|
+
return Object.freeze({
|
|
50
|
+
command: "migrate-routes",
|
|
51
|
+
ok: true,
|
|
52
|
+
appId: application.id,
|
|
53
|
+
catalogRevision: catalog.revision,
|
|
54
|
+
routes: catalog.routes.length,
|
|
55
|
+
mapped,
|
|
56
|
+
removed,
|
|
57
|
+
catalog: options.catalogPath ?? "(memory)",
|
|
58
|
+
mapping: options.mappingPath ?? "(memory)",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function readCatalog(document, diagnostics) {
|
|
62
|
+
if (!isObject(document)) {
|
|
63
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", "catalog", "must be an object");
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
if (document.schemaVersion !== 1) {
|
|
67
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", "catalog.schemaVersion", "must equal 1");
|
|
68
|
+
}
|
|
69
|
+
const applicationId = readRequiredString(document.applicationId, "catalog.applicationId", "SHIP_MIGRATION_CATALOG_INVALID", diagnostics);
|
|
70
|
+
const revision = readRequiredString(document.revision, "catalog.revision", "SHIP_MIGRATION_CATALOG_INVALID", diagnostics);
|
|
71
|
+
if (!Array.isArray(document.routes)) {
|
|
72
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", "catalog.routes", "must be an array");
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const routes = [];
|
|
76
|
+
for (const [index, value] of document.routes.entries()) {
|
|
77
|
+
const path = `catalog.routes[${index}]`;
|
|
78
|
+
if (!isObject(value)) {
|
|
79
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", path, "must be an object");
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const id = readRequiredString(value.id, `${path}.id`, "SHIP_MIGRATION_CATALOG_INVALID", diagnostics);
|
|
83
|
+
const method = readRequiredString(value.method, `${path}.method`, "SHIP_MIGRATION_CATALOG_INVALID", diagnostics);
|
|
84
|
+
const routePath = readRequiredString(value.path, `${path}.path`, "SHIP_MIGRATION_CATALOG_INVALID", diagnostics);
|
|
85
|
+
if (method && (!HTTP_METHODS.has(method) || method !== method.toUpperCase())) {
|
|
86
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", `${path}.method`, "must be an uppercase supported HTTP method");
|
|
87
|
+
}
|
|
88
|
+
if (routePath && (!routePath.startsWith("/") || /[?#]/u.test(routePath))) {
|
|
89
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", `${path}.path`, "must be an absolute path without a query string or fragment");
|
|
90
|
+
}
|
|
91
|
+
if (value.source !== undefined && !isNonEmptyString(value.source)) {
|
|
92
|
+
invalid(diagnostics, "SHIP_MIGRATION_CATALOG_INVALID", `${path}.source`, "must be a non-empty string when present");
|
|
93
|
+
}
|
|
94
|
+
if (id && method && HTTP_METHODS.has(method) && routePath?.startsWith("/")) {
|
|
95
|
+
routes.push({ id, method, path: routePath, source: value.source });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
diagnoseDuplicates(routes, (route) => route.id, "SHIP_MIGRATION_LEGACY_ID_DUPLICATE", (key) => `legacy route id ${JSON.stringify(key)} occurs more than once`, "Give every source registration one stable unique id.", diagnostics);
|
|
99
|
+
diagnoseDuplicates(routes, (route) => `${route.method} ${route.path}`, "SHIP_MIGRATION_LEGACY_ROUTE_DUPLICATE", (key) => `legacy method/path ${JSON.stringify(key)} is registered more than once`, "Resolve the duplicate registration or record one approved catalog delta before mapping.", diagnostics);
|
|
100
|
+
return applicationId && revision ? { applicationId, revision, routes } : undefined;
|
|
101
|
+
}
|
|
102
|
+
function readMapping(document, diagnostics) {
|
|
103
|
+
if (!isObject(document)) {
|
|
104
|
+
invalid(diagnostics, "SHIP_MIGRATION_MAPPING_INVALID", "mapping", "must be an object");
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
if (document.schemaVersion !== 1) {
|
|
108
|
+
invalid(diagnostics, "SHIP_MIGRATION_MAPPING_INVALID", "mapping.schemaVersion", "must equal 1");
|
|
109
|
+
}
|
|
110
|
+
const applicationId = readRequiredString(document.applicationId, "mapping.applicationId", "SHIP_MIGRATION_MAPPING_INVALID", diagnostics);
|
|
111
|
+
const catalogRevision = readRequiredString(document.catalogRevision, "mapping.catalogRevision", "SHIP_MIGRATION_MAPPING_INVALID", diagnostics);
|
|
112
|
+
if (!Array.isArray(document.entries)) {
|
|
113
|
+
invalid(diagnostics, "SHIP_MIGRATION_MAPPING_INVALID", "mapping.entries", "must be an array");
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
const entries = [];
|
|
117
|
+
for (const [index, value] of document.entries.entries()) {
|
|
118
|
+
const path = `mapping.entries[${index}]`;
|
|
119
|
+
if (!isObject(value)) {
|
|
120
|
+
invalid(diagnostics, "SHIP_MIGRATION_MAPPING_INVALID", path, "must be an object");
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const legacyRouteId = readRequiredString(value.legacyRouteId, `${path}.legacyRouteId`, "SHIP_MIGRATION_MAPPING_INVALID", diagnostics);
|
|
124
|
+
const hasOperation = isNonEmptyString(value.operationId);
|
|
125
|
+
const hasRemoval = isObject(value.removal);
|
|
126
|
+
if (hasOperation === hasRemoval) {
|
|
127
|
+
invalid(diagnostics, "SHIP_MIGRATION_MAPPING_INVALID", path, "must declare exactly one of operationId or removal");
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if (!legacyRouteId)
|
|
131
|
+
continue;
|
|
132
|
+
if (hasOperation) {
|
|
133
|
+
entries.push({ legacyRouteId, operationId: value.operationId });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const decisionId = readRequiredString(value.removal.decisionId, `${path}.removal.decisionId`, "SHIP_MIGRATION_MAPPING_INVALID", diagnostics);
|
|
137
|
+
const reason = readRequiredString(value.removal.reason, `${path}.removal.reason`, "SHIP_MIGRATION_MAPPING_INVALID", diagnostics);
|
|
138
|
+
if (decisionId && reason)
|
|
139
|
+
entries.push({ legacyRouteId, removal: { decisionId, reason } });
|
|
140
|
+
}
|
|
141
|
+
diagnoseDuplicates(entries, (entry) => entry.legacyRouteId, "SHIP_MIGRATION_DISPOSITION_DUPLICATE", (key) => `legacy route ${JSON.stringify(key)} has more than one disposition`, "Keep exactly one operation mapping or approved removal for each legacy route id.", diagnostics);
|
|
142
|
+
diagnoseDuplicates(entries.filter((entry) => entry.operationId !== undefined), (entry) => entry.operationId, "SHIP_MIGRATION_OPERATION_DUPLICATE", (key) => `target operation ${JSON.stringify(key)} receives more than one legacy route`, "Give every legacy method/path its own operation id or record an approved removal.", diagnostics);
|
|
143
|
+
return applicationId && catalogRevision ? { applicationId, catalogRevision, entries } : undefined;
|
|
144
|
+
}
|
|
145
|
+
function validateDocumentIdentity(applicationId, catalog, mapping, diagnostics) {
|
|
146
|
+
for (const [path, actual] of [
|
|
147
|
+
["catalog.applicationId", catalog.applicationId],
|
|
148
|
+
["mapping.applicationId", mapping.applicationId],
|
|
149
|
+
]) {
|
|
150
|
+
if (actual !== applicationId) {
|
|
151
|
+
diagnostics.push({
|
|
152
|
+
code: "SHIP_MIGRATION_APPLICATION_MISMATCH",
|
|
153
|
+
severity: "error",
|
|
154
|
+
message: `${path} ${JSON.stringify(actual)} does not match target app ${JSON.stringify(applicationId)}`,
|
|
155
|
+
hint: "Generate the catalog and mapping for the application being checked.",
|
|
156
|
+
path,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (mapping.catalogRevision !== catalog.revision) {
|
|
161
|
+
diagnostics.push({
|
|
162
|
+
code: "SHIP_MIGRATION_CATALOG_REVISION_MISMATCH",
|
|
163
|
+
severity: "error",
|
|
164
|
+
message: `mapping revision ${JSON.stringify(mapping.catalogRevision)} does not match catalog revision ${JSON.stringify(catalog.revision)}`,
|
|
165
|
+
hint: "Regenerate or explicitly review the mapping against the candidate-SHA catalog.",
|
|
166
|
+
path: "mapping.catalogRevision",
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function validateExactlyOnceMapping(graph, catalog, mapping, diagnostics) {
|
|
171
|
+
const routesById = new Map(catalog.routes.map((route) => [route.id, route]));
|
|
172
|
+
const entriesByLegacyId = new Map();
|
|
173
|
+
for (const entry of mapping.entries) {
|
|
174
|
+
const entries = entriesByLegacyId.get(entry.legacyRouteId) ?? [];
|
|
175
|
+
entries.push(entry);
|
|
176
|
+
entriesByLegacyId.set(entry.legacyRouteId, entries);
|
|
177
|
+
}
|
|
178
|
+
for (const route of catalog.routes) {
|
|
179
|
+
if (!entriesByLegacyId.has(route.id)) {
|
|
180
|
+
diagnostics.push({
|
|
181
|
+
code: "SHIP_MIGRATION_DISPOSITION_MISSING",
|
|
182
|
+
severity: "error",
|
|
183
|
+
message: `legacy route ${JSON.stringify(route.id)} (${route.method} ${route.path}) has no disposition`,
|
|
184
|
+
hint: "Map it to one operation id or record an approved removal.",
|
|
185
|
+
path: route.id,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const operationsById = new Map(graph.operations.map((operation) => [operation.id, operation]));
|
|
190
|
+
for (const entry of mapping.entries) {
|
|
191
|
+
const route = routesById.get(entry.legacyRouteId);
|
|
192
|
+
if (!route) {
|
|
193
|
+
diagnostics.push({
|
|
194
|
+
code: "SHIP_MIGRATION_LEGACY_UNKNOWN",
|
|
195
|
+
severity: "error",
|
|
196
|
+
message: `mapping references unknown legacy route ${JSON.stringify(entry.legacyRouteId)}`,
|
|
197
|
+
hint: "Use an id from the current candidate-SHA route catalog.",
|
|
198
|
+
path: entry.legacyRouteId,
|
|
199
|
+
});
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (entry.operationId === undefined)
|
|
203
|
+
continue;
|
|
204
|
+
const operation = operationsById.get(entry.operationId);
|
|
205
|
+
if (!operation) {
|
|
206
|
+
diagnostics.push({
|
|
207
|
+
code: "SHIP_MIGRATION_OPERATION_NOT_FOUND",
|
|
208
|
+
severity: "error",
|
|
209
|
+
message: `target operation ${JSON.stringify(entry.operationId)} does not exist`,
|
|
210
|
+
hint: "Use an operation id from the compiled target application graph.",
|
|
211
|
+
operationId: entry.operationId,
|
|
212
|
+
});
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (operation.transport?.kind !== "http" ||
|
|
216
|
+
typeof operation.transport.metadata?.method !== "string" ||
|
|
217
|
+
typeof operation.transport.metadata?.path !== "string") {
|
|
218
|
+
diagnostics.push({
|
|
219
|
+
code: "SHIP_MIGRATION_OPERATION_NOT_HTTP",
|
|
220
|
+
severity: "error",
|
|
221
|
+
message: `target operation ${JSON.stringify(entry.operationId)} has no concrete HTTP method/path`,
|
|
222
|
+
hint: "Map legacy HTTP routes only to operations with an http transport declaration.",
|
|
223
|
+
operationId: entry.operationId,
|
|
224
|
+
});
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (operation.transport.metadata.method !== route.method) {
|
|
228
|
+
diagnostics.push({
|
|
229
|
+
code: "SHIP_MIGRATION_METHOD_MISMATCH",
|
|
230
|
+
severity: "error",
|
|
231
|
+
message: `${entry.operationId} uses ${operation.transport.metadata.method}; legacy route ${entry.legacyRouteId} uses ${route.method}`,
|
|
232
|
+
hint: "Preserve the method or record an approved removal and replacement contract.",
|
|
233
|
+
operationId: entry.operationId,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (operation.transport.metadata.path !== route.path) {
|
|
237
|
+
diagnostics.push({
|
|
238
|
+
code: "SHIP_MIGRATION_PATH_MISMATCH",
|
|
239
|
+
severity: "error",
|
|
240
|
+
message: `${entry.operationId} uses ${operation.transport.metadata.path}; legacy route ${entry.legacyRouteId} uses ${route.path}`,
|
|
241
|
+
hint: "Preserve the exact public path or record an approved removal and replacement contract.",
|
|
242
|
+
operationId: entry.operationId,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
async function readJsonDocument(path, kind) {
|
|
248
|
+
let source;
|
|
249
|
+
try {
|
|
250
|
+
source = await readFile(path, "utf8");
|
|
251
|
+
}
|
|
252
|
+
catch (cause) {
|
|
253
|
+
throw documentError("SHIP_MIGRATION_DOCUMENT_READ_FAILED", `${kind} document could not be read at ${JSON.stringify(path)}`, "Pass a readable JSON document generated for the current migration candidate.", path, cause);
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
return JSON.parse(source);
|
|
257
|
+
}
|
|
258
|
+
catch (cause) {
|
|
259
|
+
throw documentError("SHIP_MIGRATION_DOCUMENT_JSON_INVALID", `${kind} document at ${JSON.stringify(path)} is not valid JSON`, "Regenerate the document; do not hand-repair a partial artifact.", path, cause);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function readRequiredString(value, path, code, diagnostics) {
|
|
263
|
+
if (isNonEmptyString(value))
|
|
264
|
+
return value;
|
|
265
|
+
invalid(diagnostics, code, path, "must be a non-empty string");
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
function diagnoseDuplicates(items, keyOf, code, message, hint, diagnostics) {
|
|
269
|
+
const counts = new Map();
|
|
270
|
+
for (const item of items) {
|
|
271
|
+
const key = keyOf(item);
|
|
272
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
273
|
+
}
|
|
274
|
+
for (const [key, count] of counts) {
|
|
275
|
+
if (count > 1) {
|
|
276
|
+
diagnostics.push({ code, severity: "error", message: message(key), hint, path: key });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function invalid(diagnostics, code, path, requirement) {
|
|
281
|
+
diagnostics.push({
|
|
282
|
+
code,
|
|
283
|
+
severity: "error",
|
|
284
|
+
message: `${path} ${requirement}`,
|
|
285
|
+
hint: "Use the documented schemaVersion 1 migration document shape.",
|
|
286
|
+
path,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function documentError(code, message, hint, path, cause) {
|
|
290
|
+
return new GraphCliError([{ code, severity: "error", message, hint, path }], GRAPH_CLI_EXIT.usageOrLoadError, { cause });
|
|
291
|
+
}
|
|
292
|
+
function sortDiagnostics(diagnostics) {
|
|
293
|
+
return diagnostics.sort((left, right) => [left.code, left.path ?? "", left.operationId ?? "", left.message]
|
|
294
|
+
.join("\0")
|
|
295
|
+
.localeCompare([right.code, right.path ?? "", right.operationId ?? "", right.message].join("\0")));
|
|
296
|
+
}
|
|
297
|
+
function isNonEmptyString(value) {
|
|
298
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
299
|
+
}
|
|
300
|
+
function isObject(value) {
|
|
301
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","sourceRoot":"","sources":["../src/migration.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"packageManager": "pnpm@10.34.6",
|
|
4
|
+
"packages": {
|
|
5
|
+
"@sixthsummit/ship-core": "1.1.1",
|
|
6
|
+
"@sixthsummit/ship-hono": "1.2.0",
|
|
7
|
+
"@sixthsummit/ship-contract": "1.3.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@hono/node-server": "^1.19.14",
|
|
11
|
+
"hono": "4.13.7",
|
|
12
|
+
"zod": "^4.3.6"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@biomejs/biome": "2.3.11",
|
|
16
|
+
"@sixthsummit/ship-cli": "1.2.0",
|
|
17
|
+
"@types/node": "^24.1.0",
|
|
18
|
+
"@vitest/coverage-v8": "^4.1.8",
|
|
19
|
+
"tsx": "^4.20.3",
|
|
20
|
+
"typescript": "^5.9.2",
|
|
21
|
+
"vitest": "^4.1.8"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {{
|
|
4
|
+
* name?: string,
|
|
5
|
+
* description?: string,
|
|
6
|
+
* version?: string,
|
|
7
|
+
* packageJsonPath?: string,
|
|
8
|
+
* cwd?: string,
|
|
9
|
+
* templateDirectory?: string,
|
|
10
|
+
* releaseManifestPath?: string,
|
|
11
|
+
* releaseManifest?: import("./create.js").ScaffoldReleaseManifest,
|
|
12
|
+
* includeCreate?: boolean,
|
|
13
|
+
* install?: (targetDirectory: string) => void
|
|
14
|
+
* }} CliOptions
|
|
15
|
+
*/
|
|
16
|
+
/** @param {Command} program @param {CliOptions} [options] */
|
|
17
|
+
export function registerApplicationCommands(program: Command, options?: CliOptions): Command;
|
|
18
|
+
/**
|
|
19
|
+
* @param {CliOptions} [options]
|
|
20
|
+
* @returns {Command}
|
|
21
|
+
*/
|
|
22
|
+
export function createCli(options?: CliOptions): Command;
|
|
23
|
+
/** @param {string[]} [argv] */
|
|
24
|
+
export function runCli(argv?: string[]): Promise<void>;
|
|
25
|
+
export type CliOptions = {
|
|
26
|
+
name?: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
version?: string;
|
|
29
|
+
packageJsonPath?: string;
|
|
30
|
+
cwd?: string;
|
|
31
|
+
templateDirectory?: string;
|
|
32
|
+
releaseManifestPath?: string;
|
|
33
|
+
releaseManifest?: import("./create.js").ScaffoldReleaseManifest;
|
|
34
|
+
includeCreate?: boolean;
|
|
35
|
+
install?: (targetDirectory: string) => void;
|
|
36
|
+
};
|
|
37
|
+
import { Command } from "commander";
|
|
38
|
+
//# sourceMappingURL=ship-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship-api.d.ts","sourceRoot":"","sources":["../src/ship-api.js"],"names":[],"mappings":";AAkBA;;;;;;;;;;;;;GAaG;AAEH,6DAA6D;AAC7D,qDADY,OAAO,YAAkB,UAAU,WA6H9C;AAED;;;GAGG;AACH,oCAHW,UAAU,GACR,OAAO,CAWnB;AAED,+BAA+B;AAC/B,8BADY,MAAM,EAAE,iBAGnB;yBA/JY;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,OAAO,aAAa,EAAE,uBAAuB,CAAC;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C;wBAzBoB,WAAW"}
|
package/lib/ship-api.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { generateContractArtifacts } from "./contract.js";
|
|
7
|
+
import { createOperationProject, loadScaffoldReleaseManifest } from "./create.js";
|
|
8
|
+
import { affectedApplication, checkApplication, inspectApplication, runGraphCommand, } from "./graph.js";
|
|
9
|
+
import { checkRouteMigration } from "./migration.js";
|
|
10
|
+
const packageDirectory = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {{
|
|
13
|
+
* name?: string,
|
|
14
|
+
* description?: string,
|
|
15
|
+
* version?: string,
|
|
16
|
+
* packageJsonPath?: string,
|
|
17
|
+
* cwd?: string,
|
|
18
|
+
* templateDirectory?: string,
|
|
19
|
+
* releaseManifestPath?: string,
|
|
20
|
+
* releaseManifest?: import("./create.js").ScaffoldReleaseManifest,
|
|
21
|
+
* includeCreate?: boolean,
|
|
22
|
+
* install?: (targetDirectory: string) => void
|
|
23
|
+
* }} CliOptions
|
|
24
|
+
*/
|
|
25
|
+
/** @param {Command} program @param {CliOptions} [options] */
|
|
26
|
+
export function registerApplicationCommands(program, options = {}) {
|
|
27
|
+
if (options.includeCreate !== false) {
|
|
28
|
+
program
|
|
29
|
+
.command("create <project-name>")
|
|
30
|
+
.description("Create a tested operation-native Ship application")
|
|
31
|
+
.option("--current-dir", "Write into the current empty directory")
|
|
32
|
+
.option("--skip-install", "Do not install dependencies")
|
|
33
|
+
.action(async (projectName, commandOptions) => {
|
|
34
|
+
try {
|
|
35
|
+
const releaseManifest = options.releaseManifest ??
|
|
36
|
+
(await loadScaffoldReleaseManifest(options.releaseManifestPath ?? join(packageDirectory, "lib/release-manifest.json")));
|
|
37
|
+
const result = await createOperationProject({
|
|
38
|
+
projectName,
|
|
39
|
+
cwd: options.cwd,
|
|
40
|
+
currentDirectory: commandOptions.currentDir,
|
|
41
|
+
skipInstall: commandOptions.skipInstall,
|
|
42
|
+
templateDirectory: options.templateDirectory ?? join(packageDirectory, "templates/operation"),
|
|
43
|
+
releaseManifest,
|
|
44
|
+
install: options.install,
|
|
45
|
+
});
|
|
46
|
+
process.stdout.write(`${result.packageName} created at ${result.targetDirectory}${result.installed ? "" : " (install skipped)"}\n`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
process.stderr.write(`ship-api create: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
50
|
+
process.exitCode = 2;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
program
|
|
55
|
+
.command("check")
|
|
56
|
+
.description("Compile and validate the application graph")
|
|
57
|
+
.option("-a, --app <path>", "Application module with a named `app` export", "ship.config.ts")
|
|
58
|
+
.option("--format <format>", "Output format: human or json", "human")
|
|
59
|
+
.option("--emit [path]", "Write the deterministic graph JSON")
|
|
60
|
+
.action(async (options) => {
|
|
61
|
+
process.exitCode = await runGraphCommand(() => checkApplication({
|
|
62
|
+
appPath: options.app,
|
|
63
|
+
emit: options.emit === true ? ".ship/graph.json" : options.emit,
|
|
64
|
+
}), options);
|
|
65
|
+
});
|
|
66
|
+
program
|
|
67
|
+
.command("inspect <kind> [id]")
|
|
68
|
+
.description("Inspect an app, module, operation, provider, channel, or job graph node")
|
|
69
|
+
.option("-a, --app <path>", "Application module with a named `app` export", "ship.config.ts")
|
|
70
|
+
.option("--format <format>", "Output format: human or json", "human")
|
|
71
|
+
.action(async (kind, id, options) => {
|
|
72
|
+
process.exitCode = await runGraphCommand(() => inspectApplication(kind, id, { appPath: options.app }), options);
|
|
73
|
+
});
|
|
74
|
+
program
|
|
75
|
+
.command("affected <kind> <id>")
|
|
76
|
+
.description("Show graph surfaces affected by a module, operation, provider, channel, or job")
|
|
77
|
+
.option("-a, --app <path>", "Application module with a named `app` export", "ship.config.ts")
|
|
78
|
+
.option("--format <format>", "Output format: human or json", "human")
|
|
79
|
+
.action(async (kind, id, options) => {
|
|
80
|
+
process.exitCode = await runGraphCommand(() => affectedApplication(kind, id, { appPath: options.app }), options);
|
|
81
|
+
});
|
|
82
|
+
program
|
|
83
|
+
.command("contract")
|
|
84
|
+
.description("Emit deterministic client-contract and OpenAPI artifacts")
|
|
85
|
+
.option("-a, --app <path>", "Application module with a named `app` export", "ship.config.ts")
|
|
86
|
+
.option("--out <path>", "Client contract output", ".ship/contract.json")
|
|
87
|
+
.option("--typescript <path>", "Browser-safe TypeScript contract output", ".ship/contract.ts")
|
|
88
|
+
.option("--openapi <path>", "OpenAPI output", ".ship/openapi.json")
|
|
89
|
+
.option("--openapi-title <title>", "OpenAPI document title")
|
|
90
|
+
.option("--api-version <version>", "Advertised API version", "0.0.0")
|
|
91
|
+
.option("--format <format>", "Output format: human or json", "human")
|
|
92
|
+
.action(async (options) => {
|
|
93
|
+
process.exitCode = await runGraphCommand(() => generateContractArtifacts({
|
|
94
|
+
appPath: options.app,
|
|
95
|
+
out: options.out,
|
|
96
|
+
typescript: options.typescript,
|
|
97
|
+
openapi: options.openapi,
|
|
98
|
+
title: options.openapiTitle,
|
|
99
|
+
version: options.apiVersion,
|
|
100
|
+
}), options);
|
|
101
|
+
});
|
|
102
|
+
program
|
|
103
|
+
.command("migrate-routes")
|
|
104
|
+
.description("Check an exactly-once legacy-route to operation mapping")
|
|
105
|
+
.requiredOption("--catalog <path>", "Legacy route catalog JSON")
|
|
106
|
+
.requiredOption("--mapping <path>", "Legacy route disposition JSON")
|
|
107
|
+
.option("-a, --app <path>", "Application module with a named `app` export", "ship.config.ts")
|
|
108
|
+
.option("--format <format>", "Output format: human or json", "human")
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
process.exitCode = await runGraphCommand(() => checkRouteMigration({
|
|
111
|
+
appPath: options.app,
|
|
112
|
+
catalogPath: options.catalog,
|
|
113
|
+
mappingPath: options.mapping,
|
|
114
|
+
}), options);
|
|
115
|
+
});
|
|
116
|
+
return program;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* @param {CliOptions} [options]
|
|
120
|
+
* @returns {Command}
|
|
121
|
+
*/
|
|
122
|
+
export function createCli(options = {}) {
|
|
123
|
+
const packageJson = JSON.parse(readFileSync(options.packageJsonPath ?? join(packageDirectory, "package.json"), "utf8"));
|
|
124
|
+
const program = new Command()
|
|
125
|
+
.name(options.name ?? "ship-api")
|
|
126
|
+
.description(options.description ?? "Inspect and project a compiled Ship application")
|
|
127
|
+
.version(options.version ?? packageJson.version);
|
|
128
|
+
return registerApplicationCommands(program, options);
|
|
129
|
+
}
|
|
130
|
+
/** @param {string[]} [argv] */
|
|
131
|
+
export async function runCli(argv = process.argv) {
|
|
132
|
+
await createCli().parseAsync(argv);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=ship-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ship-api.js","sourceRoot":"","sources":["../src/ship-api.js"],"names":[],"mappings":"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"}
|