bazis 0.97.2 → 0.97.3
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/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/scripts/agent-codegen.ts +1 -1
- package/core/scripts/di-generate.ts +7 -7
- 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;
|
|
@@ -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.3" }, 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");
|
|
@@ -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") {
|
|
@@ -545,7 +545,7 @@ function failOnFatalErrors(): void {
|
|
|
545
545
|
function renderGeneratedRuntime(targetId: string): string {
|
|
546
546
|
if (activeGeneratedDir !== APP_GENERATED_DIR) {
|
|
547
547
|
return [
|
|
548
|
-
"// This file is auto-generated by `
|
|
548
|
+
"// This file is auto-generated by `bazis codegen`.",
|
|
549
549
|
"// Do not edit manually.",
|
|
550
550
|
"",
|
|
551
551
|
'import { registerBazisGeneratedTargetDescriptor } from "bazis/core/generatedRuntime";',
|
|
@@ -565,7 +565,7 @@ function renderGeneratedRuntime(targetId: string): string {
|
|
|
565
565
|
].join("\n");
|
|
566
566
|
}
|
|
567
567
|
return [
|
|
568
|
-
"// This file is auto-generated by `
|
|
568
|
+
"// This file is auto-generated by `bazis codegen`.",
|
|
569
569
|
"// Do not edit manually.",
|
|
570
570
|
"",
|
|
571
571
|
"let registered: Promise<void> | undefined;",
|
|
@@ -615,7 +615,7 @@ function renderTargetDeps(): string {
|
|
|
615
615
|
if (dependency.target && !references.has(dependency.target)) references.set(dependency.target, `DependencyClass_${references.size}`);
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
|
-
const lines = ["// This file is auto-generated by `
|
|
618
|
+
const lines = ["// This file is auto-generated by `bazis codegen`.", "// Do not edit manually."];
|
|
619
619
|
if (entries.some(([, deps]) => deps.some(dep => dep.target && dep.lazy))) lines.push('import { lazyDependency } from "bazis/core/di";');
|
|
620
620
|
for (const [declaration, reference] of references) {
|
|
621
621
|
const name = dependencyClassExportName(declaration);
|
|
@@ -668,7 +668,7 @@ function renderTargetBindings(): string {
|
|
|
668
668
|
// bindable parameters as well as ordinary binding-bearing controllers.
|
|
669
669
|
const entries = [...new Set([...Object.keys(httpBindings), ...Object.keys(openApiOperations)])]
|
|
670
670
|
.sort((a, b) => a.localeCompare(b));
|
|
671
|
-
const lines = ["// This file is auto-generated by `
|
|
671
|
+
const lines = ["// This file is auto-generated by `bazis codegen`.", "// Do not edit manually."];
|
|
672
672
|
for (let index = 0; index < entries.length; index += 1) {
|
|
673
673
|
const name = entries[index] as string;
|
|
674
674
|
const file = httpControllerFiles[name] ?? classFilesByName.get(name);
|
|
@@ -1677,7 +1677,7 @@ function sourceLocation(node: ts.Node): string {
|
|
|
1677
1677
|
|
|
1678
1678
|
function renderListModels(imports: readonly RequestModelImport[]): string {
|
|
1679
1679
|
const lines: string[] = [];
|
|
1680
|
-
lines.push("// This file is auto-generated by `
|
|
1680
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1681
1681
|
lines.push("// Do not edit manually.");
|
|
1682
1682
|
lines.push("//");
|
|
1683
1683
|
lines.push("// Target-local immutable descriptor; runtime publication is staged by runtime.ts.");
|
|
@@ -1717,7 +1717,7 @@ function renderRequestModels(
|
|
|
1717
1717
|
hydration: RequestModelHydration,
|
|
1718
1718
|
): string {
|
|
1719
1719
|
const lines: string[] = [];
|
|
1720
|
-
lines.push("// This file is auto-generated by `
|
|
1720
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1721
1721
|
lines.push("// Do not edit manually.");
|
|
1722
1722
|
lines.push("//");
|
|
1723
1723
|
lines.push("// Registers convention body models (class-typed action params) so they are");
|
|
@@ -1780,7 +1780,7 @@ function renderOpenApiMetadata(
|
|
|
1780
1780
|
}
|
|
1781
1781
|
|
|
1782
1782
|
const lines: string[] = [];
|
|
1783
|
-
lines.push("// This file is auto-generated by `
|
|
1783
|
+
lines.push("// This file is auto-generated by `bazis codegen`.");
|
|
1784
1784
|
lines.push("// Do not edit manually.");
|
|
1785
1785
|
lines.push("");
|
|
1786
1786
|
lines.push(
|
package/package.json
CHANGED