@blinkk/root-cms 1.3.26 → 1.4.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/app.js +44 -10
- package/dist/cli.js +110 -62
- package/dist/plugin.js +137 -65
- package/dist/project.js +2 -1
- package/dist/ui/ui.css +1 -1
- package/dist/ui/ui.js +54 -54
- package/package.json +3 -3
package/dist/app.js
CHANGED
|
@@ -7,7 +7,7 @@ import { render as renderToString } from "preact-render-to-string";
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@blinkk/root-cms",
|
|
10
|
-
version: "1.
|
|
10
|
+
version: "1.4.1",
|
|
11
11
|
author: "s@blinkk.com",
|
|
12
12
|
license: "MIT",
|
|
13
13
|
engines: {
|
|
@@ -138,7 +138,7 @@ var package_default = {
|
|
|
138
138
|
vitest: "0.34.6"
|
|
139
139
|
},
|
|
140
140
|
peerDependencies: {
|
|
141
|
-
"@blinkk/root": "1.
|
|
141
|
+
"@blinkk/root": "1.4.1",
|
|
142
142
|
"firebase-admin": ">=11",
|
|
143
143
|
"firebase-functions": ">=4",
|
|
144
144
|
preact: ">=10",
|
|
@@ -151,6 +151,25 @@ var package_default = {
|
|
|
151
151
|
}
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
+
// core/project.ts
|
|
155
|
+
var IGNORED_SCHEMA_FOLDERS = ["/appengine/", "/functions/", "/gae/"];
|
|
156
|
+
var SCHEMA_MODULES = import.meta.glob("/**/*.schema.ts", {
|
|
157
|
+
eager: true
|
|
158
|
+
});
|
|
159
|
+
function getProjectSchemas() {
|
|
160
|
+
const schemas = {};
|
|
161
|
+
for (const fileId in SCHEMA_MODULES) {
|
|
162
|
+
if (IGNORED_SCHEMA_FOLDERS.some((prefix) => fileId.startsWith(prefix))) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const schemaModule = SCHEMA_MODULES[fileId];
|
|
166
|
+
if (schemaModule.default) {
|
|
167
|
+
schemas[fileId] = schemaModule.default;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return schemas;
|
|
171
|
+
}
|
|
172
|
+
|
|
154
173
|
// core/app.tsx
|
|
155
174
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
156
175
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -223,15 +242,9 @@ function App(props) {
|
|
|
223
242
|
}
|
|
224
243
|
async function renderApp(req, res, options) {
|
|
225
244
|
var _a;
|
|
226
|
-
const collectionModules = import.meta.glob("/collections/*.schema.ts", {
|
|
227
|
-
eager: true
|
|
228
|
-
});
|
|
229
245
|
const collections = {};
|
|
230
|
-
Object.
|
|
231
|
-
|
|
232
|
-
const module = collectionModules[moduleId];
|
|
233
|
-
const collection = module.default;
|
|
234
|
-
collections[collectionId] = collection;
|
|
246
|
+
Object.entries(getCollections()).forEach(([collectionId, collection]) => {
|
|
247
|
+
collections[collectionId] = serializeCollection(collection);
|
|
235
248
|
});
|
|
236
249
|
const rootConfig = options.rootConfig || {};
|
|
237
250
|
const cmsConfig = options.cmsConfig || {};
|
|
@@ -279,6 +292,16 @@ ${mainHtml}`;
|
|
|
279
292
|
setSecurityHeaders(options, req, res, nonce);
|
|
280
293
|
res.send(html);
|
|
281
294
|
}
|
|
295
|
+
function serializeCollection(collection) {
|
|
296
|
+
return {
|
|
297
|
+
name: collection.name,
|
|
298
|
+
description: collection.description,
|
|
299
|
+
domain: collection.domain,
|
|
300
|
+
url: collection.url,
|
|
301
|
+
previewUrl: collection.previewUrl,
|
|
302
|
+
preview: collection.preview
|
|
303
|
+
};
|
|
304
|
+
}
|
|
282
305
|
function SignIn(props) {
|
|
283
306
|
return /* @__PURE__ */ jsxs("html", { children: [
|
|
284
307
|
/* @__PURE__ */ jsxs("head", { children: [
|
|
@@ -357,6 +380,16 @@ ${mainHtml}`;
|
|
|
357
380
|
res.status(403);
|
|
358
381
|
res.send(html);
|
|
359
382
|
}
|
|
383
|
+
function getCollections() {
|
|
384
|
+
const collections = {};
|
|
385
|
+
const schemas = getProjectSchemas();
|
|
386
|
+
Object.entries(schemas).forEach(([fileId, schema]) => {
|
|
387
|
+
if (fileId.startsWith("/collections/")) {
|
|
388
|
+
collections[schema.name] = schema;
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
return collections;
|
|
392
|
+
}
|
|
360
393
|
function generateNonce() {
|
|
361
394
|
return crypto.randomBytes(16).toString("base64");
|
|
362
395
|
}
|
|
@@ -397,6 +430,7 @@ function cachebust(req, url) {
|
|
|
397
430
|
return `${url}?c=${value}`;
|
|
398
431
|
}
|
|
399
432
|
export {
|
|
433
|
+
getCollections,
|
|
400
434
|
renderApp,
|
|
401
435
|
renderSignIn
|
|
402
436
|
};
|
package/dist/cli.js
CHANGED
|
@@ -22,7 +22,8 @@ async function generateTypes() {
|
|
|
22
22
|
await generateSchemaDts(outputPath, schemas);
|
|
23
23
|
console.log("saved root-cms.d.ts!");
|
|
24
24
|
}
|
|
25
|
-
var TEMPLATE =
|
|
25
|
+
var TEMPLATE = `/* eslint-disable */
|
|
26
|
+
/** Root.js CMS types. This file is autogenerated. */
|
|
26
27
|
|
|
27
28
|
export interface RootCMSFile {
|
|
28
29
|
src: string;
|
|
@@ -35,6 +36,8 @@ export type RootCMSImage = RootCMSFile;
|
|
|
35
36
|
|
|
36
37
|
export type RootCMSOneOf<T = any> = T;
|
|
37
38
|
|
|
39
|
+
export type RootCMSOneOfOption<T, Base> = Base & {_type: T};
|
|
40
|
+
|
|
38
41
|
export interface RootCMSRichTextBlock {
|
|
39
42
|
type: string;
|
|
40
43
|
data: any;
|
|
@@ -75,13 +78,106 @@ export interface RootCMSDoc<Fields extends {}> {
|
|
|
75
78
|
/** User-entered field values from the CMS. */
|
|
76
79
|
fields?: Fields;
|
|
77
80
|
}`;
|
|
81
|
+
var DtsFormatter = class {
|
|
82
|
+
constructor() {
|
|
83
|
+
/**
|
|
84
|
+
* Field types defined in either `.schema.ts` files or used by `oneOf()`
|
|
85
|
+
* fields.
|
|
86
|
+
*/
|
|
87
|
+
this.fieldsTypes = {};
|
|
88
|
+
/**
|
|
89
|
+
* For `collections/*.schema.ts` files, output a corresponding "RootCMSDoc"
|
|
90
|
+
* type. For example, `collections/BlogPosts.schema.ts` would output a type
|
|
91
|
+
* called `BlogPostsDoc`.
|
|
92
|
+
*/
|
|
93
|
+
this.docTypes = {};
|
|
94
|
+
}
|
|
95
|
+
/** Adds the types for a `.schema.ts` file to the `.d.ts` file. */
|
|
96
|
+
addSchemaFile(fileId, schema) {
|
|
97
|
+
const jsdoc = `Generated from \`${fileId}\`.`;
|
|
98
|
+
const typeId = alphanumeric(path.parse(fileId).name.split(".")[0]);
|
|
99
|
+
const oneOfTypes = {};
|
|
100
|
+
const fieldsTypeId = `${typeId}Fields`;
|
|
101
|
+
const fieldsType = dom.create.interface(
|
|
102
|
+
fieldsTypeId,
|
|
103
|
+
dom.DeclarationFlags.Export
|
|
104
|
+
);
|
|
105
|
+
fieldsType.jsDocComment = jsdoc;
|
|
106
|
+
for (const field of schema.fields) {
|
|
107
|
+
if (!field.id) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
fieldsType.members.push(fieldProperty(field, { typeId, oneOfTypes }));
|
|
111
|
+
}
|
|
112
|
+
for (const oneOfTypeId in oneOfTypes) {
|
|
113
|
+
if (!this.fieldsTypes[fieldsTypeId]) {
|
|
114
|
+
this.fieldsTypes[oneOfTypeId] = oneOfTypes[oneOfTypeId];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.fieldsTypes[fieldsTypeId] = fieldsType;
|
|
118
|
+
if (fileId.startsWith("/collections/")) {
|
|
119
|
+
const docTypeId = `${typeId}Doc`;
|
|
120
|
+
const baseType = dom.create.namedTypeReference("RootCMSDoc");
|
|
121
|
+
baseType.typeArguments.push(dom.create.namedTypeReference(fieldsTypeId));
|
|
122
|
+
const docType = dom.create.alias(
|
|
123
|
+
docTypeId,
|
|
124
|
+
baseType,
|
|
125
|
+
dom.DeclarationFlags.Export
|
|
126
|
+
);
|
|
127
|
+
docType.jsDocComment = jsdoc;
|
|
128
|
+
this.docTypes[docTypeId] = docType;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Generates the `.d.ts` output as a string. */
|
|
132
|
+
toString() {
|
|
133
|
+
const results = [TEMPLATE];
|
|
134
|
+
const sortedFieldsTypes = Object.keys(this.fieldsTypes).sort();
|
|
135
|
+
for (const fieldsTypeId of sortedFieldsTypes) {
|
|
136
|
+
const fieldsType = this.fieldsTypes[fieldsTypeId];
|
|
137
|
+
results.push(this.typeToString(fieldsType));
|
|
138
|
+
const docTypeId = this.fieldsTypeToDocType(fieldsTypeId);
|
|
139
|
+
const docType = this.docTypes[docTypeId];
|
|
140
|
+
if (docType) {
|
|
141
|
+
results.push(this.typeToString(docType));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const output = results.join("\n\n").replaceAll("/** ", "/** ").replaceAll(" */", " */").replace(/\r\n|\r|\n/g, "\n") + "\n";
|
|
145
|
+
return output;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Converts "<Name>Fields" to "<Name>Doc".
|
|
149
|
+
*/
|
|
150
|
+
fieldsTypeToDocType(fieldsTypeId) {
|
|
151
|
+
if (!fieldsTypeId.endsWith("Fields")) {
|
|
152
|
+
throw new Error(`"${fieldsTypeId}" should be suffixed with "Fields"`);
|
|
153
|
+
}
|
|
154
|
+
const name = fieldsTypeId.slice(0, -6);
|
|
155
|
+
return `${name}Doc`;
|
|
156
|
+
}
|
|
157
|
+
typeToString(type2) {
|
|
158
|
+
return this.reformatOutput(dom.emit(type2, { singleLineJsDocComments: true }));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Formats the output to Google style conventions, e.g. 2-space indents and
|
|
162
|
+
* single quote strings.
|
|
163
|
+
*/
|
|
164
|
+
reformatOutput(input) {
|
|
165
|
+
const lines = input.trim().split("\n");
|
|
166
|
+
const results = [];
|
|
167
|
+
for (const line of lines) {
|
|
168
|
+
const convertedLine = line.replace(/ {4}/g, " ").replaceAll('"', "'");
|
|
169
|
+
results.push(convertedLine);
|
|
170
|
+
}
|
|
171
|
+
return results.join("\n");
|
|
172
|
+
}
|
|
173
|
+
};
|
|
78
174
|
async function generateSchemaDts(outputPath, schemas) {
|
|
79
|
-
const
|
|
175
|
+
const dtsFormatter = new DtsFormatter();
|
|
80
176
|
for (const fileId in schemas) {
|
|
81
177
|
const schema = schemas[fileId];
|
|
82
|
-
|
|
178
|
+
dtsFormatter.addSchemaFile(fileId, schema);
|
|
83
179
|
}
|
|
84
|
-
const output =
|
|
180
|
+
const output = dtsFormatter.toString();
|
|
85
181
|
await fs.writeFile(outputPath, output, "utf-8");
|
|
86
182
|
}
|
|
87
183
|
function fieldProperty(field, options) {
|
|
@@ -139,26 +235,27 @@ function fieldType(field, options) {
|
|
|
139
235
|
return;
|
|
140
236
|
}
|
|
141
237
|
const cleanName = alphanumeric(schema.name);
|
|
142
|
-
const oneOfTypeId = `${
|
|
238
|
+
const oneOfTypeId = `${cleanName}Fields`;
|
|
143
239
|
if (!options.oneOfTypes[oneOfTypeId]) {
|
|
144
240
|
const oneOfTypeInterface = dom.create.interface(
|
|
145
241
|
oneOfTypeId,
|
|
146
242
|
dom.DeclarationFlags.Export
|
|
147
243
|
);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
dom.type.stringLiteral(schema.name),
|
|
152
|
-
dom.DeclarationFlags.None
|
|
153
|
-
)
|
|
154
|
-
);
|
|
244
|
+
if (schema.description) {
|
|
245
|
+
oneOfTypeInterface.jsDocComment = schema.description;
|
|
246
|
+
}
|
|
155
247
|
const oneOfTypeFields = schema.fields || [];
|
|
156
248
|
oneOfTypeFields.forEach((f) => {
|
|
157
249
|
oneOfTypeInterface.members.push(fieldProperty(f, options));
|
|
158
250
|
});
|
|
159
251
|
options.oneOfTypes[oneOfTypeId] = oneOfTypeInterface;
|
|
160
252
|
}
|
|
161
|
-
|
|
253
|
+
const oneOfOption = dom.create.namedTypeReference("RootCMSOneOfOption");
|
|
254
|
+
oneOfOption.typeArguments = [
|
|
255
|
+
dom.type.stringLiteral(schema.name),
|
|
256
|
+
dom.create.namedTypeReference(oneOfTypeId)
|
|
257
|
+
];
|
|
258
|
+
unionTypes.push(oneOfOption);
|
|
162
259
|
});
|
|
163
260
|
if (unionTypes.length > 0) {
|
|
164
261
|
oneOf.typeArguments = [dom.create.union(unionTypes)];
|
|
@@ -188,55 +285,6 @@ function fieldType(field, options) {
|
|
|
188
285
|
}
|
|
189
286
|
return dom.type.unknown;
|
|
190
287
|
}
|
|
191
|
-
function renderSchema(fileId, schema) {
|
|
192
|
-
const jsdoc = `Generated from \`${fileId}\`.`;
|
|
193
|
-
const typeId = alphanumeric(path.parse(fileId).name.split(".")[0]);
|
|
194
|
-
const oneOfTypes = {};
|
|
195
|
-
const fieldsInterface = `${typeId}Fields`;
|
|
196
|
-
const fieldsType = dom.create.interface(
|
|
197
|
-
fieldsInterface,
|
|
198
|
-
dom.DeclarationFlags.Export
|
|
199
|
-
);
|
|
200
|
-
fieldsType.jsDocComment = jsdoc;
|
|
201
|
-
for (const field of schema.fields) {
|
|
202
|
-
if (!field.id) {
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
fieldsType.members.push(fieldProperty(field, { typeId, oneOfTypes }));
|
|
206
|
-
}
|
|
207
|
-
const typesOutput = [];
|
|
208
|
-
Object.values(oneOfTypes).forEach((oneOfTypeDef) => {
|
|
209
|
-
oneOfTypeDef.jsDocComment = jsdoc;
|
|
210
|
-
typesOutput.push(
|
|
211
|
-
dom.emit(oneOfTypeDef, { singleLineJsDocComments: true }).trim()
|
|
212
|
-
);
|
|
213
|
-
});
|
|
214
|
-
typesOutput.push(
|
|
215
|
-
dom.emit(fieldsType, { singleLineJsDocComments: true }).trim()
|
|
216
|
-
);
|
|
217
|
-
if (fileId.startsWith("/collections/")) {
|
|
218
|
-
const baseType = dom.create.namedTypeReference("RootCMSDoc");
|
|
219
|
-
baseType.typeArguments.push(dom.create.namedTypeReference(fieldsInterface));
|
|
220
|
-
const docType = dom.create.alias(
|
|
221
|
-
`${typeId}Doc`,
|
|
222
|
-
baseType,
|
|
223
|
-
dom.DeclarationFlags.Export
|
|
224
|
-
);
|
|
225
|
-
docType.jsDocComment = jsdoc;
|
|
226
|
-
const docTypeOutput = dom.emit(docType, { singleLineJsDocComments: true }).trim();
|
|
227
|
-
typesOutput.push(docTypeOutput);
|
|
228
|
-
}
|
|
229
|
-
return reformatOutput(typesOutput.join("\n\n"));
|
|
230
|
-
}
|
|
231
|
-
function reformatOutput(input) {
|
|
232
|
-
const lines = input.split("\n");
|
|
233
|
-
const results = [];
|
|
234
|
-
for (const line of lines) {
|
|
235
|
-
const convertedLine = line.replace(/ {4}/g, " ").replaceAll('"', "'");
|
|
236
|
-
results.push(convertedLine);
|
|
237
|
-
}
|
|
238
|
-
return results.join("\n");
|
|
239
|
-
}
|
|
240
288
|
function alphanumeric(input) {
|
|
241
289
|
return input.replace(/[^a-zA-Z0-9]/g, "");
|
|
242
290
|
}
|
package/dist/plugin.js
CHANGED
|
@@ -33,12 +33,12 @@ async function generateTypes() {
|
|
|
33
33
|
console.log("saved root-cms.d.ts!");
|
|
34
34
|
}
|
|
35
35
|
async function generateSchemaDts(outputPath, schemas) {
|
|
36
|
-
const
|
|
36
|
+
const dtsFormatter = new DtsFormatter();
|
|
37
37
|
for (const fileId in schemas) {
|
|
38
38
|
const schema = schemas[fileId];
|
|
39
|
-
|
|
39
|
+
dtsFormatter.addSchemaFile(fileId, schema);
|
|
40
40
|
}
|
|
41
|
-
const output =
|
|
41
|
+
const output = dtsFormatter.toString();
|
|
42
42
|
await fs.writeFile(outputPath, output, "utf-8");
|
|
43
43
|
}
|
|
44
44
|
function fieldProperty(field, options) {
|
|
@@ -96,26 +96,27 @@ function fieldType(field, options) {
|
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
const cleanName = alphanumeric(schema.name);
|
|
99
|
-
const oneOfTypeId = `${
|
|
99
|
+
const oneOfTypeId = `${cleanName}Fields`;
|
|
100
100
|
if (!options.oneOfTypes[oneOfTypeId]) {
|
|
101
101
|
const oneOfTypeInterface = dom.create.interface(
|
|
102
102
|
oneOfTypeId,
|
|
103
103
|
dom.DeclarationFlags.Export
|
|
104
104
|
);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
dom.type.stringLiteral(schema.name),
|
|
109
|
-
dom.DeclarationFlags.None
|
|
110
|
-
)
|
|
111
|
-
);
|
|
105
|
+
if (schema.description) {
|
|
106
|
+
oneOfTypeInterface.jsDocComment = schema.description;
|
|
107
|
+
}
|
|
112
108
|
const oneOfTypeFields = schema.fields || [];
|
|
113
109
|
oneOfTypeFields.forEach((f) => {
|
|
114
110
|
oneOfTypeInterface.members.push(fieldProperty(f, options));
|
|
115
111
|
});
|
|
116
112
|
options.oneOfTypes[oneOfTypeId] = oneOfTypeInterface;
|
|
117
113
|
}
|
|
118
|
-
|
|
114
|
+
const oneOfOption = dom.create.namedTypeReference("RootCMSOneOfOption");
|
|
115
|
+
oneOfOption.typeArguments = [
|
|
116
|
+
dom.type.stringLiteral(schema.name),
|
|
117
|
+
dom.create.namedTypeReference(oneOfTypeId)
|
|
118
|
+
];
|
|
119
|
+
unionTypes.push(oneOfOption);
|
|
119
120
|
});
|
|
120
121
|
if (unionTypes.length > 0) {
|
|
121
122
|
oneOf.typeArguments = [dom.create.union(unionTypes)];
|
|
@@ -145,64 +146,16 @@ function fieldType(field, options) {
|
|
|
145
146
|
}
|
|
146
147
|
return dom.type.unknown;
|
|
147
148
|
}
|
|
148
|
-
function renderSchema(fileId, schema) {
|
|
149
|
-
const jsdoc = `Generated from \`${fileId}\`.`;
|
|
150
|
-
const typeId = alphanumeric(path2.parse(fileId).name.split(".")[0]);
|
|
151
|
-
const oneOfTypes = {};
|
|
152
|
-
const fieldsInterface = `${typeId}Fields`;
|
|
153
|
-
const fieldsType = dom.create.interface(
|
|
154
|
-
fieldsInterface,
|
|
155
|
-
dom.DeclarationFlags.Export
|
|
156
|
-
);
|
|
157
|
-
fieldsType.jsDocComment = jsdoc;
|
|
158
|
-
for (const field of schema.fields) {
|
|
159
|
-
if (!field.id) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
fieldsType.members.push(fieldProperty(field, { typeId, oneOfTypes }));
|
|
163
|
-
}
|
|
164
|
-
const typesOutput = [];
|
|
165
|
-
Object.values(oneOfTypes).forEach((oneOfTypeDef) => {
|
|
166
|
-
oneOfTypeDef.jsDocComment = jsdoc;
|
|
167
|
-
typesOutput.push(
|
|
168
|
-
dom.emit(oneOfTypeDef, { singleLineJsDocComments: true }).trim()
|
|
169
|
-
);
|
|
170
|
-
});
|
|
171
|
-
typesOutput.push(
|
|
172
|
-
dom.emit(fieldsType, { singleLineJsDocComments: true }).trim()
|
|
173
|
-
);
|
|
174
|
-
if (fileId.startsWith("/collections/")) {
|
|
175
|
-
const baseType = dom.create.namedTypeReference("RootCMSDoc");
|
|
176
|
-
baseType.typeArguments.push(dom.create.namedTypeReference(fieldsInterface));
|
|
177
|
-
const docType = dom.create.alias(
|
|
178
|
-
`${typeId}Doc`,
|
|
179
|
-
baseType,
|
|
180
|
-
dom.DeclarationFlags.Export
|
|
181
|
-
);
|
|
182
|
-
docType.jsDocComment = jsdoc;
|
|
183
|
-
const docTypeOutput = dom.emit(docType, { singleLineJsDocComments: true }).trim();
|
|
184
|
-
typesOutput.push(docTypeOutput);
|
|
185
|
-
}
|
|
186
|
-
return reformatOutput(typesOutput.join("\n\n"));
|
|
187
|
-
}
|
|
188
|
-
function reformatOutput(input) {
|
|
189
|
-
const lines = input.split("\n");
|
|
190
|
-
const results = [];
|
|
191
|
-
for (const line of lines) {
|
|
192
|
-
const convertedLine = line.replace(/ {4}/g, " ").replaceAll('"', "'");
|
|
193
|
-
results.push(convertedLine);
|
|
194
|
-
}
|
|
195
|
-
return results.join("\n");
|
|
196
|
-
}
|
|
197
149
|
function alphanumeric(input) {
|
|
198
150
|
return input.replace(/[^a-zA-Z0-9]/g, "");
|
|
199
151
|
}
|
|
200
|
-
var __dirname, TEMPLATE;
|
|
152
|
+
var __dirname, TEMPLATE, DtsFormatter;
|
|
201
153
|
var init_generate_types = __esm({
|
|
202
154
|
"cli/generate-types.ts"() {
|
|
203
155
|
"use strict";
|
|
204
156
|
__dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
205
|
-
TEMPLATE =
|
|
157
|
+
TEMPLATE = `/* eslint-disable */
|
|
158
|
+
/** Root.js CMS types. This file is autogenerated. */
|
|
206
159
|
|
|
207
160
|
export interface RootCMSFile {
|
|
208
161
|
src: string;
|
|
@@ -215,6 +168,8 @@ export type RootCMSImage = RootCMSFile;
|
|
|
215
168
|
|
|
216
169
|
export type RootCMSOneOf<T = any> = T;
|
|
217
170
|
|
|
171
|
+
export type RootCMSOneOfOption<T, Base> = Base & {_type: T};
|
|
172
|
+
|
|
218
173
|
export interface RootCMSRichTextBlock {
|
|
219
174
|
type: string;
|
|
220
175
|
data: any;
|
|
@@ -255,6 +210,99 @@ export interface RootCMSDoc<Fields extends {}> {
|
|
|
255
210
|
/** User-entered field values from the CMS. */
|
|
256
211
|
fields?: Fields;
|
|
257
212
|
}`;
|
|
213
|
+
DtsFormatter = class {
|
|
214
|
+
constructor() {
|
|
215
|
+
/**
|
|
216
|
+
* Field types defined in either `.schema.ts` files or used by `oneOf()`
|
|
217
|
+
* fields.
|
|
218
|
+
*/
|
|
219
|
+
this.fieldsTypes = {};
|
|
220
|
+
/**
|
|
221
|
+
* For `collections/*.schema.ts` files, output a corresponding "RootCMSDoc"
|
|
222
|
+
* type. For example, `collections/BlogPosts.schema.ts` would output a type
|
|
223
|
+
* called `BlogPostsDoc`.
|
|
224
|
+
*/
|
|
225
|
+
this.docTypes = {};
|
|
226
|
+
}
|
|
227
|
+
/** Adds the types for a `.schema.ts` file to the `.d.ts` file. */
|
|
228
|
+
addSchemaFile(fileId, schema) {
|
|
229
|
+
const jsdoc = `Generated from \`${fileId}\`.`;
|
|
230
|
+
const typeId = alphanumeric(path2.parse(fileId).name.split(".")[0]);
|
|
231
|
+
const oneOfTypes = {};
|
|
232
|
+
const fieldsTypeId = `${typeId}Fields`;
|
|
233
|
+
const fieldsType = dom.create.interface(
|
|
234
|
+
fieldsTypeId,
|
|
235
|
+
dom.DeclarationFlags.Export
|
|
236
|
+
);
|
|
237
|
+
fieldsType.jsDocComment = jsdoc;
|
|
238
|
+
for (const field of schema.fields) {
|
|
239
|
+
if (!field.id) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
fieldsType.members.push(fieldProperty(field, { typeId, oneOfTypes }));
|
|
243
|
+
}
|
|
244
|
+
for (const oneOfTypeId in oneOfTypes) {
|
|
245
|
+
if (!this.fieldsTypes[fieldsTypeId]) {
|
|
246
|
+
this.fieldsTypes[oneOfTypeId] = oneOfTypes[oneOfTypeId];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
this.fieldsTypes[fieldsTypeId] = fieldsType;
|
|
250
|
+
if (fileId.startsWith("/collections/")) {
|
|
251
|
+
const docTypeId = `${typeId}Doc`;
|
|
252
|
+
const baseType = dom.create.namedTypeReference("RootCMSDoc");
|
|
253
|
+
baseType.typeArguments.push(dom.create.namedTypeReference(fieldsTypeId));
|
|
254
|
+
const docType = dom.create.alias(
|
|
255
|
+
docTypeId,
|
|
256
|
+
baseType,
|
|
257
|
+
dom.DeclarationFlags.Export
|
|
258
|
+
);
|
|
259
|
+
docType.jsDocComment = jsdoc;
|
|
260
|
+
this.docTypes[docTypeId] = docType;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** Generates the `.d.ts` output as a string. */
|
|
264
|
+
toString() {
|
|
265
|
+
const results = [TEMPLATE];
|
|
266
|
+
const sortedFieldsTypes = Object.keys(this.fieldsTypes).sort();
|
|
267
|
+
for (const fieldsTypeId of sortedFieldsTypes) {
|
|
268
|
+
const fieldsType = this.fieldsTypes[fieldsTypeId];
|
|
269
|
+
results.push(this.typeToString(fieldsType));
|
|
270
|
+
const docTypeId = this.fieldsTypeToDocType(fieldsTypeId);
|
|
271
|
+
const docType = this.docTypes[docTypeId];
|
|
272
|
+
if (docType) {
|
|
273
|
+
results.push(this.typeToString(docType));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const output = results.join("\n\n").replaceAll("/** ", "/** ").replaceAll(" */", " */").replace(/\r\n|\r|\n/g, "\n") + "\n";
|
|
277
|
+
return output;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Converts "<Name>Fields" to "<Name>Doc".
|
|
281
|
+
*/
|
|
282
|
+
fieldsTypeToDocType(fieldsTypeId) {
|
|
283
|
+
if (!fieldsTypeId.endsWith("Fields")) {
|
|
284
|
+
throw new Error(`"${fieldsTypeId}" should be suffixed with "Fields"`);
|
|
285
|
+
}
|
|
286
|
+
const name = fieldsTypeId.slice(0, -6);
|
|
287
|
+
return `${name}Doc`;
|
|
288
|
+
}
|
|
289
|
+
typeToString(type2) {
|
|
290
|
+
return this.reformatOutput(dom.emit(type2, { singleLineJsDocComments: true }));
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Formats the output to Google style conventions, e.g. 2-space indents and
|
|
294
|
+
* single quote strings.
|
|
295
|
+
*/
|
|
296
|
+
reformatOutput(input) {
|
|
297
|
+
const lines = input.trim().split("\n");
|
|
298
|
+
const results = [];
|
|
299
|
+
for (const line of lines) {
|
|
300
|
+
const convertedLine = line.replace(/ {4}/g, " ").replaceAll('"', "'");
|
|
301
|
+
results.push(convertedLine);
|
|
302
|
+
}
|
|
303
|
+
return results.join("\n");
|
|
304
|
+
}
|
|
305
|
+
};
|
|
258
306
|
}
|
|
259
307
|
});
|
|
260
308
|
|
|
@@ -1298,7 +1346,31 @@ function csvToArray(csvString) {
|
|
|
1298
1346
|
}
|
|
1299
1347
|
|
|
1300
1348
|
// core/api.ts
|
|
1301
|
-
function api(server) {
|
|
1349
|
+
function api(server, options) {
|
|
1350
|
+
server.use("/cms/api/collection.get", async (req, res) => {
|
|
1351
|
+
if (req.method !== "POST" || !String(req.get("content-type")).startsWith("application/json")) {
|
|
1352
|
+
res.status(400).json({ success: false, error: "BAD_REQUEST" });
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const reqBody = req.body || {};
|
|
1356
|
+
if (!reqBody.collectionId) {
|
|
1357
|
+
res.status(400).json({ success: false, error: "MISSING_COLLECTION_ID" });
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
try {
|
|
1361
|
+
const app = await options.getRenderer(req);
|
|
1362
|
+
const collections = app.getCollections();
|
|
1363
|
+
const collection = collections[reqBody.collectionId];
|
|
1364
|
+
if (!collection) {
|
|
1365
|
+
res.status(404).json({ success: false, error: "NOT_FOUND" });
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
res.status(200).json({ success: true, data: collection });
|
|
1369
|
+
} catch (err) {
|
|
1370
|
+
console.error(err.stack || err);
|
|
1371
|
+
res.status(500).json({ success: false, error: "UNKNOWN" });
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1302
1374
|
server.use("/cms/api/cron.run", async (req, res) => {
|
|
1303
1375
|
try {
|
|
1304
1376
|
await runCronJobs(req.rootConfig);
|
|
@@ -1752,7 +1824,7 @@ function cmsPlugin(options) {
|
|
|
1752
1824
|
});
|
|
1753
1825
|
const staticDir = path3.resolve(__dirname2, "ui");
|
|
1754
1826
|
server.use("/cms/static", sirv(staticDir, { dev: false }));
|
|
1755
|
-
api(server);
|
|
1827
|
+
api(server, { getRenderer });
|
|
1756
1828
|
server.use("/cms", async (req, res) => {
|
|
1757
1829
|
try {
|
|
1758
1830
|
if (!req.user) {
|
package/dist/project.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// core/project.ts
|
|
2
|
+
var IGNORED_SCHEMA_FOLDERS = ["/appengine/", "/functions/", "/gae/"];
|
|
2
3
|
var SCHEMA_MODULES = import.meta.glob("/**/*.schema.ts", {
|
|
3
4
|
eager: true
|
|
4
5
|
});
|
|
5
6
|
function getProjectSchemas() {
|
|
6
7
|
const schemas = {};
|
|
7
8
|
for (const fileId in SCHEMA_MODULES) {
|
|
8
|
-
if (fileId.startsWith(
|
|
9
|
+
if (IGNORED_SCHEMA_FOLDERS.some((prefix) => fileId.startsWith(prefix))) {
|
|
9
10
|
continue;
|
|
10
11
|
}
|
|
11
12
|
const schemaModule = SCHEMA_MODULES[fileId];
|