@monkeyplus/flow 6.0.13 → 6.0.15

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.
Files changed (56) hide show
  1. package/modules/content/module.mjs +12 -0
  2. package/modules/content/query.d.ts +1 -1
  3. package/modules/content/query.mjs +157 -57
  4. package/modules/netlify-cms/handler.d.ts +2 -0
  5. package/modules/netlify-cms/handler.mjs +5 -0
  6. package/modules/netlify-cms/module.d.ts +6 -0
  7. package/modules/netlify-cms/module.mjs +66 -0
  8. package/modules/netlify-cms/resources/admin.html +16 -0
  9. package/modules/netlify-cms/resources/adminV2.html +15 -0
  10. package/modules/netlify-cms/runtime/cms.d.ts +3 -0
  11. package/modules/netlify-cms/runtime/cms.mjs +3 -0
  12. package/modules/netlify-cms/server/api/admin.d.ts +2 -0
  13. package/modules/netlify-cms/server/api/admin.mjs +20 -0
  14. package/modules/netlify-cms/server/api/config.d.ts +2 -0
  15. package/modules/netlify-cms/server/api/config.mjs +72 -0
  16. package/modules/netlify-cms/server/api/local-fs.d.ts +2 -0
  17. package/modules/netlify-cms/server/api/local-fs.mjs +189 -0
  18. package/modules/netlify-cms/server/api/meta.d.ts +2 -0
  19. package/modules/netlify-cms/server/api/meta.mjs +8 -0
  20. package/modules/netlify-cms/server/lib/cms/handler.d.ts +2 -0
  21. package/modules/netlify-cms/server/lib/cms/handler.mjs +37 -0
  22. package/modules/netlify-cms/server/lib/cms/handlerV1.d.ts +2 -0
  23. package/modules/netlify-cms/server/lib/cms/handlerV1.mjs +40 -0
  24. package/modules/netlify-cms/server/lib/cms/helpers.d.ts +14 -0
  25. package/modules/netlify-cms/server/lib/cms/helpers.mjs +76 -0
  26. package/modules/netlify-cms/server/lib/cms/widgets.d.ts +113 -0
  27. package/modules/netlify-cms/server/lib/cms/widgets.mjs +168 -0
  28. package/modules/netlify-cms/server/lib/composables.d.ts +28 -0
  29. package/modules/netlify-cms/server/lib/composables.mjs +14 -0
  30. package/modules/netlify-cms/server/lib/entries.d.ts +25 -0
  31. package/modules/netlify-cms/server/lib/entries.mjs +39 -0
  32. package/modules/netlify-cms/server/lib/fs.d.ts +5 -0
  33. package/modules/netlify-cms/server/lib/fs.mjs +43 -0
  34. package/modules/netlify-cms/server/lib/types/collections.d.ts +16 -0
  35. package/modules/netlify-cms/server/lib/types/collections.mjs +0 -0
  36. package/modules/netlify-cms/server/lib/types/helpers.d.ts +23 -0
  37. package/modules/netlify-cms/server/lib/types/helpers.mjs +0 -0
  38. package/modules/netlify-cms/server/lib/types/index.d.ts +23 -0
  39. package/modules/netlify-cms/server/lib/types/index.mjs +11 -0
  40. package/modules/netlify-cms/server/lib/types/widgets.d.ts +39 -0
  41. package/modules/netlify-cms/server/lib/types/widgets.mjs +0 -0
  42. package/package.json +1 -1
  43. package/server/lib/handler.mjs +2 -2
  44. package/server/renderer.mjs +4 -0
  45. package/src/main.d.ts +1 -1
  46. package/src/main.mjs +2 -1
  47. package/src/public/nitro.mjs +2 -0
  48. package/src/public/query-content.d.ts +8 -0
  49. package/src/public/query-content.mjs +103 -37
  50. package/src/public/vite.mjs +19 -6
  51. package/src/runtime/config.d.ts +7 -0
  52. package/src/runtime/modules.mjs +2 -1
  53. package/src/runtime/nitro-plugin.d.ts +1 -0
  54. package/src/runtime/nitro-plugin.mjs +5 -0
  55. package/src/runtime/virtual-pages.d.ts +1 -0
  56. package/src/runtime/virtual-pages.mjs +18 -0
