@kosdev-code/kos-codegen-core 0.1.0-next.861 → 0.1.0-next.864
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/index.d.ts +1 -1
- package/index.d.ts.map +1 -1
- package/index.js +391 -23
- package/index.js.map +1 -1
- package/index.mjs +391 -23
- package/index.mjs.map +1 -1
- package/lib/generators/augment/model-mocks.d.ts +47 -0
- package/lib/generators/augment/model-mocks.d.ts.map +1 -0
- package/lib/generators/augment/ts-toolkit.d.ts +7 -0
- package/lib/generators/augment/ts-toolkit.d.ts.map +1 -1
- package/lib/generators/index.d.ts +2 -2
- package/lib/generators/index.d.ts.map +1 -1
- package/lib/generators/member-mutators/add-service-request.d.ts +71 -0
- package/lib/generators/member-mutators/add-service-request.d.ts.map +1 -1
- package/lib/generators/member-mutators/index.d.ts +1 -1
- package/lib/generators/member-mutators/index.d.ts.map +1 -1
- package/lib/generators/service-catalog.d.ts +12 -0
- package/lib/generators/service-catalog.d.ts.map +1 -1
- package/package.json +2 -2
package/index.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export { getCurrentDirectoryName, getProject, getKosProjectConfiguration, getKos
|
|
|
13
13
|
export type { KosModelConfiguration, KosProjectConfiguration, } from './lib/kos-config';
|
|
14
14
|
export { getTemplateDir } from './lib/template-resolver';
|
|
15
15
|
export { generateSplashProject, generateInit, generatePolyglotWorkspace, ensureJavaAggregatorPom, finalizeArchetypeModule, addJavaArtifactToManifests, syncCiManifests, discoverUiArtifacts, discoverJavaArtifacts, buildKabTargets, buildSbomTarget, listServiceCatalog, resolveKabPath, KAB_OUTPUT_DIR, KAB_OUTPUT_PATH, UPDATE_RELEASE_VERSION_SCRIPT, UPDATE_RELEASE_VERSION_SCRIPT_PATH, normalizeOptions, appendBarrelExport, updateModelIndex, generateHook, generateContext, generateContainerModel, generateCompanionModel, generateModel, addFutureToModel, addContainerSupportToModel, addModelEffectToModel, addDependencyToModel, addChildToModel, addTopicHandlerToModel, addConfigPropertyToModel, addServiceRequestToModel, addPropertyToModel, addComputedToModel, validateModel, describeModel, lookupSdkType, resolveModelFilePath, generateComponent, PLUGIN_TYPES, CONTRIBUTION_TYPE_MAP, LOCALIZED_PLUGIN_TYPES, KOS_JSON_PATHS, PluginHandlerFactory, BasePluginHandler, KosConfigBuilder, ValidationError, } from './lib/generators';
|
|
16
|
-
export type { SplashProjectOptions, KosInitOptions, KabTargetsOptions, KabTargetDefinition, PolyglotWorkspaceOptions, PolyglotWorkspaceResult, EnsureJavaAggregatorOptions, FinalizeArchetypeModuleOptions, AddJavaArtifactOptions, CiSyncOptions, CiSyncResult, CiSyncManifestResult, DiscoveredArtifact, KosBaseGeneratorOptions, NormalizedOptions, HookOptions, ContextOptions, ContainerModelOptions, CompanionModelOptions, ModelOptions, GenerateModelParams, AddFutureToModelOptions, NormalizedAddFutureToModelOptions, AddContainerSupportOptions, AddModelEffectOptions, AddDependencyOptions, AddChildOptions, ChildShape, AddTopicHandlerOptions, AddConfigPropertyOptions, AddServiceRequestOptions, AddPropertyOptions, AddComputedOptions, ValidateModelOptions, ValidationFinding, ValidationResult, DescribeModelOptions, DescribedMember, ModelDescription, ModelFileQuery, LookupSdkTypeOptions, SdkSymbolDeclaration, SdkTypeLookupResult, ComponentOptions, NormalizedComponentOptions, PluginConfiguration, PluginContribution, ExperienceConfig, PluginType, PluginHandler, } from './lib/generators';
|
|
16
|
+
export type { SplashProjectOptions, KosInitOptions, KabTargetsOptions, KabTargetDefinition, PolyglotWorkspaceOptions, PolyglotWorkspaceResult, EnsureJavaAggregatorOptions, FinalizeArchetypeModuleOptions, AddJavaArtifactOptions, CiSyncOptions, CiSyncResult, CiSyncManifestResult, DiscoveredArtifact, KosBaseGeneratorOptions, NormalizedOptions, HookOptions, ContextOptions, ContainerModelOptions, CompanionModelOptions, ModelOptions, GenerateModelParams, AddFutureToModelOptions, NormalizedAddFutureToModelOptions, AddContainerSupportOptions, AddModelEffectOptions, AddDependencyOptions, AddChildOptions, ChildShape, AddTopicHandlerOptions, AddConfigPropertyOptions, AddServiceRequestOptions, AddServiceRequestResult, ServiceRequestMockMode, UntypedEndpointDetails, UntypedEndpointError, AddPropertyOptions, AddComputedOptions, ValidateModelOptions, ValidationFinding, ValidationResult, DescribeModelOptions, DescribedMember, ModelDescription, ModelFileQuery, LookupSdkTypeOptions, SdkSymbolDeclaration, SdkTypeLookupResult, ComponentOptions, NormalizedComponentOptions, PluginConfiguration, PluginContribution, ExperienceConfig, PluginType, PluginHandler, } from './lib/generators';
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/kos-codegen-core/src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../packages/kos-codegen-core/src/index.ts"],"names":[],"mappings":"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"}
|
package/index.js
CHANGED
|
@@ -1088,7 +1088,8 @@ function ensureConstCatalogEntry(sourceFile, spec) {
|
|
|
1088
1088
|
}
|
|
1089
1089
|
literal.addPropertyAssignment({
|
|
1090
1090
|
name: spec.key,
|
|
1091
|
-
initializer: spec.initializer
|
|
1091
|
+
initializer: spec.initializer,
|
|
1092
|
+
leadingTrivia: spec.leadingTrivia
|
|
1092
1093
|
});
|
|
1093
1094
|
return { key: spec.key, created: true };
|
|
1094
1095
|
}
|
|
@@ -1106,7 +1107,8 @@ function ensureConstCatalogEntry(sourceFile, spec) {
|
|
|
1106
1107
|
}
|
|
1107
1108
|
literal.addPropertyAssignment({
|
|
1108
1109
|
name: spec.key,
|
|
1109
|
-
initializer: spec.initializer
|
|
1110
|
+
initializer: spec.initializer,
|
|
1111
|
+
leadingTrivia: spec.leadingTrivia
|
|
1110
1112
|
});
|
|
1111
1113
|
return { key: spec.key, created: true };
|
|
1112
1114
|
}
|
|
@@ -1115,7 +1117,8 @@ function ensureExportedTypeAlias(sourceFile, spec) {
|
|
|
1115
1117
|
sourceFile.addTypeAlias({
|
|
1116
1118
|
name: spec.name,
|
|
1117
1119
|
type: spec.type,
|
|
1118
|
-
isExported: true
|
|
1120
|
+
isExported: true,
|
|
1121
|
+
docs: spec.docs ? [spec.docs] : void 0
|
|
1119
1122
|
});
|
|
1120
1123
|
return true;
|
|
1121
1124
|
}
|
|
@@ -1145,6 +1148,7 @@ function addDecoratedMethod(cls, spec) {
|
|
|
1145
1148
|
name: spec.name,
|
|
1146
1149
|
isAsync: spec.isAsync,
|
|
1147
1150
|
returnType: spec.returnType,
|
|
1151
|
+
docs: spec.docs ? [spec.docs] : void 0,
|
|
1148
1152
|
parameters: spec.parameters?.map((p) => {
|
|
1149
1153
|
return { name: p.name, type: p.type, hasQuestionToken: p.optional };
|
|
1150
1154
|
}),
|
|
@@ -1152,6 +1156,7 @@ function addDecoratedMethod(cls, spec) {
|
|
|
1152
1156
|
decorators: [
|
|
1153
1157
|
{
|
|
1154
1158
|
name: spec.decoratorName,
|
|
1159
|
+
typeArguments: spec.decoratorTypeArgs,
|
|
1155
1160
|
arguments: spec.decoratorArgsText ? [spec.decoratorArgsText] : []
|
|
1156
1161
|
}
|
|
1157
1162
|
]
|
|
@@ -1234,17 +1239,28 @@ function listServiceCatalog(codegenFs, query, projects) {
|
|
|
1234
1239
|
app,
|
|
1235
1240
|
version,
|
|
1236
1241
|
serviceModulePath: posix,
|
|
1237
|
-
operations: readOperations(codegenFs, openapiPath)
|
|
1242
|
+
operations: readOperations(codegenFs, openapiPath) ?? []
|
|
1238
1243
|
});
|
|
1239
1244
|
}
|
|
1240
1245
|
return entries.sort(
|
|
1241
1246
|
(a, b) => a.app.localeCompare(b.app) || a.version.localeCompare(b.version)
|
|
1242
1247
|
);
|
|
1243
1248
|
}
|
|
1249
|
+
function readServiceModuleOperations(codegenFs, serviceModuleFile) {
|
|
1250
|
+
const moduleFile = serviceModuleFile.endsWith(".ts") ? serviceModuleFile : `${serviceModuleFile}.ts`;
|
|
1251
|
+
const posix = moduleFile.split(path__namespace.sep).join("/");
|
|
1252
|
+
const openapiPath = posix.replace(/service\.ts$/, "openapi.d.ts");
|
|
1253
|
+
for (const candidate of [openapiPath, posix]) {
|
|
1254
|
+
if (!codegenFs.exists(candidate)) continue;
|
|
1255
|
+
const operations = readOperations(codegenFs, candidate);
|
|
1256
|
+
if (operations) return operations;
|
|
1257
|
+
}
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1244
1260
|
function readOperations(codegenFs, openapiPath) {
|
|
1245
1261
|
return readSourceFile(codegenFs, openapiPath, (sf) => {
|
|
1246
1262
|
const paths = sf.getInterface("paths");
|
|
1247
|
-
if (!paths) return
|
|
1263
|
+
if (!paths) return null;
|
|
1248
1264
|
const operations = [];
|
|
1249
1265
|
for (const pathProp of paths.getProperties()) {
|
|
1250
1266
|
const servicePath = unquote(pathProp.getName());
|
|
@@ -1766,7 +1782,7 @@ function servicesFilePathFor(modelFilePath, modelBase) {
|
|
|
1766
1782
|
`${modelBase}-services.ts`
|
|
1767
1783
|
);
|
|
1768
1784
|
}
|
|
1769
|
-
function header(modelBase) {
|
|
1785
|
+
function header$1(modelBase) {
|
|
1770
1786
|
return `/**
|
|
1771
1787
|
* Service layer for the ${modelBase} model: the endpoints it calls and the
|
|
1772
1788
|
* types derived from them. Standalone service functions for callers outside a
|
|
@@ -1777,7 +1793,7 @@ function header(modelBase) {
|
|
|
1777
1793
|
function ensureServicesModule(codegenFs, modelFilePath, modelBase) {
|
|
1778
1794
|
const servicesFilePath = servicesFilePathFor(modelFilePath, modelBase);
|
|
1779
1795
|
if (!codegenFs.exists(servicesFilePath)) {
|
|
1780
|
-
codegenFs.write(servicesFilePath, header(modelBase));
|
|
1796
|
+
codegenFs.write(servicesFilePath, header$1(modelBase));
|
|
1781
1797
|
}
|
|
1782
1798
|
const barrelPath = path__namespace.join(path__namespace.dirname(servicesFilePath), "index.ts");
|
|
1783
1799
|
if (!codegenFs.exists(barrelPath)) {
|
|
@@ -2537,6 +2553,154 @@ function addComputedToModel(codegenFs, options, projects) {
|
|
|
2537
2553
|
});
|
|
2538
2554
|
return { modelFilePath };
|
|
2539
2555
|
}
|
|
2556
|
+
function mocksFilePathFor(modelFilePath, modelBase) {
|
|
2557
|
+
return path__namespace.join(
|
|
2558
|
+
path__namespace.dirname(modelFilePath),
|
|
2559
|
+
"mocks",
|
|
2560
|
+
`${modelBase}-mocks.ts`
|
|
2561
|
+
);
|
|
2562
|
+
}
|
|
2563
|
+
function mockRegisterFunctionName(modelBase) {
|
|
2564
|
+
return `register${pascalCase(modelBase)}Mocks`;
|
|
2565
|
+
}
|
|
2566
|
+
function toMockRoutePattern(servicePath) {
|
|
2567
|
+
return servicePath.replace(/\{([^}]+)\}/g, ":$1");
|
|
2568
|
+
}
|
|
2569
|
+
function mockRouteCall(method, pattern, body) {
|
|
2570
|
+
const shorthand = {
|
|
2571
|
+
get: "get",
|
|
2572
|
+
post: "post",
|
|
2573
|
+
put: "put",
|
|
2574
|
+
delete: "del"
|
|
2575
|
+
};
|
|
2576
|
+
const fn = shorthand[method];
|
|
2577
|
+
return fn ? `KosMock.${fn}(${JSON.stringify(pattern)}, ${body});` : `KosMock.route(${JSON.stringify(method.toUpperCase())}, ${JSON.stringify(
|
|
2578
|
+
pattern
|
|
2579
|
+
)}, ${body});`;
|
|
2580
|
+
}
|
|
2581
|
+
function header(modelBase, registerFn) {
|
|
2582
|
+
return `/**
|
|
2583
|
+
* KosMock routes for the ${modelBase} model's PROVISIONAL endpoints — the ones
|
|
2584
|
+
* this project's generated OpenAPI types do not declare.
|
|
2585
|
+
*
|
|
2586
|
+
* NOTHING IMPORTS THIS FILE. Call \`${registerFn}()\` from the app's dev entry,
|
|
2587
|
+
* gated so it cannot run in a production build (\`import.meta.env.DEV\`, a
|
|
2588
|
+
* dev-only entry module, or behind your own switch). Registering a route enables
|
|
2589
|
+
* KosMock, and a mock that shipped would shadow the real endpoint once it exists.
|
|
2590
|
+
*
|
|
2591
|
+
* Unmatched requests still pass through to the real device (KosMock's hybrid
|
|
2592
|
+
* default), so these routes shadow only the paths named below. Every mocked
|
|
2593
|
+
* response carries the \`kos-mocked: true\` wire header, so mock-fed data is
|
|
2594
|
+
* identifiable in devtools.
|
|
2595
|
+
*
|
|
2596
|
+
* DELETE THIS FILE once every endpoint below is in the generated types.
|
|
2597
|
+
*/
|
|
2598
|
+
`;
|
|
2599
|
+
}
|
|
2600
|
+
function ensureMockRoute(codegenFs, options) {
|
|
2601
|
+
const mocksFilePath = mocksFilePathFor(
|
|
2602
|
+
options.modelFilePath,
|
|
2603
|
+
options.modelBase
|
|
2604
|
+
);
|
|
2605
|
+
const registerFunction = mockRegisterFunctionName(options.modelBase);
|
|
2606
|
+
const routePattern = toMockRoutePattern(options.servicePath);
|
|
2607
|
+
const sampleName = `SAMPLE_${constantCase(dashCase(options.endpointKey))}`;
|
|
2608
|
+
const samplePlaceholder = !options.sampleText;
|
|
2609
|
+
if (!codegenFs.exists(mocksFilePath)) {
|
|
2610
|
+
codegenFs.write(mocksFilePath, header(options.modelBase, registerFunction));
|
|
2611
|
+
}
|
|
2612
|
+
const sdkSpecifier = options.sdkModuleSpecifier.startsWith(".") ? `../${options.sdkModuleSpecifier}` : options.sdkModuleSpecifier;
|
|
2613
|
+
let routeCreated = false;
|
|
2614
|
+
transformSourceFile(codegenFs, mocksFilePath, (sf) => {
|
|
2615
|
+
ensureNamedImport(sf, sdkSpecifier, [{ name: "KosMock" }]);
|
|
2616
|
+
ensureNamedImport(sf, "../services", [
|
|
2617
|
+
{ name: options.rawAlias, isTypeOnly: true }
|
|
2618
|
+
]);
|
|
2619
|
+
ensureSample(sf, {
|
|
2620
|
+
name: sampleName,
|
|
2621
|
+
type: options.rawAlias,
|
|
2622
|
+
servicePath: options.servicePath,
|
|
2623
|
+
method: options.method,
|
|
2624
|
+
sampleText: options.sampleText
|
|
2625
|
+
});
|
|
2626
|
+
const statement = mockRouteCall(
|
|
2627
|
+
options.method,
|
|
2628
|
+
routePattern,
|
|
2629
|
+
`{ data: ${sampleName} }`
|
|
2630
|
+
);
|
|
2631
|
+
routeCreated = ensureRegisteredRoute(sf, {
|
|
2632
|
+
registerFunction,
|
|
2633
|
+
modelBase: options.modelBase,
|
|
2634
|
+
statement,
|
|
2635
|
+
// Matching on the pattern literal alone would collide across methods.
|
|
2636
|
+
marker: `${options.method.toUpperCase()} ${routePattern}`,
|
|
2637
|
+
matches: (existing) => existing.includes(JSON.stringify(routePattern)) && existing.includes(shorthandOrMethod(options.method))
|
|
2638
|
+
});
|
|
2639
|
+
});
|
|
2640
|
+
return {
|
|
2641
|
+
mocksFilePath,
|
|
2642
|
+
registerFunction,
|
|
2643
|
+
routePattern,
|
|
2644
|
+
sampleName,
|
|
2645
|
+
routeCreated,
|
|
2646
|
+
samplePlaceholder
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
function shorthandOrMethod(method) {
|
|
2650
|
+
const shorthand = {
|
|
2651
|
+
get: "KosMock.get(",
|
|
2652
|
+
post: "KosMock.post(",
|
|
2653
|
+
put: "KosMock.put(",
|
|
2654
|
+
delete: "KosMock.del("
|
|
2655
|
+
};
|
|
2656
|
+
return shorthand[method] ?? `"${method.toUpperCase()}"`;
|
|
2657
|
+
}
|
|
2658
|
+
function ensureSample(sf, spec) {
|
|
2659
|
+
if (sf.getVariableDeclaration(spec.name)) return;
|
|
2660
|
+
const lines = [
|
|
2661
|
+
`Sample payload for \`${spec.method.toUpperCase()} ${spec.servicePath}\` — the`,
|
|
2662
|
+
"UNWRAPPED `data` payload, i.e. exactly what the transform receives."
|
|
2663
|
+
];
|
|
2664
|
+
if (!spec.sampleText) {
|
|
2665
|
+
lines.push(
|
|
2666
|
+
"",
|
|
2667
|
+
"TODO: replace the placeholder with something the backend would actually",
|
|
2668
|
+
"serve. Until then the route answers with nothing and the transform is",
|
|
2669
|
+
"never exercised."
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
const docs = lines.join("\n");
|
|
2673
|
+
sf.addVariableStatement({
|
|
2674
|
+
isExported: true,
|
|
2675
|
+
declarationKind: tsMorph.VariableDeclarationKind.Const,
|
|
2676
|
+
docs: [docs],
|
|
2677
|
+
declarations: [
|
|
2678
|
+
{
|
|
2679
|
+
name: spec.name,
|
|
2680
|
+
type: spec.type,
|
|
2681
|
+
initializer: spec.sampleText ?? `null as unknown as ${spec.type}`
|
|
2682
|
+
}
|
|
2683
|
+
]
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2686
|
+
function ensureRegisteredRoute(sf, spec) {
|
|
2687
|
+
let fn = sf.getFunction(spec.registerFunction);
|
|
2688
|
+
if (!fn) {
|
|
2689
|
+
fn = sf.addFunction({
|
|
2690
|
+
name: spec.registerFunction,
|
|
2691
|
+
isExported: true,
|
|
2692
|
+
returnType: "void",
|
|
2693
|
+
docs: [
|
|
2694
|
+
`Arm the ${spec.modelBase} model's provisional endpoints. Call this from a dev-only entry point — never from code that ships.`
|
|
2695
|
+
]
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
const already = fn.getStatements().some((statement) => spec.matches(statement.getText()));
|
|
2699
|
+
if (already) return false;
|
|
2700
|
+
fn.addStatements(`// ${spec.marker}
|
|
2701
|
+
${spec.statement}`);
|
|
2702
|
+
return true;
|
|
2703
|
+
}
|
|
2540
2704
|
const SERVICE_MODULE_RE = /\/utils\/services\/.*\/service\.ts$/;
|
|
2541
2705
|
function findServiceModules(codegenFs, sourceRoot) {
|
|
2542
2706
|
return codegenFs.listFiles(sourceRoot).filter((f) => SERVICE_MODULE_RE.test(f.split(path__namespace.sep).join("/")));
|
|
@@ -2561,10 +2725,23 @@ function assertServiceModuleAcceptsTransform(codegenFs, serviceModuleFile, model
|
|
|
2561
2725
|
`${file} predates the transform-aware service layer (EndpointCtx takes ${typeParams} type parameter). Run \`kosui api:generate --project ${modelProject} --helpers-only\` to refresh the helper layer in place (no spec fetch, openapi.d.ts untouched), then add the service request.`
|
|
2562
2726
|
);
|
|
2563
2727
|
}
|
|
2728
|
+
function assertServiceModuleAcceptsProvisional(codegenFs, serviceModuleFile, modelProject) {
|
|
2729
|
+
const file = `${serviceModuleFile}.ts`;
|
|
2730
|
+
if (!codegenFs.exists(file)) return;
|
|
2731
|
+
const declared = readSourceFile(
|
|
2732
|
+
codegenFs,
|
|
2733
|
+
file,
|
|
2734
|
+
(sf) => Boolean(sf.getFunction("provisionalServiceRequest"))
|
|
2735
|
+
);
|
|
2736
|
+
if (declared) return;
|
|
2737
|
+
throw new Error(
|
|
2738
|
+
`${file} has no \`provisionalServiceRequest\` — the helper layer predates provisional endpoints. Run \`kosui api:generate --project ${modelProject} --helpers-only\` to refresh it in place (no spec fetch, openapi.d.ts untouched), then add the service request.`
|
|
2739
|
+
);
|
|
2740
|
+
}
|
|
2564
2741
|
function sameEndpoint(existing, candidate) {
|
|
2565
2742
|
const args = (text) => {
|
|
2566
2743
|
const match = text.match(
|
|
2567
|
-
/^endpoint\s*\(\s*(['"])(.*?)\1\s*,\s*(['"])(.*?)\3\s*,?\s*\)$/
|
|
2744
|
+
/^endpoint\s*\(\s*(['"])(.*?)\1(?:\s+as\s+ApiPath)?\s*,\s*(['"])(.*?)\3\s*,?\s*\)$/
|
|
2568
2745
|
);
|
|
2569
2746
|
return match ? [match[2], match[4].toLowerCase()] : null;
|
|
2570
2747
|
};
|
|
@@ -2572,6 +2749,104 @@ function sameEndpoint(existing, candidate) {
|
|
|
2572
2749
|
const b = args(candidate.trim());
|
|
2573
2750
|
return !!a && !!b && a[0] === b[0] && a[1] === b[1];
|
|
2574
2751
|
}
|
|
2752
|
+
function editDistance(a, b) {
|
|
2753
|
+
let previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
2754
|
+
for (let i = 1; i <= a.length; i++) {
|
|
2755
|
+
const current = [i];
|
|
2756
|
+
for (let j = 1; j <= b.length; j++) {
|
|
2757
|
+
current[j] = Math.min(
|
|
2758
|
+
previous[j] + 1,
|
|
2759
|
+
current[j - 1] + 1,
|
|
2760
|
+
previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2763
|
+
previous = current;
|
|
2764
|
+
}
|
|
2765
|
+
return previous[b.length];
|
|
2766
|
+
}
|
|
2767
|
+
const NEAREST_SHOWN = 5;
|
|
2768
|
+
function provisionalEntryComment(servicePath, method, catalogName) {
|
|
2769
|
+
return `/**
|
|
2770
|
+
* PROVISIONAL — \`${method.toUpperCase()} ${servicePath}\` is NOT in this project's
|
|
2771
|
+
* generated OpenAPI types. \`as ApiPath\` is standing in for a \`paths\` entry that
|
|
2772
|
+
* does not exist, so nothing about this endpoint is checked against a spec and
|
|
2773
|
+
* its response cannot be derived from one. Do not read this as a real endpoint.
|
|
2774
|
+
*
|
|
2775
|
+
* WHEN THE ENDPOINT LANDS:
|
|
2776
|
+
* 1. regenerate this project's API types (\`kosui api:generate\`)
|
|
2777
|
+
* 2. delete \` as ApiPath\` from the entry below
|
|
2778
|
+
* 3. point the endpoint's \`…Raw\` alias at
|
|
2779
|
+
* \`EndpointResponse<typeof ${catalogName}.…>\`
|
|
2780
|
+
* 4. swap \`provisionalServiceRequest\` for \`serviceRequest\` in the model
|
|
2781
|
+
* 5. delete the model's \`mocks/\` module
|
|
2782
|
+
* 6. KEEP the transform — it is real code and survives all of the above
|
|
2783
|
+
*/
|
|
2784
|
+
`;
|
|
2785
|
+
}
|
|
2786
|
+
function provisionalMethodDocs(servicePath, method) {
|
|
2787
|
+
return [
|
|
2788
|
+
`PROVISIONAL — \`${method.toUpperCase()} ${servicePath}\` is not in the`,
|
|
2789
|
+
"generated OpenAPI types, so this request is served by a KosMock route, not",
|
|
2790
|
+
"by the device. The feature it backs is NOT complete: report the missing",
|
|
2791
|
+
"endpoint rather than treating this as finished.",
|
|
2792
|
+
"",
|
|
2793
|
+
"See the endpoint's entry in `./services` for what to undo when it lands."
|
|
2794
|
+
].join("\n");
|
|
2795
|
+
}
|
|
2796
|
+
function rawTypeDocs(servicePath, method, rawType) {
|
|
2797
|
+
const shape = rawType ? [
|
|
2798
|
+
"Stated by hand and unverified: there is no spec entry to check it",
|
|
2799
|
+
"against."
|
|
2800
|
+
] : [
|
|
2801
|
+
"TODO: state the shape the backend is expected to serve. `unknown`",
|
|
2802
|
+
"compiles, but leaves the response boundary undescribed and the",
|
|
2803
|
+
"transform with nothing to narrow."
|
|
2804
|
+
];
|
|
2805
|
+
return [
|
|
2806
|
+
`Raw wire shape of \`${method.toUpperCase()} ${servicePath}\` — the UNWRAPPED`,
|
|
2807
|
+
"`data` payload, since the client strips the `{status, data}` envelope",
|
|
2808
|
+
"before the transform runs.",
|
|
2809
|
+
"",
|
|
2810
|
+
...shape,
|
|
2811
|
+
"",
|
|
2812
|
+
"Replace with `EndpointResponse<…>` once the endpoint is in the generated",
|
|
2813
|
+
"types."
|
|
2814
|
+
].join("\n");
|
|
2815
|
+
}
|
|
2816
|
+
function removalSteps(spec) {
|
|
2817
|
+
return [
|
|
2818
|
+
`Regenerate the API types for ${spec.modelProject} (generate_api_types), and confirm ${spec.method.toUpperCase()} ${spec.servicePath} is now in them.`,
|
|
2819
|
+
`In ${spec.servicesFilePath}: delete \` as ApiPath\` from \`${spec.catalogName}.${spec.endpointKey}\`.`,
|
|
2820
|
+
`In ${spec.servicesFilePath}: point the endpoint's \`…Raw\` alias at \`EndpointResponse<typeof ${spec.catalogName}.${spec.endpointKey}>\` and drop the hand-written shape.`,
|
|
2821
|
+
`In the model: swap \`provisionalServiceRequest\` for \`serviceRequest\` and drop its explicit type arguments — the response type comes from the spec again.`,
|
|
2822
|
+
spec.mocksFilePath ? `Delete ${spec.mocksFilePath} (and the call to its register function in the app) once no provisional endpoint is left in it.` : `Delete the model's mocks module once no provisional endpoint is left in it.`,
|
|
2823
|
+
`KEEP \`${spec.mapperName}\` and the data type it produces. The transform is real code; it is what let the model read the final shape all along.`
|
|
2824
|
+
];
|
|
2825
|
+
}
|
|
2826
|
+
function untypedEndpointError(spec) {
|
|
2827
|
+
const methodsForPath = spec.operations.filter((op) => op.path === spec.servicePath).map((op) => op.method);
|
|
2828
|
+
const pathTypedForOtherMethods = methodsForPath.length > 0;
|
|
2829
|
+
const nearest = [...new Set(spec.operations.map((op) => op.path))].sort(
|
|
2830
|
+
(a, b) => editDistance(a, spec.servicePath) - editDistance(b, spec.servicePath)
|
|
2831
|
+
).slice(0, NEAREST_SHOWN);
|
|
2832
|
+
const waysForward = [
|
|
2833
|
+
`The endpoint EXISTS on the device but this project has not pulled types for it: re-run api:generate (generate_api_types) for ${spec.modelProject}, then add the request unchanged. Confirm on the device first — kos-device search_services / describe_endpoint — since the live OpenAPI is what says whether it exists.`,
|
|
2834
|
+
`The endpoint DOES NOT EXIST yet: pass mock:"auto" (the default) or mock:"always" to emit the provisional, mock-backed form — real decorator, lifecycle, error-first handler and transform, with a KosMock route standing in for the wire response.`,
|
|
2835
|
+
`What is NOT supported: falling back to resolveServiceUrl / ServiceFactory.build / getAll to make the UI render. That compiles and looks finished, which is worse than the hole. A missing endpoint is a blocker to report, not a licence to route around the generated service layer.`
|
|
2836
|
+
];
|
|
2837
|
+
const message = pathTypedForOtherMethods ? `${spec.method.toUpperCase()} ${spec.servicePath} is not in the generated OpenAPI types for ${spec.modelProject} — the path is typed, but only for: ${methodsForPath.map((m) => m.toUpperCase()).join(", ")}.` : `${spec.method.toUpperCase()} ${spec.servicePath} is not in the generated OpenAPI types for ${spec.modelProject} — the path is absent entirely. Nothing was written.`;
|
|
2838
|
+
const error = new Error(message);
|
|
2839
|
+
error.details = {
|
|
2840
|
+
servicePath: spec.servicePath,
|
|
2841
|
+
method: spec.method,
|
|
2842
|
+
pathTypedForOtherMethods,
|
|
2843
|
+
methodsForPath,
|
|
2844
|
+
otherEndpointsInThisApi: nearest,
|
|
2845
|
+
warning: "These are OTHER endpoints in this API, listed only so they can be ruled out — they are almost certainly NOT what you want. Do not substitute one for the requested path because the strings look similar.",
|
|
2846
|
+
waysForward
|
|
2847
|
+
};
|
|
2848
|
+
return error;
|
|
2849
|
+
}
|
|
2575
2850
|
function addServiceRequestToModel(codegenFs, options, projects) {
|
|
2576
2851
|
const logger = getCodegenLogger();
|
|
2577
2852
|
const { modelFilePath, sourceRoot } = resolveModelFilePath(
|
|
@@ -2633,34 +2908,86 @@ function addServiceRequestToModel(codegenFs, options, projects) {
|
|
|
2633
2908
|
const mode = options.mode ?? (options.lifecycle ? "lifecycle" : "method");
|
|
2634
2909
|
const lifecycle = options.lifecycle || "LOAD";
|
|
2635
2910
|
const catalogName = `${pascalCase(modelBase)}Endpoints`;
|
|
2911
|
+
const mockMode = options.mock ?? "auto";
|
|
2912
|
+
const operations = readServiceModuleOperations(codegenFs, serviceModuleFile);
|
|
2913
|
+
const pathValidated = operations !== null;
|
|
2914
|
+
const operationTyped = operations === null || operations.some(
|
|
2915
|
+
(op) => op.path === options.servicePath && op.method === method
|
|
2916
|
+
);
|
|
2917
|
+
if (!operationTyped && mockMode === "never") {
|
|
2918
|
+
throw untypedEndpointError({
|
|
2919
|
+
servicePath: options.servicePath,
|
|
2920
|
+
method,
|
|
2921
|
+
modelProject: options.modelProject,
|
|
2922
|
+
operations: operations ?? []
|
|
2923
|
+
});
|
|
2924
|
+
}
|
|
2925
|
+
const provisional = !operationTyped;
|
|
2926
|
+
const writeMock = provisional || mockMode === "always";
|
|
2927
|
+
if (provisional) {
|
|
2928
|
+
assertServiceModuleAcceptsProvisional(
|
|
2929
|
+
codegenFs,
|
|
2930
|
+
serviceModuleFile,
|
|
2931
|
+
options.modelProject
|
|
2932
|
+
);
|
|
2933
|
+
}
|
|
2636
2934
|
logger.info(
|
|
2637
|
-
`Adding ${mode}-driven @kosServiceRequest "${options.methodName}" (${method} ${options.servicePath}) to ${options.modelName}`
|
|
2935
|
+
`Adding ${mode}-driven ${provisional ? "PROVISIONAL " : ""}@kosServiceRequest "${options.methodName}" (${method} ${options.servicePath}) to ${options.modelName}`
|
|
2638
2936
|
);
|
|
2937
|
+
if (provisional) {
|
|
2938
|
+
logger.warn(
|
|
2939
|
+
`${method.toUpperCase()} ${options.servicePath} is not in ${options.modelProject}'s generated OpenAPI types — emitting the provisional, mock-backed form. The feature is NOT complete until the endpoint lands.`
|
|
2940
|
+
);
|
|
2941
|
+
}
|
|
2639
2942
|
ensureServicesModule(codegenFs, modelFilePath, modelBase);
|
|
2640
2943
|
let endpointKey = options.methodName;
|
|
2641
2944
|
let endpointCreated = true;
|
|
2642
2945
|
let dataAlias = "";
|
|
2643
2946
|
let mapperName = "";
|
|
2644
2947
|
let ctxAlias = "";
|
|
2948
|
+
let rawAlias = "";
|
|
2645
2949
|
transformSourceFile(codegenFs, servicesFilePath, (sf) => {
|
|
2646
2950
|
ensureNamedImport(sf, serviceImportFromServices, [{ name: "endpoint" }]);
|
|
2951
|
+
if (provisional) {
|
|
2952
|
+
ensureNamedImport(sf, serviceImportFromServices, [
|
|
2953
|
+
{ name: "ApiPath", isTypeOnly: true }
|
|
2954
|
+
]);
|
|
2955
|
+
}
|
|
2956
|
+
const pathText = provisional ? `${JSON.stringify(options.servicePath)} as ApiPath` : JSON.stringify(options.servicePath);
|
|
2647
2957
|
const entry = ensureConstCatalogEntry(sf, {
|
|
2648
2958
|
catalogName,
|
|
2649
2959
|
key: options.methodName,
|
|
2650
|
-
initializer: `endpoint(${JSON.stringify(
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
equals: sameEndpoint
|
|
2960
|
+
initializer: `endpoint(${pathText}, ${JSON.stringify(method)})`,
|
|
2961
|
+
equals: sameEndpoint,
|
|
2962
|
+
leadingTrivia: provisional ? provisionalEntryComment(options.servicePath, method, catalogName) : void 0
|
|
2654
2963
|
});
|
|
2655
2964
|
endpointKey = entry.key;
|
|
2656
2965
|
endpointCreated = entry.created;
|
|
2657
2966
|
dataAlias = `${pascalCase(endpointKey)}Data`;
|
|
2658
2967
|
mapperName = `to${pascalCase(endpointKey)}Data`;
|
|
2659
2968
|
ctxAlias = `${pascalCase(endpointKey)}Ctx`;
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2969
|
+
rawAlias = `${pascalCase(endpointKey)}Raw`;
|
|
2970
|
+
let rawType;
|
|
2971
|
+
if (provisional) {
|
|
2972
|
+
ensureExportedTypeAlias(sf, {
|
|
2973
|
+
name: rawAlias,
|
|
2974
|
+
type: options.rawType || "unknown",
|
|
2975
|
+
docs: rawTypeDocs(options.servicePath, method, options.rawType)
|
|
2976
|
+
});
|
|
2977
|
+
rawType = rawAlias;
|
|
2978
|
+
} else {
|
|
2979
|
+
rawType = `EndpointResponse<typeof ${catalogName}.${endpointKey}>`;
|
|
2980
|
+
ensureNamedImport(sf, serviceImportFromServices, [
|
|
2981
|
+
{ name: "EndpointResponse", isTypeOnly: true }
|
|
2982
|
+
]);
|
|
2983
|
+
if (writeMock) {
|
|
2984
|
+
ensureExportedTypeAlias(sf, {
|
|
2985
|
+
name: rawAlias,
|
|
2986
|
+
type: rawType,
|
|
2987
|
+
docs: `Raw wire shape of \`${method.toUpperCase()} ${options.servicePath}\`, as the spec declares it — what a mock for this endpoint must serve.`
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2664
2991
|
ensureExportedTypeAlias(sf, { name: dataAlias, type: rawType });
|
|
2665
2992
|
ensureExportedMapper(sf, {
|
|
2666
2993
|
name: mapperName,
|
|
@@ -2681,20 +3008,25 @@ function addServiceRequestToModel(codegenFs, options, projects) {
|
|
|
2681
3008
|
const className = getModelClass(sf).getName();
|
|
2682
3009
|
if (!className) throw new Error("Model class has no name.");
|
|
2683
3010
|
const typeParams = getModelClass(sf).getTypeParameters().map((tp) => tp.getText());
|
|
2684
|
-
|
|
3011
|
+
const decoratorName = provisional ? "provisionalServiceRequest" : "serviceRequest";
|
|
3012
|
+
const decoratorTypeArgs = provisional ? [rawAlias, dataAlias] : void 0;
|
|
3013
|
+
ensureNamedImport(sf, serviceImportFromModel, [{ name: decoratorName }]);
|
|
2685
3014
|
if (mode === "lifecycle") {
|
|
2686
3015
|
ensureNamedImport(sf, "./services", [
|
|
2687
3016
|
{ name: catalogName },
|
|
2688
3017
|
{ name: mapperName },
|
|
2689
|
-
{ name: dataAlias, isTypeOnly: true }
|
|
3018
|
+
{ name: dataAlias, isTypeOnly: true },
|
|
3019
|
+
...provisional ? [{ name: rawAlias, isTypeOnly: true }] : []
|
|
2690
3020
|
]);
|
|
2691
3021
|
ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [
|
|
2692
3022
|
{ name: "DependencyLifecycle" }
|
|
2693
3023
|
]);
|
|
2694
3024
|
addDecoratedMethod(getModelClass(sf), {
|
|
2695
3025
|
name: options.methodName,
|
|
2696
|
-
decoratorName
|
|
3026
|
+
decoratorName,
|
|
3027
|
+
decoratorTypeArgs,
|
|
2697
3028
|
decoratorArgsText: `${catalogName}.${endpointKey}, { lifecycle: DependencyLifecycle.${lifecycle}, transform: ${mapperName} }`,
|
|
3029
|
+
docs: provisional ? provisionalMethodDocs(options.servicePath, method) : void 0,
|
|
2698
3030
|
// The manager invokes phase handlers error-first, passing (null, data)
|
|
2699
3031
|
// on success. The `error` half is only ever reached because
|
|
2700
3032
|
// `serviceRequest` supplies an errorHandler — the bare decorator
|
|
@@ -2711,7 +3043,11 @@ function addServiceRequestToModel(codegenFs, options, projects) {
|
|
|
2711
3043
|
ensureNamedImport(sf, "./services", [
|
|
2712
3044
|
{ name: catalogName },
|
|
2713
3045
|
{ name: mapperName },
|
|
2714
|
-
{ name: ctxAlias, isTypeOnly: true }
|
|
3046
|
+
{ name: ctxAlias, isTypeOnly: true },
|
|
3047
|
+
...provisional ? [
|
|
3048
|
+
{ name: rawAlias, isTypeOnly: true },
|
|
3049
|
+
{ name: dataAlias, isTypeOnly: true }
|
|
3050
|
+
] : []
|
|
2715
3051
|
]);
|
|
2716
3052
|
ensureNamedImport(sf, resolveSdkModuleSpecifier(sf), [
|
|
2717
3053
|
{ name: "executeServiceRequest" },
|
|
@@ -2726,8 +3062,10 @@ function addServiceRequestToModel(codegenFs, options, projects) {
|
|
|
2726
3062
|
addClassDecorator(getModelClass(sf), "kosLoggerAware", { argsText: "" });
|
|
2727
3063
|
addDecoratedMethod(getModelClass(sf), {
|
|
2728
3064
|
name: options.methodName,
|
|
2729
|
-
decoratorName
|
|
3065
|
+
decoratorName,
|
|
3066
|
+
decoratorTypeArgs,
|
|
2730
3067
|
decoratorArgsText: `${catalogName}.${endpointKey}, { transform: ${mapperName} }`,
|
|
3068
|
+
docs: provisional ? provisionalMethodDocs(options.servicePath, method) : void 0,
|
|
2731
3069
|
// Optional: the framework appends the context, callers never pass it.
|
|
2732
3070
|
parameters: [{ name: "$ctx", type: ctxAlias, optional: true }],
|
|
2733
3071
|
isAsync: true,
|
|
@@ -2739,13 +3077,43 @@ function addServiceRequestToModel(codegenFs, options, projects) {
|
|
|
2739
3077
|
].join("\n")
|
|
2740
3078
|
});
|
|
2741
3079
|
});
|
|
3080
|
+
const mock = writeMock ? ensureMockRoute(codegenFs, {
|
|
3081
|
+
modelFilePath,
|
|
3082
|
+
modelBase,
|
|
3083
|
+
sdkModuleSpecifier: readSourceFile(
|
|
3084
|
+
codegenFs,
|
|
3085
|
+
modelFilePath,
|
|
3086
|
+
resolveSdkModuleSpecifier
|
|
3087
|
+
),
|
|
3088
|
+
rawAlias,
|
|
3089
|
+
servicePath: options.servicePath,
|
|
3090
|
+
method,
|
|
3091
|
+
endpointKey,
|
|
3092
|
+
sampleText: options.sample
|
|
3093
|
+
}) : void 0;
|
|
2742
3094
|
return {
|
|
2743
3095
|
modelFilePath,
|
|
2744
3096
|
servicesFilePath,
|
|
2745
3097
|
serviceModule: serviceImportFromModel,
|
|
2746
3098
|
mode,
|
|
2747
3099
|
endpointKey,
|
|
2748
|
-
endpointCreated
|
|
3100
|
+
endpointCreated,
|
|
3101
|
+
pathValidated,
|
|
3102
|
+
provisional,
|
|
3103
|
+
mocksFilePath: mock?.mocksFilePath,
|
|
3104
|
+
mockRegisterFunction: mock?.registerFunction,
|
|
3105
|
+
mockRoute: mock && `${method.toUpperCase()} ${mock.routePattern}`,
|
|
3106
|
+
mockSamplePlaceholder: mock?.samplePlaceholder,
|
|
3107
|
+
removalSteps: provisional ? removalSteps({
|
|
3108
|
+
modelProject: options.modelProject,
|
|
3109
|
+
servicePath: options.servicePath,
|
|
3110
|
+
method,
|
|
3111
|
+
catalogName,
|
|
3112
|
+
endpointKey,
|
|
3113
|
+
servicesFilePath,
|
|
3114
|
+
mocksFilePath: mock?.mocksFilePath,
|
|
3115
|
+
mapperName
|
|
3116
|
+
}) : void 0
|
|
2749
3117
|
};
|
|
2750
3118
|
}
|
|
2751
3119
|
function modelElementType(typeText) {
|