@blinkk/root-cms 2.4.9 → 2.4.10

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.
@@ -0,0 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export {
8
+ __export
9
+ };
@@ -0,0 +1,302 @@
1
+ // cli/generate-types.ts
2
+ import { promises as fs } from "fs";
3
+ import path from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { loadRootConfig, viteSsrLoadModule } from "@blinkk/root/node";
6
+ import * as dom from "dts-dom";
7
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+ async function generateTypes() {
9
+ const rootDir = process.cwd();
10
+ const rootConfig = await loadRootConfig(rootDir, { command: "root-cms" });
11
+ const modulePath = path.resolve(__dirname, "./project.js");
12
+ const project = await viteSsrLoadModule(
13
+ rootConfig,
14
+ modulePath
15
+ );
16
+ const schemas = await project.getProjectSchemas();
17
+ const outputPath = path.resolve(rootDir, "root-cms.d.ts");
18
+ await generateSchemaDts(outputPath, schemas);
19
+ console.log("saved root-cms.d.ts!");
20
+ }
21
+ var TEMPLATE = `/* eslint-disable */
22
+ /** Root.js CMS types. This file is autogenerated. */
23
+
24
+ export interface RootCMSFile {
25
+ src: string;
26
+ width?: number;
27
+ height?: number;
28
+ alt?: string;
29
+ }
30
+
31
+ export type RootCMSImage = RootCMSFile;
32
+
33
+ export type RootCMSOneOf<T = any> = T;
34
+
35
+ export type RootCMSOneOfOption<T, Base> = Base & {_type: T};
36
+
37
+ export interface RootCMSRichTextBlock {
38
+ type: string;
39
+ data: any;
40
+ }
41
+
42
+ export interface RootCMSRichText {
43
+ blocks: RootCMSRichTextBlock[];
44
+ }
45
+
46
+ export interface RootCMSReference {
47
+ /** The id of the doc, e.g. "Pages/foo-bar". */
48
+ id: string;
49
+ /** The collection id of the doc, e.g. "Pages". */
50
+ collection: string;
51
+ /** The slug of the doc, e.g. "foo-bar". */
52
+ slug: string;
53
+ }
54
+
55
+ export interface RootCMSDoc<Fields extends {}> {
56
+ /** The id of the doc, e.g. "Pages/foo-bar". */
57
+ id: string;
58
+ /** The collection id of the doc, e.g. "Pages". */
59
+ collection: string;
60
+ /** The slug of the doc, e.g. "foo-bar". */
61
+ slug: string;
62
+ /** System-level metadata. */
63
+ sys: {
64
+ createdAt: number;
65
+ createdBy: string;
66
+ modifiedAt: number;
67
+ modifiedBy: string;
68
+ firstPublishedAt?: number;
69
+ firstPublishedBy?: string;
70
+ publishedAt?: number;
71
+ publishedBy?: string;
72
+ locales?: string[];
73
+ };
74
+ /** User-entered field values from the CMS. */
75
+ fields?: Fields;
76
+ }`;
77
+ var DtsFormatter = class {
78
+ constructor() {
79
+ /**
80
+ * Field types defined in either `.schema.ts` files or used by `oneOf()`
81
+ * fields.
82
+ */
83
+ this.fieldsTypes = {};
84
+ /**
85
+ * For `collections/*.schema.ts` files, output a corresponding "RootCMSDoc"
86
+ * type. For example, `collections/BlogPosts.schema.ts` would output a type
87
+ * called `BlogPostsDoc`.
88
+ */
89
+ this.docTypes = {};
90
+ }
91
+ /** Adds the types for a `.schema.ts` file to the `.d.ts` file. */
92
+ addSchemaFile(fileId, schema) {
93
+ const jsdoc = `Generated from \`${fileId}\`.`;
94
+ const typeId = alphanumeric(path.parse(fileId).name.split(".")[0]);
95
+ const oneOfTypes = {};
96
+ const fieldsTypeId = `${typeId}Fields`;
97
+ const fieldsType = dom.create.interface(
98
+ fieldsTypeId,
99
+ dom.DeclarationFlags.Export
100
+ );
101
+ fieldsType.jsDocComment = jsdoc;
102
+ for (const field of schema.fields) {
103
+ if (!field.id) {
104
+ continue;
105
+ }
106
+ fieldsType.members.push(fieldProperty(field, { typeId, oneOfTypes }));
107
+ }
108
+ for (const oneOfTypeId in oneOfTypes) {
109
+ if (!this.fieldsTypes[fieldsTypeId]) {
110
+ this.fieldsTypes[oneOfTypeId] = oneOfTypes[oneOfTypeId];
111
+ }
112
+ }
113
+ this.fieldsTypes[fieldsTypeId] = fieldsType;
114
+ if (fileId.startsWith("/collections/")) {
115
+ const docTypeId = `${typeId}Doc`;
116
+ const baseType = dom.create.namedTypeReference("RootCMSDoc");
117
+ baseType.typeArguments.push(dom.create.namedTypeReference(fieldsTypeId));
118
+ const docType = dom.create.alias(
119
+ docTypeId,
120
+ baseType,
121
+ dom.DeclarationFlags.Export
122
+ );
123
+ docType.jsDocComment = jsdoc;
124
+ this.docTypes[docTypeId] = docType;
125
+ }
126
+ }
127
+ /** Generates the `.d.ts` output as a string. */
128
+ toString() {
129
+ const results = [TEMPLATE];
130
+ const sortedFieldsTypes = Object.keys(this.fieldsTypes).sort();
131
+ for (const fieldsTypeId of sortedFieldsTypes) {
132
+ const fieldsType = this.fieldsTypes[fieldsTypeId];
133
+ results.push(this.typeToString(fieldsType));
134
+ const docTypeId = this.fieldsTypeToDocType(fieldsTypeId);
135
+ const docType = this.docTypes[docTypeId];
136
+ if (docType) {
137
+ results.push(this.typeToString(docType));
138
+ }
139
+ }
140
+ const output = results.join("\n\n").replaceAll("/** ", "/** ").replaceAll(" */", " */").replace(/\r\n|\r|\n/g, "\n") + "\n";
141
+ return output;
142
+ }
143
+ /**
144
+ * Converts "<Name>Fields" to "<Name>Doc".
145
+ */
146
+ fieldsTypeToDocType(fieldsTypeId) {
147
+ if (!fieldsTypeId.endsWith("Fields")) {
148
+ throw new Error(`"${fieldsTypeId}" should be suffixed with "Fields"`);
149
+ }
150
+ const name = fieldsTypeId.slice(0, -6);
151
+ return `${name}Doc`;
152
+ }
153
+ typeToString(type2) {
154
+ return this.reformatOutput(dom.emit(type2, { singleLineJsDocComments: true }));
155
+ }
156
+ /**
157
+ * Formats the output to Google style conventions, e.g. 2-space indents and
158
+ * single quote strings.
159
+ */
160
+ reformatOutput(input) {
161
+ const lines = input.trim().split("\n");
162
+ const results = [];
163
+ for (const line of lines) {
164
+ const convertedLine = line.replace(/ {4}/g, " ").replaceAll('"', "'");
165
+ results.push(convertedLine);
166
+ }
167
+ return results.join("\n");
168
+ }
169
+ };
170
+ async function generateSchemaDts(outputPath, schemas) {
171
+ const dtsFormatter = new DtsFormatter();
172
+ for (const fileId in schemas) {
173
+ const schema = schemas[fileId];
174
+ dtsFormatter.addSchemaFile(fileId, schema);
175
+ }
176
+ const output = dtsFormatter.toString();
177
+ await fs.writeFile(outputPath, output, "utf-8");
178
+ }
179
+ function fieldProperty(field, options) {
180
+ const prop = dom.create.property(
181
+ field.id,
182
+ fieldType(field, options),
183
+ dom.DeclarationFlags.Optional
184
+ );
185
+ const jsdoc = [];
186
+ if (field.label) {
187
+ if (field.help) {
188
+ jsdoc.push(`${field.label}. ${field.help}`);
189
+ } else {
190
+ jsdoc.push(field.label);
191
+ }
192
+ }
193
+ if (field.deprecated) {
194
+ jsdoc.push("@deprecated");
195
+ }
196
+ if (jsdoc.length > 0) {
197
+ prop.jsDocComment = jsdoc.join("\n");
198
+ }
199
+ return prop;
200
+ }
201
+ function fieldType(field, options) {
202
+ if (field.type === "array") {
203
+ return dom.type.array(fieldType(field.of, options));
204
+ }
205
+ if (field.type === "boolean") {
206
+ return dom.type.boolean;
207
+ }
208
+ if (field.type === "date") {
209
+ return dom.type.string;
210
+ }
211
+ if (field.type === "datetime") {
212
+ return dom.type.number;
213
+ }
214
+ if (field.type === "file") {
215
+ const fileType = dom.create.namedTypeReference("RootCMSFile");
216
+ return fileType;
217
+ }
218
+ if (field.type === "image") {
219
+ const imageType = dom.create.namedTypeReference("RootCMSImage");
220
+ return imageType;
221
+ }
222
+ if (field.type === "multiselect") {
223
+ return dom.type.array(dom.type.string);
224
+ }
225
+ if (field.type === "oneof") {
226
+ const oneOf = dom.create.namedTypeReference("RootCMSOneOf");
227
+ if (field.types && Array.isArray(field.types)) {
228
+ const unionTypes = [];
229
+ field.types.forEach((schema) => {
230
+ let typeName;
231
+ if (typeof schema === "string") {
232
+ typeName = schema;
233
+ return;
234
+ } else {
235
+ typeName = schema.name;
236
+ }
237
+ if (!typeName) {
238
+ return;
239
+ }
240
+ const cleanName = alphanumeric(typeName);
241
+ const oneOfTypeId = `${cleanName}Fields`;
242
+ if (typeof schema === "object" && !options.oneOfTypes[oneOfTypeId]) {
243
+ const oneOfTypeInterface = dom.create.interface(
244
+ oneOfTypeId,
245
+ dom.DeclarationFlags.Export
246
+ );
247
+ if (schema.description) {
248
+ oneOfTypeInterface.jsDocComment = schema.description;
249
+ }
250
+ const oneOfTypeFields = schema.fields || [];
251
+ oneOfTypeFields.forEach((f) => {
252
+ oneOfTypeInterface.members.push(fieldProperty(f, options));
253
+ });
254
+ options.oneOfTypes[oneOfTypeId] = oneOfTypeInterface;
255
+ }
256
+ const oneOfOption = dom.create.namedTypeReference("RootCMSOneOfOption");
257
+ oneOfOption.typeArguments = [
258
+ dom.type.stringLiteral(typeName),
259
+ dom.create.namedTypeReference(oneOfTypeId)
260
+ ];
261
+ unionTypes.push(oneOfOption);
262
+ });
263
+ if (unionTypes.length > 0) {
264
+ oneOf.typeArguments = [dom.create.union(unionTypes)];
265
+ }
266
+ }
267
+ return oneOf;
268
+ }
269
+ if (field.type === "reference") {
270
+ const referenceType = dom.create.namedTypeReference("RootCMSReference");
271
+ return referenceType;
272
+ }
273
+ if (field.type === "references") {
274
+ const referenceType = dom.create.namedTypeReference("RootCMSReference");
275
+ return dom.type.array(referenceType);
276
+ }
277
+ if (field.type === "richtext") {
278
+ const richtextType = dom.create.namedTypeReference("RootCMSRichText");
279
+ return richtextType;
280
+ }
281
+ if (field.type === "select") {
282
+ return dom.type.string;
283
+ }
284
+ if (field.type === "string") {
285
+ return dom.type.string;
286
+ }
287
+ if (field.type === "object") {
288
+ const subproperties = (field.fields || []).map(
289
+ (f) => fieldProperty(f, options)
290
+ );
291
+ return dom.create.objectType(subproperties);
292
+ }
293
+ return dom.type.unknown;
294
+ }
295
+ function alphanumeric(input) {
296
+ return input.replace(/[^a-zA-Z0-9]/g, "");
297
+ }
298
+
299
+ export {
300
+ generateTypes,
301
+ generateSchemaDts
302
+ };
@@ -0,0 +1,136 @@
1
+ import {
2
+ RootCMSClient,
3
+ getCmsPlugin
4
+ } from "./chunk-62EVNFXB.js";
5
+
6
+ // core/versions.ts
7
+ import path from "path";
8
+ import { Timestamp } from "firebase-admin/firestore";
9
+ import glob from "tiny-glob";
10
+ var DOCUMENT_SAVE_OFFSET = 5 * 60 * 1e3;
11
+ var VersionsService = class {
12
+ constructor(rootConfig) {
13
+ this.rootConfig = rootConfig;
14
+ const cmsPlugin = getCmsPlugin(rootConfig);
15
+ const cmsPluginOptions = cmsPlugin.getConfig();
16
+ const projectId = cmsPluginOptions.id || "default";
17
+ this.projectId = projectId;
18
+ this.db = cmsPlugin.getFirestore();
19
+ }
20
+ /**
21
+ * Saves a version of all documents that have been edited since the last run.
22
+ */
23
+ async saveVersions() {
24
+ const lastRun = await this.getLastRun();
25
+ const lastRunWithOffset = lastRun === 0 ? lastRun : lastRun - DOCUMENT_SAVE_OFFSET;
26
+ const changedDocs = await this.getDocsModifiedAfter(lastRunWithOffset);
27
+ const now = Timestamp.now().toMillis();
28
+ const versions = changedDocs.filter((doc) => {
29
+ const modifiedAt = doc.sys.modifiedAt.toMillis();
30
+ return modifiedAt <= now - DOCUMENT_SAVE_OFFSET;
31
+ });
32
+ if (versions.length > 0) {
33
+ this.saveVersionsToFirestore(versions);
34
+ }
35
+ this.saveLastRun(now);
36
+ }
37
+ async saveVersionsToFirestore(versions) {
38
+ const batch = this.db.batch();
39
+ versions.forEach((version) => {
40
+ if (!version.collection || !version.slug || !version.sys?.modifiedAt) {
41
+ return;
42
+ }
43
+ const modifiedAtMillis = version.sys.modifiedAt.toMillis();
44
+ const versionPath = `Projects/${this.projectId}/Collections/${version.collection}/Drafts/${version.slug}/Versions/${modifiedAtMillis}`;
45
+ console.log(versionPath);
46
+ const versionRef = this.db.doc(versionPath);
47
+ batch.set(versionRef, version);
48
+ });
49
+ await batch.commit();
50
+ console.log(`versions: saved ${versions.length} versions`);
51
+ }
52
+ /**
53
+ * Returns the last time (in millis) saveVersions() was run, or 0 if has
54
+ * never been run.
55
+ */
56
+ async getLastRun() {
57
+ const projectDocRef = this.db.collection("Projects").doc(this.projectId);
58
+ const projectDoc = await projectDocRef.get();
59
+ if (projectDoc.exists) {
60
+ const data = projectDoc.data() || {};
61
+ const ts = data.versionsLastRun;
62
+ if (ts) {
63
+ return ts.toMillis();
64
+ }
65
+ }
66
+ return 0;
67
+ }
68
+ /**
69
+ * Saves {versionLastRun: <timestamp>} to the Projects/<projectId> doc.
70
+ */
71
+ async saveLastRun(millis) {
72
+ const ts = Timestamp.fromMillis(millis);
73
+ const projectDocRef = this.db.collection("Projects").doc(this.projectId);
74
+ await projectDocRef.set({ versionsLastRun: ts }, { merge: true });
75
+ }
76
+ /**
77
+ * Returns a list of all docs that were edited after a certain time.
78
+ */
79
+ async getDocsModifiedAfter(millis) {
80
+ const ts = Timestamp.fromMillis(millis);
81
+ const results = [];
82
+ const collectionIds = await this.listCollections();
83
+ for (const collectionId of collectionIds) {
84
+ const collectionPath = `Projects/${this.projectId}/Collections/${collectionId}/Drafts`;
85
+ const query = this.db.collection(collectionPath).where("sys.modifiedAt", ">=", ts);
86
+ const querySnapshot = await query.get();
87
+ querySnapshot.forEach((doc) => {
88
+ results.push(doc.data());
89
+ });
90
+ }
91
+ return results;
92
+ }
93
+ /**
94
+ * Returns a list of collection ids for the Root project.
95
+ */
96
+ async listCollections() {
97
+ const collectionIds = [];
98
+ const collectionFileNames = await glob("*.schema.ts", {
99
+ cwd: path.join(this.rootConfig.rootDir, "collections")
100
+ });
101
+ collectionFileNames.forEach((filename) => {
102
+ collectionIds.push(filename.slice(0, -10));
103
+ });
104
+ return collectionIds;
105
+ }
106
+ };
107
+
108
+ // core/cron.ts
109
+ async function runCronJobs(rootConfig) {
110
+ await Promise.all([
111
+ runCronJob("publishScheduledDocs", runPublishScheduledDocs, rootConfig),
112
+ runCronJob("saveVersions", runSaveVersions, rootConfig)
113
+ ]);
114
+ }
115
+ async function runCronJob(name, fn, ...args) {
116
+ try {
117
+ await fn(...args);
118
+ } catch (err) {
119
+ console.log(`cron failed: ${name}`);
120
+ console.error(String(err.stack || err));
121
+ throw err;
122
+ }
123
+ }
124
+ async function runPublishScheduledDocs(rootConfig) {
125
+ const cmsClient = new RootCMSClient(rootConfig);
126
+ await cmsClient.publishScheduledDocs();
127
+ await cmsClient.publishScheduledReleases();
128
+ }
129
+ async function runSaveVersions(rootConfig) {
130
+ const service = new VersionsService(rootConfig);
131
+ await service.saveVersions();
132
+ }
133
+
134
+ export {
135
+ runCronJobs
136
+ };
@@ -0,0 +1,193 @@
1
+ // package.json
2
+ var package_default = {
3
+ name: "@blinkk/root-cms",
4
+ version: "2.4.10",
5
+ author: "s@blinkk.com",
6
+ license: "MIT",
7
+ engines: {
8
+ node: ">=16.0.0"
9
+ },
10
+ repository: {
11
+ type: "git",
12
+ url: "git+https://github.com/blinkk/rootjs.git",
13
+ directory: "packages/root-cms"
14
+ },
15
+ files: [
16
+ "dist/**/*"
17
+ ],
18
+ bin: {
19
+ "root-cms": "./bin/root-cms.js"
20
+ },
21
+ type: "module",
22
+ module: "./dist/index.js",
23
+ types: "./dist/index.d.ts",
24
+ exports: {
25
+ ".": {
26
+ types: "./dist/core.d.ts",
27
+ import: "./dist/core.js"
28
+ },
29
+ "./client": {
30
+ types: "./dist/client.d.ts",
31
+ import: "./dist/client.js"
32
+ },
33
+ "./core": {
34
+ types: "./dist/core.d.ts",
35
+ import: "./dist/core.js"
36
+ },
37
+ "./functions": {
38
+ types: "./dist/functions.d.ts",
39
+ import: "./dist/functions.js"
40
+ },
41
+ "./plugin": {
42
+ types: "./dist/plugin.d.ts",
43
+ import: "./dist/plugin.js"
44
+ },
45
+ "./project": {
46
+ types: "./dist/project.d.ts",
47
+ import: "./dist/project.js"
48
+ },
49
+ "./richtext": {
50
+ types: "./dist/richtext.d.ts",
51
+ import: "./dist/richtext.js"
52
+ }
53
+ },
54
+ scripts: {
55
+ build: 'rm -rf dist && concurrently -n "core,signin,ui" npm:build:core npm:build:signin npm:build:ui',
56
+ "build:core": "tsup-node --config=./core/tsup.config.ts",
57
+ "//": "NOTE: esbuild is used here because tsup doesn't currently support aliases.",
58
+ "build:ui": "esbuild ui/ui.tsx --bundle --minify --alias:react=@preact/compat --alias:react-dom=@preact/compat --tsconfig=ui/tsconfig.json --outdir=dist/ui --legal-comments=external",
59
+ "build:signin": "esbuild signin/signin.tsx --bundle --minify --tsconfig=signin/tsconfig.json --outdir=dist/ui --legal-comments=external",
60
+ dev: 'rm -rf dist && concurrently -k -n "core,ui" npm:dev:core npm:dev:signin npm:dev:ui',
61
+ "dev:core": "pnpm build:core --watch",
62
+ "dev:signin": "pnpm build:signin --watch",
63
+ "dev:ui": "pnpm build:ui --watch",
64
+ test: "pnpm build && firebase emulators:exec 'vitest run --exclude=**/*.visual.test.tsx'",
65
+ "test:visual": "vitest run --config=vitest.config.visual.ts",
66
+ "test:watch": "pnpm build && firebase emulators:exec 'vitest'"
67
+ },
68
+ dependencies: {
69
+ "@ag-grid-community/client-side-row-model": "32.3.9",
70
+ "@ag-grid-community/core": "32.3.9",
71
+ "@ag-grid-community/react": "32.3.9",
72
+ "@ag-grid-community/styles": "32.3.9",
73
+ "@genkit-ai/ai": "1.26.0",
74
+ "@genkit-ai/core": "1.26.0",
75
+ "@genkit-ai/google-genai": "1.26.0",
76
+ "@google-cloud/firestore": "7.11.3",
77
+ "@hello-pangea/dnd": "18.0.1",
78
+ "@types/cli-progress": "3.11.6",
79
+ "body-parser": "1.20.2",
80
+ "cli-progress": "3.12.0",
81
+ commander: "11.0.0",
82
+ "csv-parse": "5.5.2",
83
+ "csv-stringify": "6.4.4",
84
+ "date-fns": "4.1.0",
85
+ "date-fns-tz": "3.2.0",
86
+ diff: "8.0.2",
87
+ "dts-dom": "3.7.0",
88
+ "fnv-plus": "1.3.1",
89
+ genkit: "1.26.0",
90
+ jsonwebtoken: "9.0.2",
91
+ kleur: "4.1.5",
92
+ "react-easy-crop": "5.5.6",
93
+ sirv: "2.0.3",
94
+ "tiny-glob": "0.2.9"
95
+ },
96
+ "//": "NOTE(stevenle): due to compat issues with mantine and preact, mantine is pinned to v4.2.12",
97
+ devDependencies: {
98
+ "@babel/core": "7.17.9",
99
+ "@blinkk/root": "workspace:*",
100
+ "@editorjs/editorjs": "2.30.8",
101
+ "@editorjs/header": "2.8.8",
102
+ "@editorjs/image": "2.10.2",
103
+ "@editorjs/list": "2.0.6",
104
+ "@editorjs/nested-list": "1.4.3",
105
+ "@editorjs/raw": "2.5.1",
106
+ "@editorjs/table": "2.4.4",
107
+ "@editorjs/underline": "1.2.1",
108
+ "@emotion/react": "11.10.5",
109
+ "@firebase/app-compat": "0.5.2",
110
+ "@firebase/app-types": "0.9.3",
111
+ "@firebase/rules-unit-testing": "5.0.0",
112
+ "@lexical/code": "0.33.1",
113
+ "@lexical/html": "0.33.1",
114
+ "@lexical/link": "0.33.1",
115
+ "@lexical/list": "0.33.1",
116
+ "@lexical/markdown": "0.33.1",
117
+ "@lexical/react": "0.33.1",
118
+ "@lexical/rich-text": "0.33.1",
119
+ "@lexical/selection": "0.33.1",
120
+ "@lexical/table": "0.33.1",
121
+ "@lexical/utils": "0.33.1",
122
+ "@mantine/core": "4.2.12",
123
+ "@mantine/hooks": "4.2.12",
124
+ "@mantine/modals": "4.2.12",
125
+ "@mantine/notifications": "4.2.12",
126
+ "@mantine/spotlight": "4.2.12",
127
+ "@preact/compat": "18.3.1",
128
+ "@tabler/icons-preact": "3.35.0",
129
+ "@testing-library/preact": "3.2.4",
130
+ "@testing-library/user-event": "14.6.1",
131
+ "@types/body-parser": "1.19.3",
132
+ "@types/fnv-plus": "1.3.2",
133
+ "@types/gapi": "0.0.47",
134
+ "@types/gapi.client.drive-v3": "0.0.4",
135
+ "@types/gapi.client.sheets-v4": "0.0.4",
136
+ "@types/google.accounts": "0.0.14",
137
+ "@types/jsonwebtoken": "9.0.1",
138
+ "@types/node": "24.3.1",
139
+ "@vitest/browser": "4.0.10",
140
+ "@vitest/browser-playwright": "4.0.10",
141
+ concurrently: "7.6.0",
142
+ esbuild: "0.25.9",
143
+ firebase: "12.2.1",
144
+ "firebase-admin": "13.5.0",
145
+ "firebase-functions": "6.4.0",
146
+ "firebase-tools": "14.15.2",
147
+ "highlight.js": "11.6.0",
148
+ jsdom: "27.2.0",
149
+ "json-diff-kit": "1.0.29",
150
+ lexical: "0.33.1",
151
+ marked: "9.1.1",
152
+ "mdast-util-from-markdown": "2.0.1",
153
+ "mdast-util-gfm": "3.0.0",
154
+ "micromark-extension-gfm": "3.0.0",
155
+ playwright: "1.56.1",
156
+ preact: "10.27.1",
157
+ "preact-render-to-string": "6.6.1",
158
+ "preact-router": "4.1.2",
159
+ react: "npm:@preact/compat@18.3.1",
160
+ "react-dom": "npm:@preact/compat@18.3.1",
161
+ "react-json-view-compare": "2.0.2",
162
+ tsup: "8.5.0",
163
+ typescript: "5.9.2",
164
+ vite: "7.1.4",
165
+ vitest: "4.0.10",
166
+ yjs: "13.6.27"
167
+ },
168
+ peerDependencies: {
169
+ "@blinkk/root": "2.4.10",
170
+ "firebase-admin": ">=11",
171
+ "firebase-functions": ">=4",
172
+ preact: ">=10",
173
+ "preact-render-to-string": ">=5"
174
+ },
175
+ peerDependenciesMeta: {
176
+ "firebase-functions": {
177
+ optional: true
178
+ }
179
+ }
180
+ };
181
+
182
+ // core/server-version.ts
183
+ var SERVER_STARTUP_TS = String(Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3));
184
+ function getServerVersion() {
185
+ if (process.env.NODE_ENV === "development") {
186
+ return SERVER_STARTUP_TS;
187
+ }
188
+ return package_default?.version || "root-3.0.0";
189
+ }
190
+
191
+ export {
192
+ getServerVersion
193
+ };