bazis 0.97.2 → 0.97.4
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/cli/build.ts +7 -7
- package/cli/main.ts +1 -1
- package/core/agent/generated/catalog.ts +1 -1
- package/core/app/ui/uiProfileResolver.ts +1 -1
- package/core/di/ServiceProvider.ts +17 -0
- package/core/di/errors/ClassDependenciesMismatchError.ts +1 -1
- package/core/di/internal/GraphValidator.ts +1 -1
- package/core/generatedFingerprint.ts +11 -0
- package/core/http/Binding/autoBindings.ts +2 -2
- package/core/http/Binding/generatedSpec.ts +1 -1
- package/core/http/Binding/modelBinder.ts +1 -1
- package/core/http/Binding/requestModelRegistry.ts +1 -1
- package/core/http/Routing/RouterBuilder.ts +27 -0
- package/core/http/options.ts +1 -1
- package/core/infra/connectors/codex/CodexAppServerClient.ts +1 -1
- package/core/kernel/Kernel.ts +4 -0
- package/core/scripts/agent-codegen.ts +1 -1
- package/core/scripts/di-generate.ts +14 -8
- package/package.json +1 -1
package/cli/build.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface BuildOptions {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* `bazis dev`: codegen, then run the default target's entrypoint from source.
|
|
16
|
+
* `bazis dev`: codegen of every target, then run the default target's entrypoint from source.
|
|
17
17
|
* With `watch`, a change under src/ (except src/generated) stops the app,
|
|
18
18
|
* reruns codegen and starts it again; a failed codegen waits for the next change.
|
|
19
19
|
* The app runs as `development` unless BAZIS_ENV is set in the shell.
|
|
@@ -28,7 +28,7 @@ export async function runDev(cwd: string, codegen: Codegen, log: (message: strin
|
|
|
28
28
|
const entry = await projectEntry(cwd);
|
|
29
29
|
const env = devEnvironment(process.env);
|
|
30
30
|
if (!options.watch) {
|
|
31
|
-
const generated = await codegen(cwd);
|
|
31
|
+
const generated = await codegen(cwd, "all");
|
|
32
32
|
if (generated !== 0) return generated;
|
|
33
33
|
const child = Bun.spawn([bun, "run", entry], { cwd, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" });
|
|
34
34
|
// The app owns graceful shutdown; forward the signal instead of dying first.
|
|
@@ -55,7 +55,7 @@ export async function runDev(cwd: string, codegen: Codegen, log: (message: strin
|
|
|
55
55
|
await running.exited;
|
|
56
56
|
};
|
|
57
57
|
const start = async () => {
|
|
58
|
-
if (await codegen(cwd) !== 0) { log("[bazis] codegen failed; waiting for changes..."); return; }
|
|
58
|
+
if (await codegen(cwd, "all") !== 0) { log("[bazis] codegen failed; waiting for changes..."); return; }
|
|
59
59
|
child = Bun.spawn([bun, "run", entry], { cwd, env, stdin: "inherit", stdout: "inherit", stderr: "inherit" });
|
|
60
60
|
};
|
|
61
61
|
const watcher = watch(path.join(cwd, "src"), { recursive: true }, (_event, file) => {
|
|
@@ -84,16 +84,16 @@ export async function runDev(cwd: string, codegen: Codegen, log: (message: strin
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
/** `bazis test [args]`: codegen, then `bun test` with the given arguments. */
|
|
87
|
+
/** `bazis test [args]`: codegen of every target, then `bun test` with the given arguments. */
|
|
88
88
|
export async function runTest(cwd: string, args: readonly string[], codegen: Codegen): Promise<number> {
|
|
89
|
-
const generated = await codegen(cwd);
|
|
89
|
+
const generated = await codegen(cwd, "all");
|
|
90
90
|
if (generated !== 0) return generated;
|
|
91
91
|
return await Bun.spawn([await resolveBun(cwd), "test", ...args], { cwd, stdin: "inherit", stdout: "inherit", stderr: "inherit" }).exited;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
/** `bazis build [--bin]`: codegen and typecheck; with `bin`, also compile. */
|
|
94
|
+
/** `bazis build [--bin]`: codegen of every target and typecheck; with `bin`, also compile. */
|
|
95
95
|
export async function runBuild(cwd: string, options: BuildOptions, codegen: Codegen, log: (message: string) => void): Promise<number> {
|
|
96
|
-
const generated = await codegen(cwd);
|
|
96
|
+
const generated = await codegen(cwd, "all");
|
|
97
97
|
if (generated !== 0) return generated;
|
|
98
98
|
const bun = await resolveBun(cwd);
|
|
99
99
|
const tsc = path.join(cwd, "node_modules/typescript/bin/tsc");
|
package/cli/main.ts
CHANGED
|
@@ -115,7 +115,7 @@ export async function runCli(argv: readonly string[], runtime: CliRuntime = defa
|
|
|
115
115
|
runtime.log(`[bazis] codegen skipped: ${!args.codegen ? "--no-codegen" : "module is not connected by this command"}.`);
|
|
116
116
|
return 0;
|
|
117
117
|
}
|
|
118
|
-
runtime.log("[bazis] running
|
|
118
|
+
runtime.log("[bazis] running codegen...");
|
|
119
119
|
const exitCode = await runtime.codegen(process.cwd(), args.target);
|
|
120
120
|
if (exitCode !== 0) runtime.error("[bazis] codegen failed; scaffold files were kept. Fix the error and run bazis codegen.");
|
|
121
121
|
return exitCode;
|
|
@@ -746,7 +746,7 @@ function resolveAndValidateResponseSchema(
|
|
|
746
746
|
diagnostics.push(uiDiagnosticV1(
|
|
747
747
|
"error",
|
|
748
748
|
"UIV1_RESPONSE_MODEL_NOT_REGISTERED",
|
|
749
|
-
`${profileName} response class is not bound to a generated OpenAPI schema. Run
|
|
749
|
+
`${profileName} response class is not bound to a generated OpenAPI schema. Run \`bazis codegen\`.`,
|
|
750
750
|
{ profile: profileName, path: "response" },
|
|
751
751
|
));
|
|
752
752
|
return actual;
|
|
@@ -112,6 +112,23 @@ export class ServiceProvider implements ServiceResolver {
|
|
|
112
112
|
return this.resolveSingleAsync(token, key, this.lifetime.root, []);
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Creates every singleton registered with an async factory (keyed ones
|
|
117
|
+
* included), in registration order. Afterwards `resolve` and constructor
|
|
118
|
+
* injection return the cached instances. The kernel calls it at startup, so a
|
|
119
|
+
* failing factory stops the start instead of failing every request.
|
|
120
|
+
*/
|
|
121
|
+
public async initializeAsyncSingletons(): Promise<void> {
|
|
122
|
+
this.lifetime.assertLive(this.lifetime.root);
|
|
123
|
+
for (const group of this.registry.groups()) {
|
|
124
|
+
for (const registration of group) {
|
|
125
|
+
if (registration.lifetime === "singleton" && isAsyncFactoryProvider(registration.provider)) {
|
|
126
|
+
await this.resolveRegistrationAsync(registration, registration.key, this.lifetime.root, [], undefined);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
115
132
|
public tryResolve<T>(token: Token<T>, key?: ServiceKey): T | undefined {
|
|
116
133
|
return this.tryResolveForScope(token, key, this.lifetime.root);
|
|
117
134
|
}
|
|
@@ -9,7 +9,7 @@ export class ClassDependenciesMismatchError extends DiError {
|
|
|
9
9
|
declaredDeps: number,
|
|
10
10
|
) {
|
|
11
11
|
super(
|
|
12
|
-
`Class provider "${tokenToDebugName(token)}" requires at least ${requiredConstructorParams} constructor deps, but only ${declaredDeps} declared.`,
|
|
12
|
+
`Class provider "${tokenToDebugName(token)}" requires at least ${requiredConstructorParams} constructor deps, but only ${declaredDeps} declared. Constructor dependencies are wired by codegen: if the constructor was added or changed after the last run, run \`bazis codegen\` (bazis dev, bazis test and bazis build run it automatically); otherwise pass the deps explicitly.`,
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -70,7 +70,7 @@ export class GraphValidator {
|
|
|
70
70
|
const shape = this.context.classShape(registration.provider);
|
|
71
71
|
if (shape && shape.required > shape.declared) {
|
|
72
72
|
issues.add(
|
|
73
|
-
`Class provider "${tokenToDebugName(registration.token)}" requires at least ${shape.required} constructor deps, but only ${shape.declared} declared.`,
|
|
73
|
+
`Class provider "${tokenToDebugName(registration.token)}" requires at least ${shape.required} constructor deps, but only ${shape.declared} declared. Constructor dependencies are wired by codegen: if the constructor was added or changed after the last run, run \`bazis codegen\` (bazis dev, bazis test and bazis build run it automatically); otherwise pass the deps explicitly.`,
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
|
|
@@ -37,6 +37,16 @@ export function frameworkVersion(): string | undefined {
|
|
|
37
37
|
* (or with another framework version): new routes and dependencies would be
|
|
38
38
|
* silently missing. A compiled binary carries no sources, so it is skipped.
|
|
39
39
|
*/
|
|
40
|
+
let staleGeneratedSources = false;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* True when the loaded generated code was produced from older sources (or
|
|
44
|
+
* another bazis version) than the ones running now.
|
|
45
|
+
*/
|
|
46
|
+
export function generatedSourcesAreStale(): boolean {
|
|
47
|
+
return staleGeneratedSources;
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
export function warnIfGeneratedSourcesChanged(
|
|
41
51
|
generatedDir: string,
|
|
42
52
|
fingerprint: GeneratedSourceFingerprint,
|
|
@@ -49,6 +59,7 @@ export function warnIfGeneratedSourcesChanged(
|
|
|
49
59
|
const version = frameworkVersion();
|
|
50
60
|
if (version !== undefined && version !== fingerprint.framework) changes.push(`bazis ${fingerprint.framework} -> ${version}`);
|
|
51
61
|
if (changes.length === 0) return false;
|
|
62
|
+
staleGeneratedSources = true;
|
|
52
63
|
warn([
|
|
53
64
|
"",
|
|
54
65
|
`[bazis] WARNING: generated code is out of date (${changes.join("; ")}).`,
|
|
@@ -24,7 +24,7 @@ export function registerGeneratedBindings(
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Binding conventions inferred by codegen (`
|
|
27
|
+
* Binding conventions inferred by codegen (`bazis codegen`) from the
|
|
28
28
|
* controller method signature, the counterpart of DI auto deps:
|
|
29
29
|
*
|
|
30
30
|
* - a parameter named like a route `:name` -> from the route;
|
|
@@ -72,7 +72,7 @@ function toBinding(spec: GeneratedBindingSpec, controllerName: string, methodNam
|
|
|
72
72
|
if (ctor === undefined) {
|
|
73
73
|
throw new HttpSetupError(
|
|
74
74
|
`${controllerName}.${methodName}: list model "${spec.model}" is not registered. ` +
|
|
75
|
-
`Make sure the class extends ListRequest and its module is imported, then run \`
|
|
75
|
+
`Make sure the class extends ListRequest and its module is imported, then run \`bazis codegen\`.`,
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
if (ctor === AMBIGUOUS_LIST_MODEL) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Format of the generated binding conventions (`
|
|
2
|
+
* Format of the generated binding conventions (`bazis codegen`).
|
|
3
3
|
*
|
|
4
4
|
* Plain data without class references: the body model is given **by name** and
|
|
5
5
|
* resolved at startup through the class index of the generated target.
|
|
@@ -48,7 +48,7 @@ export interface ModelBindingOptions {
|
|
|
48
48
|
*
|
|
49
49
|
* The model class must have a parameterless constructor. Class-typed nested
|
|
50
50
|
* DTOs (including arrays) are recursively hydrated from metadata emitted by
|
|
51
|
-
* `
|
|
51
|
+
* `bazis codegen`; initialized nested DTO fields remain supported as a
|
|
52
52
|
* runtime fallback.
|
|
53
53
|
*/
|
|
54
54
|
export function bindModel<T extends object>(model: Class<T>, data: unknown, validator?: ModelValidator, options: ModelBindingOptions = {}): T {
|
|
@@ -13,7 +13,7 @@ export const AMBIGUOUS_REQUEST_MODEL: unique symbol = Symbol("ambiguous-request-
|
|
|
13
13
|
export type RequestModelClass = new () => object;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Runtime hydration metadata emitted by `
|
|
16
|
+
* Runtime hydration metadata emitted by `bazis codegen` for a class-
|
|
17
17
|
* typed request-model field. Standard TC39 decorators deliberately do not
|
|
18
18
|
* expose design types, so this tiny registry is the dependency-free bridge
|
|
19
19
|
* from TypeScript source types to the HTTP binder.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Class, Token } from "../../di";
|
|
2
2
|
import { bindArguments } from "../Binding/ParameterBinder";
|
|
3
3
|
import { resolveGeneratedBindings } from "../Binding/autoBindings";
|
|
4
|
+
import { generatedSourcesAreStale } from "../../generatedFingerprint";
|
|
4
5
|
import { controllerMetaOf, type ActionMeta, type ControllerMeta } from "../Decorators/metadata";
|
|
5
6
|
import { HttpSetupError } from "../Errors/HttpError";
|
|
6
7
|
import type { HttpContext } from "../HttpContext/HttpContext";
|
|
@@ -108,6 +109,7 @@ export class RouterBuilder {
|
|
|
108
109
|
const filters: readonly ActionFilterHooks[] = [...meta.filters, ...action.filters];
|
|
109
110
|
const catches = meta.catches;
|
|
110
111
|
const bindings = resolveGeneratedBindings(controllerClass, methodName);
|
|
112
|
+
assertBindingsFresh(controllerClass, methodName, bindings);
|
|
111
113
|
const responseDefaults = { httpCode: action.httpCode, produces: action.produces };
|
|
112
114
|
const bindingDefaults = { consumes: action.consumes };
|
|
113
115
|
const token = controllerClass as unknown as Token<object>;
|
|
@@ -182,3 +184,28 @@ export class RouterBuilder {
|
|
|
182
184
|
return { boundary, terminal };
|
|
183
185
|
}
|
|
184
186
|
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Without generated bindings a method receives only the HttpContext. When the
|
|
190
|
+
* generated code is older than the sources, a method that declares parameters
|
|
191
|
+
* but has no bindings was most likely added or changed after the last codegen:
|
|
192
|
+
* its arguments would silently get wrong values, so the server refuses to start.
|
|
193
|
+
*/
|
|
194
|
+
function assertBindingsFresh(
|
|
195
|
+
controllerClass: Class<object>,
|
|
196
|
+
methodName: string | symbol,
|
|
197
|
+
bindings: readonly unknown[] | undefined,
|
|
198
|
+
): void {
|
|
199
|
+
if (bindings !== undefined || !generatedSourcesAreStale()) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const method = (controllerClass.prototype as Record<string | symbol, unknown>)[methodName];
|
|
203
|
+
if (typeof method !== "function" || method.length === 0) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
throw new HttpSetupError(
|
|
207
|
+
`${controllerClass.name}.${String(methodName)} has parameters but no generated argument bindings: ` +
|
|
208
|
+
"the generated code is older than this controller. Run `bazis codegen` " +
|
|
209
|
+
"(bazis dev, bazis test and bazis build run it automatically).",
|
|
210
|
+
);
|
|
211
|
+
}
|
package/core/http/options.ts
CHANGED
|
@@ -116,7 +116,7 @@ export interface HttpModuleOptions {
|
|
|
116
116
|
readonly health?: HealthEndpointOptions | boolean;
|
|
117
117
|
/**
|
|
118
118
|
* Built-in generated API docs. No user-facing Swagger decorators are needed:
|
|
119
|
-
* `
|
|
119
|
+
* `bazis codegen` derives request models and schemas from controllers.
|
|
120
120
|
*
|
|
121
121
|
* Default: enabled in debug environments, disabled in production. `true`
|
|
122
122
|
* serves `/docs` and `/docs/openapi.json`; pass an object to change paths or
|
|
@@ -232,7 +232,7 @@ export class CodexAppServerClient implements CodexClient {
|
|
|
232
232
|
if (method === "account/updated") this.modelCache = undefined;
|
|
233
233
|
}, () => { this.clearLogin(); this.modelCache = undefined; });
|
|
234
234
|
const initialized = await client.request("initialize", {
|
|
235
|
-
clientInfo: { name: "bazis", title: "Bazis", version: "0.97.
|
|
235
|
+
clientInfo: { name: "bazis", title: "Bazis", version: "0.97.4" }, capabilities: { experimentalApi: true },
|
|
236
236
|
}, 15_000, signal);
|
|
237
237
|
if (resolve(text(initialized.codexHome, 4096)) !== this.paths.home) throw new CodexError("PROTOCOL_ERROR");
|
|
238
238
|
client.notify("initialized");
|
package/core/kernel/Kernel.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { UnhandledErrorPolicy } from "./types";
|
|
|
13
13
|
import { redactSensitive } from "../../library/redaction";
|
|
14
14
|
import { validateTimeout } from "./internal/validateTimeout";
|
|
15
15
|
import { awaitShutdown } from "./internal/awaitShutdown";
|
|
16
|
+
import { awaitAbortable } from "./internal/awaitAbortable";
|
|
16
17
|
import { reportDiagnosticFailure } from "./internal/reportDiagnosticFailure";
|
|
17
18
|
|
|
18
19
|
export interface KernelTimings {
|
|
@@ -97,6 +98,9 @@ export class Kernel {
|
|
|
97
98
|
);
|
|
98
99
|
}
|
|
99
100
|
try {
|
|
101
|
+
// Async singletons first: hosted services and controllers take them
|
|
102
|
+
// through constructors, which resolve synchronously.
|
|
103
|
+
await awaitAbortable(this.container.initializeAsyncSingletons(), abortController.signal);
|
|
100
104
|
await this.coordinator.start(abortController.signal, this.options.shutdownTimeoutMs);
|
|
101
105
|
coordinatorStarted = true;
|
|
102
106
|
this.startupMs = performance.now() - this.timings.buildStartedAt;
|
|
@@ -879,7 +879,7 @@ function renderAgentCatalog(context: AgentCodegenContext): RenderedAgentCatalog
|
|
|
879
879
|
const validPrompts = filterImportablePromptEntries(context.prompts, imports, context);
|
|
880
880
|
|
|
881
881
|
const lines: string[] = [];
|
|
882
|
-
lines.push("// This file is auto-generated by `
|
|
882
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
883
883
|
lines.push("// Do not edit manually.");
|
|
884
884
|
lines.push("");
|
|
885
885
|
if (context.frameworkImports === "public") {
|
|
@@ -156,6 +156,8 @@ interface CollectedDependency { readonly name: string; readonly target?: ts.Clas
|
|
|
156
156
|
interface ConstructorDependencies {
|
|
157
157
|
readonly deps: CollectedDependency[];
|
|
158
158
|
readonly unsupportedInheritedParameter?: string;
|
|
159
|
+
/** An own constructor parameter whose type cannot name a DI dependency (`string`, `number`, an inline type). */
|
|
160
|
+
readonly unsupportedParameter?: { readonly index: number; readonly name: string; readonly type: string };
|
|
159
161
|
}
|
|
160
162
|
let classDeps = new Map<ts.ClassDeclaration, readonly CollectedDependency[]>();
|
|
161
163
|
let inferredDiClasses = new Set<ts.ClassDeclaration>();
|
|
@@ -545,7 +547,7 @@ function failOnFatalErrors(): void {
|
|
|
545
547
|
function renderGeneratedRuntime(targetId: string): string {
|
|
546
548
|
if (activeGeneratedDir !== APP_GENERATED_DIR) {
|
|
547
549
|
return [
|
|
548
|
-
"// This file is auto-generated by `
|
|
550
|
+
"// This file is auto-generated by `bazis codegen`.",
|
|
549
551
|
"// Do not edit manually.",
|
|
550
552
|
"",
|
|
551
553
|
'import { registerBazisGeneratedTargetDescriptor } from "bazis/core/generatedRuntime";',
|
|
@@ -565,7 +567,7 @@ function renderGeneratedRuntime(targetId: string): string {
|
|
|
565
567
|
].join("\n");
|
|
566
568
|
}
|
|
567
569
|
return [
|
|
568
|
-
"// This file is auto-generated by `
|
|
570
|
+
"// This file is auto-generated by `bazis codegen`.",
|
|
569
571
|
"// Do not edit manually.",
|
|
570
572
|
"",
|
|
571
573
|
"let registered: Promise<void> | undefined;",
|
|
@@ -615,7 +617,7 @@ function renderTargetDeps(): string {
|
|
|
615
617
|
if (dependency.target && !references.has(dependency.target)) references.set(dependency.target, `DependencyClass_${references.size}`);
|
|
616
618
|
}
|
|
617
619
|
}
|
|
618
|
-
const lines = ["// This file is auto-generated by `
|
|
620
|
+
const lines = ["// This file is auto-generated by `bazis codegen`.", "// Do not edit manually."];
|
|
619
621
|
if (entries.some(([, deps]) => deps.some(dep => dep.target && dep.lazy))) lines.push('import { lazyDependency } from "bazis/core/di";');
|
|
620
622
|
for (const [declaration, reference] of references) {
|
|
621
623
|
const name = dependencyClassExportName(declaration);
|
|
@@ -668,7 +670,7 @@ function renderTargetBindings(): string {
|
|
|
668
670
|
// bindable parameters as well as ordinary binding-bearing controllers.
|
|
669
671
|
const entries = [...new Set([...Object.keys(httpBindings), ...Object.keys(openApiOperations)])]
|
|
670
672
|
.sort((a, b) => a.localeCompare(b));
|
|
671
|
-
const lines = ["// This file is auto-generated by `
|
|
673
|
+
const lines = ["// This file is auto-generated by `bazis codegen`.", "// Do not edit manually."];
|
|
672
674
|
for (let index = 0; index < entries.length; index += 1) {
|
|
673
675
|
const name = entries[index] as string;
|
|
674
676
|
const file = httpControllerFiles[name] ?? classFilesByName.get(name);
|
|
@@ -796,6 +798,10 @@ function collectClassDeps(source: ts.SourceFile): void {
|
|
|
796
798
|
const visit = (node: ts.Node): void => {
|
|
797
799
|
if (ts.isClassDeclaration(node) && node.name) {
|
|
798
800
|
const result = readConstructorTypeNames(node);
|
|
801
|
+
if (result.unsupportedParameter !== undefined && needsInferredDiDeps(node)) {
|
|
802
|
+
const { index, name, type } = result.unsupportedParameter;
|
|
803
|
+
fatalErrors.push(`BAZIS_DI_DEPENDENCY_UNKNOWN: ${sourceLocation(node)}: constructor parameter ${index + 1} "${name}" of "${node.name.text}" has type "${type}", which cannot be injected: DI resolves dependencies by class, contract or token, and a plain type does not say which value to inject. Declare a token with the same name as a type alias (export type Prefix = string; export const Prefix = createToken<Prefix>("Prefix")) and register a value, or pass the deps explicitly: scoped(${node.name.text}, ${node.name.text}, [TOKEN] as const).`);
|
|
804
|
+
}
|
|
799
805
|
if (result.unsupportedInheritedParameter !== undefined && needsInferredDiDeps(node)) {
|
|
800
806
|
fatalErrors.push(`BAZIS_DI_CONSTRUCTOR_UNRESOLVED: ${sourceLocation(node)}: cannot infer inherited constructor parameter "${result.unsupportedInheritedParameter}" for "${node.name.text}". The parameter needs a runtime DI token or an explicit value/factory binding.`);
|
|
801
807
|
}
|
|
@@ -984,7 +990,7 @@ function readConstructorTypeNames(node: ts.ClassDeclaration): ConstructorDepende
|
|
|
984
990
|
const paramType = param.type;
|
|
985
991
|
const refName = paramType ? getDependencyTypeName(paramType) : undefined;
|
|
986
992
|
if (!refName || BUILTIN_DEPENDENCY_NAMES.has(refName)) {
|
|
987
|
-
return { deps: [] };
|
|
993
|
+
return { deps: [], unsupportedParameter: { index, name: param.name.getText(), type: paramType?.getText() ?? "(no type)" } };
|
|
988
994
|
}
|
|
989
995
|
|
|
990
996
|
// `Lazy<X>` is a deferred dependency on X: encode it with a marker prefix
|
|
@@ -1677,7 +1683,7 @@ function sourceLocation(node: ts.Node): string {
|
|
|
1677
1683
|
|
|
1678
1684
|
function renderListModels(imports: readonly RequestModelImport[]): string {
|
|
1679
1685
|
const lines: string[] = [];
|
|
1680
|
-
lines.push("// This file is auto-generated by `
|
|
1686
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1681
1687
|
lines.push("// Do not edit manually.");
|
|
1682
1688
|
lines.push("//");
|
|
1683
1689
|
lines.push("// Target-local immutable descriptor; runtime publication is staged by runtime.ts.");
|
|
@@ -1717,7 +1723,7 @@ function renderRequestModels(
|
|
|
1717
1723
|
hydration: RequestModelHydration,
|
|
1718
1724
|
): string {
|
|
1719
1725
|
const lines: string[] = [];
|
|
1720
|
-
lines.push("// This file is auto-generated by `
|
|
1726
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1721
1727
|
lines.push("// Do not edit manually.");
|
|
1722
1728
|
lines.push("//");
|
|
1723
1729
|
lines.push("// Registers convention body models (class-typed action params) so they are");
|
|
@@ -1780,7 +1786,7 @@ function renderOpenApiMetadata(
|
|
|
1780
1786
|
}
|
|
1781
1787
|
|
|
1782
1788
|
const lines: string[] = [];
|
|
1783
|
-
lines.push("// This file is auto-generated by `
|
|
1789
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1784
1790
|
lines.push("// Do not edit manually.");
|
|
1785
1791
|
lines.push("");
|
|
1786
1792
|
lines.push(
|
package/package.json
CHANGED