@metaobjectsdev/codegen-ts 0.21.5 → 0.22.0-rc.1
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/projection/build-projection-views.d.ts.map +1 -1
- package/dist/projection/build-projection-views.js +6 -4
- package/dist/projection/build-projection-views.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts.map +1 -1
- package/dist/projection/extract-view-spec.js +3 -3
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/projection/projection-detector.d.ts.map +1 -1
- package/dist/projection/projection-detector.js +7 -3
- package/dist/projection/projection-detector.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +5 -2
- package/dist/runner.js.map +1 -1
- package/dist/source-detect.d.ts.map +1 -1
- package/dist/source-detect.js +17 -15
- package/dist/source-detect.js.map +1 -1
- package/dist/templates/callable-file.d.ts.map +1 -1
- package/dist/templates/callable-file.js +4 -2
- package/dist/templates/callable-file.js.map +1 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +4 -1
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/projection-decl.d.ts.map +1 -1
- package/dist/templates/projection-decl.js +8 -4
- package/dist/templates/projection-decl.js.map +1 -1
- package/dist/templates/view-decl.d.ts +9 -0
- package/dist/templates/view-decl.d.ts.map +1 -1
- package/dist/templates/view-decl.js +14 -6
- package/dist/templates/view-decl.js.map +1 -1
- package/dist/templates/zod-validators.d.ts +4 -0
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +3 -2
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +14 -0
- package/src/projection/build-projection-views.ts +10 -9
- package/src/projection/extract-view-spec.ts +4 -5
- package/src/projection/projection-detector.ts +7 -7
- package/src/reference/entity.ts +6 -1
- package/src/reference/queries.ts +6 -1
- package/src/runner.ts +5 -2
- package/src/source-detect.ts +18 -11
- package/src/templates/callable-file.ts +5 -2
- package/src/templates/entity-file.ts +4 -1
- package/src/templates/projection-decl.ts +8 -4
- package/src/templates/view-decl.ts +23 -7
- package/src/templates/zod-validators.ts +3 -2
|
@@ -12,7 +12,7 @@ import { FIELD_ATTR_OBJECT_REF } from "@metaobjectsdev/metadata";
|
|
|
12
12
|
import { fieldDeclaringPackage, type RenderContext } from "../render-context.js";
|
|
13
13
|
import { renderDrizzleSchema } from "./drizzle-schema.js";
|
|
14
14
|
import { renderInferredTypes, renderEnumTypeAliases } from "./inferred-types.js";
|
|
15
|
-
import { renderZodValidators, isTphSubtype } from "./zod-validators.js";
|
|
15
|
+
import { renderZodValidators, isTphSubtype, primaryIdentityFieldNames } from "./zod-validators.js";
|
|
16
16
|
import { renderEntityConstants } from "./entity-constants.js";
|
|
17
17
|
import { renderFilterAllowlist, renderSortAllowlist } from "./filter-allowlist.js";
|
|
18
18
|
import { renderFilterType } from "./filter-type.js";
|
|
@@ -143,6 +143,9 @@ export function renderEntityFile(
|
|
|
143
143
|
};
|
|
144
144
|
const viewOpts = {
|
|
145
145
|
dialect: ctx.dialect, columnNamingStrategy: ctx.columnNamingStrategy, timestampMode: ctx.timestampMode, voRef,
|
|
146
|
+
// PK fields type non-null in the replica-view decl + read schema even
|
|
147
|
+
// without @required (a PK is never NULL; see ViewDeclOpts.pkFieldNames).
|
|
148
|
+
pkFieldNames: new Set(primaryIdentityFieldNames(entity)) as ReadonlySet<string>,
|
|
146
149
|
};
|
|
147
150
|
const z = imp("z@zod");
|
|
148
151
|
const docs = renderDocsFor(entity);
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { code, imp, joinCode, type Code } from "ts-poet";
|
|
11
11
|
import {
|
|
12
|
-
MetaField, MetaObject, type MetaRoot,
|
|
12
|
+
MetaField, MetaObject, type MetaRoot, isMetaObject,
|
|
13
13
|
FIELD_ATTR_OBJECT_REF, stripPackage,
|
|
14
14
|
} from "@metaobjectsdev/metadata";
|
|
15
15
|
import { projectionViewName } from "../projection/extract-view-spec.js";
|
|
@@ -22,6 +22,7 @@ import { renderFilterAllowlist, renderSortAllowlist } from "./filter-allowlist.j
|
|
|
22
22
|
import { renderFilterType } from "./filter-type.js";
|
|
23
23
|
import { inferViewKind, currencyMetaFor, labelFor } from "./field-meta.js";
|
|
24
24
|
import { renderExistingViewDecl, renderViewReadZodObject } from "./view-decl.js";
|
|
25
|
+
import { primaryIdentityFieldNames } from "./zod-validators.js";
|
|
25
26
|
|
|
26
27
|
// ---------------------------------------------------------------------------
|
|
27
28
|
// Public interface
|
|
@@ -125,7 +126,7 @@ export function renderProjectionDecl(
|
|
|
125
126
|
const superName = superModel?.name ?? projection.superRef;
|
|
126
127
|
if (superName) {
|
|
127
128
|
const baseObj =
|
|
128
|
-
superModel
|
|
129
|
+
isMetaObject(superModel) ? superModel : root.findObject(superName);
|
|
129
130
|
if (baseObj) {
|
|
130
131
|
// fields() returns effective fields, so inherited fields (from extends:/super:) are included.
|
|
131
132
|
for (const f of baseObj.fields()) allFields.push(f);
|
|
@@ -152,15 +153,18 @@ export function renderProjectionDecl(
|
|
|
152
153
|
const camelName = projName.charAt(0).toLowerCase() + projName.slice(1);
|
|
153
154
|
const path = pathFromProjectionName(projName);
|
|
154
155
|
|
|
156
|
+
// The projection's primary-identity fields type non-null in the view decl +
|
|
157
|
+
// read schema even without @required (a PK is never NULL; see ViewDeclOpts).
|
|
158
|
+
const pkFieldNames: ReadonlySet<string> = new Set(primaryIdentityFieldNames(projection));
|
|
155
159
|
const sections: Code[] = [
|
|
156
160
|
...(includeViewDecl
|
|
157
161
|
? [renderExistingViewDecl(allFields, viewName, `${camelName}View`, {
|
|
158
|
-
dialect, columnNamingStrategy, timestampMode, voRef,
|
|
162
|
+
dialect, columnNamingStrategy, timestampMode, voRef, pkFieldNames,
|
|
159
163
|
})]
|
|
160
164
|
: []),
|
|
161
165
|
code`
|
|
162
166
|
export const ${projName}Schema = ${renderViewReadZodObject(allFields, {
|
|
163
|
-
dialect, columnNamingStrategy, timestampMode, voRef,
|
|
167
|
+
dialect, columnNamingStrategy, timestampMode, voRef, pkFieldNames,
|
|
164
168
|
})};
|
|
165
169
|
`,
|
|
166
170
|
code`
|
|
@@ -29,6 +29,15 @@ export interface ViewDeclOpts {
|
|
|
29
29
|
* `RenderContext.resolveValueObjectName` + `valueObjectModuleSpecifier`.
|
|
30
30
|
*/
|
|
31
31
|
readonly voRef: (field: MetaField) => { name: string; module: string };
|
|
32
|
+
/**
|
|
33
|
+
* Field names of the owning object's PRIMARY identity (see
|
|
34
|
+
* `primaryIdentityFieldNames` in zod-validators). A PK column sits on the FROM
|
|
35
|
+
* side of every synthesized view, so it is never NULL even when the field
|
|
36
|
+
* carries no `@required` — the view column gets `.notNull()` and the read
|
|
37
|
+
* schema stays non-nullable, matching the generated api-docs, queries and
|
|
38
|
+
* UpdateSchema, all of which already treat the PK as non-null.
|
|
39
|
+
*/
|
|
40
|
+
readonly pkFieldNames: ReadonlySet<string>;
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
/**
|
|
@@ -49,9 +58,13 @@ function viewColumnLine(f: MetaField, opts: ViewDeclOpts): Code {
|
|
|
49
58
|
// typing) and `.notNull()` (shapes the SELECT type) carry to an existing view;
|
|
50
59
|
// `.primaryKey()`/`.default()`/`.references()`/`.unique()` are table-DDL concerns
|
|
51
60
|
// and invalid on a `.existing()` view declaration. Preserve the canonical order.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
// A primary-identity column additionally gains `.notNull()`: on the table side
|
|
62
|
+
// its non-null comes from `.primaryKey()` (which the view cannot carry), so
|
|
63
|
+
// without this the view SELECT type — and the Zod read schema derived from it —
|
|
64
|
+
// typed the PK `T | null` for a column that can never be NULL.
|
|
65
|
+
const kept = spec.modifiers.filter((m) => m === ".array()" || m === ".notNull()");
|
|
66
|
+
if (opts.pkFieldNames.has(f.name) && !kept.includes(".notNull()")) kept.push(".notNull()");
|
|
67
|
+
const viewModifiers = kept.join("");
|
|
55
68
|
// Narrow the column to its resolved element/value type — `.$type<…>()` — mirroring
|
|
56
69
|
// the entity column so the read row is typed (not `unknown`) and an array column
|
|
57
70
|
// reads as `T[]`, not `T`.
|
|
@@ -113,10 +126,13 @@ export function renderViewReadZodObject(fields: readonly MetaField[], opts: View
|
|
|
113
126
|
const { dialect, columnNamingStrategy, timestampMode } = opts;
|
|
114
127
|
const z = imp("z@zod");
|
|
115
128
|
const lines: Code[] = fields.map((f) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
// Non-null when the column is `.notNull()` OR it is a primary-identity
|
|
130
|
+
// field — a PK is never NULL, but its table-side non-null is expressed via
|
|
131
|
+
// `.primaryKey()`, not a `.notNull()` modifier (see viewColumnLine above).
|
|
132
|
+
const nonNull =
|
|
133
|
+
mapColumnType(f, dialect, columnNamingStrategy, timestampMode).modifiers.includes(".notNull()") ||
|
|
134
|
+
opts.pkFieldNames.has(f.name);
|
|
135
|
+
const nullable = nonNull ? "" : ".nullable()";
|
|
120
136
|
const hasObjectRef =
|
|
121
137
|
f.subType === FIELD_SUBTYPE_OBJECT &&
|
|
122
138
|
typeof f.attr(FIELD_ATTR_OBJECT_REF) === "string" &&
|
|
@@ -129,8 +129,9 @@ ${joinCode(fieldLines, { on: ",\n" })}
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/** Field names participating in the object's PRIMARY identity, normalized to a
|
|
132
|
-
* list. Empty when the object has no primary identity.
|
|
133
|
-
|
|
132
|
+
* list. Empty when the object has no primary identity. Exported for the
|
|
133
|
+
* view-decl read-schema path, which must type PK columns non-null too. */
|
|
134
|
+
export function primaryIdentityFieldNames(obj: MetaObject): string[] {
|
|
134
135
|
const primary = obj.primaryIdentity();
|
|
135
136
|
if (!primary) return [];
|
|
136
137
|
const fields = primary.attr(IDENTITY_ATTR_FIELDS);
|