@blinkk/root-cms 1.0.0-alpha.9 → 1.0.0-beta.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.
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {createRequire} from 'node:module';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {Command} from 'commander';
7
+ import {bgGreen, black} from 'kleur/colors';
8
+ import {initFirebase, generateTypes} from '../dist/cli.js';
9
+ import {loadRootConfig} from '@blinkk/root/node';
10
+
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ const require = createRequire(import.meta.url);
13
+ const packageJson = require(path.join(__dirname, '../package.json'));
14
+
15
+ async function main() {
16
+ console.log(`🌱 ${bgGreen(black(' root.js cms '))} v${packageJson.version}`);
17
+
18
+ const rootDir = process.cwd();
19
+ const rootConfig = await loadRootConfig(rootDir, {command: 'root-cms'});
20
+
21
+ const program = new Command('root-cms');
22
+ program.version(packageJson.version);
23
+ program
24
+ .command('init-firebase')
25
+ .description('inits the firebase project with proper security rules')
26
+ .option('--project <project>', 'gcp project id')
27
+ .action(initFirebase(rootConfig));
28
+ program
29
+ .command('generate-types')
30
+ .description('generates root-cms.d.ts from *.schema.ts files in the project')
31
+ .action(generateTypes(rootConfig));
32
+ await program.parseAsync(process.argv);
33
+ }
34
+
35
+ main();
package/dist/app.js ADDED
@@ -0,0 +1,190 @@
1
+ // core/app.tsx
2
+ import { render as renderToString } from "preact-render-to-string";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { jsx, jsxs } from "preact/jsx-runtime";
6
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ function App(props) {
8
+ return /* @__PURE__ */ jsxs("html", {
9
+ children: [
10
+ /* @__PURE__ */ jsxs("head", {
11
+ children: [
12
+ /* @__PURE__ */ jsx("title", {
13
+ children: props.title
14
+ }),
15
+ /* @__PURE__ */ jsx("link", {
16
+ rel: "preconnect",
17
+ href: "https://fonts.googleapis.com"
18
+ }),
19
+ /* @__PURE__ */ jsx("link", {
20
+ rel: "preconnect",
21
+ href: "https://fonts.gstatic.com",
22
+ crossOrigin: "anonymous"
23
+ }),
24
+ /* @__PURE__ */ jsx("link", {
25
+ rel: "stylesheet",
26
+ href: "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap"
27
+ }),
28
+ /* @__PURE__ */ jsx("link", {
29
+ rel: "stylesheet",
30
+ href: "https://fonts.googleapis.com/css2?family=Google+Sans:wght@500&display=swap"
31
+ }),
32
+ /* @__PURE__ */ jsx("link", {
33
+ rel: "stylesheet",
34
+ href: "{CSS_URL}"
35
+ })
36
+ ]
37
+ }),
38
+ /* @__PURE__ */ jsxs("body", {
39
+ children: [
40
+ /* @__PURE__ */ jsx("div", {
41
+ id: "root",
42
+ children: /* @__PURE__ */ jsxs("div", {
43
+ className: "bootstrap",
44
+ children: [
45
+ /* @__PURE__ */ jsx("h1", {
46
+ className: "bootstrap__loading",
47
+ children: "Loading..."
48
+ }),
49
+ /* @__PURE__ */ jsx("div", {
50
+ className: "bootstrap-error",
51
+ children: "If this page fails to load, try a force refresh by holding the shift key while refreshing the page."
52
+ })
53
+ ]
54
+ })
55
+ }),
56
+ /* @__PURE__ */ jsx("script", {
57
+ dangerouslySetInnerHTML: {
58
+ __html: `window.__ROOT_CTX = ${JSON.stringify(props.ctx)}`
59
+ }
60
+ }),
61
+ /* @__PURE__ */ jsx("script", {
62
+ type: "module",
63
+ src: "{JS_URL}"
64
+ })
65
+ ]
66
+ })
67
+ ]
68
+ });
69
+ }
70
+ async function renderApp(req, res, options) {
71
+ const collectionModules = import.meta.glob("/collections/*.schema.ts", {
72
+ eager: true
73
+ });
74
+ const collections = {};
75
+ Object.keys(collectionModules).forEach((moduleId) => {
76
+ const collectionId = path.parse(moduleId).base.split(".")[0];
77
+ const module = collectionModules[moduleId];
78
+ const collection = module.default;
79
+ collections[collectionId] = collection;
80
+ });
81
+ const rootConfig = options.rootConfig || {};
82
+ const cmsConfig = options.cmsConfig || {};
83
+ const ctx = {
84
+ rootConfig: {
85
+ projectId: cmsConfig.id || "default",
86
+ domain: rootConfig.domain || "https://example.com"
87
+ },
88
+ firebaseConfig: options.firebaseConfig,
89
+ collections
90
+ };
91
+ const mainHtml = renderToString(/* @__PURE__ */ jsx(App, {
92
+ title: "Root.js CMS",
93
+ ctx
94
+ }));
95
+ let html = `<!doctype html>
96
+ ${mainHtml}`;
97
+ if (req.viteServer) {
98
+ const uiCssPath = path.join(__dirname, "ui/ui.css");
99
+ const uiJsPath = path.join(__dirname, "ui/ui.js");
100
+ const tpl = html.replace("{CSS_URL}", `/@fs${uiCssPath}`).replace("{JS_URL}", `/@fs${uiJsPath}`);
101
+ html = await req.viteServer.transformIndexHtml(req.originalUrl, tpl);
102
+ } else {
103
+ html = html.replace("{CSS_URL}", "/cms/static/ui.css").replace("{JS_URL}", "/cms/static/ui.js");
104
+ }
105
+ res.setHeader("Content-Type", "text/html");
106
+ res.send(html);
107
+ }
108
+ function SignIn(props) {
109
+ return /* @__PURE__ */ jsxs("html", {
110
+ children: [
111
+ /* @__PURE__ */ jsxs("head", {
112
+ children: [
113
+ /* @__PURE__ */ jsx("title", {
114
+ children: props.title
115
+ }),
116
+ /* @__PURE__ */ jsx("link", {
117
+ rel: "preconnect",
118
+ href: "https://fonts.googleapis.com"
119
+ }),
120
+ /* @__PURE__ */ jsx("link", {
121
+ rel: "preconnect",
122
+ href: "https://fonts.gstatic.com",
123
+ crossOrigin: "anonymous"
124
+ }),
125
+ /* @__PURE__ */ jsx("link", {
126
+ rel: "stylesheet",
127
+ href: "https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&display=swap"
128
+ }),
129
+ /* @__PURE__ */ jsx("link", {
130
+ rel: "stylesheet",
131
+ href: "{CSS_URL}"
132
+ })
133
+ ]
134
+ }),
135
+ /* @__PURE__ */ jsxs("body", {
136
+ children: [
137
+ /* @__PURE__ */ jsx("div", {
138
+ id: "root",
139
+ children: /* @__PURE__ */ jsxs("div", {
140
+ className: "bootstrap",
141
+ children: [
142
+ /* @__PURE__ */ jsx("h1", {
143
+ className: "bootstrap__loading",
144
+ children: "Loading..."
145
+ }),
146
+ /* @__PURE__ */ jsx("div", {
147
+ className: "bootstrap-error",
148
+ children: "If this page fails to load, try a force refresh by holding the shift key while refreshing the page."
149
+ })
150
+ ]
151
+ })
152
+ }),
153
+ /* @__PURE__ */ jsx("script", {
154
+ dangerouslySetInnerHTML: {
155
+ __html: `window.__ROOT_CTX = ${JSON.stringify(props.ctx)}`
156
+ }
157
+ }),
158
+ /* @__PURE__ */ jsx("script", {
159
+ type: "module",
160
+ src: "{JS_URL}"
161
+ })
162
+ ]
163
+ })
164
+ ]
165
+ });
166
+ }
167
+ async function renderSignIn(req, res, options) {
168
+ const ctx = { firebaseConfig: options.firebaseConfig };
169
+ const mainHtml = renderToString(/* @__PURE__ */ jsx(SignIn, {
170
+ title: "Sign in",
171
+ ctx
172
+ }));
173
+ let html = `<!doctype html>
174
+ ${mainHtml}`;
175
+ if (req.viteServer) {
176
+ const cssPath = path.join(__dirname, "ui/signin.css");
177
+ const jsPath = path.join(__dirname, "ui/signin.js");
178
+ const tpl = html.replace("{CSS_URL}", `/@fs${cssPath}`).replace("{JS_URL}", `/@fs${jsPath}`);
179
+ html = await req.viteServer.transformIndexHtml(req.originalUrl, tpl);
180
+ } else {
181
+ html = html.replace("{CSS_URL}", "/cms/static/signin.css").replace("{JS_URL}", "/cms/static/signin.js");
182
+ }
183
+ res.setHeader("Content-Type", "text/html");
184
+ res.send(html);
185
+ }
186
+ export {
187
+ renderApp,
188
+ renderSignIn
189
+ };
190
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9hcHAudHN4Il0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge1JlcXVlc3QsIFJlc3BvbnNlfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0IHtDb2xsZWN0aW9ufSBmcm9tICcuL3NjaGVtYS5qcyc7XG5pbXBvcnQge3JlbmRlciBhcyByZW5kZXJUb1N0cmluZ30gZnJvbSAncHJlYWN0LXJlbmRlci10by1zdHJpbmcnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7ZmlsZVVSTFRvUGF0aH0gZnJvbSAnbm9kZTp1cmwnO1xuXG5jb25zdCBfX2Rpcm5hbWUgPSBwYXRoLmRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcblxuaW50ZXJmYWNlIEFwcFByb3BzIHtcbiAgdGl0bGU6IHN0cmluZztcbiAgY3R4OiBhbnk7XG59XG5cbmZ1bmN0aW9uIEFwcChwcm9wczogQXBwUHJvcHMpIHtcbiAgcmV0dXJuIChcbiAgICA8aHRtbD5cbiAgICAgIDxoZWFkPlxuICAgICAgICA8dGl0bGU+e3Byb3BzLnRpdGxlfTwvdGl0bGU+XG4gICAgICAgIDxsaW5rIHJlbD1cInByZWNvbm5lY3RcIiBocmVmPVwiaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbVwiIC8+XG4gICAgICAgIDxsaW5rXG4gICAgICAgICAgcmVsPVwicHJlY29ubmVjdFwiXG4gICAgICAgICAgaHJlZj1cImh0dHBzOi8vZm9udHMuZ3N0YXRpYy5jb21cIlxuICAgICAgICAgIGNyb3NzT3JpZ2luPVwiYW5vbnltb3VzXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGxpbmtcbiAgICAgICAgICByZWw9XCJzdHlsZXNoZWV0XCJcbiAgICAgICAgICBocmVmPVwiaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1JbnRlcjp3Z2h0QDMwMDs0MDA7NTAwOzYwMDs3MDA7OTAwJmRpc3BsYXk9c3dhcFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxsaW5rXG4gICAgICAgICAgcmVsPVwic3R5bGVzaGVldFwiXG4gICAgICAgICAgaHJlZj1cImh0dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzMj9mYW1pbHk9R29vZ2xlK1NhbnM6d2dodEA1MDAmZGlzcGxheT1zd2FwXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGxpbmsgcmVsPVwic3R5bGVzaGVldFwiIGhyZWY9XCJ7Q1NTX1VSTH1cIiAvPlxuICAgICAgPC9oZWFkPlxuICAgICAgPGJvZHk+XG4gICAgICAgIDxkaXYgaWQ9XCJyb290XCI+XG4gICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJib290c3RyYXBcIj5cbiAgICAgICAgICAgIDxoMSBjbGFzc05hbWU9XCJib290c3RyYXBfX2xvYWRpbmdcIj5Mb2FkaW5nLi4uPC9oMT5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYm9vdHN0cmFwLWVycm9yXCI+XG4gICAgICAgICAgICAgIElmIHRoaXMgcGFnZSBmYWlscyB0byBsb2FkLCB0cnkgYSBmb3JjZSByZWZyZXNoIGJ5IGhvbGRpbmcgdGhlXG4gICAgICAgICAgICAgIHNoaWZ0IGtleSB3aGlsZSByZWZyZXNoaW5nIHRoZSBwYWdlLlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8c2NyaXB0XG4gICAgICAgICAgZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUw9e3tcbiAgICAgICAgICAgIF9faHRtbDogYHdpbmRvdy5fX1JPT1RfQ1RYID0gJHtKU09OLnN0cmluZ2lmeShwcm9wcy5jdHgpfWAsXG4gICAgICAgICAgfX1cbiAgICAgICAgLz5cbiAgICAgICAgPHNjcmlwdCB0eXBlPVwibW9kdWxlXCIgc3JjPVwie0pTX1VSTH1cIj48L3NjcmlwdD5cbiAgICAgIDwvYm9keT5cbiAgICA8L2h0bWw+XG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW5kZXJBcHAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBvcHRpb25zOiBhbnkpIHtcbiAgY29uc3QgY29sbGVjdGlvbk1vZHVsZXMgPSBpbXBvcnQubWV0YS5nbG9iKCcvY29sbGVjdGlvbnMvKi5zY2hlbWEudHMnLCB7XG4gICAgZWFnZXI6IHRydWUsXG4gIH0pIGFzIGFueTtcbiAgY29uc3QgY29sbGVjdGlvbnM6IFJlY29yZDxzdHJpbmcsIENvbGxlY3Rpb24+ID0ge307XG4gIE9iamVjdC5rZXlzKGNvbGxlY3Rpb25Nb2R1bGVzKS5mb3JFYWNoKChtb2R1bGVJZDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgY29sbGVjdGlvbklkID0gcGF0aC5wYXJzZShtb2R1bGVJZCkuYmFzZS5zcGxpdCgnLicpWzBdO1xuICAgIGNvbnN0IG1vZHVsZSA9IGNvbGxlY3Rpb25Nb2R1bGVzW21vZHVsZUlkXTtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gbW9kdWxlLmRlZmF1bHQgYXMgQ29sbGVjdGlvbjtcbiAgICBjb2xsZWN0aW9uc1tjb2xsZWN0aW9uSWRdID0gY29sbGVjdGlvbjtcbiAgfSk7XG4gIGNvbnN0IHJvb3RDb25maWcgPSBvcHRpb25zLnJvb3RDb25maWcgfHwge307XG4gIGNvbnN0IGNtc0NvbmZpZyA9IG9wdGlvbnMuY21zQ29uZmlnIHx8IHt9O1xuICBjb25zdCBjdHggPSB7XG4gICAgcm9vdENvbmZpZzoge1xuICAgICAgcHJvamVjdElkOiBjbXNDb25maWcuaWQgfHwgJ2RlZmF1bHQnLFxuICAgICAgZG9tYWluOiByb290Q29uZmlnLmRvbWFpbiB8fCAnaHR0cHM6Ly9leGFtcGxlLmNvbScsXG4gICAgfSxcbiAgICBmaXJlYmFzZUNvbmZpZzogb3B0aW9ucy5maXJlYmFzZUNvbmZpZyxcbiAgICBjb2xsZWN0aW9uczogY29sbGVjdGlvbnMsXG4gIH07XG4gIGNvbnN0IG1haW5IdG1sID0gcmVuZGVyVG9TdHJpbmcoPEFwcCB0aXRsZT1cIlJvb3QuanMgQ01TXCIgY3R4PXtjdHh9IC8+KTtcbiAgbGV0IGh0bWwgPSBgPCFkb2N0eXBlIGh0bWw+XFxuJHttYWluSHRtbH1gO1xuICBpZiAocmVxLnZpdGVTZXJ2ZXIpIHtcbiAgICBjb25zdCB1aUNzc1BhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAndWkvdWkuY3NzJyk7XG4gICAgY29uc3QgdWlKc1BhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAndWkvdWkuanMnKTtcbiAgICBjb25zdCB0cGwgPSBodG1sXG4gICAgICAucmVwbGFjZSgne0NTU19VUkx9JywgYC9AZnMke3VpQ3NzUGF0aH1gKVxuICAgICAgLnJlcGxhY2UoJ3tKU19VUkx9JywgYC9AZnMke3VpSnNQYXRofWApO1xuICAgIGh0bWwgPSBhd2FpdCByZXEudml0ZVNlcnZlciEudHJhbnNmb3JtSW5kZXhIdG1sKHJlcS5vcmlnaW5hbFVybCwgdHBsKTtcbiAgfSBlbHNlIHtcbiAgICBodG1sID0gaHRtbFxuICAgICAgLnJlcGxhY2UoJ3tDU1NfVVJMfScsICcvY21zL3N0YXRpYy91aS5jc3MnKVxuICAgICAgLnJlcGxhY2UoJ3tKU19VUkx9JywgJy9jbXMvc3RhdGljL3VpLmpzJyk7XG4gIH1cbiAgcmVzLnNldEhlYWRlcignQ29udGVudC1UeXBlJywgJ3RleHQvaHRtbCcpO1xuICByZXMuc2VuZChodG1sKTtcbn1cblxuaW50ZXJmYWNlIFNpZ25JblByb3BzIHtcbiAgdGl0bGU6IHN0cmluZztcbiAgY3R4OiBhbnk7XG59XG5cbmZ1bmN0aW9uIFNpZ25Jbihwcm9wczogU2lnbkluUHJvcHMpIHtcbiAgcmV0dXJuIChcbiAgICA8aHRtbD5cbiAgICAgIDxoZWFkPlxuICAgICAgICA8dGl0bGU+e3Byb3BzLnRpdGxlfTwvdGl0bGU+XG4gICAgICAgIDxsaW5rIHJlbD1cInByZWNvbm5lY3RcIiBocmVmPVwiaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbVwiIC8+XG4gICAgICAgIDxsaW5rXG4gICAgICAgICAgcmVsPVwicHJlY29ubmVjdFwiXG4gICAgICAgICAgaHJlZj1cImh0dHBzOi8vZm9udHMuZ3N0YXRpYy5jb21cIlxuICAgICAgICAgIGNyb3NzT3JpZ2luPVwiYW5vbnltb3VzXCJcbiAgICAgICAgLz5cbiAgICAgICAgPGxpbmtcbiAgICAgICAgICByZWw9XCJzdHlsZXNoZWV0XCJcbiAgICAgICAgICBocmVmPVwiaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1JbnRlcjp3Z2h0QDMwMDs0MDA7NTAwOzYwMDs3MDA7OTAwJmRpc3BsYXk9c3dhcFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxsaW5rIHJlbD1cInN0eWxlc2hlZXRcIiBocmVmPVwie0NTU19VUkx9XCIgLz5cbiAgICAgIDwvaGVhZD5cbiAgICAgIDxib2R5PlxuICAgICAgICA8ZGl2IGlkPVwicm9vdFwiPlxuICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiYm9vdHN0cmFwXCI+XG4gICAgICAgICAgICA8aDEgY2xhc3NOYW1lPVwiYm9vdHN0cmFwX19sb2FkaW5nXCI+TG9hZGluZy4uLjwvaDE+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cImJvb3RzdHJhcC1lcnJvclwiPlxuICAgICAgICAgICAgICBJZiB0aGlzIHBhZ2UgZmFpbHMgdG8gbG9hZCwgdHJ5IGEgZm9yY2UgcmVmcmVzaCBieSBob2xkaW5nIHRoZVxuICAgICAgICAgICAgICBzaGlmdCBrZXkgd2hpbGUgcmVmcmVzaGluZyB0aGUgcGFnZS5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHNjcmlwdFxuICAgICAgICAgIGRhbmdlcm91c2x5U2V0SW5uZXJIVE1MPXt7XG4gICAgICAgICAgICBfX2h0bWw6IGB3aW5kb3cuX19ST09UX0NUWCA9ICR7SlNPTi5zdHJpbmdpZnkocHJvcHMuY3R4KX1gLFxuICAgICAgICAgIH19XG4gICAgICAgIC8+XG4gICAgICAgIDxzY3JpcHQgdHlwZT1cIm1vZHVsZVwiIHNyYz1cIntKU19VUkx9XCI+PC9zY3JpcHQ+XG4gICAgICA8L2JvZHk+XG4gICAgPC9odG1sPlxuICApO1xufVxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbmRlclNpZ25JbihyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG9wdGlvbnM6IGFueSkge1xuICBjb25zdCBjdHggPSB7ZmlyZWJhc2VDb25maWc6IG9wdGlvbnMuZmlyZWJhc2VDb25maWd9O1xuICBjb25zdCBtYWluSHRtbCA9IHJlbmRlclRvU3RyaW5nKDxTaWduSW4gdGl0bGU9XCJTaWduIGluXCIgY3R4PXtjdHh9IC8+KTtcbiAgbGV0IGh0bWwgPSBgPCFkb2N0eXBlIGh0bWw+XFxuJHttYWluSHRtbH1gO1xuICBpZiAocmVxLnZpdGVTZXJ2ZXIpIHtcbiAgICBjb25zdCBjc3NQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ3VpL3NpZ25pbi5jc3MnKTtcbiAgICBjb25zdCBqc1BhdGggPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAndWkvc2lnbmluLmpzJyk7XG4gICAgY29uc3QgdHBsID0gaHRtbFxuICAgICAgLnJlcGxhY2UoJ3tDU1NfVVJMfScsIGAvQGZzJHtjc3NQYXRofWApXG4gICAgICAucmVwbGFjZSgne0pTX1VSTH0nLCBgL0BmcyR7anNQYXRofWApO1xuICAgIGh0bWwgPSBhd2FpdCByZXEudml0ZVNlcnZlciEudHJhbnNmb3JtSW5kZXhIdG1sKHJlcS5vcmlnaW5hbFVybCwgdHBsKTtcbiAgfSBlbHNlIHtcbiAgICBodG1sID0gaHRtbFxuICAgICAgLnJlcGxhY2UoJ3tDU1NfVVJMfScsICcvY21zL3N0YXRpYy9zaWduaW4uY3NzJylcbiAgICAgIC5yZXBsYWNlKCd7SlNfVVJMfScsICcvY21zL3N0YXRpYy9zaWduaW4uanMnKTtcbiAgfVxuICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAndGV4dC9odG1sJyk7XG4gIHJlcy5zZW5kKGh0bWwpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUVBLFNBQVEsVUFBVSxzQkFBcUI7QUFDdkMsT0FBTyxVQUFVO0FBQ2pCLFNBQVEscUJBQW9CO0FBWXRCLFNBQ0UsS0FERjtBQVZOLElBQU0sWUFBWSxLQUFLLFFBQVEsY0FBYyxZQUFZLEdBQUcsQ0FBQztBQU83RCxTQUFTLElBQUksT0FBaUI7QUFDNUIsU0FDRSxxQkFBQztBQUFBLElBQ0M7QUFBQSwyQkFBQztBQUFBLFFBQ0M7QUFBQSw4QkFBQztBQUFBLFlBQU8sZ0JBQU07QUFBQSxXQUFNO0FBQUEsVUFDcEIsb0JBQUM7QUFBQSxZQUFLLEtBQUk7QUFBQSxZQUFhLE1BQUs7QUFBQSxXQUErQjtBQUFBLFVBQzNELG9CQUFDO0FBQUEsWUFDQyxLQUFJO0FBQUEsWUFDSixNQUFLO0FBQUEsWUFDTCxhQUFZO0FBQUEsV0FDZDtBQUFBLFVBQ0Esb0JBQUM7QUFBQSxZQUNDLEtBQUk7QUFBQSxZQUNKLE1BQUs7QUFBQSxXQUNQO0FBQUEsVUFDQSxvQkFBQztBQUFBLFlBQ0MsS0FBSTtBQUFBLFlBQ0osTUFBSztBQUFBLFdBQ1A7QUFBQSxVQUNBLG9CQUFDO0FBQUEsWUFBSyxLQUFJO0FBQUEsWUFBYSxNQUFLO0FBQUEsV0FBWTtBQUFBO0FBQUEsT0FDMUM7QUFBQSxNQUNBLHFCQUFDO0FBQUEsUUFDQztBQUFBLDhCQUFDO0FBQUEsWUFBSSxJQUFHO0FBQUEsWUFDTiwrQkFBQztBQUFBLGNBQUksV0FBVTtBQUFBLGNBQ2I7QUFBQSxvQ0FBQztBQUFBLGtCQUFHLFdBQVU7QUFBQSxrQkFBcUI7QUFBQSxpQkFBVTtBQUFBLGdCQUM3QyxvQkFBQztBQUFBLGtCQUFJLFdBQVU7QUFBQSxrQkFBa0I7QUFBQSxpQkFHakM7QUFBQTtBQUFBLGFBQ0Y7QUFBQSxXQUNGO0FBQUEsVUFDQSxvQkFBQztBQUFBLFlBQ0MseUJBQXlCO0FBQUEsY0FDdkIsUUFBUSx1QkFBdUIsS0FBSyxVQUFVLE1BQU0sR0FBRztBQUFBLFlBQ3pEO0FBQUEsV0FDRjtBQUFBLFVBQ0Esb0JBQUM7QUFBQSxZQUFPLE1BQUs7QUFBQSxZQUFTLEtBQUk7QUFBQSxXQUFXO0FBQUE7QUFBQSxPQUN2QztBQUFBO0FBQUEsR0FDRjtBQUVKO0FBRUEsZUFBc0IsVUFBVSxLQUFjLEtBQWUsU0FBYztBQUN6RSxRQUFNLG9CQUFvQixZQUFZLEtBQUssNEJBQTRCO0FBQUEsSUFDckUsT0FBTztBQUFBLEVBQ1QsQ0FBQztBQUNELFFBQU0sY0FBMEMsQ0FBQztBQUNqRCxTQUFPLEtBQUssaUJBQWlCLEVBQUUsUUFBUSxDQUFDLGFBQXFCO0FBQzNELFVBQU0sZUFBZSxLQUFLLE1BQU0sUUFBUSxFQUFFLEtBQUssTUFBTSxHQUFHLEVBQUU7QUFDMUQsVUFBTSxTQUFTLGtCQUFrQjtBQUNqQyxVQUFNLGFBQWEsT0FBTztBQUMxQixnQkFBWSxnQkFBZ0I7QUFBQSxFQUM5QixDQUFDO0FBQ0QsUUFBTSxhQUFhLFFBQVEsY0FBYyxDQUFDO0FBQzFDLFFBQU0sWUFBWSxRQUFRLGFBQWEsQ0FBQztBQUN4QyxRQUFNLE1BQU07QUFBQSxJQUNWLFlBQVk7QUFBQSxNQUNWLFdBQVcsVUFBVSxNQUFNO0FBQUEsTUFDM0IsUUFBUSxXQUFXLFVBQVU7QUFBQSxJQUMvQjtBQUFBLElBQ0EsZ0JBQWdCLFFBQVE7QUFBQSxJQUN4QjtBQUFBLEVBQ0Y7QUFDQSxRQUFNLFdBQVcsZUFBZSxvQkFBQztBQUFBLElBQUksT0FBTTtBQUFBLElBQWM7QUFBQSxHQUFVLENBQUU7QUFDckUsTUFBSSxPQUFPO0FBQUEsRUFBb0I7QUFDL0IsTUFBSSxJQUFJLFlBQVk7QUFDbEIsVUFBTSxZQUFZLEtBQUssS0FBSyxXQUFXLFdBQVc7QUFDbEQsVUFBTSxXQUFXLEtBQUssS0FBSyxXQUFXLFVBQVU7QUFDaEQsVUFBTSxNQUFNLEtBQ1QsUUFBUSxhQUFhLE9BQU8sV0FBVyxFQUN2QyxRQUFRLFlBQVksT0FBTyxVQUFVO0FBQ3hDLFdBQU8sTUFBTSxJQUFJLFdBQVksbUJBQW1CLElBQUksYUFBYSxHQUFHO0FBQUEsRUFDdEUsT0FBTztBQUNMLFdBQU8sS0FDSixRQUFRLGFBQWEsb0JBQW9CLEVBQ3pDLFFBQVEsWUFBWSxtQkFBbUI7QUFBQSxFQUM1QztBQUNBLE1BQUksVUFBVSxnQkFBZ0IsV0FBVztBQUN6QyxNQUFJLEtBQUssSUFBSTtBQUNmO0FBT0EsU0FBUyxPQUFPLE9BQW9CO0FBQ2xDLFNBQ0UscUJBQUM7QUFBQSxJQUNDO0FBQUEsMkJBQUM7QUFBQSxRQUNDO0FBQUEsOEJBQUM7QUFBQSxZQUFPLGdCQUFNO0FBQUEsV0FBTTtBQUFBLFVBQ3BCLG9CQUFDO0FBQUEsWUFBSyxLQUFJO0FBQUEsWUFBYSxNQUFLO0FBQUEsV0FBK0I7QUFBQSxVQUMzRCxvQkFBQztBQUFBLFlBQ0MsS0FBSTtBQUFBLFlBQ0osTUFBSztBQUFBLFlBQ0wsYUFBWTtBQUFBLFdBQ2Q7QUFBQSxVQUNBLG9CQUFDO0FBQUEsWUFDQyxLQUFJO0FBQUEsWUFDSixNQUFLO0FBQUEsV0FDUDtBQUFBLFVBQ0Esb0JBQUM7QUFBQSxZQUFLLEtBQUk7QUFBQSxZQUFhLE1BQUs7QUFBQSxXQUFZO0FBQUE7QUFBQSxPQUMxQztBQUFBLE1BQ0EscUJBQUM7QUFBQSxRQUNDO0FBQUEsOEJBQUM7QUFBQSxZQUFJLElBQUc7QUFBQSxZQUNOLCtCQUFDO0FBQUEsY0FBSSxXQUFVO0FBQUEsY0FDYjtBQUFBLG9DQUFDO0FBQUEsa0JBQUcsV0FBVTtBQUFBLGtCQUFxQjtBQUFBLGlCQUFVO0FBQUEsZ0JBQzdDLG9CQUFDO0FBQUEsa0JBQUksV0FBVTtBQUFBLGtCQUFrQjtBQUFBLGlCQUdqQztBQUFBO0FBQUEsYUFDRjtBQUFBLFdBQ0Y7QUFBQSxVQUNBLG9CQUFDO0FBQUEsWUFDQyx5QkFBeUI7QUFBQSxjQUN2QixRQUFRLHVCQUF1QixLQUFLLFVBQVUsTUFBTSxHQUFHO0FBQUEsWUFDekQ7QUFBQSxXQUNGO0FBQUEsVUFDQSxvQkFBQztBQUFBLFlBQU8sTUFBSztBQUFBLFlBQVMsS0FBSTtBQUFBLFdBQVc7QUFBQTtBQUFBLE9BQ3ZDO0FBQUE7QUFBQSxHQUNGO0FBRUo7QUFDQSxlQUFzQixhQUFhLEtBQWMsS0FBZSxTQUFjO0FBQzVFLFFBQU0sTUFBTSxFQUFDLGdCQUFnQixRQUFRLGVBQWM7QUFDbkQsUUFBTSxXQUFXLGVBQWUsb0JBQUM7QUFBQSxJQUFPLE9BQU07QUFBQSxJQUFVO0FBQUEsR0FBVSxDQUFFO0FBQ3BFLE1BQUksT0FBTztBQUFBLEVBQW9CO0FBQy9CLE1BQUksSUFBSSxZQUFZO0FBQ2xCLFVBQU0sVUFBVSxLQUFLLEtBQUssV0FBVyxlQUFlO0FBQ3BELFVBQU0sU0FBUyxLQUFLLEtBQUssV0FBVyxjQUFjO0FBQ2xELFVBQU0sTUFBTSxLQUNULFFBQVEsYUFBYSxPQUFPLFNBQVMsRUFDckMsUUFBUSxZQUFZLE9BQU8sUUFBUTtBQUN0QyxXQUFPLE1BQU0sSUFBSSxXQUFZLG1CQUFtQixJQUFJLGFBQWEsR0FBRztBQUFBLEVBQ3RFLE9BQU87QUFDTCxXQUFPLEtBQ0osUUFBUSxhQUFhLHdCQUF3QixFQUM3QyxRQUFRLFlBQVksdUJBQXVCO0FBQUEsRUFDaEQ7QUFDQSxNQUFJLFVBQVUsZ0JBQWdCLFdBQVc7QUFDekMsTUFBSSxLQUFLLElBQUk7QUFDZjsiLAogICJuYW1lcyI6IFtdCn0K
package/dist/cli.js ADDED
@@ -0,0 +1,228 @@
1
+ // core/runtime.ts
2
+ import { initializeApp, getApps, applicationDefault } from "firebase-admin/app";
3
+ import { getFirestore } from "firebase-admin/firestore";
4
+ function getFirebaseApp(gcpProjectId) {
5
+ const apps = getApps();
6
+ if (apps.length > 0 && apps[0]) {
7
+ return apps[0];
8
+ }
9
+ return initializeApp({
10
+ projectId: gcpProjectId,
11
+ credential: applicationDefault()
12
+ });
13
+ }
14
+ function getCmsPlugin(rootConfig) {
15
+ const plugins = rootConfig.plugins || [];
16
+ const plugin = plugins.find((plugin2) => plugin2.name === "root-cms");
17
+ if (!plugin) {
18
+ throw new Error("could not find root-cms plugin config in root.config.ts");
19
+ }
20
+ return plugin;
21
+ }
22
+
23
+ // core/security.ts
24
+ import { getSecurityRules } from "firebase-admin/security-rules";
25
+ var FIRESTORE_RULES = `rules_version = '2';
26
+ service cloud.firestore {
27
+ match /databases/{database}/documents {
28
+ match /Projects/{project}/{document=**} {
29
+ allow write:
30
+ if request.auth != null
31
+ && exists(/databases/$(database)/documents/Projects/$(project))
32
+ && get(/databases/$(database)/documents/Projects/$(project)).data.roles[request.auth.token.email] in ['ADMIN', 'EDITOR'];
33
+ allow read:
34
+ if request.auth != null
35
+ && exists(/databases/$(database)/documents/Projects/$(project))
36
+ && get(/databases/$(database)/documents/Projects/$(project)).data.roles[request.auth.token.email] in ['ADMIN', 'EDITOR', 'VIEWER'];
37
+ }
38
+
39
+ match /Projects/{project}/Collections/{collection}/{document=**} {
40
+ allow write:
41
+ if request.auth != null
42
+ && exists(/databases/$(database)/documents/Projects/$(project)/Collections/$(collection))
43
+ && get(/databases/$(database)/documents/Projects/$(project)/Collections/$(collection)).data.roles[request.auth.token.email] in ['ADMIN', 'EDITOR'];
44
+ allow read:
45
+ if request.auth != null
46
+ && exists(/databases/$(database)/documents/Projects/$(project)/Collections/$(collection))
47
+ && get(/databases/$(database)/documents/Projects/$(project)/Collections/$(collection)).data.roles[request.auth.token.email] in ['ADMIN', 'EDITOR', 'VIEWER'];
48
+ }
49
+ }
50
+ }
51
+ `;
52
+ async function applySecurityRules(projectId) {
53
+ const app = getFirebaseApp(projectId);
54
+ const securityRules = getSecurityRules(app);
55
+ await securityRules.releaseFirestoreRulesetFromSource(FIRESTORE_RULES);
56
+ }
57
+
58
+ // cli/commands/init-firebase.ts
59
+ function initFirebase(rootConfig) {
60
+ return (options) => {
61
+ let gcpProjectId;
62
+ if (options.project) {
63
+ gcpProjectId = options.project;
64
+ } else {
65
+ const cmsPlugin = getCmsPlugin(rootConfig);
66
+ const cmsPluginOptions = cmsPlugin.getConfig();
67
+ gcpProjectId = cmsPluginOptions.firebaseConfig.projectId;
68
+ }
69
+ if (!gcpProjectId) {
70
+ throw new Error("firebaseConfig.projectId not set in cms plugin options");
71
+ }
72
+ console.log(`gcp project: ${gcpProjectId}`);
73
+ console.log("\u{1F46E} updating security rules...");
74
+ applySecurityRules(gcpProjectId);
75
+ console.log("done initializing firebase project!");
76
+ };
77
+ }
78
+
79
+ // cli/commands/generate-types.ts
80
+ import { promises as fs } from "node:fs";
81
+ import path from "node:path";
82
+ import { fileURLToPath } from "node:url";
83
+ import { viteSsrLoadModule } from "@blinkk/root/node";
84
+ import * as dom from "dts-dom";
85
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
86
+ function generateTypes(rootConfig) {
87
+ const rootDir = rootConfig.rootDir;
88
+ return async () => {
89
+ const modulePath = path.resolve(__dirname, "./project.js");
90
+ const project = await viteSsrLoadModule(
91
+ rootConfig,
92
+ modulePath
93
+ );
94
+ const schemas = project.getProjectSchemas();
95
+ console.log(`generating root-cms.d.ts from ${rootDir}...`);
96
+ const outputPath = path.resolve(rootDir, "root-cms.d.ts");
97
+ await generateSchemaDts(outputPath, schemas);
98
+ console.log("saved root-cms.d.ts!");
99
+ };
100
+ }
101
+ var TEMPLATE = `/** Root.js CMS types. This file is autogenerated. */
102
+
103
+ export interface RootCMSDoc<Fields extends {}> {
104
+ /** The id of the doc, e.g. "Pages/foo-bar". */
105
+ id: string;
106
+ /** The collection id of the doc, e.g. "Pages". */
107
+ collectionId: string;
108
+ /** The slug of the doc, e.g. "foo-bar". */
109
+ slug: string;
110
+ /** System-level metadata. */
111
+ sys: {
112
+ createdAt: number;
113
+ createdBy: string;
114
+ modifiedAt: number;
115
+ modifiedBy: string;
116
+ firstPublishedAt?: string;
117
+ firstPublishedBy?: string;
118
+ publishedAt?: string;
119
+ publishedBy?: string;
120
+ };
121
+ /** User-entered field values from the CMS. */
122
+ fields?: Fields;
123
+ }`;
124
+ async function generateSchemaDts(outputPath, schemas) {
125
+ const results = [TEMPLATE];
126
+ for (const fileId in schemas) {
127
+ const schema = schemas[fileId];
128
+ results.push(renderSchema(fileId, schema));
129
+ }
130
+ const output = results.join("\n\n").replaceAll("/** ", "/** ").replaceAll(" */", " */").replace(/\r\n|\r|\n/g, "\n");
131
+ await fs.writeFile(outputPath, output, "utf-8");
132
+ }
133
+ function fieldProperty(field) {
134
+ const prop = dom.create.property(
135
+ field.id,
136
+ fieldType(field),
137
+ dom.DeclarationFlags.Optional
138
+ );
139
+ const jsdoc = [];
140
+ if (field.label) {
141
+ if (field.help) {
142
+ jsdoc.push(`${field.label}. ${field.help}`);
143
+ } else {
144
+ jsdoc.push(field.label);
145
+ }
146
+ }
147
+ if (field.deprecated) {
148
+ jsdoc.push("@deprecated");
149
+ }
150
+ if (jsdoc.length > 0) {
151
+ prop.jsDocComment = jsdoc.join("\n");
152
+ }
153
+ return prop;
154
+ }
155
+ function fieldType(field) {
156
+ if (field.type === "array") {
157
+ return dom.type.array(fieldType(field.of));
158
+ }
159
+ if (field.type === "image") {
160
+ return dom.create.objectType([
161
+ dom.create.property("src", dom.type.string),
162
+ dom.create.property(
163
+ "alt",
164
+ dom.type.string,
165
+ dom.DeclarationFlags.Optional
166
+ ),
167
+ dom.create.property(
168
+ "width",
169
+ dom.type.number,
170
+ dom.DeclarationFlags.Optional
171
+ ),
172
+ dom.create.property(
173
+ "height",
174
+ dom.type.number,
175
+ dom.DeclarationFlags.Optional
176
+ )
177
+ ]);
178
+ }
179
+ if (field.type === "multiselect") {
180
+ return dom.type.array(dom.type.string);
181
+ }
182
+ if (field.type === "select") {
183
+ return dom.type.string;
184
+ }
185
+ if (field.type === "string") {
186
+ return dom.type.string;
187
+ }
188
+ if (field.type === "object") {
189
+ const subproperties = (field.fields || []).map((f) => fieldProperty(f));
190
+ return dom.create.objectType(subproperties);
191
+ }
192
+ return dom.type.unknown;
193
+ }
194
+ function renderSchema(fileId, schema) {
195
+ const jsdoc = `Generated from \`${fileId}\`.`;
196
+ const id = path.parse(fileId).name.split(".")[0];
197
+ const fieldsInterface = `${id}Fields`;
198
+ const fields = dom.create.interface(
199
+ fieldsInterface,
200
+ dom.DeclarationFlags.Export
201
+ );
202
+ fields.jsDocComment = jsdoc;
203
+ for (const field of schema.fields) {
204
+ if (!field.id) {
205
+ continue;
206
+ }
207
+ fields.members.push(fieldProperty(field));
208
+ }
209
+ const fieldsTypeOutput = dom.emit(fields, { singleLineJsDocComments: true }).trim();
210
+ if (fileId.startsWith("/collections/")) {
211
+ const baseType = dom.create.namedTypeReference("RootCMSDoc");
212
+ baseType.typeArguments.push(dom.create.namedTypeReference(fieldsInterface));
213
+ const docType = dom.create.alias(
214
+ `${id}Doc`,
215
+ baseType,
216
+ dom.DeclarationFlags.Export
217
+ );
218
+ docType.jsDocComment = jsdoc;
219
+ const docTypeOutput = dom.emit(docType, { singleLineJsDocComments: true }).trim();
220
+ return fieldsTypeOutput + "\n\n" + docTypeOutput;
221
+ }
222
+ return fieldsTypeOutput;
223
+ }
224
+ export {
225
+ generateTypes,
226
+ initFirebase
227
+ };
228
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY29yZS9ydW50aW1lLnRzIiwgIi4uL2NvcmUvc2VjdXJpdHkudHMiLCAiLi4vY2xpL2NvbW1hbmRzL2luaXQtZmlyZWJhc2UudHMiLCAiLi4vY2xpL2NvbW1hbmRzL2dlbmVyYXRlLXR5cGVzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQge1BsdWdpbiwgUm9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7aW5pdGlhbGl6ZUFwcCwgZ2V0QXBwcywgYXBwbGljYXRpb25EZWZhdWx0fSBmcm9tICdmaXJlYmFzZS1hZG1pbi9hcHAnO1xuaW1wb3J0IHtnZXRGaXJlc3RvcmV9IGZyb20gJ2ZpcmViYXNlLWFkbWluL2ZpcmVzdG9yZSc7XG5pbXBvcnQge0NNU1BsdWdpbn0gZnJvbSAnLi9wbHVnaW4uanMnO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlyZWJhc2VBcHAoZ2NwUHJvamVjdElkOiBzdHJpbmcpIHtcbiAgY29uc3QgYXBwcyA9IGdldEFwcHMoKTtcbiAgaWYgKGFwcHMubGVuZ3RoID4gMCAmJiBhcHBzWzBdKSB7XG4gICAgcmV0dXJuIGFwcHNbMF07XG4gIH1cbiAgcmV0dXJuIGluaXRpYWxpemVBcHAoe1xuICAgIHByb2plY3RJZDogZ2NwUHJvamVjdElkLFxuICAgIGNyZWRlbnRpYWw6IGFwcGxpY2F0aW9uRGVmYXVsdCgpLFxuICB9KTtcbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYSBkb2MgZnJvbSBSb290LmpzIENNUy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldERvYzxUPihcbiAgcm9vdENvbmZpZzogUm9vdENvbmZpZyxcbiAgY29sbGVjdGlvbklkOiBzdHJpbmcsXG4gIHNsdWc6IHN0cmluZyxcbiAgb3B0aW9uczoge21vZGU6ICdkcmFmdCcgfCAncHVibGlzaGVkJ31cbik6IFByb21pc2U8VCB8IG51bGw+IHtcbiAgY29uc3QgY21zUGx1Z2luID0gZ2V0Q21zUGx1Z2luKHJvb3RDb25maWcpO1xuICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICBjb25zdCBwcm9qZWN0SWQgPSBjbXNQbHVnaW5PcHRpb25zLmlkIHx8ICdkZWZhdWx0JztcbiAgY29uc3QgZ2NwUHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5maXJlYmFzZUNvbmZpZy5wcm9qZWN0SWQ7XG4gIGNvbnN0IG1vZGUgPSBvcHRpb25zLm1vZGU7XG4gIGNvbnN0IG1vZGVDb2xsZWN0aW9uID0gbW9kZSA9PT0gJ2RyYWZ0JyA/ICdEcmFmdHMnIDogJ1B1Ymxpc2hlZCc7XG4gIGNvbnN0IGFwcCA9IGdldEZpcmViYXNlQXBwKGdjcFByb2plY3RJZCk7XG4gIGNvbnN0IGRiID0gZ2V0RmlyZXN0b3JlKGFwcCk7XG4gIC8vIFNsdWdzIHdpdGggc2xhc2hlcyBhcmUgZW5jb2RlZCBhcyBgLS1gIGluIHRoZSBEQi5cbiAgc2x1ZyA9IHNsdWcucmVwbGFjZUFsbCgnLycsICctLScpO1xuICBjb25zdCBkYlBhdGggPSBgUHJvamVjdHMvJHtwcm9qZWN0SWR9L0NvbGxlY3Rpb25zLyR7Y29sbGVjdGlvbklkfS8ke21vZGVDb2xsZWN0aW9ufS8ke3NsdWd9YDtcbiAgY29uc3QgZG9jUmVmID0gZGIuZG9jKGRiUGF0aCk7XG4gIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKTtcbiAgaWYgKGRvYy5leGlzdHMpIHtcbiAgICBjb25zdCBkYXRhID0gZG9jLmRhdGEoKTtcbiAgICByZXR1cm4gbm9ybWFsaXplRGF0YShkYXRhKSBhcyBUO1xuICB9XG4gIGNvbnNvbGUubG9nKGBkb2Mgbm90IGZvdW5kOiAke2RiUGF0aH1gKTtcbiAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogV2Fsa3MgdGhlIGRhdGEgdHJlZSBhbmQgY29udmVydHMgYW55IFRpbWVzdGFtcCBvYmplY3RzIHRvIG1pbGxpcyBhbmQgYW55XG4gKiBfYXJyYXkgbWFwcyB0byBub3JtYWwgYXJyYXlzLlxuICpcbiAqIEUuZy46XG4gKlxuICogbm9ybWFsaXplRGF0YSh7XG4gKiAgIHN5czoge21vZGlmaWVkQXQ6IFRpbWVzdGFtcCgxMjMpfSxcbiAqICAgZmllbGRzOiB7XG4gKiAgICAgX2FycmF5OiBbJ2FzZGYnXSxcbiAqICAgICBhc2RmOiB7dGl0bGU6ICdoZWxsbyd9XG4gKiAgIH1cbiAqIH0pXG4gKiAvLyA9PiB7c3lzOiB7bW9kaWZpZWRBdDogMTIzfSwgZmllbGRzOiB7Zm9vOiBbe3RpdGxlOiAnaGVsbG8nfV19fVxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplRGF0YShkYXRhOiBhbnkpOiBhbnkge1xuICBjb25zdCByZXN1bHQ6IGFueSA9IHt9O1xuICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG4gICAgY29uc3QgdmFsID0gZGF0YVtrZXldO1xuICAgIGlmIChpc09iamVjdCh2YWwpKSB7XG4gICAgICBpZiAodmFsLnRvTWlsbGlzKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsLnRvTWlsbGlzKCk7XG4gICAgICB9IGVsc2UgaWYgKE9iamVjdC5oYXNPd24odmFsLCAnX2FycmF5JykgJiYgQXJyYXkuaXNBcnJheSh2YWwuX2FycmF5KSkge1xuICAgICAgICBjb25zdCBhcnIgPSB2YWwuX2FycmF5Lm1hcCgoazogc3RyaW5nKSA9PiB2YWxba10gfHwge30pO1xuICAgICAgICByZXN1bHRba2V5XSA9IGFycjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gbm9ybWFsaXplRGF0YSh2YWwpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoZGF0YTogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YSAhPT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENtc1BsdWdpbihyb290Q29uZmlnOiBSb290Q29uZmlnKTogQ01TUGx1Z2luIHtcbiAgY29uc3QgcGx1Z2luczogUGx1Z2luW10gPSByb290Q29uZmlnLnBsdWdpbnMgfHwgW107XG4gIGNvbnN0IHBsdWdpbiA9IHBsdWdpbnMuZmluZCgocGx1Z2luKSA9PiBwbHVnaW4ubmFtZSA9PT0gJ3Jvb3QtY21zJyk7XG4gIGlmICghcGx1Z2luKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgZmluZCByb290LWNtcyBwbHVnaW4gY29uZmlnIGluIHJvb3QuY29uZmlnLnRzJyk7XG4gIH1cbiAgcmV0dXJuIHBsdWdpbiBhcyBDTVNQbHVnaW47XG59XG4iLCAiaW1wb3J0IHtnZXRTZWN1cml0eVJ1bGVzfSBmcm9tICdmaXJlYmFzZS1hZG1pbi9zZWN1cml0eS1ydWxlcyc7XG5pbXBvcnQge2dldEZpcmViYXNlQXBwfSBmcm9tICcuL3J1bnRpbWUuanMnO1xuXG5leHBvcnQgY29uc3QgRklSRVNUT1JFX1JVTEVTID0gYHJ1bGVzX3ZlcnNpb24gPSAnMic7XG5zZXJ2aWNlIGNsb3VkLmZpcmVzdG9yZSB7XG4gIG1hdGNoIC9kYXRhYmFzZXMve2RhdGFiYXNlfS9kb2N1bWVudHMge1xuICAgIG1hdGNoIC9Qcm9qZWN0cy97cHJvamVjdH0ve2RvY3VtZW50PSoqfSB7XG4gICAgICBhbGxvdyB3cml0ZTpcbiAgICAgICAgaWYgcmVxdWVzdC5hdXRoICE9IG51bGxcbiAgICAgICAgJiYgZXhpc3RzKC9kYXRhYmFzZXMvJChkYXRhYmFzZSkvZG9jdW1lbnRzL1Byb2plY3RzLyQocHJvamVjdCkpXG4gICAgICAgICYmIGdldCgvZGF0YWJhc2VzLyQoZGF0YWJhc2UpL2RvY3VtZW50cy9Qcm9qZWN0cy8kKHByb2plY3QpKS5kYXRhLnJvbGVzW3JlcXVlc3QuYXV0aC50b2tlbi5lbWFpbF0gaW4gWydBRE1JTicsICdFRElUT1InXTtcbiAgICAgIGFsbG93IHJlYWQ6XG4gICAgICAgIGlmIHJlcXVlc3QuYXV0aCAhPSBudWxsXG4gICAgICAgICYmIGV4aXN0cygvZGF0YWJhc2VzLyQoZGF0YWJhc2UpL2RvY3VtZW50cy9Qcm9qZWN0cy8kKHByb2plY3QpKVxuICAgICAgICAmJiBnZXQoL2RhdGFiYXNlcy8kKGRhdGFiYXNlKS9kb2N1bWVudHMvUHJvamVjdHMvJChwcm9qZWN0KSkuZGF0YS5yb2xlc1tyZXF1ZXN0LmF1dGgudG9rZW4uZW1haWxdIGluIFsnQURNSU4nLCAnRURJVE9SJywgJ1ZJRVdFUiddO1xuICAgIH1cblxuICAgIG1hdGNoIC9Qcm9qZWN0cy97cHJvamVjdH0vQ29sbGVjdGlvbnMve2NvbGxlY3Rpb259L3tkb2N1bWVudD0qKn0ge1xuICAgICAgYWxsb3cgd3JpdGU6XG4gICAgICAgIGlmIHJlcXVlc3QuYXV0aCAhPSBudWxsXG4gICAgICAgICYmIGV4aXN0cygvZGF0YWJhc2VzLyQoZGF0YWJhc2UpL2RvY3VtZW50cy9Qcm9qZWN0cy8kKHByb2plY3QpL0NvbGxlY3Rpb25zLyQoY29sbGVjdGlvbikpXG4gICAgICAgICYmIGdldCgvZGF0YWJhc2VzLyQoZGF0YWJhc2UpL2RvY3VtZW50cy9Qcm9qZWN0cy8kKHByb2plY3QpL0NvbGxlY3Rpb25zLyQoY29sbGVjdGlvbikpLmRhdGEucm9sZXNbcmVxdWVzdC5hdXRoLnRva2VuLmVtYWlsXSBpbiBbJ0FETUlOJywgJ0VESVRPUiddO1xuICAgICAgYWxsb3cgcmVhZDpcbiAgICAgICAgaWYgcmVxdWVzdC5hdXRoICE9IG51bGxcbiAgICAgICAgJiYgZXhpc3RzKC9kYXRhYmFzZXMvJChkYXRhYmFzZSkvZG9jdW1lbnRzL1Byb2plY3RzLyQocHJvamVjdCkvQ29sbGVjdGlvbnMvJChjb2xsZWN0aW9uKSlcbiAgICAgICAgJiYgZ2V0KC9kYXRhYmFzZXMvJChkYXRhYmFzZSkvZG9jdW1lbnRzL1Byb2plY3RzLyQocHJvamVjdCkvQ29sbGVjdGlvbnMvJChjb2xsZWN0aW9uKSkuZGF0YS5yb2xlc1tyZXF1ZXN0LmF1dGgudG9rZW4uZW1haWxdIGluIFsnQURNSU4nLCAnRURJVE9SJywgJ1ZJRVdFUiddO1xuICAgIH1cbiAgfVxufVxuYDtcblxuLyoqXG4gKiBBZGRzIHRoZSByb290LWNtcyBzZWN1cml0eSBydWxlcyB0byBhIEZpcmViYXNlIHByb2plY3QuXG4gKiBOT1RFOiBUaGlzIGZ1bmN0aW9uIHdpbGwgb3ZlcndyaXRlIGFueSBleGlzdGluZyBydWxlcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFwcGx5U2VjdXJpdHlSdWxlcyhwcm9qZWN0SWQ6IHN0cmluZykge1xuICBjb25zdCBhcHAgPSBnZXRGaXJlYmFzZUFwcChwcm9qZWN0SWQpO1xuICBjb25zdCBzZWN1cml0eVJ1bGVzID0gZ2V0U2VjdXJpdHlSdWxlcyhhcHApO1xuICBhd2FpdCBzZWN1cml0eVJ1bGVzLnJlbGVhc2VGaXJlc3RvcmVSdWxlc2V0RnJvbVNvdXJjZShGSVJFU1RPUkVfUlVMRVMpO1xufVxuIiwgImltcG9ydCB7Um9vdENvbmZpZ30gZnJvbSAnQGJsaW5ray9yb290JztcbmltcG9ydCB7Z2V0Q21zUGx1Z2lufSBmcm9tICcuLi8uLi9jb3JlL3J1bnRpbWUuanMnO1xuaW1wb3J0IHthcHBseVNlY3VyaXR5UnVsZXN9IGZyb20gJy4uLy4uL2NvcmUvc2VjdXJpdHkuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluaXRGaXJlYmFzZU9wdGlvbnMge1xuICAvKiogR0NQIHByb2plY3QgaWQuICovXG4gIHByb2plY3Q/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0RmlyZWJhc2Uocm9vdENvbmZpZzogUm9vdENvbmZpZykge1xuICByZXR1cm4gKG9wdGlvbnM6IEluaXRGaXJlYmFzZU9wdGlvbnMpID0+IHtcbiAgICBsZXQgZ2NwUHJvamVjdElkOiBzdHJpbmc7XG4gICAgaWYgKG9wdGlvbnMucHJvamVjdCkge1xuICAgICAgZ2NwUHJvamVjdElkID0gb3B0aW9ucy5wcm9qZWN0O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBjbXNQbHVnaW4gPSBnZXRDbXNQbHVnaW4ocm9vdENvbmZpZyk7XG4gICAgICBjb25zdCBjbXNQbHVnaW5PcHRpb25zID0gY21zUGx1Z2luLmdldENvbmZpZygpO1xuICAgICAgZ2NwUHJvamVjdElkID0gY21zUGx1Z2luT3B0aW9ucy5maXJlYmFzZUNvbmZpZy5wcm9qZWN0SWQ7XG4gICAgfVxuICAgIGlmICghZ2NwUHJvamVjdElkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ZpcmViYXNlQ29uZmlnLnByb2plY3RJZCBub3Qgc2V0IGluIGNtcyBwbHVnaW4gb3B0aW9ucycpO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBnY3AgcHJvamVjdDogJHtnY3BQcm9qZWN0SWR9YCk7XG4gICAgY29uc29sZS5sb2coJ1x1RDgzRFx1REM2RSB1cGRhdGluZyBzZWN1cml0eSBydWxlcy4uLicpO1xuICAgIGFwcGx5U2VjdXJpdHlSdWxlcyhnY3BQcm9qZWN0SWQpO1xuICAgIGNvbnNvbGUubG9nKCdkb25lIGluaXRpYWxpemluZyBmaXJlYmFzZSBwcm9qZWN0IScpO1xuICB9O1xufVxuIiwgImltcG9ydCB7cHJvbWlzZXMgYXMgZnN9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7ZmlsZVVSTFRvUGF0aH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHt2aXRlU3NyTG9hZE1vZHVsZX0gZnJvbSAnQGJsaW5ray9yb290L25vZGUnO1xuaW1wb3J0IHtSb290Q29uZmlnfSBmcm9tICdAYmxpbmtrL3Jvb3QnO1xuaW1wb3J0ICogYXMgZG9tIGZyb20gJ2R0cy1kb20nO1xuaW1wb3J0IHtGaWVsZCwgU2NoZW1hfSBmcm9tICcuLi8uLi9jb3JlL3NjaGVtYS5qcyc7XG5cbnR5cGUgUHJvamVjdE1vZHVsZSA9IHR5cGVvZiBpbXBvcnQoJy4uLy4uL2NvcmUvcHJvamVjdC5qcycpO1xuY29uc3QgX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZVR5cGVzKHJvb3RDb25maWc6IFJvb3RDb25maWcpIHtcbiAgY29uc3Qgcm9vdERpciA9IHJvb3RDb25maWcucm9vdERpcjtcbiAgcmV0dXJuIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtb2R1bGVQYXRoID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgJy4vcHJvamVjdC5qcycpO1xuICAgIGNvbnN0IHByb2plY3QgPSAoYXdhaXQgdml0ZVNzckxvYWRNb2R1bGUoXG4gICAgICByb290Q29uZmlnLFxuICAgICAgbW9kdWxlUGF0aFxuICAgICkpIGFzIFByb2plY3RNb2R1bGU7XG4gICAgY29uc3Qgc2NoZW1hcyA9IHByb2plY3QuZ2V0UHJvamVjdFNjaGVtYXMoKTtcbiAgICBjb25zb2xlLmxvZyhgZ2VuZXJhdGluZyByb290LWNtcy5kLnRzIGZyb20gJHtyb290RGlyfS4uLmApO1xuICAgIGNvbnN0IG91dHB1dFBhdGggPSBwYXRoLnJlc29sdmUocm9vdERpciwgJ3Jvb3QtY21zLmQudHMnKTtcbiAgICBhd2FpdCBnZW5lcmF0ZVNjaGVtYUR0cyhvdXRwdXRQYXRoLCBzY2hlbWFzKTtcbiAgICBjb25zb2xlLmxvZygnc2F2ZWQgcm9vdC1jbXMuZC50cyEnKTtcbiAgfTtcbn1cblxuLy8gVGhlIGBkdHMtZG9tYCBwYWNrYWdlIHVzZXMgNC1zcGFjZSBpbmRlbnRzLCB1c2UgdGhlIHNhbWUgZm9yIGNvbnNpc3RlbmN5LlxuY29uc3QgVEVNUExBVEUgPSBgLyoqIFJvb3QuanMgQ01TIHR5cGVzLiBUaGlzIGZpbGUgaXMgYXV0b2dlbmVyYXRlZC4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBSb290Q01TRG9jPEZpZWxkcyBleHRlbmRzIHt9PiB7XG4gICAgLyoqIFRoZSBpZCBvZiB0aGUgZG9jLCBlLmcuIFwiUGFnZXMvZm9vLWJhclwiLiAqL1xuICAgIGlkOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBjb2xsZWN0aW9uIGlkIG9mIHRoZSBkb2MsIGUuZy4gXCJQYWdlc1wiLiAqL1xuICAgIGNvbGxlY3Rpb25JZDogc3RyaW5nO1xuICAgIC8qKiBUaGUgc2x1ZyBvZiB0aGUgZG9jLCBlLmcuIFwiZm9vLWJhclwiLiAqL1xuICAgIHNsdWc6IHN0cmluZztcbiAgICAvKiogU3lzdGVtLWxldmVsIG1ldGFkYXRhLiAqL1xuICAgIHN5czoge1xuICAgICAgICBjcmVhdGVkQXQ6IG51bWJlcjtcbiAgICAgICAgY3JlYXRlZEJ5OiBzdHJpbmc7XG4gICAgICAgIG1vZGlmaWVkQXQ6IG51bWJlcjtcbiAgICAgICAgbW9kaWZpZWRCeTogc3RyaW5nO1xuICAgICAgICBmaXJzdFB1Ymxpc2hlZEF0Pzogc3RyaW5nO1xuICAgICAgICBmaXJzdFB1Ymxpc2hlZEJ5Pzogc3RyaW5nO1xuICAgICAgICBwdWJsaXNoZWRBdD86IHN0cmluZztcbiAgICAgICAgcHVibGlzaGVkQnk/OiBzdHJpbmc7XG4gICAgfTtcbiAgICAvKiogVXNlci1lbnRlcmVkIGZpZWxkIHZhbHVlcyBmcm9tIHRoZSBDTVMuICovXG4gICAgZmllbGRzPzogRmllbGRzO1xufWA7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgcm9vdC1jbXMuZC50cyBmaWxlIGZyb20gdGhlIC5zY2hlbWEudHMgZmlsZXMgaW4gdGhlIHByb2plY3QuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZVNjaGVtYUR0cyhcbiAgb3V0cHV0UGF0aDogc3RyaW5nLFxuICBzY2hlbWFzOiBSZWNvcmQ8c3RyaW5nLCBTY2hlbWE+XG4pIHtcbiAgY29uc3QgcmVzdWx0cyA9IFtURU1QTEFURV07XG4gIGZvciAoY29uc3QgZmlsZUlkIGluIHNjaGVtYXMpIHtcbiAgICBjb25zdCBzY2hlbWEgPSBzY2hlbWFzW2ZpbGVJZF07XG4gICAgcmVzdWx0cy5wdXNoKHJlbmRlclNjaGVtYShmaWxlSWQsIHNjaGVtYSkpO1xuICB9XG4gIGNvbnN0IG91dHB1dCA9IHJlc3VsdHNcbiAgICAuam9pbignXFxuXFxuJylcbiAgICAucmVwbGFjZUFsbCgnLyoqICAnLCAnLyoqICcpXG4gICAgLnJlcGxhY2VBbGwoJyAgKi8nLCAnICovJylcbiAgICAucmVwbGFjZSgvXFxyXFxufFxccnxcXG4vZywgJ1xcbicpO1xuICBhd2FpdCBmcy53cml0ZUZpbGUob3V0cHV0UGF0aCwgb3V0cHV0LCAndXRmLTgnKTtcbn1cblxuZnVuY3Rpb24gZmllbGRQcm9wZXJ0eShmaWVsZDogRmllbGQpOiBkb20uUHJvcGVydHlEZWNsYXJhdGlvbiB7XG4gIGNvbnN0IHByb3AgPSBkb20uY3JlYXRlLnByb3BlcnR5KFxuICAgIGZpZWxkLmlkISxcbiAgICBmaWVsZFR5cGUoZmllbGQpLFxuICAgIGRvbS5EZWNsYXJhdGlvbkZsYWdzLk9wdGlvbmFsXG4gICk7XG4gIGNvbnN0IGpzZG9jID0gW107XG4gIGlmIChmaWVsZC5sYWJlbCkge1xuICAgIGlmIChmaWVsZC5oZWxwKSB7XG4gICAgICBqc2RvYy5wdXNoKGAke2ZpZWxkLmxhYmVsfS4gJHtmaWVsZC5oZWxwfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBqc2RvYy5wdXNoKGZpZWxkLmxhYmVsKTtcbiAgICB9XG4gIH1cbiAgaWYgKGZpZWxkLmRlcHJlY2F0ZWQpIHtcbiAgICBqc2RvYy5wdXNoKCdAZGVwcmVjYXRlZCcpO1xuICB9XG4gIGlmIChqc2RvYy5sZW5ndGggPiAwKSB7XG4gICAgcHJvcC5qc0RvY0NvbW1lbnQgPSBqc2RvYy5qb2luKCdcXG4nKTtcbiAgfVxuICByZXR1cm4gcHJvcDtcbn1cblxuZnVuY3Rpb24gZmllbGRUeXBlKGZpZWxkOiBGaWVsZCk6IGRvbS5UeXBlIHtcbiAgaWYgKGZpZWxkLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICByZXR1cm4gZG9tLnR5cGUuYXJyYXkoZmllbGRUeXBlKGZpZWxkLm9mKSk7XG4gIH1cbiAgaWYgKGZpZWxkLnR5cGUgPT09ICdpbWFnZScpIHtcbiAgICByZXR1cm4gZG9tLmNyZWF0ZS5vYmplY3RUeXBlKFtcbiAgICAgIGRvbS5jcmVhdGUucHJvcGVydHkoJ3NyYycsIGRvbS50eXBlLnN0cmluZyksXG4gICAgICBkb20uY3JlYXRlLnByb3BlcnR5KFxuICAgICAgICAnYWx0JyxcbiAgICAgICAgZG9tLnR5cGUuc3RyaW5nLFxuICAgICAgICBkb20uRGVjbGFyYXRpb25GbGFncy5PcHRpb25hbFxuICAgICAgKSxcbiAgICAgIGRvbS5jcmVhdGUucHJvcGVydHkoXG4gICAgICAgICd3aWR0aCcsXG4gICAgICAgIGRvbS50eXBlLm51bWJlcixcbiAgICAgICAgZG9tLkRlY2xhcmF0aW9uRmxhZ3MuT3B0aW9uYWxcbiAgICAgICksXG4gICAgICBkb20uY3JlYXRlLnByb3BlcnR5KFxuICAgICAgICAnaGVpZ2h0JyxcbiAgICAgICAgZG9tLnR5cGUubnVtYmVyLFxuICAgICAgICBkb20uRGVjbGFyYXRpb25GbGFncy5PcHRpb25hbFxuICAgICAgKSxcbiAgICBdKTtcbiAgfVxuICBpZiAoZmllbGQudHlwZSA9PT0gJ211bHRpc2VsZWN0Jykge1xuICAgIHJldHVybiBkb20udHlwZS5hcnJheShkb20udHlwZS5zdHJpbmcpO1xuICB9XG4gIGlmIChmaWVsZC50eXBlID09PSAnc2VsZWN0Jykge1xuICAgIHJldHVybiBkb20udHlwZS5zdHJpbmc7XG4gIH1cbiAgaWYgKGZpZWxkLnR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGRvbS50eXBlLnN0cmluZztcbiAgfVxuICBpZiAoZmllbGQudHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICBjb25zdCBzdWJwcm9wZXJ0aWVzID0gKGZpZWxkLmZpZWxkcyB8fCBbXSkubWFwKChmKSA9PiBmaWVsZFByb3BlcnR5KGYpKTtcbiAgICByZXR1cm4gZG9tLmNyZWF0ZS5vYmplY3RUeXBlKHN1YnByb3BlcnRpZXMpO1xuICB9XG4gIHJldHVybiBkb20udHlwZS51bmtub3duO1xufVxuXG5mdW5jdGlvbiByZW5kZXJTY2hlbWEoZmlsZUlkOiBzdHJpbmcsIHNjaGVtYTogU2NoZW1hKTogc3RyaW5nIHtcbiAgY29uc3QganNkb2MgPSBgR2VuZXJhdGVkIGZyb20gXFxgJHtmaWxlSWR9XFxgLmA7XG4gIGNvbnN0IGlkID0gcGF0aC5wYXJzZShmaWxlSWQpLm5hbWUuc3BsaXQoJy4nKVswXTtcbiAgY29uc3QgZmllbGRzSW50ZXJmYWNlID0gYCR7aWR9RmllbGRzYDtcbiAgY29uc3QgZmllbGRzID0gZG9tLmNyZWF0ZS5pbnRlcmZhY2UoXG4gICAgZmllbGRzSW50ZXJmYWNlLFxuICAgIGRvbS5EZWNsYXJhdGlvbkZsYWdzLkV4cG9ydFxuICApO1xuICBmaWVsZHMuanNEb2NDb21tZW50ID0ganNkb2M7XG4gIGZvciAoY29uc3QgZmllbGQgb2Ygc2NoZW1hLmZpZWxkcykge1xuICAgIGlmICghZmllbGQuaWQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBmaWVsZHMubWVtYmVycy5wdXNoKGZpZWxkUHJvcGVydHkoZmllbGQpKTtcbiAgfVxuXG4gIGNvbnN0IGZpZWxkc1R5cGVPdXRwdXQgPSBkb21cbiAgICAuZW1pdChmaWVsZHMsIHtzaW5nbGVMaW5lSnNEb2NDb21tZW50czogdHJ1ZX0pXG4gICAgLnRyaW0oKTtcbiAgaWYgKGZpbGVJZC5zdGFydHNXaXRoKCcvY29sbGVjdGlvbnMvJykpIHtcbiAgICBjb25zdCBiYXNlVHlwZSA9IGRvbS5jcmVhdGUubmFtZWRUeXBlUmVmZXJlbmNlKCdSb290Q01TRG9jJyk7XG4gICAgYmFzZVR5cGUudHlwZUFyZ3VtZW50cy5wdXNoKGRvbS5jcmVhdGUubmFtZWRUeXBlUmVmZXJlbmNlKGZpZWxkc0ludGVyZmFjZSkpO1xuICAgIGNvbnN0IGRvY1R5cGUgPSBkb20uY3JlYXRlLmFsaWFzKFxuICAgICAgYCR7aWR9RG9jYCxcbiAgICAgIGJhc2VUeXBlLFxuICAgICAgZG9tLkRlY2xhcmF0aW9uRmxhZ3MuRXhwb3J0XG4gICAgKTtcbiAgICBkb2NUeXBlLmpzRG9jQ29tbWVudCA9IGpzZG9jO1xuXG4gICAgY29uc3QgZG9jVHlwZU91dHB1dCA9IGRvbVxuICAgICAgLmVtaXQoZG9jVHlwZSwge3NpbmdsZUxpbmVKc0RvY0NvbW1lbnRzOiB0cnVlfSlcbiAgICAgIC50cmltKCk7XG4gICAgcmV0dXJuIGZpZWxkc1R5cGVPdXRwdXQgKyAnXFxuXFxuJyArIGRvY1R5cGVPdXRwdXQ7XG4gIH1cbiAgcmV0dXJuIGZpZWxkc1R5cGVPdXRwdXQ7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUSxlQUFlLFNBQVMsMEJBQXlCO0FBQ3pELFNBQVEsb0JBQW1CO0FBR3BCLFNBQVMsZUFBZSxjQUFzQjtBQUNuRCxRQUFNLE9BQU8sUUFBUTtBQUNyQixNQUFJLEtBQUssU0FBUyxLQUFLLEtBQUssSUFBSTtBQUM5QixXQUFPLEtBQUs7QUFBQSxFQUNkO0FBQ0EsU0FBTyxjQUFjO0FBQUEsSUFDbkIsV0FBVztBQUFBLElBQ1gsWUFBWSxtQkFBbUI7QUFBQSxFQUNqQyxDQUFDO0FBQ0g7QUF1RU8sU0FBUyxhQUFhLFlBQW1DO0FBQzlELFFBQU0sVUFBb0IsV0FBVyxXQUFXLENBQUM7QUFDakQsUUFBTSxTQUFTLFFBQVEsS0FBSyxDQUFDQSxZQUFXQSxRQUFPLFNBQVMsVUFBVTtBQUNsRSxNQUFJLENBQUMsUUFBUTtBQUNYLFVBQU0sSUFBSSxNQUFNLHlEQUF5RDtBQUFBLEVBQzNFO0FBQ0EsU0FBTztBQUNUOzs7QUM1RkEsU0FBUSx3QkFBdUI7QUFHeEIsSUFBTSxrQkFBa0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZ0MvQixlQUFzQixtQkFBbUIsV0FBbUI7QUFDMUQsUUFBTSxNQUFNLGVBQWUsU0FBUztBQUNwQyxRQUFNLGdCQUFnQixpQkFBaUIsR0FBRztBQUMxQyxRQUFNLGNBQWMsa0NBQWtD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
package/dist/core.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ export { s as schema } from './schema-f8000274.js';
2
+ import * as firebase_admin_app from 'firebase-admin/app';
3
+ import { RootConfig } from '@blinkk/root';
4
+ import { CMSPlugin } from './plugin.js';
5
+ import 'preact';
6
+ import 'firebase-admin/auth';
7
+
8
+ declare function getFirebaseApp(gcpProjectId: string): firebase_admin_app.App;
9
+ /**
10
+ * Retrieves a doc from Root.js CMS.
11
+ */
12
+ declare function getDoc<T>(rootConfig: RootConfig, collectionId: string, slug: string, options: {
13
+ mode: 'draft' | 'published';
14
+ }): Promise<T | null>;
15
+ /**
16
+ * Walks the data tree and converts any Timestamp objects to millis and any
17
+ * _array maps to normal arrays.
18
+ *
19
+ * E.g.:
20
+ *
21
+ * normalizeData({
22
+ * sys: {modifiedAt: Timestamp(123)},
23
+ * fields: {
24
+ * _array: ['asdf'],
25
+ * asdf: {title: 'hello'}
26
+ * }
27
+ * })
28
+ * // => {sys: {modifiedAt: 123}, fields: {foo: [{title: 'hello'}]}}
29
+ */
30
+ declare function normalizeData(data: any): any;
31
+ declare function getCmsPlugin(rootConfig: RootConfig): CMSPlugin;
32
+
33
+ export { getCmsPlugin, getDoc, getFirebaseApp, normalizeData };