@ogygie/generate 0.0.0-stage → 0.20.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 +21 -0
- package/README.md +39 -2
- package/dist/behavior-binding.d.ts +47 -0
- package/dist/behavior-grammar.d.ts +53 -0
- package/dist/check-spec.d.ts +53 -0
- package/dist/chunk-WVFHAPGC.js +10992 -0
- package/dist/cli/check-command.d.ts +3 -0
- package/dist/cli/fill-command.d.ts +39 -0
- package/dist/cli/generate-command.d.ts +8 -0
- package/dist/cli/generate-screen-command.d.ts +6 -0
- package/dist/cli/output.d.ts +9 -0
- package/dist/cli/preview-command.d.ts +19 -0
- package/dist/cli/project.d.ts +97 -0
- package/dist/cli/run.d.ts +13 -0
- package/dist/cli/run.js +1127 -0
- package/dist/cli/schemas-command.d.ts +31 -0
- package/dist/cli/verify-command.d.ts +3 -0
- package/dist/consumed-feature.d.ts +32 -0
- package/dist/emit/db.d.ts +27 -0
- package/dist/emit/factories.d.ts +14 -0
- package/dist/emit/hole-doc.d.ts +18 -0
- package/dist/emit/hole-tests.d.ts +28 -0
- package/dist/emit/manifest-entry.d.ts +44 -0
- package/dist/emit/mssql/migration.d.ts +2 -0
- package/dist/emit/mssql/repository.d.ts +17 -0
- package/dist/emit/mssql/sql-types.d.ts +23 -0
- package/dist/emit/mssql/statements.d.ts +55 -0
- package/dist/emit/mssql/stub.d.ts +17 -0
- package/dist/emit/names.d.ts +34 -0
- package/dist/emit/plan.d.ts +428 -0
- package/dist/emit/repository.d.ts +16 -0
- package/dist/emit/routes.d.ts +22 -0
- package/dist/emit/runtime.d.ts +47 -0
- package/dist/emit/screen/container.d.ts +17 -0
- package/dist/emit/screen/fixtures.d.ts +14 -0
- package/dist/emit/screen/hole-doc.d.ts +2 -0
- package/dist/emit/screen/previews.d.ts +24 -0
- package/dist/emit/screen/queries.d.ts +10 -0
- package/dist/emit/screen/shared.d.ts +35 -0
- package/dist/emit/screen/spec-contracts.d.ts +10 -0
- package/dist/emit/screen/tests-static.d.ts +21 -0
- package/dist/emit/screen/tests.d.ts +19 -0
- package/dist/emit/screen/views.d.ts +10 -0
- package/dist/emit/screen/writes.d.ts +9 -0
- package/dist/emit/screen-plan.d.ts +187 -0
- package/dist/emit/service.d.ts +18 -0
- package/dist/emit/spec-contracts.d.ts +27 -0
- package/dist/emit/tests.d.ts +3 -0
- package/dist/fill/body.d.ts +26 -0
- package/dist/fill/fill.d.ts +97 -0
- package/dist/fill/model-draw.d.ts +25 -0
- package/dist/generate-feature.d.ts +23 -0
- package/dist/generate-screen.d.ts +19 -0
- package/dist/generation-block.schema.d.ts +1279 -0
- package/dist/hole-shape.d.ts +100 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +401 -0
- package/dist/manifest-generation.schema.d.ts +239 -0
- package/dist/motif-catalog.d.ts +175 -0
- package/dist/package-root.d.ts +5 -0
- package/dist/prompt-card.d.ts +3 -0
- package/dist/schema-checks.d.ts +32 -0
- package/dist/schemas/draft.d.ts +111 -0
- package/dist/screen-block.schema.d.ts +146 -0
- package/dist/screen-checks.d.ts +34 -0
- package/dist/screen-grammar.d.ts +36 -0
- package/dist/screen-vocabulary.d.ts +47 -0
- package/dist/spec-sections.d.ts +51 -0
- package/dist/verify-generation.d.ts +93 -0
- package/dist/vocabulary.d.ts +39 -0
- package/dist/zod-introspection.d.ts +119 -0
- package/holes-library/27560e1760bb184c.json +28 -0
- package/holes-library/2c26136fc6bff99a.json +30 -0
- package/holes-library/43a27770407bb38a.json +27 -0
- package/holes-library/46e67880a81012bc.json +27 -0
- package/holes-library/48dc5c44dc2cf3b7.json +32 -0
- package/holes-library/63d0825a61f6f5d3.json +27 -0
- package/holes-library/6784ed6c8e353dac.json +27 -0
- package/holes-library/8b4e4c8f04a5fc6a.json +31 -0
- package/holes-library/README.md +33 -0
- package/holes-library/d3597f50c265ba0c.json +27 -0
- package/holes-library/e48695e16221ff1a.json +32 -0
- package/package.json +59 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ModelClient } from "@ogygie/core/model";
|
|
2
|
+
import type { CommandOutput } from "./output.js";
|
|
3
|
+
import { type GenerateProject } from "./project.js";
|
|
4
|
+
/** `--model <model>`: the spec model of D24, overridable. */
|
|
5
|
+
export declare function parseSchemasFlags(argv: readonly string[]): {
|
|
6
|
+
model: string;
|
|
7
|
+
};
|
|
8
|
+
/** An external gate of the product: a script of its package.json, run without any secret; red lines come back as problems. */
|
|
9
|
+
export interface SchemasGateRunner {
|
|
10
|
+
(input: {
|
|
11
|
+
projectRoot: string;
|
|
12
|
+
script: string;
|
|
13
|
+
}): {
|
|
14
|
+
green: boolean;
|
|
15
|
+
lines: string[];
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** D52 names them: the product's typecheck and the purity of its contracts. */
|
|
19
|
+
export declare const SCHEMAS_GATE_SCRIPTS: readonly ["typecheck", "ogygie:verify-contracts"];
|
|
20
|
+
export declare const pnpmGateRunner: SchemasGateRunner;
|
|
21
|
+
export interface SchemasCommandDeps {
|
|
22
|
+
modelApiKey?: string | undefined;
|
|
23
|
+
fetchImpl?: typeof fetch;
|
|
24
|
+
/** A client in place of the Messages client — tests script the model here. */
|
|
25
|
+
client?: ModelClient;
|
|
26
|
+
gateRunner?: SchemasGateRunner;
|
|
27
|
+
summaryPath?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** The feature folder of the api app, as its sibling features are laid out (`src/features` when none says otherwise). */
|
|
30
|
+
export declare function featureFolderFor(project: GenerateProject, featureId: string): string;
|
|
31
|
+
export declare function runSchemasCommand(project: GenerateProject, featureId: string | undefined, argv: readonly string[], out: CommandOutput, deps?: SchemasCommandDeps): Promise<number>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent What a screen may consume of a feature of the map (D41, precision
|
|
3
|
+
* of lot 4 M3): the operations it can name. A feature whose spec carries a
|
|
4
|
+
* `# Génération` block offers the HTTP operations of that block. A feature
|
|
5
|
+
* WITHOUT a block — hand-written, delivered — offers its READS only: every GET
|
|
6
|
+
* route the map declares for it becomes a read operation named after its
|
|
7
|
+
* input schema (`GetReferentialInputSchema` → `getReferential`), its contracts
|
|
8
|
+
* read in the `schemas.ts` of its folder; its writes are not consumable — a
|
|
9
|
+
* screen that needs one asks the feature for a block. The map does not say
|
|
10
|
+
* which guard such a route carries, so a derived read names an undeclared
|
|
11
|
+
* guard and the generator emits no refusal of its own for it.
|
|
12
|
+
*/
|
|
13
|
+
import { type GenerationBlock, type HttpOperation, type ReadOperation } from "./generation-block.schema.js";
|
|
14
|
+
/** A route of a consumed feature as the map declares it — where `invalidates` lives. */
|
|
15
|
+
export interface ConsumedRoute {
|
|
16
|
+
method: string;
|
|
17
|
+
path: string;
|
|
18
|
+
schemaInput: string;
|
|
19
|
+
schemaOutput: string;
|
|
20
|
+
invalidates?: string[] | undefined;
|
|
21
|
+
}
|
|
22
|
+
/** The guard a derived read names: the map does not tell which guard the route carries. */
|
|
23
|
+
export declare const DERIVED_READ_GUARD = "undeclared";
|
|
24
|
+
/** `GetReferentialInputSchema` → `getReferential`, `ListNotesInputSchema` → `listNotes`, `RateHistoryQuerySchema` → `rateHistoryQuery`. */
|
|
25
|
+
export declare function readIdOfInputSchema(schemaInput: string): string;
|
|
26
|
+
/** The reads a feature without a block offers: one per GET route of the map, in the map's order. */
|
|
27
|
+
export declare function derivedReadsOf(routes: readonly ConsumedRoute[]): ReadOperation[];
|
|
28
|
+
/** The operations a screen may consume of a feature: the HTTP operations of its block, or the reads derived from its routes when it has none. */
|
|
29
|
+
export declare function consumableOperationsOf(feature: {
|
|
30
|
+
block: GenerationBlock | null;
|
|
31
|
+
routes: readonly ConsumedRoute[];
|
|
32
|
+
}): HttpOperation[];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Emits the Drizzle tables (`db.schema.gen.ts`) and the SQL migration
|
|
3
|
+
* (`<n>_<table>.gen.sql`) of a feature from its plan: the resource table —
|
|
4
|
+
* one column per resource field (type from the Zod structure, override from
|
|
5
|
+
* `contracts.columns`), the tenant column with its foreign key, the declared
|
|
6
|
+
* indexes prefixed by the tenant column, the unique that makes the business
|
|
7
|
+
* key a key (D28), the append-only motif's partial unique index on the current
|
|
8
|
+
* rows and its DEFERRABLE `superseded_by` foreign key —, the slot tables and
|
|
9
|
+
* the owned reference tables (D28: composite foreign key to the tenant column
|
|
10
|
+
* and the resource key, cascade for a slot, restrict for a reference), the
|
|
11
|
+
* read-only mapping of every view hole (D32: Drizzle sees a table, the
|
|
12
|
+
* repository reads it through the tenant facade, nothing is ever written
|
|
13
|
+
* through it), and the Row-Level Security policy every tenant table carries
|
|
14
|
+
* (AGENTS.md §Multi-tenant 3). The migration is regenerated AROUND the SQL
|
|
15
|
+
* bodies of the view holes, between `-- @hole <id>` and `-- @end-hole <id>`:
|
|
16
|
+
* those lines are the human's, kept as they are; a view nobody wrote yet is an
|
|
17
|
+
* empty marker pair the bench fails on.
|
|
18
|
+
*/
|
|
19
|
+
import type { FeaturePlan, TablePlan } from "./plan.js";
|
|
20
|
+
/** Every table of the feature, resource first, then slots, then the references with a schema — adopted ones included (D36). */
|
|
21
|
+
export declare function tablesOf(plan: FeaturePlan): TablePlan[];
|
|
22
|
+
/** The tables the generator CREATES and owns: every table of the feature but the adopted ones (D36). */
|
|
23
|
+
export declare function ownedTables(plan: FeaturePlan): TablePlan[];
|
|
24
|
+
export declare function emitDbSchema(plan: FeaturePlan): string;
|
|
25
|
+
/** The SQL bodies of the view holes an existing migration carries, by hole id. */
|
|
26
|
+
export declare function viewBodiesOf(existingMigration: string | null): Map<string, string>;
|
|
27
|
+
export declare function emitMigration(plan: FeaturePlan, existingMigration?: string | null): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FeaturePlan, OperationPlan } from "./plan.js";
|
|
2
|
+
/** Valid inputs of an operation: variant 0 overlays the first accept examples, variant n the n-th. */
|
|
3
|
+
export declare function validInputsOf(plan: FeaturePlan, operation: OperationPlan): Record<string, unknown>[];
|
|
4
|
+
/** The derived fields of the create's valid input, from the derive holes' first example outputs — what an arranged row carries. */
|
|
5
|
+
export declare function derivedOf(operation: OperationPlan, variant?: number): Record<string, unknown>;
|
|
6
|
+
/** The import file the transform hole accepts, and what it yields. */
|
|
7
|
+
export declare function importFixturesOf(plan: FeaturePlan): {
|
|
8
|
+
validCsv: string;
|
|
9
|
+
rowCount: number;
|
|
10
|
+
unreadableCsv: string;
|
|
11
|
+
faultyLineCsv: string;
|
|
12
|
+
faultyLineNumber: number;
|
|
13
|
+
} | null;
|
|
14
|
+
export declare function emitFactories(plan: FeaturePlan): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Emits `holes/<id>.gen.md`, the ONE context handed to whoever fills a
|
|
3
|
+
* hole (D23, D32, budget 2 000 tokens): what the hole is for and where it is
|
|
4
|
+
* called, its generated signature (or, for a view, the SQL columns it must
|
|
5
|
+
* produce and where its body lives), the fields it reads with their types,
|
|
6
|
+
* the examples its test rests on, the spec lines that cite it, its normalized
|
|
7
|
+
* shape, the library's neighbours of the same shape (D24 — bodies filled
|
|
8
|
+
* elsewhere, as templates), and the conventions a body obeys. French prose:
|
|
9
|
+
* a document for the humans and agents of the project; identifiers stay
|
|
10
|
+
* English.
|
|
11
|
+
*/
|
|
12
|
+
import type { HoleLibraryEntry } from "../hole-shape.js";
|
|
13
|
+
import type { FeaturePlan, HolePlan } from "./plan.js";
|
|
14
|
+
export declare const MARKDOWN_HEADER_PREFIX = "<!-- @generated by ogygie-generate ";
|
|
15
|
+
export declare function markdownGeneratedHeader(version: string): string;
|
|
16
|
+
/** The operations calling a hole, as `\`id\` (METHOD /path)` — shared with the spec's generated contracts. */
|
|
17
|
+
export declare function carriersOf(hole: HolePlan, plan: FeaturePlan): string[];
|
|
18
|
+
export declare function emitHoleDoc(plan: FeaturePlan, hole: HolePlan, library: readonly HoleLibraryEntry[]): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Emits `holes.gen.test.ts`: the PURE test of every hole, derived from
|
|
3
|
+
* its examples (D23, D32) — each accept example passes (a derive answers its
|
|
4
|
+
* example output, a project shapes the example output from the example
|
|
5
|
+
* context), the reject example answers the hole's code with a non-empty
|
|
6
|
+
* suggestedFix (and, for a transform, the faulty line). Red at generation,
|
|
7
|
+
* since a `todo` body throws; what lot 2 bis will run a candidate body
|
|
8
|
+
* against, in milliseconds, without the bench. A view hole has no pure test:
|
|
9
|
+
* its SQL is proven on the bench by the behavior tests, and documented in its
|
|
10
|
+
* holes/<id>.gen.md.
|
|
11
|
+
*/
|
|
12
|
+
import { type FieldModel } from "../zod-introspection.js";
|
|
13
|
+
import type { FeaturePlan, OperationPlan } from "./plan.js";
|
|
14
|
+
/** A partial example laid over a full sample, arrays merged by position — so the test parses a COMPLETE output. */
|
|
15
|
+
export declare function deepOverlay(base: unknown, overlay: unknown): unknown;
|
|
16
|
+
/** A COMPLETE value of the model under a partial example: every field the example omits is sampled, every array item completed by its element. */
|
|
17
|
+
export declare function sampleUnder(model: FieldModel, overlay: unknown): unknown;
|
|
18
|
+
/** The complete output a project hole receives in its test: the read's output sample under the example's input. */
|
|
19
|
+
export declare function projectInputOf(plan: FeaturePlan, carrier: OperationPlan, partial: unknown): unknown;
|
|
20
|
+
/** The instant the emitted tests freeze the clock at — the same one `tests.ts` uses, so a hole and its operation see one today (épreuve pdlc 2026-10-29). */
|
|
21
|
+
export declare const HOLE_TESTS_CLOCK_INSTANT = "2026-01-01T00:00:00.000Z";
|
|
22
|
+
/** A hole that declares the clock effect receives it as its second parameter: the test passes the frozen one. */
|
|
23
|
+
export declare function holeDeclaresClock(hole: {
|
|
24
|
+
hole: {
|
|
25
|
+
effects?: readonly string[];
|
|
26
|
+
};
|
|
27
|
+
}): boolean;
|
|
28
|
+
export declare function emitHoleTests(plan: FeaturePlan): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { FeaturePlan, OperationPlan } from "./plan.js";
|
|
2
|
+
export interface ManifestRouteEntry {
|
|
3
|
+
method: string;
|
|
4
|
+
path: string;
|
|
5
|
+
description: string;
|
|
6
|
+
schemaInput: string;
|
|
7
|
+
schemaOutput: string;
|
|
8
|
+
invalidates?: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface GeneratedManifestEntry {
|
|
11
|
+
routes: ManifestRouteEntry[];
|
|
12
|
+
dbTables: string[];
|
|
13
|
+
}
|
|
14
|
+
/** What the map says about the feature today — the two generated fields, as declared. */
|
|
15
|
+
export interface DeclaredManifestEntry {
|
|
16
|
+
routes: unknown;
|
|
17
|
+
dbTables: unknown;
|
|
18
|
+
}
|
|
19
|
+
export type ManifestEntryField = "routes" | "dbTables";
|
|
20
|
+
export interface ApplyManifestEntryResult {
|
|
21
|
+
manifest: Record<string, unknown>;
|
|
22
|
+
/** `created` when no entry carried the feature's name, `updated` when a generated field changed. */
|
|
23
|
+
outcome: "created" | "updated" | "unchanged";
|
|
24
|
+
}
|
|
25
|
+
/** The French sentence the map shows for a route — domain-free words, identifiers in backticks. */
|
|
26
|
+
export declare function routeDescriptionOf(operation: OperationPlan, plan: FeaturePlan): string;
|
|
27
|
+
export declare function manifestEntryOf(plan: FeaturePlan): GeneratedManifestEntry;
|
|
28
|
+
/** The generated fields the declared entry gets wrong — empty when the map tells the truth. */
|
|
29
|
+
export declare function manifestEntryDrift(declared: DeclaredManifestEntry | undefined, plan: FeaturePlan): Array<ManifestEntryField | "entry">;
|
|
30
|
+
/** First paragraph of the spec's `# @intent` section, one line — null when the section has none. */
|
|
31
|
+
export declare function intentOfSpec(markdown: string): string | null;
|
|
32
|
+
/** The intent as the manifest accepts it: whole sentences within the core's bounds. */
|
|
33
|
+
export declare function intentForManifest(intent: string | null, specPath: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* The manifest with the feature's generated fields in place. The raw JSON is
|
|
36
|
+
* taken as parsed (never through the core's schema, which strips the keys it
|
|
37
|
+
* does not know): everything but `routes` and `dbTables` of the entry is left
|
|
38
|
+
* untouched, and a feature absent from `features[]` is added after the others.
|
|
39
|
+
*/
|
|
40
|
+
/** The status a created entry gets: `skeleton` while the spec is still `draft` (a folder on a branch is a proposal, not a delivery — verify-specs refuses `in-progress` under a draft), `in-progress` once it is validated; `delivered` stays a human word (D25). */
|
|
41
|
+
export declare function entryStatusForSpec(specStatus: string | null | undefined): "skeleton" | "in-progress";
|
|
42
|
+
export declare function applyManifestEntry(rawManifest: unknown, plan: FeaturePlan, intent: string | null, entryStatus?: "skeleton" | "in-progress"): ApplyManifestEntryResult;
|
|
43
|
+
/** The manifest as the repo keeps it: two-space JSON and a final newline. */
|
|
44
|
+
export declare function serializeManifest(manifest: Record<string, unknown>): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Emits `repository.gen.ts` for the SQL Server target (D33,
|
|
3
|
+
* `mssql-raw`): the only file of the feature touching the database, through
|
|
4
|
+
* the product's `Database.query` port — parameterised T-SQL (`@name`), never a
|
|
5
|
+
* concatenation —, the row types the driver answers (dates as Date), the
|
|
6
|
+
* statements as an exported `SQL` constant (the stub answers the SAME texts),
|
|
7
|
+
* and the functions the service calls, named like the Postgres ones: the
|
|
8
|
+
* reads, the slot and reference reads, the view reads, the keyed writes of D28
|
|
9
|
+
* (load by key or the operation's 404; update the fields sent through
|
|
10
|
+
* COALESCE, OUTPUT INSERTED telling written from not found; set or clear a slot
|
|
11
|
+
* with the idempotent rule of D31; delete unless referenced, 409 with the
|
|
12
|
+
* count in cause), uniqueKey (409 on a taken key, the unique constraint as the
|
|
13
|
+
* belt) and the signature of every write. No tenant column: the target has
|
|
14
|
+
* no tenant.
|
|
15
|
+
*/
|
|
16
|
+
import type { FeaturePlan } from "../plan.js";
|
|
17
|
+
export declare function emitMssqlRepository(plan: FeaturePlan): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent What the SQL Server target (D33, `mssql-raw`) makes of a column
|
|
3
|
+
* plan: the T-SQL type for the Postgres type the plan carries, the PascalCase
|
|
4
|
+
* column name when the target says `naming: pascal`, and the qualified table
|
|
5
|
+
* name under the target's schema. One place, so the migration, the repository
|
|
6
|
+
* and the stub agree on every name — the stub is emitted from the SAME source
|
|
7
|
+
* as the SQL it answers.
|
|
8
|
+
*/
|
|
9
|
+
import type { ColumnPlan, FeaturePlan, TablePlan } from "../plan.js";
|
|
10
|
+
/** `label` → `Label` (pascal) or `label` (camel) — of the LOGICAL column name, which an adopted table may declare apart from the key (D36). */
|
|
11
|
+
export declare function sqlColumnName(plan: FeaturePlan, column: Pick<ColumnPlan, "columnName">): string;
|
|
12
|
+
/** The column of a table by its TS key, or a loud failure — the emitters never guess a column. */
|
|
13
|
+
export declare function columnNamed(table: TablePlan, key: string): ColumnPlan;
|
|
14
|
+
/** `grades` → `app.grades` under a schema, `grades` without. */
|
|
15
|
+
export declare function qualifiedTable(plan: FeaturePlan, sqlName: string): string;
|
|
16
|
+
/** The T-SQL type of a column, from the Postgres type the plan resolved from the Zod structure. */
|
|
17
|
+
export declare function tsqlTypeOf(column: ColumnPlan): string;
|
|
18
|
+
/** The CHECK a column carries, translated: `in (...)` keeps its values. */
|
|
19
|
+
export declare function tsqlCheckOf(plan: FeaturePlan, column: ColumnPlan): string | null;
|
|
20
|
+
/** The columns a table writes — never the one the database defaults (`id` when it has a default). */
|
|
21
|
+
export declare function tableColumns(table: TablePlan): ColumnPlan[];
|
|
22
|
+
/** The TypeScript type of a row field as the driver returns it: dates come back as Date, numbers as number. */
|
|
23
|
+
export declare function tsRowTypeOf(column: ColumnPlan): string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent The T-SQL statements of a feature on the SQL Server target (D33,
|
|
3
|
+
* `mssql-raw`), as DATA: one descriptor per statement — its key in the `SQL`
|
|
4
|
+
* constant the repository exports, its text with `@named` parameters, the
|
|
5
|
+
* table it touches and what it MEANS (`kind`) — so the repository emits the
|
|
6
|
+
* text and the stub emits, from the same descriptors, the in-memory answer of
|
|
7
|
+
* each statement (D33: the stub is emitted with the SQL, nothing can drift
|
|
8
|
+
* between a query and its simulated reply). Columns are read back under their
|
|
9
|
+
* camelCase alias (`g.Label AS label`), the keyed writes answer through
|
|
10
|
+
* `OUTPUT INSERTED` / `OUTPUT DELETED` so a miss is an empty result, a limit
|
|
11
|
+
* is `OFFSET … FETCH`.
|
|
12
|
+
*/
|
|
13
|
+
import type { ColumnPlan, FeaturePlan, SlotPlan } from "../plan.js";
|
|
14
|
+
export type StatementKind = "selectAll" | "selectByKey" | "selectByUniqueKey" | "countByColumn" | "countByKey" | "insert" | "updateByKey" | "selectSlot" | "insertSlot" | "updateSlotById" | "updateSlotByKey" | "deleteById" | "deleteSlotByKey" | "deleteByKey" | "selectView";
|
|
15
|
+
export interface Statement {
|
|
16
|
+
/** Key in the exported `SQL` constant, e.g. `selectListAll`. */
|
|
17
|
+
key: string;
|
|
18
|
+
kind: StatementKind;
|
|
19
|
+
text: string;
|
|
20
|
+
/** The owned table (or view) the statement touches, by SQL name. */
|
|
21
|
+
table: string;
|
|
22
|
+
/** Row type the statement returns (its camelCase aliases). */
|
|
23
|
+
rowType: string;
|
|
24
|
+
/** Parameter names in `@name` order of appearance. */
|
|
25
|
+
parameters: string[];
|
|
26
|
+
/** Extra meaning the stub needs: ordering, limit, the columns written, the key or slot fields. */
|
|
27
|
+
order?: Array<{
|
|
28
|
+
field: string;
|
|
29
|
+
direction: "asc" | "desc";
|
|
30
|
+
enumValues: Array<string | number> | null;
|
|
31
|
+
}>;
|
|
32
|
+
limit?: number | null;
|
|
33
|
+
written?: string[];
|
|
34
|
+
keyField?: string;
|
|
35
|
+
slot?: {
|
|
36
|
+
parentKey: string;
|
|
37
|
+
key: string;
|
|
38
|
+
value: string;
|
|
39
|
+
};
|
|
40
|
+
unique?: string[];
|
|
41
|
+
countColumn?: string;
|
|
42
|
+
signed?: {
|
|
43
|
+
by: string;
|
|
44
|
+
at: string;
|
|
45
|
+
} | null;
|
|
46
|
+
/** The fields an OUTPUT clause hands back when it is not the whole row: `["id"]`, or the key fields of a table without id (D36). */
|
|
47
|
+
outputs?: string[];
|
|
48
|
+
}
|
|
49
|
+
/** `g.Id AS id, g.Code AS code, …` for every column of a table. */
|
|
50
|
+
export declare function selectList(plan: FeaturePlan, prefix: string, columns: readonly ColumnPlan[]): string;
|
|
51
|
+
export declare function mssqlStatements(plan: FeaturePlan): Statement[];
|
|
52
|
+
/** The statement of a key, or a loud failure — the emitters never guess a name. */
|
|
53
|
+
export declare function statementNamed(statements: readonly Statement[], key: string): Statement;
|
|
54
|
+
/** The slot plan a statement belongs to. */
|
|
55
|
+
export declare function slotOf(plan: FeaturePlan, statement: Statement): SlotPlan | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Emits `repository.stub.gen.ts` for a SQL Server target tested on a
|
|
3
|
+
* stub (D33, `tests: stub`): an in-memory `Database` whose `query` answers the
|
|
4
|
+
* SAME statements the repository exports — matched on the exact text of the
|
|
5
|
+
* `SQL` constant, never on a fragment — by executing their meaning over plain
|
|
6
|
+
* arrays: a select returns the table ordered as the statement orders it, a
|
|
7
|
+
* keyed write answers OUTPUT rows (one per row touched, none when the key is
|
|
8
|
+
* unknown), an insert simulates the unique constraint (error 2627), a delete
|
|
9
|
+
* cascades the slot rows as the foreign key would, a view returns the rows the
|
|
10
|
+
* test arranged (a view's SQL is not run on a stub, D32). The stub is emitted
|
|
11
|
+
* from the statement descriptors the repository was emitted from: a repository
|
|
12
|
+
* that changes its SQL changes its stub in the same generation. `answer…Query`
|
|
13
|
+
* returns `undefined` for a text it does not know, so a product's own test kit
|
|
14
|
+
* can chain it with other stubs.
|
|
15
|
+
*/
|
|
16
|
+
import type { FeaturePlan } from "../plan.js";
|
|
17
|
+
export declare function emitMssqlStub(plan: FeaturePlan): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @intent Naming and header helpers every emitter shares (DECISIONS.md D21):
|
|
3
|
+
* the `@generated` header is LINE 1 of every emitted file, the `@intent` block
|
|
4
|
+
* comes next; identifiers derive mechanically from the feature id and the
|
|
5
|
+
* schema names (kebab → Pascal, camel → snake), so the same spec always yields
|
|
6
|
+
* the same names. Deterministic string building only — no clock, no random.
|
|
7
|
+
*/
|
|
8
|
+
export declare const GENERATOR_NAME = "ogygie-generate";
|
|
9
|
+
/** `// @generated by ogygie-generate <version> — do not edit` — line 1 of a TypeScript file. */
|
|
10
|
+
export declare function tsGeneratedHeader(version: string): string;
|
|
11
|
+
/** The same header for SQL, where `--` opens a comment. */
|
|
12
|
+
export declare function sqlGeneratedHeader(version: string): string;
|
|
13
|
+
/** A `/** @intent … *\/` block from wrapped lines. */
|
|
14
|
+
export declare function intentBlock(lines: readonly string[]): string;
|
|
15
|
+
/** Wraps a sentence at ~78 columns on word boundaries, for comments. */
|
|
16
|
+
export declare function wrap(text: string, width?: number): string[];
|
|
17
|
+
/** `publication-de-taux` → `PublicationDeTaux`. */
|
|
18
|
+
export declare function pascalCaseOf(kebab: string): string;
|
|
19
|
+
/** `PublicationDeTaux` → `publicationDeTaux`. */
|
|
20
|
+
export declare function camelCaseOf(kebab: string): string;
|
|
21
|
+
/** `effectiveDate` → `effective_date`. */
|
|
22
|
+
export declare function snakeCaseOf(camel: string): string;
|
|
23
|
+
/** `rate_publications` → `ratePublications`. */
|
|
24
|
+
export declare function camelOfSnake(snake: string): string;
|
|
25
|
+
/** `CreateRateInputSchema` → `CreateRateInput` (AGENTS.md template 2: the inferred type sits next to the schema). */
|
|
26
|
+
export declare function typeNameOfSchema(schemaName: string): string;
|
|
27
|
+
/** `import` → `runImport` — service functions never collide with a reserved word. */
|
|
28
|
+
export declare function serviceFunctionNameOf(operationId: string): string;
|
|
29
|
+
/** Relative import path from a folder to a module, both repo-relative, `.ts` → `.js`, always `./`-or-`../`-prefixed. */
|
|
30
|
+
export declare function relativeImportPath(fromFolder: string, toModule: string): string;
|
|
31
|
+
/** A TypeScript string literal, JSON-quoted. */
|
|
32
|
+
export declare function quote(value: string): string;
|
|
33
|
+
/** Lines joined with newlines and a trailing newline — every emitted file ends with one. `null` omits a part; `""` is a blank line. */
|
|
34
|
+
export declare function fileOf(...parts: ReadonlyArray<string | null>): string;
|