@@ -29,6 +29,18 @@ export default defineFlowModule({
29
29
  context.nitro.routeRules[`${options.apiBase}/**`] = {
30
30
  cors: true
31
31
  };
32
+ const fetchPluginPath = context.projectRoot === resolvePackagePath() ? resolve(context.projectRoot, "src/runtime/nitro-plugin.ts") : resolvePackageFile("src/runtime/nitro-plugin.ts", "src/runtime/nitro-plugin.mjs", "src/runtime/nitro-plugin.js");
33
+ context.nitro.plugins = context.nitro.plugins || [];
34
+ if (!context.nitro.plugins.includes(fetchPluginPath)) {
35
+ context.nitro.plugins.push(fetchPluginPath);
36
+ }
37
+ context.nitro.storage = {
38
+ ...context.nitro.storage || {},
39
+ content: {
40
+ driver: "fs",
41
+ base: contentDir
42
+ }
43
+ };
32
44
  context.nitro.runtimeConfig.flow = {
33
45
  ...typeof context.nitro.runtimeConfig.flow === "object" && context.nitro.runtimeConfig.flow ? context.nitro.runtimeConfig.flow : {},
34
46
  content: {
@@ -20,7 +20,7 @@ export interface ContentFileNode extends ContentEntry {
20
20
  }
21
21
  export type ContentTreeNode = ContentDirectoryNode | ContentFileNode;
22
22
  export declare function findContentEntries(entries: ContentEntry[], path?: string): ContentEntry[];
23
- export declare function readContentEntries(contentDir: string): ContentEntry[];
23
+ export declare function readContentEntries(): Promise<ContentEntry[]>;
24
24
  export declare function buildContentTree(entries: ContentEntry[]): ContentTreeNode[];
25
25
  export declare function findContentTree(tree: ContentTreeNode[], path?: string): ContentTreeNode[];
26
26
  declare const _default: any;
@@ -1,33 +1,11 @@
1
- import { existsSync, readdirSync, readFileSync } from "node:fs";
2
- import { extname, relative, resolve } from "node:path";
1
+ import { extname } from "node:path";
3
2
  import { defineEventHandler, getQuery, getRequestURL } from "nitro/h3";
4
- import { useRuntimeConfig } from "nitro/runtime-config";
5
- function collectFiles(rootDir, currentDir = rootDir) {
6
- const entries = readdirSync(currentDir, { withFileTypes: true });
7
- const files = [];
8
- for (const entry of entries) {
9
- const fullPath = resolve(currentDir, entry.name);
10
- if (entry.isDirectory()) {
11
- files.push(...collectFiles(rootDir, fullPath));
12
- continue;
13
- }
14
- if (!entry.isFile()) {
15
- continue;
16
- }
17
- const extension = extname(entry.name);
18
- if (![".md", ".json", ".yml", ".yaml", ".txt"].includes(extension)) {
19
- continue;
20
- }
21
- files.push(fullPath);
22
- }
23
- return files.sort((left, right) => left.localeCompare(right));
24
- }
3
+ import { useStorage } from "nitro/storage";
25
4
  function normalizeQueryPath(path) {
26
- if (!path) {
5
+ if (!path || path === "/") {
27
6
  return "/";
28
7
  }
29
- const normalized = `/${path}`.replace(/\/+/g, "/");
30
- return normalized.length > 1 && normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
8
+ return path.startsWith("/") ? path : `/${path}`;
31
9
  }
32
10
  export function findContentEntries(entries, path) {
33
11
  const normalizedPath = normalizeQueryPath(path);
@@ -36,8 +14,8 @@ export function findContentEntries(entries, path) {
36
14
  }
37
15
  return entries.filter((entry) => entry.path === normalizedPath || entry.path.startsWith(`${normalizedPath}/`));
38
16
  }
39
- function normalizeContentPath(rootDir, filePath) {
40
- const shortPath = relative(rootDir, filePath).replaceAll("\\", "/");
17
+ function normalizeContentPath(keyPath) {
18
+ const shortPath = keyPath;
41
19
  const stem = shortPath.replace(/\.(md|json|ya?ml|txt)$/i, "");
42
20
  const segments = stem.split("/").filter(Boolean);
43
21
  return {
@@ -59,35 +37,36 @@ function parseKeyValueBlock(block) {
59
37
  return data;
60
38
  }, {});
61
39
  }
62
- function parseContentFile(rootDir, filePath) {
63
- const raw = readFileSync(filePath, "utf8");
64
- const extension = extname(filePath).toLowerCase();
65
- const normalizedPath = normalizeContentPath(rootDir, filePath);
40
+ function parseContentFile(keyPath, raw) {
41
+ const extension = extname(keyPath).toLowerCase();
42
+ const normalizedPath = normalizeContentPath(keyPath);
66
43
  if (extension === ".json") {
67
- const parsed = JSON.parse(raw);
44
+ const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
45
+ const body = typeof raw === "string" ? raw : JSON.stringify(raw);
68
46
  return {
69
47
  ...normalizedPath,
70
48
  extension,
71
49
  title: typeof parsed.title === "string" ? parsed.title : void 0,
72
- body: raw,
50
+ body,
73
51
  data: parsed
74
52
  };
75
53
  }
76
- if ((extension === ".yml" || extension === ".yaml") && raw.trim()) {
77
- const data = parseKeyValueBlock(raw);
54
+ const rawString = String(raw);
55
+ if ((extension === ".yml" || extension === ".yaml") && rawString.trim()) {
56
+ const data = parseKeyValueBlock(rawString);
78
57
  return {
79
58
  ...normalizedPath,
80
59
  extension,
81
60
  title: data.title,
82
- body: raw,
61
+ body: rawString,
83
62
  data
84
63
  };
85
64
  }
86
- if (raw.startsWith("---\n")) {
87
- const end = raw.indexOf("\n---\n", 4);
65
+ if (rawString.startsWith("---\n")) {
66
+ const end = rawString.indexOf("\n---\n", 4);
88
67
  if (end >= 0) {
89
- const frontmatter = raw.slice(4, end);
90
- const body = raw.slice(end + 5).trim();
68
+ const frontmatter = rawString.slice(4, end);
69
+ const body = rawString.slice(end + 5).trim();
91
70
  const data = parseKeyValueBlock(frontmatter);
92
71
  return {
93
72
  ...normalizedPath,
@@ -101,15 +80,60 @@ function parseContentFile(rootDir, filePath) {
101
80
  return {
102
81
  ...normalizedPath,
103
82
  extension,
104
- body: raw,
83
+ body: rawString,
105
84
  data: {}
106
85
  };
107
86
  }
108
- export function readContentEntries(contentDir) {
109
- if (!contentDir || !existsSync(contentDir)) {
110
- return [];
87
+ export async function readContentEntries() {
88
+ const storage = useStorage("content");
89
+ const keys = await storage.getKeys();
90
+ const entries = [];
91
+ if (keys.length === 0) {
92
+ try {
93
+ const fs = await import("node:fs/promises");
94
+ const path = await import("node:path");
95
+ const contentDir = path.resolve(process.cwd(), "content");
96
+ async function walkDir(dir, baseDir) {
97
+ const files = await fs.readdir(dir, { withFileTypes: true });
98
+ for (const file of files) {
99
+ const res = path.resolve(dir, file.name);
100
+ if (file.isDirectory()) {
101
+ await walkDir(res, baseDir);
102
+ } else {
103
+ const extension = path.extname(res).toLowerCase();
104
+ if ([".md", ".json", ".yml", ".yaml", ".txt"].includes(extension)) {
105
+ const relativePath = path.relative(baseDir, res);
106
+ const normalizedKey = relativePath.replace(/\\/g, "/");
107
+ const raw = await fs.readFile(res, "utf-8");
108
+ const entry = parseContentFile(normalizedKey, raw);
109
+ entries.push(entry);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ try {
115
+ await fs.access(contentDir);
116
+ await walkDir(contentDir, contentDir);
117
+ } catch (e) {
118
+ }
119
+ return entries.sort((left, right) => left.path.localeCompare(right.path));
120
+ } catch (e) {
121
+ console.error("[Flow Content] fs fallback failed:", e);
122
+ }
123
+ }
124
+ for (const key of keys) {
125
+ const normalizedKey = key.replace(/:/g, "/");
126
+ const extension = extname(normalizedKey).toLowerCase();
127
+ if (![".md", ".json", ".yml", ".yaml", ".txt"].includes(extension)) {
128
+ continue;
129
+ }
130
+ const raw = await storage.getItem(key);
131
+ if (raw !== null && raw !== void 0) {
132
+ const entry = parseContentFile(normalizedKey, raw);
133
+ entries.push(entry);
134
+ }
111
135
  }
112
- return collectFiles(contentDir).map((filePath) => parseContentFile(contentDir, filePath));
136
+ return entries.sort((left, right) => left.path.localeCompare(right.path));
113
137
  }
114
138
  function sortTree(nodes) {
115
139
  nodes.sort((left, right) => {
@@ -129,17 +153,19 @@ export function buildContentTree(entries) {
129
153
  const roots = [];
130
154
  const directories = /* @__PURE__ */ new Map();
131
155
  for (const entry of entries) {
132
- const segments = entry.stem.split("/").filter(Boolean);
133
- const dirSegments = segments.slice(0, -1);
156
+ const parts = entry.path.split("/").filter(Boolean);
157
+ let currentPath = "";
134
158
  let siblings = roots;
135
- for (let index = 0; index < dirSegments.length; index += 1) {
136
- const stem = dirSegments.slice(0, index + 1).join("/");
159
+ for (let i = 0; i < parts.length - 1; i++) {
160
+ const part = parts[i];
161
+ currentPath += `/${part}`;
162
+ const stem = currentPath.slice(1);
137
163
  let directory = directories.get(stem);
138
164
  if (!directory) {
139
165
  directory = {
140
166
  kind: "directory",
141
- name: dirSegments[index],
142
- path: `/${stem}`,
167
+ name: part,
168
+ path: currentPath,
143
169
  stem,
144
170
  children: []
145
171
  };
@@ -172,19 +198,93 @@ export function findContentTree(tree, path) {
172
198
  }
173
199
  return [];
174
200
  }
175
- export default defineEventHandler((event) => {
176
- const runtimeConfig = useRuntimeConfig();
201
+ function getField(obj, path) {
202
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
203
+ }
204
+ function setField(obj, path, value) {
205
+ const parts = path.split(".");
206
+ const last = parts.pop();
207
+ const target = parts.reduce((acc, part) => {
208
+ if (!acc[part])
209
+ acc[part] = {};
210
+ return acc[part];
211
+ }, obj);
212
+ target[last] = value;
213
+ }
214
+ export default defineEventHandler(async (event) => {
177
215
  const query = getQuery(event);
178
- const contentDir = runtimeConfig.flow?.content?.dir;
179
216
  const requestUrl = getRequestURL(event);
180
217
  const isTreeRequest = requestUrl.pathname.endsWith("/tree") || query.tree === true || query.tree === "true" || query.tree === "1";
181
- const entries = readContentEntries(contentDir || "");
218
+ let entries = await readContentEntries();
182
219
  if (isTreeRequest) {
183
220
  const tree = buildContentTree(entries);
184
221
  return findContentTree(tree, query.path);
185
222
  }
186
223
  if (query.path) {
187
- return findContentEntries(entries, query.path);
224
+ entries = findContentEntries(entries, query.path);
225
+ }
226
+ if (query.where) {
227
+ try {
228
+ const whereConditions = JSON.parse(query.where);
229
+ entries = entries.filter((entry) => {
230
+ return whereConditions.every((cond) => {
231
+ const val = getField(entry, cond.field);
232
+ switch (cond.operator.toUpperCase()) {
233
+ case "=":
234
+ return val === cond.value;
235
+ case "!=":
236
+ return val !== cond.value;
237
+ case ">":
238
+ return val > cond.value;
239
+ case ">=":
240
+ return val >= cond.value;
241
+ case "<":
242
+ return val < cond.value;
243
+ case "<=":
244
+ return val <= cond.value;
245
+ case "IN":
246
+ return Array.isArray(cond.value) && cond.value.includes(val);
247
+ case "LIKE":
248
+ return typeof val === "string" && val.includes(cond.value);
249
+ default:
250
+ return false;
251
+ }
252
+ });
253
+ });
254
+ } catch {
255
+ }
256
+ }
257
+ if (query.order) {
258
+ try {
259
+ const orderConditions = JSON.parse(query.order);
260
+ entries = entries.sort((a, b) => {
261
+ for (const cond of orderConditions) {
262
+ const valA = getField(a, cond.field);
263
+ const valB = getField(b, cond.field);
264
+ if (valA === valB)
265
+ continue;
266
+ const dir = cond.direction.toUpperCase() === "DESC" ? -1 : 1;
267
+ return valA > valB ? dir : -dir;
268
+ }
269
+ return 0;
270
+ });
271
+ } catch {
272
+ }
273
+ }
274
+ const skip = query.skip ? Number.parseInt(query.skip, 10) : 0;
275
+ const limit = query.limit ? Number.parseInt(query.limit, 10) : 0;
276
+ if (skip > 0 || limit > 0) {
277
+ entries = entries.slice(skip, limit > 0 ? skip + limit : void 0);
278
+ }
279
+ if (query.select) {
280
+ const fields = query.select.split(",");
281
+ entries = entries.map((entry) => {
282
+ const result = {};
283
+ for (const field of fields) {
284
+ setField(result, field, getField(entry, field));
285
+ }
286
+ return result;
287
+ });
188
288
  }
189
289
  return entries;
190
290
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { defineEventHandler } from "nitro/h3";
2
+ console.log("Loading handler.ts");
3
+ export default defineEventHandler(async (event) => {
4
+ return "hola";
5
+ });
@@ -0,0 +1,6 @@
1
+ export interface NetlifyCmsModuleOptions {
2
+ base?: string;
3
+ dir?: string;
4
+ }
5
+ declare const _default: import("../../src/runtime/config.ts").FlowModuleDefinition<NetlifyCmsModuleOptions>;
6
+ export default _default;
@@ -0,0 +1,66 @@
1
+ import { resolve } from "node:path";
2
+ import process from "node:process";
3
+ import { resolvePackageFile, resolvePackagePath } from "../../src/public/shared.mjs";
4
+ import { defineFlowModule } from "../../src/runtime/config.mjs";
5
+ export default defineFlowModule({
6
+ meta: {
7
+ name: "netlify-cms",
8
+ configKey: "netlifyCms"
9
+ },
10
+ defaults: {
11
+ base: "/cms",
12
+ dir: "content"
13
+ },
14
+ setup(options, context) {
15
+ const isDev = process.env.NODE_ENV !== "production";
16
+ const handlerPath = context.projectRoot === resolvePackagePath() ? resolve(context.projectRoot, "modules/netlify-cms/server/api/local-fs.ts") : resolvePackageFile("modules/netlify-cms/server/api/local-fs.ts", "modules/netlify-cms/server/api/local-fs.mjs", "modules/netlify-cms/server/api/local-fs.js");
17
+ const configHandlerPath = context.projectRoot === resolvePackagePath() ? resolve(context.projectRoot, "modules/netlify-cms/server/api/config.ts") : resolvePackageFile("modules/netlify-cms/server/api/config.ts", "modules/netlify-cms/server/api/config.mjs", "modules/netlify-cms/server/api/config.js");
18
+ const adminHandlerPath = context.projectRoot === resolvePackagePath() ? resolve(context.projectRoot, "modules/netlify-cms/server/api/admin.ts") : resolvePackageFile("modules/netlify-cms/server/api/admin.ts", "modules/netlify-cms/server/api/admin.mjs", "modules/netlify-cms/server/api/admin.js");
19
+ const metaHandlerPath = context.projectRoot === resolvePackagePath() ? resolve(context.projectRoot, "modules/netlify-cms/server/api/meta.ts") : resolvePackageFile("modules/netlify-cms/server/api/meta.ts", "modules/netlify-cms/server/api/meta.mjs", "modules/netlify-cms/server/api/meta.js");
20
+ const locales = context.flowConfig.locale?.locales || ["es"];
21
+ context.nitro.virtual = context.nitro.virtual || {};
22
+ context.nitro.virtual["#cms-meta"] = `export const localeConfig = ${JSON.stringify(context.flowConfig.locale || {})};`;
23
+ context.nitro.handlers.push({
24
+ method: "get",
25
+ route: "/cms/v2/app/**",
26
+ handler: adminHandlerPath
27
+ });
28
+ context.nitro.handlers.push({
29
+ method: "get",
30
+ route: "/cms/v2/app.html",
31
+ handler: adminHandlerPath
32
+ });
33
+ context.nitro.handlers.push({
34
+ method: "get",
35
+ route: "/_flow/cms-meta.json",
36
+ handler: metaHandlerPath
37
+ });
38
+ context.prerenderRoutes?.add("/_flow/cms-meta.json");
39
+ context.prerenderRoutes?.add("/cms/v2/app.html");
40
+ for (const locale of locales) {
41
+ const configRoute = `/cms/${locale}/config.yml`;
42
+ context.nitro.handlers.push({
43
+ method: "get",
44
+ route: configRoute,
45
+ handler: configHandlerPath
46
+ });
47
+ context.prerenderRoutes?.add(configRoute);
48
+ }
49
+ if (isDev) {
50
+ context.nitro.handlers.push({
51
+ method: "post",
52
+ route: "/api/v1",
53
+ handler: handlerPath
54
+ });
55
+ context.nitro.routeRules = context.nitro.routeRules || {};
56
+ context.nitro.routeRules["/api/v1"] = {
57
+ cors: true
58
+ };
59
+ context.nitro.imports = context.nitro.imports || { imports: [] };
60
+ (context.nitro.imports.imports = context.nitro.imports.imports || []).push({
61
+ name: "defineCmsCollection",
62
+ from: resolvePackageFile("modules/netlify-cms/server/lib/composables.ts", "modules/netlify-cms/server/lib/composables.mjs", "modules/netlify-cms/server/lib/composables.js")
63
+ });
64
+ }
65
+ }
66
+ });
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Content Manager</title>
7
+ <link href="configV1.yml" type="text/yaml" rel="cms-config-url">
8
+
9
+ <!-- Include the script that enables Netlify Identity on this page. -->
10
+ <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
11
+ </head>
12
+ <body>
13
+ <!-- Include the script that builds the page and powers Netlify CMS -->
14
+ <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
15
+ </body>
16
+ </html>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Cms</title>
8
+ <link rel="stylesheet" href="https://cms2-demo.netlify.app/assets/windi.css">
9
+ <link rel="stylesheet" href="https://cms2-demo.netlify.app/assets/cms.css">
10
+ <script type="module" crossorigin src="https://cms2-demo.netlify.app/assets/cms.js"></script>
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ </body>
15
+ </html>
@@ -0,0 +1,3 @@
1
+ export { defineCmsCollection } from '../server/lib/composables';
2
+ export { widgets } from '../server/lib/cms/widgets';
3
+ export { collections } from '../server/lib/cms/helpers';
@@ -0,0 +1,3 @@
1
+ export { defineCmsCollection } from "../server/lib/composables.mjs";
2
+ export { widgets } from "../server/lib/cms/widgets.mjs";
3
+ export { collections } from "../server/lib/cms/helpers.mjs";
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { defineEventHandler, setResponseHeader } from "nitro/h3";
2
+ const adminHtml = `<!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <title>Cms</title>
9
+ <link rel="stylesheet" href="https://cms2-demo.netlify.app/assets/windi.css">
10
+ <link rel="stylesheet" href="https://cms2-demo.netlify.app/assets/cms.css">
11
+ <script type="module" crossorigin src="https://cms2-demo.netlify.app/assets/cms.js"><\/script>
12
+ </head>
13
+ <body>
14
+ <div id="app"></div>
15
+ </body>
16
+ </html>`;
17
+ export default defineEventHandler(async (event) => {
18
+ setResponseHeader(event, "Content-Type", "text/html;charset=utf-8");
19
+ return adminHtml;
20
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,72 @@
1
+ import defu from "defu";
2
+ import yml from "js-yaml";
3
+ import { defineEventHandler, setResponseHeader } from "nitro/h3";
4
+ import { collections, defineCms } from "../lib/cms/helpers.mjs";
5
+ import { widgets } from "../lib/cms/widgets.mjs";
6
+ import fs from "node:fs";
7
+ import { resolve } from "node:path";
8
+ import { createJiti } from "jiti";
9
+ import process from "node:process";
10
+ import { defineCmsCollection } from "../lib/composables.mjs";
11
+ export default defineEventHandler(async (event) => {
12
+ if (!globalThis.defineCmsCollection) {
13
+ globalThis.defineCmsCollection = defineCmsCollection;
14
+ }
15
+ const urlParts = event.path?.split("?")[0].split("/") || [];
16
+ urlParts.pop();
17
+ const locale = urlParts.pop() || "es";
18
+ const options = {};
19
+ const defaultOptions = {
20
+ config: {
21
+ backend: {
22
+ name: "git-gateway",
23
+ branch: "master"
24
+ },
25
+ media_folder: "public/media",
26
+ public_folder: "/media",
27
+ locale,
28
+ local_backend: {
29
+ url: "/api/v1"
30
+ }
31
+ },
32
+ base: "/"
33
+ };
34
+ const { config, base } = defu(options, defaultOptions);
35
+ config.media_folder = base + config.media_folder;
36
+ const projectRoot = process.cwd();
37
+ const cmsDir = resolve(projectRoot, "cms");
38
+ let loadedCollections = [];
39
+ try {
40
+ if (fs.existsSync(cmsDir)) {
41
+ const jiti = createJiti(resolve(projectRoot, "cms", "dummy.ts"), { interopDefault: true, fsCache: false, requireCache: false });
42
+ const walkSync = (dir, filelist = []) => {
43
+ const files = fs.readdirSync(dir);
44
+ for (const file of files) {
45
+ const filepath = resolve(dir, file);
46
+ const stat = fs.statSync(filepath);
47
+ if (stat.isDirectory()) {
48
+ filelist = walkSync(filepath, filelist);
49
+ } else if (file.endsWith(".ts")) {
50
+ filelist.push(filepath);
51
+ }
52
+ }
53
+ return filelist;
54
+ };
55
+ const cmsFiles = walkSync(cmsDir);
56
+ for (const filePath of cmsFiles) {
57
+ const mod = jiti(filePath);
58
+ const colFn = mod.default || mod;
59
+ if (typeof colFn === "function") {
60
+ loadedCollections.push(colFn);
61
+ }
62
+ }
63
+ }
64
+ } catch (e) {
65
+ console.error("[CMS CONFIG] Error loading collections dynamically:", e);
66
+ }
67
+ const resolvedCollections = loadedCollections.map((c) => c({ widgets, collections }));
68
+ const manifest = defineCms(config, resolvedCollections)(`${base}content/${locale}/`, { rootDir: base });
69
+ const ymlConfig = yml.dump(manifest, { skipInvalid: true });
70
+ setResponseHeader(event, "Content-Type", "text/yml;charset=utf-8");
71
+ return ymlConfig;
72
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;