fimo 0.4.0-experimental.5 → 0.4.0-staging.2
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/assets/content-templates/hooks-template.eta +41 -3
- package/assets/content-templates/types-template.eta +29 -10
- package/assets/skills/fimo/references/content.md +18 -1
- package/assets/skills/fimo-cli/references/content.md +6 -2
- package/dist/cli/bundle.json +2 -2
- package/dist/cli/index.js +75 -8
- package/dist/runtime/primitives/index.d.ts +1 -1
- package/dist/runtime/primitives/index.d.ts.map +1 -1
- package/dist/runtime/primitives/lib/index.d.ts +1 -1
- package/dist/runtime/primitives/lib/index.d.ts.map +1 -1
- package/dist/runtime/primitives/lib/primitives.d.ts +5 -0
- package/dist/runtime/primitives/lib/primitives.d.ts.map +1 -1
- package/dist/runtime/primitives/lib/query.d.ts +2 -2
- package/dist/runtime/primitives/lib/query.d.ts.map +1 -1
- package/dist/scripts/generated-types.test.d.ts +1 -0
- package/dist/scripts/generated-types.test.js +172 -0
- package/dist/scripts/sync-schemas.js +22 -3
- package/dist/scripts/validate-schemas.js +39 -4
- package/package.json +1 -1
- package/scripts/lib/release-core.mjs +24 -0
- package/scripts/lib/release-core.test.ts +37 -2
- package/scripts/publish-npm.mjs +4 -9
- package/templates/react-router/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<%
|
|
2
2
|
/**
|
|
3
3
|
* INPUT ▸ model = {
|
|
4
|
-
* uid: "
|
|
5
|
-
* pascal: "
|
|
6
|
-
* fields: {key: {type, required?, multiple?}}
|
|
4
|
+
* uid: "Post", // matches src/schemas/<uid>.json (letters, numbers, underscores)
|
|
5
|
+
* pascal: "Post", // pascalCase(uid), used for generated type names
|
|
6
|
+
* fields: {key: {type, required?, multiple?, many?, target?, targetPascal?}},
|
|
7
|
+
* relationImports: [{uid, pascal}] // relation targets other than this schema
|
|
7
8
|
* }
|
|
8
9
|
*/
|
|
9
10
|
%>
|
|
@@ -80,6 +81,20 @@ if (model.fields) {
|
|
|
80
81
|
}
|
|
81
82
|
break;
|
|
82
83
|
case 'reference': {
|
|
84
|
+
if (Array.isArray(field.targetRefs) && field.targetRefs.length > 0) {
|
|
85
|
+
const wrapperFor = (ref) => ref.uid === model.uid ? 'wrapWithSource' : `wrap${ref.pascal}WithSource`;
|
|
86
|
+
const wrappers = `{ ${field.targetRefs.map((ref) => `"${ref.uid}": ${wrapperFor(ref)}`).join(', ')} }`;
|
|
87
|
+
if (field.many) {
|
|
88
|
+
-%>
|
|
89
|
+
<%= key %>: Array.isArray(entry.<%= key %>) ? entry.<%= key %>.map((value: any) => wrapPolymorphic(value, <%= wrappers %>)) : entry.<%= key %>,
|
|
90
|
+
<%
|
|
91
|
+
} else {
|
|
92
|
+
-%>
|
|
93
|
+
<%= key %>: wrapPolymorphic(entry.<%= key %>, <%= wrappers %>),
|
|
94
|
+
<%
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
83
98
|
const wrapper = field.target === model.uid ? 'wrapWithSource' : `wrap${field.targetPascal}WithSource`;
|
|
84
99
|
if (field.many) {
|
|
85
100
|
-%>
|
|
@@ -103,6 +118,29 @@ if (model.fields) {
|
|
|
103
118
|
} as <%= model.pascal %>;
|
|
104
119
|
}
|
|
105
120
|
|
|
121
|
+
<%
|
|
122
|
+
const hasPolymorphicReferences = model.fields && Object.values(model.fields).some((field) => field.type === 'reference' && Array.isArray(field.targetRefs) && field.targetRefs.length > 0);
|
|
123
|
+
if (hasPolymorphicReferences) {
|
|
124
|
+
-%>
|
|
125
|
+
/**
|
|
126
|
+
* Wraps one polymorphic reference value. Populated entries carry their type
|
|
127
|
+
* marker; the wrapper picks the right per-type wrapping and stamps a
|
|
128
|
+
* top-level $type so the generated union narrows in a switch. Raw
|
|
129
|
+
* (unpopulated) values pass through untouched.
|
|
130
|
+
*/
|
|
131
|
+
function wrapPolymorphic(value: any, wrappers: Record<string, (entry: Record<string, any>) => any>): any {
|
|
132
|
+
if (value == null || typeof value !== "object" || typeof value.id !== "string") return value;
|
|
133
|
+
const contentType = value.__fimo && typeof value.__fimo.contentType === "string" ? value.__fimo.contentType : null;
|
|
134
|
+
const wrapper = contentType ? wrappers[contentType] : undefined;
|
|
135
|
+
if (!wrapper) return value;
|
|
136
|
+
const wrapped = wrapper(value) as Record<string, unknown>;
|
|
137
|
+
wrapped.$type = contentType;
|
|
138
|
+
return wrapped;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
<%
|
|
142
|
+
}
|
|
143
|
+
-%>
|
|
106
144
|
/*───────────────────────────────────────────────────────────────*/
|
|
107
145
|
/* ──────────── 🔌 Low-level fetch helpers ──────────── */
|
|
108
146
|
/*───────────────────────────────────────────────────────────────*/
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<%
|
|
2
2
|
/**
|
|
3
3
|
* INPUT ▸ model = {
|
|
4
|
-
* uid: "
|
|
5
|
-
* pascal: "
|
|
6
|
-
* fields: {key: {type, required?, multiple?}}
|
|
4
|
+
* uid: "Post", // matches src/schemas/<uid>.json (letters, numbers, underscores)
|
|
5
|
+
* pascal: "Post", // pascalCase(uid), used for generated type names
|
|
6
|
+
* fields: {key: {type, required?, multiple?, many?, target?, targetPascal?}},
|
|
7
|
+
* relationImports: [{uid, pascal}] // relation targets other than this schema
|
|
7
8
|
* }
|
|
8
9
|
*/
|
|
9
10
|
%>
|
|
10
11
|
// AUTO-GENERATED ⚠️ – do not edit by hand
|
|
11
|
-
import { type Fields, type FimoBoolean, type FimoMedia, type FimoReference, type FimoRichText, type FimoRichTextContent, type FimoString, type Populate, type PopulatedResult, type ProjectedWithPopulate, type Query, type Sort, type Where, type WithReferences } from "fimo/ui";
|
|
12
|
+
import { type Fields, type FimoBoolean, type FimoMedia, type FimoPolymorphicReference, type FimoReference, type FimoRichText, type FimoRichTextContent, type FimoString, type Populate, type PopulatedResult, type ProjectedWithPopulate, type Query, type Sort, type Where, type WithReferences } from "fimo/ui";
|
|
12
13
|
<%
|
|
13
14
|
if (model.referenceImports && model.referenceImports.length > 0) {
|
|
14
15
|
model.referenceImports.forEach((referenceImport) => {
|
|
@@ -51,6 +52,7 @@ if (model.fields) {
|
|
|
51
52
|
});
|
|
52
53
|
}
|
|
53
54
|
-%>
|
|
55
|
+
}
|
|
54
56
|
|
|
55
57
|
export interface <%= model.pascal %>Input {
|
|
56
58
|
slug?: string;
|
|
@@ -93,8 +95,10 @@ function getTypeForField(field) {
|
|
|
93
95
|
return 'Record<string, any>';
|
|
94
96
|
case 'media':
|
|
95
97
|
return field.multiple ? 'FimoMedia[]' : 'FimoMedia';
|
|
96
|
-
case 'reference':
|
|
97
|
-
|
|
98
|
+
case 'reference': {
|
|
99
|
+
const raw = Array.isArray(field.targets) && field.targets.length > 0 ? 'FimoPolymorphicReference' : 'FimoReference';
|
|
100
|
+
return field.many ? `${raw}[]` : `${raw} | null`;
|
|
101
|
+
}
|
|
98
102
|
default:
|
|
99
103
|
return 'any';
|
|
100
104
|
}
|
|
@@ -118,20 +122,35 @@ function getInputTypeForField(field) {
|
|
|
118
122
|
const media = 'Pick<FimoMedia, "url" | "alt" | "name" | "mime" | "width" | "height">';
|
|
119
123
|
return field.multiple ? `${media}[]` : media;
|
|
120
124
|
}
|
|
121
|
-
case 'reference':
|
|
122
|
-
|
|
125
|
+
case 'reference': {
|
|
126
|
+
const raw = Array.isArray(field.targets) && field.targets.length > 0 ? 'FimoPolymorphicReference' : 'FimoReference';
|
|
127
|
+
return field.many ? `${raw}[]` : `${raw} | null`;
|
|
128
|
+
}
|
|
123
129
|
default:
|
|
124
130
|
return 'unknown';
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
133
|
-%>
|
|
128
|
-
}
|
|
129
134
|
|
|
130
135
|
export interface <%= model.pascal %>References {
|
|
131
136
|
<%
|
|
132
137
|
if (model.fields) {
|
|
133
138
|
Object.entries(model.fields).forEach(([key, field]) => {
|
|
134
|
-
if (field.type !== 'reference'
|
|
139
|
+
if (field.type !== 'reference') {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// Polymorphic populated values form a discriminated union on $type —
|
|
143
|
+
// the generated wrapper stamps it, so `switch (item.$type)` narrows.
|
|
144
|
+
if (Array.isArray(field.targetRefs) && field.targetRefs.length > 0) {
|
|
145
|
+
const memberFor = (ref) => `(${ref.uid === model.uid ? model.pascal : ref.pascal} & { $type: "${ref.uid}" })`;
|
|
146
|
+
const union = field.targetRefs.map(memberFor).join(' | ');
|
|
147
|
+
const type = field.many ? `(${union})[]` : `${union} | null`;
|
|
148
|
+
-%>
|
|
149
|
+
<%= key %>: <%= type %>;
|
|
150
|
+
<%
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (typeof field.targetPascal !== 'string') {
|
|
135
154
|
return;
|
|
136
155
|
}
|
|
137
156
|
const type = field.many ? `${field.targetPascal}[]` : `${field.targetPascal} | null`;
|
|
@@ -224,7 +224,24 @@ For shared content, set `i18n: { "enabled": false }` on the schema and create ea
|
|
|
224
224
|
- ignore locale on owner reads and writes;
|
|
225
225
|
- still use the active/requested locale when a populated reference targets a localized schema.
|
|
226
226
|
|
|
227
|
-
Do not duplicate shared entries across locales or add field-level localization settings.
|
|
227
|
+
Do not duplicate shared entries across locales or add field-level localization settings.
|
|
228
|
+
|
|
229
|
+
A populated reference whose target has no variant in the requested locale resolves to null. Reads accept an opt-in `localeFallbacks: true` that resolves those to the best available variant instead (project default first), marked by its `locale` field — never implement fallbacks by hand; public reads stay strict unless the option is passed.
|
|
230
|
+
|
|
231
|
+
**Polymorphic references:** a field may declare `targets: ["Post", "Video"]` instead of a single `target` (never both) when one slot genuinely holds different types — mixed feeds, hero blocks, curated collections. Prefer a fixed `target` whenever every value is the same type: fixed fields keep `where` filtering and simpler generated types. Polymorphic values store `{ contentType, documentId }`; populated values in generated hooks carry a top-level `$type` that narrows the union:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
for (const item of page.featured) {
|
|
235
|
+
switch (item.$type) {
|
|
236
|
+
case 'Post':
|
|
237
|
+
return item.title; // typed as Post here
|
|
238
|
+
case 'Video':
|
|
239
|
+
return item.clips; // typed as Video here
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Filtering on polymorphic fields is not supported yet.
|
|
228
245
|
|
|
229
246
|
**Generated API:**
|
|
230
247
|
|
|
@@ -60,10 +60,14 @@ fimo entries list BlogPost --fields slug,title,author --populate author
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Use the canonical read query flags: `--search`, `--sort`, `--where`, `--limit`, `--offset`, `--fields`, and `--populate`.
|
|
63
|
-
`--where` is a JSON object keyed by schema field name. Simple values mean equality
|
|
63
|
+
`--where` is a JSON object keyed by schema field name. Simple values mean equality and stay typed inside the JSON (`{"featured":true}`, `{"category":"react"}`, `{"rank":{"$gte":3}}`); operator objects support `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$contains`, `$startsWith`, and `$null`, subject to the field type. Public Fimo-owned metadata lives under `__fimo`; currently `__fimo.contentType` is filterable.
|
|
64
|
+
|
|
65
|
+
Reference filters take the target `documentId` string even though stored values are objects (`{"author":"750e..."}`). On a to-many field, `$eq` and `$contains` mean membership, `$in` means any listed document is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted; use `--sort field` / `--sort -field` on scalar fields.
|
|
64
66
|
`--fields` is a comma-separated projection for list payloads. The API always keeps `id`; pass only the fields your view needs, such as `slug,title,excerpt,coverImage`.
|
|
65
67
|
|
|
66
|
-
`--populate` is a comma-separated list of reference fields to embed. Without
|
|
68
|
+
`--populate` is a comma-separated list of reference fields to embed. Without it, reference fields return reference objects like `{ "documentId": "..." }`; with `--populate author,contributors`, those fields return the target entry objects for the requested locale. Only reference fields can be populated (scalar fields 400), and populate never selects which target fields come back. A populated target missing in the requested locale resolves to null unless you pass `localeFallbacks=true`, which falls back to the best available locale variant, marked by its `locale` field. Limits: 200 references per to-many write, 500 distinct populated documents per field per request (400 past either).
|
|
69
|
+
|
|
70
|
+
Polymorphic references declare `targets: ["Post", "Product"]` instead of `target` (never both) and their values carry both parts: `{ "contentType": "Post", "documentId": "..." }`. Populate returns mixed full entries, and generated hooks expose `$type` on each populated value to branch on. `--where` on polymorphic fields is not supported yet and fails with a clear error.
|
|
67
71
|
|
|
68
72
|
In generated React code, the equivalent is `populate: ['author', 'contributors'] as const` in the schema hook/query params. Let hooks infer the result when possible; if a named TypeScript shape is needed, use the generated `BlogPostResult<TFields, TPopulate>` type documented in `fimo/references/content.md`. Writes use the separate generated `BlogPostInput` type.
|
|
69
73
|
|
package/dist/cli/bundle.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -42169,7 +42169,22 @@ function toReferenceValue(value) {
|
|
|
42169
42169
|
documentId
|
|
42170
42170
|
} : null;
|
|
42171
42171
|
}
|
|
42172
|
-
|
|
42172
|
+
function referenceContentType(value) {
|
|
42173
|
+
if (value && typeof value === "object" && "contentType" in value) {
|
|
42174
|
+
const contentType = value.contentType;
|
|
42175
|
+
return typeof contentType === "string" && contentType.length > 0 ? contentType : null;
|
|
42176
|
+
}
|
|
42177
|
+
return null;
|
|
42178
|
+
}
|
|
42179
|
+
function toPolymorphicReferenceValue(value) {
|
|
42180
|
+
const documentId = referenceDocumentId(value);
|
|
42181
|
+
const contentType = referenceContentType(value);
|
|
42182
|
+
return documentId && contentType ? {
|
|
42183
|
+
contentType,
|
|
42184
|
+
documentId
|
|
42185
|
+
} : null;
|
|
42186
|
+
}
|
|
42187
|
+
var ReferenceValueSchema, PolymorphicReferenceValueSchema;
|
|
42173
42188
|
var init_references = __esm({
|
|
42174
42189
|
"../../packages/api-contracts/dist/esm/types/references.js"() {
|
|
42175
42190
|
"use strict";
|
|
@@ -42179,6 +42194,12 @@ var init_references = __esm({
|
|
|
42179
42194
|
ReferenceValueSchema = external_exports.preprocess((value) => toReferenceValue(value) ?? value, external_exports.object({
|
|
42180
42195
|
documentId: external_exports.uuid()
|
|
42181
42196
|
}));
|
|
42197
|
+
__name(referenceContentType, "referenceContentType");
|
|
42198
|
+
__name(toPolymorphicReferenceValue, "toPolymorphicReferenceValue");
|
|
42199
|
+
PolymorphicReferenceValueSchema = external_exports.preprocess((value) => toPolymorphicReferenceValue(value) ?? value, external_exports.object({
|
|
42200
|
+
contentType: external_exports.string().min(1),
|
|
42201
|
+
documentId: external_exports.uuid()
|
|
42202
|
+
}));
|
|
42182
42203
|
}
|
|
42183
42204
|
});
|
|
42184
42205
|
|
|
@@ -47137,6 +47158,7 @@ function normalizeFields(fields) {
|
|
|
47137
47158
|
}
|
|
47138
47159
|
const field = value;
|
|
47139
47160
|
const target = typeof field.target === "string" ? field.target : void 0;
|
|
47161
|
+
const targets = Array.isArray(field.targets) ? field.targets.filter((candidate) => typeof candidate === "string") : void 0;
|
|
47140
47162
|
return [
|
|
47141
47163
|
key,
|
|
47142
47164
|
{
|
|
@@ -47144,6 +47166,8 @@ function normalizeFields(fields) {
|
|
|
47144
47166
|
type: typeof field.type === "string" ? field.type : void 0,
|
|
47145
47167
|
target,
|
|
47146
47168
|
targetPascal: target ? pascalCase(target) : void 0,
|
|
47169
|
+
targets: targets && targets.length > 0 ? targets : void 0,
|
|
47170
|
+
targetRefs: targets && targets.length > 0 ? targets.map((candidate) => ({ uid: candidate, pascal: pascalCase(candidate) })) : void 0,
|
|
47147
47171
|
many: typeof field.many === "boolean" ? field.many : void 0,
|
|
47148
47172
|
multiple: typeof field.multiple === "boolean" ? field.multiple : void 0
|
|
47149
47173
|
}
|
|
@@ -47154,10 +47178,16 @@ function normalizeFields(fields) {
|
|
|
47154
47178
|
function referenceImportsFor(schema, fields) {
|
|
47155
47179
|
const imports = /* @__PURE__ */ new Map();
|
|
47156
47180
|
for (const field of Object.values(fields)) {
|
|
47157
|
-
if (field.type !== "reference"
|
|
47181
|
+
if (field.type !== "reference") {
|
|
47158
47182
|
continue;
|
|
47159
47183
|
}
|
|
47160
|
-
|
|
47184
|
+
const targets = field.targets ?? (field.target ? [field.target] : []);
|
|
47185
|
+
for (const target of targets) {
|
|
47186
|
+
if (target === schema.uid) {
|
|
47187
|
+
continue;
|
|
47188
|
+
}
|
|
47189
|
+
imports.set(target, { uid: target, pascal: pascalCase(target) });
|
|
47190
|
+
}
|
|
47161
47191
|
}
|
|
47162
47192
|
return [...imports.values()].sort((a, b) => a.pascal.localeCompare(b.pascal));
|
|
47163
47193
|
}
|
|
@@ -47168,7 +47198,13 @@ function schemaToModel(schema, localizedByUid) {
|
|
|
47168
47198
|
pascal: pascalCase(schema.uid),
|
|
47169
47199
|
isSingleton: schema.isSingleton ?? false,
|
|
47170
47200
|
localized: schema.i18n?.enabled !== false,
|
|
47171
|
-
localizedReferenceFields: Object.entries(fields).filter(([, field]) =>
|
|
47201
|
+
localizedReferenceFields: Object.entries(fields).filter(([, field]) => {
|
|
47202
|
+
if (field.type !== "reference") {
|
|
47203
|
+
return false;
|
|
47204
|
+
}
|
|
47205
|
+
const targets = field.targets ?? (field.target ? [field.target] : []);
|
|
47206
|
+
return targets.some((target) => localizedByUid.get(target) !== false);
|
|
47207
|
+
}).map(([fieldName]) => fieldName),
|
|
47172
47208
|
fields,
|
|
47173
47209
|
referenceImports: referenceImportsFor(schema, fields)
|
|
47174
47210
|
};
|
|
@@ -103120,11 +103156,42 @@ function validateSchemaFile(absolutePath, file2, schemaUids = /* @__PURE__ */ ne
|
|
|
103120
103156
|
});
|
|
103121
103157
|
}
|
|
103122
103158
|
if (type === "reference") {
|
|
103123
|
-
const { target, many } = definition;
|
|
103124
|
-
if (
|
|
103159
|
+
const { target, targets, many } = definition;
|
|
103160
|
+
if (targets !== void 0 && target !== void 0) {
|
|
103161
|
+
errors2.push({
|
|
103162
|
+
rule: "schemas/reference-target",
|
|
103163
|
+
message: `Reference field "${fieldName}" declares both "target" and "targets" \u2014 a field is fixed or polymorphic, never both.`,
|
|
103164
|
+
file: file2
|
|
103165
|
+
});
|
|
103166
|
+
} else if (targets !== void 0) {
|
|
103167
|
+
const targetList = Array.isArray(targets) ? targets : null;
|
|
103168
|
+
if (!targetList || targetList.length === 0 || new Set(targetList).size !== targetList.length) {
|
|
103169
|
+
errors2.push({
|
|
103170
|
+
rule: "schemas/reference-target",
|
|
103171
|
+
message: `Reference field "${fieldName}" must declare "targets" as a non-empty array of unique content types.`,
|
|
103172
|
+
file: file2
|
|
103173
|
+
});
|
|
103174
|
+
} else {
|
|
103175
|
+
for (const candidate of targetList) {
|
|
103176
|
+
if (typeof candidate !== "string" || !CONTENT_TYPE_NAME_PATTERN.test(candidate)) {
|
|
103177
|
+
errors2.push({
|
|
103178
|
+
rule: "schemas/reference-target",
|
|
103179
|
+
message: `Reference field "${fieldName}" has an invalid entry in "targets".`,
|
|
103180
|
+
file: file2
|
|
103181
|
+
});
|
|
103182
|
+
} else if (schemaUids.size > 0 && !schemaUids.has(candidate)) {
|
|
103183
|
+
errors2.push({
|
|
103184
|
+
rule: "schemas/reference-target",
|
|
103185
|
+
message: `Reference field "${fieldName}" targets unknown schema "${candidate}".`,
|
|
103186
|
+
file: file2
|
|
103187
|
+
});
|
|
103188
|
+
}
|
|
103189
|
+
}
|
|
103190
|
+
}
|
|
103191
|
+
} else if (typeof target !== "string" || !CONTENT_TYPE_NAME_PATTERN.test(target)) {
|
|
103125
103192
|
errors2.push({
|
|
103126
103193
|
rule: "schemas/reference-target",
|
|
103127
|
-
message: `Reference field "${fieldName}" must declare a valid "target" content type.`,
|
|
103194
|
+
message: `Reference field "${fieldName}" must declare a valid "target" content type (or "targets" for a polymorphic field).`,
|
|
103128
103195
|
file: file2
|
|
103129
103196
|
});
|
|
103130
103197
|
} else if (schemaUids.size > 0 && !schemaUids.has(target)) {
|
|
@@ -103142,7 +103209,7 @@ function validateSchemaFile(absolutePath, file2, schemaUids = /* @__PURE__ */ ne
|
|
|
103142
103209
|
});
|
|
103143
103210
|
}
|
|
103144
103211
|
} else {
|
|
103145
|
-
for (const referenceOnlyKey of ["target", "many"]) {
|
|
103212
|
+
for (const referenceOnlyKey of ["target", "targets", "many"]) {
|
|
103146
103213
|
if (referenceOnlyKey in definition) {
|
|
103147
103214
|
errors2.push({
|
|
103148
103215
|
rule: "schemas/reference-shape",
|
|
@@ -6,6 +6,6 @@ export { Date } from './components/Date.js';
|
|
|
6
6
|
export { Boolean } from './components/Boolean.js';
|
|
7
7
|
export { RichText } from './components/RichText.js';
|
|
8
8
|
export { useLabels, useTranslations } from './translations.js';
|
|
9
|
-
export { FimoString, FimoDate, FimoMedia, FimoBoolean, FimoRichText, type FimoReference, type FimoSource, type FimoPart, type FimoRichTextContent, type FimoRichTextNodeProps, type FimoRichTextMarkProps, type FimoRichTextComponents, FIMO_SOURCE, FIMO_PARTS, isFimoString, isFimoDate, hasFimoSource, getFimoSource, getFimoParts, fimo, useFimoLiveValue, } from './lib/index.js';
|
|
9
|
+
export { FimoString, FimoDate, FimoMedia, FimoBoolean, FimoRichText, type FimoPolymorphicReference, type FimoReference, type FimoSource, type FimoPart, type FimoRichTextContent, type FimoRichTextNodeProps, type FimoRichTextMarkProps, type FimoRichTextComponents, FIMO_SOURCE, FIMO_PARTS, isFimoString, isFimoDate, hasFimoSource, getFimoSource, getFimoParts, fimo, useFimoLiveValue, } from './lib/index.js';
|
|
10
10
|
export type { BoolOps, DateOps, Field, Fields, FilterFor, NullOnlyOps, NumberOps, Populate, Populated, PopulatedResult, Projected, ProjectedWithPopulate, Query, ReferenceField, ReferenceMap, ScalarOps, Sort, SortField, StringOps, WithReferences, Where, } from './lib/index.js';
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/primitives/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG/D,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACZ,IAAI,EACJ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,OAAO,EACP,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,SAAS,EACT,qBAAqB,EACrB,KAAK,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,cAAc,EACd,KAAK,GACN,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/primitives/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAG/D,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACZ,IAAI,EACJ,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,OAAO,EACP,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,SAAS,EACT,qBAAqB,EACrB,KAAK,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,cAAc,EACd,KAAK,GACN,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { FimoString, FimoDate, FimoMedia, FimoBoolean, FimoRichText, type FimoReference, type FimoSource, type FimoPart, type FimoRichTextContent, type FimoRichTextNodeProps, type FimoRichTextMarkProps, type FimoRichTextComponents, FIMO_SOURCE, FIMO_PARTS, isFimoString, isFimoDate, hasFimoSource, getFimoSource, getFimoParts, } from './primitives.js';
|
|
1
|
+
export { FimoString, FimoDate, FimoMedia, FimoBoolean, FimoRichText, type FimoPolymorphicReference, type FimoReference, type FimoSource, type FimoPart, type FimoRichTextContent, type FimoRichTextNodeProps, type FimoRichTextMarkProps, type FimoRichTextComponents, FIMO_SOURCE, FIMO_PARTS, isFimoString, isFimoDate, hasFimoSource, getFimoSource, getFimoParts, } from './primitives.js';
|
|
2
2
|
export { fimo } from './template.js';
|
|
3
3
|
export { useFimoLiveValue } from './useFimoLiveValue.js';
|
|
4
4
|
export type { BoolOps, DateOps, Field, Fields, FilterFor, NullOnlyOps, NumberOps, Populate, Populated, PopulatedResult, ProjectedWithPopulate, Projected, Query, ReferenceField, ReferenceMap, ScalarOps, Sort, SortField, StringOps, Where, WithReferences, } from './query.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,YAAY,EACV,OAAO,EACP,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,SAAS,EACT,KAAK,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,KAAK,EACL,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,WAAW,EACX,UAAU,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,YAAY,EACV,OAAO,EACP,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EACT,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,SAAS,EACT,KAAK,EACL,cAAc,EACd,YAAY,EACZ,SAAS,EACT,IAAI,EACJ,SAAS,EACT,SAAS,EACT,KAAK,EACL,cAAc,GACf,MAAM,YAAY,CAAC"}
|
|
@@ -11,6 +11,11 @@ export interface FimoSource {
|
|
|
11
11
|
export interface FimoReference {
|
|
12
12
|
documentId: string;
|
|
13
13
|
}
|
|
14
|
+
/** Polymorphic reference value: the schema names a target set, so every value carries its own type. */
|
|
15
|
+
export interface FimoPolymorphicReference {
|
|
16
|
+
contentType: string;
|
|
17
|
+
documentId: string;
|
|
18
|
+
}
|
|
14
19
|
export declare const FIMO_SOURCE: unique symbol;
|
|
15
20
|
export declare const FIMO_PARTS: unique symbol;
|
|
16
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/primitives.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/primitives.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FimoBoolean, FimoDate, FimoMedia, FimoReference, FimoRichText, FimoString } from './primitives.js';
|
|
1
|
+
import type { FimoBoolean, FimoDate, FimoMedia, FimoPolymorphicReference, FimoReference, FimoRichText, FimoString } from './primitives.js';
|
|
2
2
|
export type ScalarOps<T> = {
|
|
3
3
|
$eq?: T;
|
|
4
4
|
$ne?: T;
|
|
@@ -40,7 +40,7 @@ export type ManyReferenceOps = {
|
|
|
40
40
|
$contains?: string;
|
|
41
41
|
$null?: boolean;
|
|
42
42
|
};
|
|
43
|
-
export type FilterFor<T> = [T] extends [FimoString | string] ? string | StringOps : [T] extends [FimoBoolean | boolean] ? boolean | BoolOps : [T] extends [FimoDate | Date] ? string | DateOps : [T] extends [number] ? number | NumberOps : [T] extends [FimoReference | null] ? string | null | ReferenceOps : [T] extends [FimoReference[]] ? string | ManyReferenceOps : [T] extends [FimoMedia | FimoMedia[]] ? NullOnlyOps : [T] extends [FimoRichText] ? string | StringOps : NullOnlyOps;
|
|
43
|
+
export type FilterFor<T> = [T] extends [FimoString | string] ? string | StringOps : [T] extends [FimoBoolean | boolean] ? boolean | BoolOps : [T] extends [FimoDate | Date] ? string | DateOps : [T] extends [number] ? number | NumberOps : [T] extends [FimoPolymorphicReference | null] ? never : [T] extends [FimoPolymorphicReference[]] ? never : [T] extends [FimoReference | null] ? string | null | ReferenceOps : [T] extends [FimoReference[]] ? string | ManyReferenceOps : [T] extends [FimoMedia | FimoMedia[]] ? NullOnlyOps : [T] extends [FimoRichText] ? string | StringOps : NullOnlyOps;
|
|
44
44
|
type BaseTopLevelWhere = {
|
|
45
45
|
id?: string | StringOps;
|
|
46
46
|
documentId?: string | StringOps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/runtime/primitives/lib/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { dirname, join, resolve } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { afterAll, describe, expect, it } from 'vitest';
|
|
8
|
+
import { syncSchemas } from './sync-schemas.js';
|
|
9
|
+
/**
|
|
10
|
+
* The generated-types gate: generate hooks + types from fixture schemas that
|
|
11
|
+
* cover every field type and reference shape, add usage code written the way
|
|
12
|
+
* an agent writes site code, and run the real TypeScript compiler over the
|
|
13
|
+
* output. A template regression fails this test — never a user project.
|
|
14
|
+
*/
|
|
15
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
17
|
+
const runtimeBarrel = resolve(here, '../runtime/index.ts');
|
|
18
|
+
const tscBin = requireFromHere.resolve('typescript/bin/tsc');
|
|
19
|
+
const fixtureRoot = mkdtempSync(join(tmpdir(), 'fimo-generated-types-'));
|
|
20
|
+
const schemasDir = join(fixtureRoot, 'src', 'schemas');
|
|
21
|
+
const SCHEMAS = {
|
|
22
|
+
Author: {
|
|
23
|
+
uid: 'Author',
|
|
24
|
+
name: 'Author',
|
|
25
|
+
i18n: { enabled: true },
|
|
26
|
+
fields: {
|
|
27
|
+
name: { type: 'string', required: true },
|
|
28
|
+
bio: { type: 'richtext' },
|
|
29
|
+
avatar: { type: 'media' },
|
|
30
|
+
active: { type: 'boolean' },
|
|
31
|
+
bornAt: { type: 'date' },
|
|
32
|
+
meta: { type: 'json' },
|
|
33
|
+
rating: { type: 'number' },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
Video: {
|
|
37
|
+
uid: 'Video',
|
|
38
|
+
name: 'Video',
|
|
39
|
+
i18n: { enabled: false },
|
|
40
|
+
fields: {
|
|
41
|
+
title: { type: 'string', required: true },
|
|
42
|
+
clips: { type: 'media', multiple: true },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
Post: {
|
|
46
|
+
uid: 'Post',
|
|
47
|
+
name: 'Post',
|
|
48
|
+
i18n: { enabled: true },
|
|
49
|
+
fields: {
|
|
50
|
+
title: { type: 'string', required: true },
|
|
51
|
+
author: { type: 'reference', target: 'Author' },
|
|
52
|
+
contributors: { type: 'reference', target: 'Author', many: true },
|
|
53
|
+
related: { type: 'reference', target: 'Post', many: true },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
Page: {
|
|
57
|
+
uid: 'Page',
|
|
58
|
+
name: 'Page',
|
|
59
|
+
i18n: { enabled: true },
|
|
60
|
+
fields: {
|
|
61
|
+
title: { type: 'string' },
|
|
62
|
+
featured: { type: 'reference', targets: ['Post', 'Video'], many: true },
|
|
63
|
+
hero: { type: 'reference', targets: ['Author', 'Video'] },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
SiteSettings: {
|
|
67
|
+
uid: 'SiteSettings',
|
|
68
|
+
name: 'SiteSettings',
|
|
69
|
+
isSingleton: true,
|
|
70
|
+
i18n: { enabled: false },
|
|
71
|
+
fields: {
|
|
72
|
+
siteName: { type: 'string', required: true },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
const USAGE = `// Agent-style usage of the generated types — compile-time contract.
|
|
77
|
+
import type { PageResult, PageWhere } from "./Page";
|
|
78
|
+
import type { PostResult } from "./Post";
|
|
79
|
+
|
|
80
|
+
export function renderFeatured(page: PageResult<undefined, readonly ["featured", "hero"]>): string[] {
|
|
81
|
+
const out: string[] = [];
|
|
82
|
+
for (const item of page.featured) {
|
|
83
|
+
switch (item.$type) {
|
|
84
|
+
case "Post":
|
|
85
|
+
out.push(\`post \${String(item.title)} by \${item.author?.documentId ?? "nobody"}\`);
|
|
86
|
+
break;
|
|
87
|
+
case "Video":
|
|
88
|
+
out.push(\`video \${String(item.title)} with \${item.clips.length} clip(s)\`);
|
|
89
|
+
break;
|
|
90
|
+
default: {
|
|
91
|
+
const exhaustive: never = item;
|
|
92
|
+
return exhaustive;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const hero = page.hero;
|
|
97
|
+
if (hero && hero.$type === "Author") {
|
|
98
|
+
out.push(\`hero \${String(hero.name)}\`);
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function renderPost(post: PostResult<undefined, readonly ["author", "contributors"]>): string {
|
|
104
|
+
const contributors = post.contributors.map((author) => String(author.name)).join(", ");
|
|
105
|
+
return \`\${String(post.title)} — \${post.author ? String(post.author.name) : "anonymous"} (\${contributors})\`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function whereContract(): PageWhere {
|
|
109
|
+
return {
|
|
110
|
+
title: "Home",
|
|
111
|
+
// @ts-expect-error filtering on polymorphic reference fields is not supported
|
|
112
|
+
featured: "some-document-id",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
`;
|
|
116
|
+
const SHIMS = `declare module "virtual:fimo-config" {
|
|
117
|
+
const config: Record<string, unknown>;
|
|
118
|
+
export default config;
|
|
119
|
+
}
|
|
120
|
+
declare module "virtual:translations" {
|
|
121
|
+
export const dictionaries: Record<string, Record<string, string>>;
|
|
122
|
+
export const defaultLocale: string;
|
|
123
|
+
export const signature: string;
|
|
124
|
+
export const updatedAt: string;
|
|
125
|
+
}
|
|
126
|
+
declare module "*.css" {}
|
|
127
|
+
`;
|
|
128
|
+
afterAll(() => {
|
|
129
|
+
rmSync(fixtureRoot, { recursive: true, force: true });
|
|
130
|
+
});
|
|
131
|
+
describe('generated types gate', () => {
|
|
132
|
+
it('generates hooks + types for every field shape and the output typechecks with agent-style usage', () => {
|
|
133
|
+
mkdirSync(schemasDir, { recursive: true });
|
|
134
|
+
// Real react-query types: the fixture resolves them like a real project.
|
|
135
|
+
const reactQueryDir = dirname(requireFromHere.resolve('@tanstack/react-query/package.json'));
|
|
136
|
+
mkdirSync(join(fixtureRoot, 'node_modules', '@tanstack'), { recursive: true });
|
|
137
|
+
symlinkSync(reactQueryDir, join(fixtureRoot, 'node_modules', '@tanstack', 'react-query'));
|
|
138
|
+
for (const [uid, schema] of Object.entries(SCHEMAS)) {
|
|
139
|
+
writeFileSync(join(schemasDir, `${uid}.json`), JSON.stringify(schema, null, 2));
|
|
140
|
+
}
|
|
141
|
+
const result = syncSchemas({ cwd: fixtureRoot, verbose: false });
|
|
142
|
+
expect(result.created).toBeGreaterThanOrEqual(Object.keys(SCHEMAS).length * 2);
|
|
143
|
+
writeFileSync(join(schemasDir, 'usage.ts'), USAGE);
|
|
144
|
+
writeFileSync(join(fixtureRoot, 'shims.d.ts'), SHIMS);
|
|
145
|
+
writeFileSync(join(fixtureRoot, 'tsconfig.json'), JSON.stringify({
|
|
146
|
+
compilerOptions: {
|
|
147
|
+
strict: true,
|
|
148
|
+
noEmit: true,
|
|
149
|
+
skipLibCheck: true,
|
|
150
|
+
target: 'ES2022',
|
|
151
|
+
module: 'ESNext',
|
|
152
|
+
moduleResolution: 'bundler',
|
|
153
|
+
jsx: 'react-jsx',
|
|
154
|
+
allowImportingTsExtensions: true,
|
|
155
|
+
baseUrl: '.',
|
|
156
|
+
paths: {
|
|
157
|
+
'fimo/ui': [runtimeBarrel],
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
include: ['src/**/*.ts', 'shims.d.ts'],
|
|
161
|
+
}, null, 2));
|
|
162
|
+
let output = '';
|
|
163
|
+
try {
|
|
164
|
+
output = execFileSync(process.execPath, [tscBin, '-p', fixtureRoot], { encoding: 'utf8' });
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
const failure = error;
|
|
168
|
+
throw new Error(`generated types failed to typecheck:\n${failure.stdout ?? ''}${failure.stderr ?? ''}`);
|
|
169
|
+
}
|
|
170
|
+
expect(output.trim()).toBe('');
|
|
171
|
+
}, 120_000);
|
|
172
|
+
});
|
|
@@ -35,6 +35,9 @@ function normalizeFields(fields) {
|
|
|
35
35
|
}
|
|
36
36
|
const field = value;
|
|
37
37
|
const target = typeof field.target === 'string' ? field.target : undefined;
|
|
38
|
+
const targets = Array.isArray(field.targets)
|
|
39
|
+
? field.targets.filter((candidate) => typeof candidate === 'string')
|
|
40
|
+
: undefined;
|
|
38
41
|
return [
|
|
39
42
|
key,
|
|
40
43
|
{
|
|
@@ -42,6 +45,10 @@ function normalizeFields(fields) {
|
|
|
42
45
|
type: typeof field.type === 'string' ? field.type : undefined,
|
|
43
46
|
target,
|
|
44
47
|
targetPascal: target ? pascalCase(target) : undefined,
|
|
48
|
+
targets: targets && targets.length > 0 ? targets : undefined,
|
|
49
|
+
targetRefs: targets && targets.length > 0
|
|
50
|
+
? targets.map((candidate) => ({ uid: candidate, pascal: pascalCase(candidate) }))
|
|
51
|
+
: undefined,
|
|
45
52
|
many: typeof field.many === 'boolean' ? field.many : undefined,
|
|
46
53
|
multiple: typeof field.multiple === 'boolean' ? field.multiple : undefined,
|
|
47
54
|
},
|
|
@@ -51,10 +58,16 @@ function normalizeFields(fields) {
|
|
|
51
58
|
function referenceImportsFor(schema, fields) {
|
|
52
59
|
const imports = new Map();
|
|
53
60
|
for (const field of Object.values(fields)) {
|
|
54
|
-
if (field.type !== 'reference'
|
|
61
|
+
if (field.type !== 'reference') {
|
|
55
62
|
continue;
|
|
56
63
|
}
|
|
57
|
-
|
|
64
|
+
const targets = field.targets ?? (field.target ? [field.target] : []);
|
|
65
|
+
for (const target of targets) {
|
|
66
|
+
if (target === schema.uid) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
imports.set(target, { uid: target, pascal: pascalCase(target) });
|
|
70
|
+
}
|
|
58
71
|
}
|
|
59
72
|
return [...imports.values()].sort((a, b) => a.pascal.localeCompare(b.pascal));
|
|
60
73
|
}
|
|
@@ -66,7 +79,13 @@ function schemaToModel(schema, localizedByUid) {
|
|
|
66
79
|
isSingleton: schema.isSingleton ?? false,
|
|
67
80
|
localized: schema.i18n?.enabled !== false,
|
|
68
81
|
localizedReferenceFields: Object.entries(fields)
|
|
69
|
-
.filter(([, field]) =>
|
|
82
|
+
.filter(([, field]) => {
|
|
83
|
+
if (field.type !== 'reference') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const targets = field.targets ?? (field.target ? [field.target] : []);
|
|
87
|
+
return targets.some((target) => localizedByUid.get(target) !== false);
|
|
88
|
+
})
|
|
70
89
|
.map(([fieldName]) => fieldName),
|
|
71
90
|
fields,
|
|
72
91
|
referenceImports: referenceImportsFor(schema, fields),
|
|
@@ -170,11 +170,46 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
172
|
if (type === 'reference') {
|
|
173
|
-
const { target, many } = definition;
|
|
174
|
-
if (
|
|
173
|
+
const { target, targets, many } = definition;
|
|
174
|
+
if (targets !== undefined && target !== undefined) {
|
|
175
175
|
errors.push({
|
|
176
176
|
rule: 'schemas/reference-target',
|
|
177
|
-
message: `Reference field "${fieldName}"
|
|
177
|
+
message: `Reference field "${fieldName}" declares both "target" and "targets" — a field is fixed or polymorphic, never both.`,
|
|
178
|
+
file,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if (targets !== undefined) {
|
|
182
|
+
const targetList = Array.isArray(targets) ? targets : null;
|
|
183
|
+
if (!targetList || targetList.length === 0 || new Set(targetList).size !== targetList.length) {
|
|
184
|
+
errors.push({
|
|
185
|
+
rule: 'schemas/reference-target',
|
|
186
|
+
message: `Reference field "${fieldName}" must declare "targets" as a non-empty array of unique content types.`,
|
|
187
|
+
file,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
for (const candidate of targetList) {
|
|
192
|
+
if (typeof candidate !== 'string' || !CONTENT_TYPE_NAME_PATTERN.test(candidate)) {
|
|
193
|
+
errors.push({
|
|
194
|
+
rule: 'schemas/reference-target',
|
|
195
|
+
message: `Reference field "${fieldName}" has an invalid entry in "targets".`,
|
|
196
|
+
file,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else if (schemaUids.size > 0 && !schemaUids.has(candidate)) {
|
|
200
|
+
errors.push({
|
|
201
|
+
rule: 'schemas/reference-target',
|
|
202
|
+
message: `Reference field "${fieldName}" targets unknown schema "${candidate}".`,
|
|
203
|
+
file,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else if (typeof target !== 'string' || !CONTENT_TYPE_NAME_PATTERN.test(target)) {
|
|
210
|
+
errors.push({
|
|
211
|
+
rule: 'schemas/reference-target',
|
|
212
|
+
message: `Reference field "${fieldName}" must declare a valid "target" content type (or "targets" for a polymorphic field).`,
|
|
178
213
|
file,
|
|
179
214
|
});
|
|
180
215
|
}
|
|
@@ -194,7 +229,7 @@ export function validateSchemaFile(absolutePath, file, schemaUids = new Set()) {
|
|
|
194
229
|
}
|
|
195
230
|
}
|
|
196
231
|
else {
|
|
197
|
-
for (const referenceOnlyKey of ['target', 'many']) {
|
|
232
|
+
for (const referenceOnlyKey of ['target', 'targets', 'many']) {
|
|
198
233
|
if (referenceOnlyKey in definition) {
|
|
199
234
|
errors.push({
|
|
200
235
|
rule: 'schemas/reference-shape',
|
package/package.json
CHANGED
|
@@ -100,6 +100,30 @@ export function stripTemplateLockfile(cliRoot) {
|
|
|
100
100
|
return () => writeFileSync(file, original);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Parse `npm view <name> versions --json` output into a flat list of version
|
|
105
|
+
* strings, tolerating every shape npm has shipped: an array of strings
|
|
106
|
+
* (npm <= 11), a bare string when exactly one version is published
|
|
107
|
+
* (npm <= 11), and the npm 12 wrapper — "npm view --json now always returns
|
|
108
|
+
* an array", one entry per matched version, i.e. `[[...versions]]` for a bare
|
|
109
|
+
* package name. Returns null when nothing version-shaped survives (error
|
|
110
|
+
* envelopes, empty output), so callers fall back to the run-number/timestamp
|
|
111
|
+
* counter instead of trusting garbage.
|
|
112
|
+
*
|
|
113
|
+
* @param {string} stdout - raw stdout of `npm view <name> versions --json`
|
|
114
|
+
* @returns {string[] | null}
|
|
115
|
+
*/
|
|
116
|
+
export function parsePublishedVersions(stdout) {
|
|
117
|
+
let parsed;
|
|
118
|
+
try {
|
|
119
|
+
parsed = JSON.parse(stdout);
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
const versions = (Array.isArray(parsed) ? parsed : [parsed]).flat().filter((version) => typeof version === 'string');
|
|
124
|
+
return versions.length > 0 ? versions : null;
|
|
125
|
+
}
|
|
126
|
+
|
|
103
127
|
/**
|
|
104
128
|
* Next per-version prerelease counter: one past the highest already-published
|
|
105
129
|
* `<base>-<distTag>.<n>` on npm. Counting from what's actually published
|
|
@@ -4,8 +4,13 @@ import { join } from 'node:path';
|
|
|
4
4
|
|
|
5
5
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
computePublishVersion,
|
|
9
|
+
nextPrereleaseCounter,
|
|
10
|
+
nextVersionFromChangesets,
|
|
11
|
+
parsePublishedVersions,
|
|
12
|
+
// @ts-expect-error plain mjs module without types
|
|
13
|
+
} from './release-core.mjs';
|
|
9
14
|
|
|
10
15
|
const stagingChannel = { prerelease: true, distTag: 'staging' };
|
|
11
16
|
const latestChannel = { prerelease: false, distTag: 'latest' };
|
|
@@ -34,6 +39,36 @@ describe('computePublishVersion', () => {
|
|
|
34
39
|
});
|
|
35
40
|
});
|
|
36
41
|
|
|
42
|
+
describe('parsePublishedVersions', () => {
|
|
43
|
+
it('passes through the npm <= 11 array-of-strings shape', () => {
|
|
44
|
+
expect(parsePublishedVersions('["0.3.4", "0.3.5-staging.1"]')).toEqual(['0.3.4', '0.3.5-staging.1']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('wraps the npm <= 11 bare string returned for a single published version', () => {
|
|
48
|
+
expect(parsePublishedVersions('"0.0.0"')).toEqual(['0.0.0']);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('unwraps the npm 12 shape (--json always returns an array)', () => {
|
|
52
|
+
expect(parsePublishedVersions('[["0.3.4", "0.3.5-staging.1", "0.3.5"]]')).toEqual([
|
|
53
|
+
'0.3.4',
|
|
54
|
+
'0.3.5-staging.1',
|
|
55
|
+
'0.3.5',
|
|
56
|
+
]);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('returns null for unparseable output', () => {
|
|
60
|
+
expect(parsePublishedVersions('')).toBeNull();
|
|
61
|
+
expect(parsePublishedVersions('npm ERR! something')).toBeNull();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('returns null when nothing version-shaped survives (error envelopes, empty lists)', () => {
|
|
65
|
+
expect(parsePublishedVersions('{"error":{"code":"E401"}}')).toBeNull();
|
|
66
|
+
expect(parsePublishedVersions('[]')).toBeNull();
|
|
67
|
+
expect(parsePublishedVersions('[{"error":{"code":"E404"}}]')).toBeNull();
|
|
68
|
+
expect(parsePublishedVersions('null')).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
37
72
|
describe('nextPrereleaseCounter', () => {
|
|
38
73
|
it('returns 1 when nothing matches the base + tag', () => {
|
|
39
74
|
expect(nextPrereleaseCounter([], '0.3.5', 'staging')).toBe(1);
|
package/scripts/publish-npm.mjs
CHANGED
|
@@ -36,6 +36,7 @@ import { writeDevReleaseState } from './lib/dev-release-state.mjs';
|
|
|
36
36
|
import {
|
|
37
37
|
computePublishVersion,
|
|
38
38
|
nextVersionFromChangesets,
|
|
39
|
+
parsePublishedVersions,
|
|
39
40
|
pinTemplateFimo,
|
|
40
41
|
stripTemplateLockfile,
|
|
41
42
|
writeReleaseJson,
|
|
@@ -72,20 +73,14 @@ function run(cmd, args, cwd) {
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
// All published versions of the package, or null when the registry can't be
|
|
75
|
-
// reached (offline, first-ever publish)
|
|
76
|
-
// run-number/timestamp counter.
|
|
76
|
+
// reached (offline, first-ever publish) or the output shape is unrecognized —
|
|
77
|
+
// callers fall back to the run-number/timestamp counter.
|
|
77
78
|
function fetchPublishedVersions(name) {
|
|
78
79
|
const result = spawnSync('npm', ['view', name, 'versions', '--json'], { encoding: 'utf8' });
|
|
79
80
|
if (result.status !== 0) {
|
|
80
81
|
return null;
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
-
const parsed = JSON.parse(result.stdout);
|
|
84
|
-
// npm view returns a bare string when exactly one version is published.
|
|
85
|
-
return Array.isArray(parsed) ? parsed : [parsed];
|
|
86
|
-
} catch {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
83
|
+
return parsePublishedVersions(result.stdout);
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
const { channel: channelName, dryRun, bootstrap, plan } = parseArgs(process.argv.slice(2));
|