@webstudio-is/sdk 0.264.0 → 0.266.0

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/lib/index.js CHANGED
@@ -97,10 +97,6 @@ var commonPageFields = {
97
97
  )
98
98
  };
99
99
  var HomePagePath = z2.string().refine((path) => path === "", "Home page path must be empty");
100
- var HomePage = z2.object({
101
- ...commonPageFields,
102
- path: HomePagePath
103
- });
104
100
  var DefaultPagePage = z2.string().refine((path) => path !== "", "Can't be empty").refine((path) => path !== "/", "Can't be just a /").refine((path) => path.endsWith("/") === false, "Can't end with a /").refine((path) => path.includes("//") === false, "Can't contain repeating /").refine(
105
101
  (path) => /^[-_a-z0-9*:?\\/.]*$/.test(path),
106
102
  "Only a-z, 0-9, -, _, /, :, ?, . and * are allowed"
@@ -133,7 +129,7 @@ var PagePath = DefaultPagePage.refine(
133
129
  );
134
130
  var Page = z2.object({
135
131
  ...commonPageFields,
136
- path: PagePath
132
+ path: z2.union([HomePagePath, PagePath])
137
133
  });
138
134
  var ProjectMeta = z2.object({
139
135
  // All fields are optional to ensure consistency and allow for the addition of new fields without requiring migration
@@ -163,9 +159,123 @@ var Pages = z2.object({
163
159
  meta: ProjectMeta.optional(),
164
160
  compiler: CompilerSettings.optional(),
165
161
  redirects: z2.array(PageRedirect).optional(),
166
- homePage: HomePage,
167
- pages: z2.array(Page),
168
- folders: z2.array(Folder).refine((folders) => folders.length > 0, "Folders can't be empty")
162
+ homePageId: PageId,
163
+ rootFolderId: FolderId,
164
+ pages: z2.map(PageId, Page),
165
+ folders: z2.map(FolderId, Folder).refine((folders) => folders.size > 0, "Folders can't be empty")
166
+ }).superRefine((pages, context) => {
167
+ const homePage = pages.pages.get(pages.homePageId);
168
+ const rootFolder = pages.folders.get(pages.rootFolderId);
169
+ if (homePage === void 0) {
170
+ context.addIssue({
171
+ code: z2.ZodIssueCode.custom,
172
+ path: ["homePageId"],
173
+ message: "Home page must reference an existing page"
174
+ });
175
+ }
176
+ if (rootFolder === void 0) {
177
+ context.addIssue({
178
+ code: z2.ZodIssueCode.custom,
179
+ path: ["rootFolderId"],
180
+ message: "Root folder must reference an existing folder"
181
+ });
182
+ }
183
+ if (homePage !== void 0 && homePage.path !== "") {
184
+ context.addIssue({
185
+ code: z2.ZodIssueCode.custom,
186
+ path: ["pages", pages.homePageId, "path"],
187
+ message: "Home page path must be empty"
188
+ });
189
+ }
190
+ for (const [pageId, page] of pages.pages) {
191
+ if (page.id !== pageId) {
192
+ context.addIssue({
193
+ code: z2.ZodIssueCode.custom,
194
+ path: ["pages", pageId, "id"],
195
+ message: "Page id must match its record key"
196
+ });
197
+ }
198
+ if (pageId !== pages.homePageId && page.path === "") {
199
+ context.addIssue({
200
+ code: z2.ZodIssueCode.custom,
201
+ path: ["pages", pageId, "path"],
202
+ message: "Page path can't be empty"
203
+ });
204
+ }
205
+ }
206
+ for (const [folderId, folder] of pages.folders) {
207
+ if (folder.id !== folderId) {
208
+ context.addIssue({
209
+ code: z2.ZodIssueCode.custom,
210
+ path: ["folders", folderId, "id"],
211
+ message: "Folder id must match its record key"
212
+ });
213
+ }
214
+ for (const [index, childId] of folder.children.entries()) {
215
+ if (pages.pages.has(childId) === false && pages.folders.has(childId) === false) {
216
+ context.addIssue({
217
+ code: z2.ZodIssueCode.custom,
218
+ path: ["folders", folderId, "children", index],
219
+ message: "Folder child must reference an existing page or folder"
220
+ });
221
+ }
222
+ if (childId === pages.rootFolderId) {
223
+ context.addIssue({
224
+ code: z2.ZodIssueCode.custom,
225
+ path: ["folders", folderId, "children", index],
226
+ message: "Root folder can't be nested"
227
+ });
228
+ }
229
+ }
230
+ }
231
+ if (rootFolder !== void 0 && rootFolder.children[0] !== pages.homePageId) {
232
+ context.addIssue({
233
+ code: z2.ZodIssueCode.custom,
234
+ path: ["folders", pages.rootFolderId, "children"],
235
+ message: "Root folder must start with the home page"
236
+ });
237
+ }
238
+ const childParents = /* @__PURE__ */ new Map();
239
+ for (const [folderId, folder] of pages.folders) {
240
+ for (const [index, childId] of folder.children.entries()) {
241
+ const parentId = childParents.get(childId);
242
+ if (parentId !== void 0) {
243
+ context.addIssue({
244
+ code: z2.ZodIssueCode.custom,
245
+ path: ["folders", folderId, "children", index],
246
+ message: `Child is already registered in folder "${parentId}"`
247
+ });
248
+ continue;
249
+ }
250
+ childParents.set(childId, folderId);
251
+ }
252
+ }
253
+ const hasFolderCycle = (folderId, path = /* @__PURE__ */ new Set()) => {
254
+ if (path.has(folderId)) {
255
+ return true;
256
+ }
257
+ const folder = pages.folders.get(folderId);
258
+ if (folder === void 0) {
259
+ return false;
260
+ }
261
+ path.add(folderId);
262
+ for (const childId of folder.children) {
263
+ if (pages.folders.has(childId) && hasFolderCycle(childId, path)) {
264
+ return true;
265
+ }
266
+ }
267
+ path.delete(folderId);
268
+ return false;
269
+ };
270
+ for (const folderId of pages.folders.keys()) {
271
+ if (hasFolderCycle(folderId)) {
272
+ context.addIssue({
273
+ code: z2.ZodIssueCode.custom,
274
+ path: ["folders", folderId, "children"],
275
+ message: "Folders can't contain cycles"
276
+ });
277
+ }
278
+ }
169
279
  });
170
280
 
171
281
  // src/schema/instances.ts
@@ -700,7 +810,8 @@ import { z as z14 } from "zod";
700
810
  var common = {
701
811
  label: z14.string().optional(),
702
812
  description: z14.string().optional(),
703
- required: z14.boolean()
813
+ required: z14.boolean(),
814
+ contentMode: z14.boolean().optional()
704
815
  };
705
816
  var Tag = z14.object({
706
817
  ...common,
@@ -2364,16 +2475,36 @@ var isAbsoluteUrl = (href) => {
2364
2475
  // src/page-utils.ts
2365
2476
  var ROOT_FOLDER_ID = "root";
2366
2477
  var isRootFolder = ({ id }) => id === ROOT_FOLDER_ID;
2478
+ var getPageById = (pages, pageId) => {
2479
+ return pages.pages.get(pageId);
2480
+ };
2481
+ var getFolderById = (pages, folderId) => {
2482
+ return pages.folders.get(folderId);
2483
+ };
2484
+ var getAllPages = (pages) => {
2485
+ return Array.from(pages.pages.values());
2486
+ };
2487
+ var getAllFolders = (pages) => {
2488
+ return Array.from(pages.folders.values());
2489
+ };
2490
+ var getHomePage = (pages) => {
2491
+ const homePage = getPageById(pages, pages.homePageId);
2492
+ if (homePage === void 0) {
2493
+ throw new Error(`Home page "${pages.homePageId}" was not found.`);
2494
+ }
2495
+ return homePage;
2496
+ };
2367
2497
  var findPageByIdOrPath = (idOrPath, pages) => {
2368
- if (idOrPath === "" || idOrPath === "/" || idOrPath === pages.homePage.id) {
2369
- return pages.homePage;
2498
+ if (idOrPath === "" || idOrPath === "/" || idOrPath === pages.homePageId) {
2499
+ return getHomePage(pages);
2370
2500
  }
2371
- return pages.pages.find(
2501
+ return getAllPages(pages).find(
2372
2502
  (page) => page.id === idOrPath || getPagePath(page.id, pages) === idOrPath
2373
2503
  );
2374
2504
  };
2375
2505
  var findParentFolderByChildId = (id, folders) => {
2376
- for (const folder of folders) {
2506
+ const folderList = folders instanceof Map ? folders.values() : folders;
2507
+ for (const folder of folderList) {
2377
2508
  if (folder.children.includes(id)) {
2378
2509
  return folder;
2379
2510
  }
@@ -2382,7 +2513,7 @@ var findParentFolderByChildId = (id, folders) => {
2382
2513
  var getPagePath = (id, pages) => {
2383
2514
  const foldersMap = /* @__PURE__ */ new Map();
2384
2515
  const childParentMap = /* @__PURE__ */ new Map();
2385
- for (const folder of pages.folders) {
2516
+ for (const folder of getAllFolders(pages)) {
2386
2517
  foldersMap.set(folder.id, folder);
2387
2518
  for (const childId of folder.children) {
2388
2519
  childParentMap.set(childId, folder.id);
@@ -2390,7 +2521,7 @@ var getPagePath = (id, pages) => {
2390
2521
  }
2391
2522
  const paths = [];
2392
2523
  let currentId = id;
2393
- const allPages = [pages.homePage, ...pages.pages];
2524
+ const allPages = getAllPages(pages);
2394
2525
  for (const page of allPages) {
2395
2526
  if (page.id === id) {
2396
2527
  paths.push(page.path);
@@ -2409,7 +2540,7 @@ var getPagePath = (id, pages) => {
2409
2540
  return paths.reverse().join("/").replace(/\/+/g, "/");
2410
2541
  };
2411
2542
  var getStaticSiteMapXml = (pages, updatedAt) => {
2412
- const allPages = [pages.homePage, ...pages.pages];
2543
+ const allPages = getAllPages(pages);
2413
2544
  return allPages.filter((page) => (page.meta.documentType ?? "html") === "html").filter(
2414
2545
  (page) => executeExpression(page.meta.excludePageFromSearch) !== true
2415
2546
  ).filter((page) => false === isPathnamePattern(page.path)).map((page) => ({
@@ -3008,6 +3139,7 @@ export {
3008
3139
  FONT_EXTENSIONS,
3009
3140
  FileAsset,
3010
3141
  Folder,
3142
+ FolderId,
3011
3143
  FolderName,
3012
3144
  FontAsset,
3013
3145
  HomePagePath,
@@ -3021,6 +3153,7 @@ export {
3021
3153
  Instances,
3022
3154
  MIME_CATEGORIES,
3023
3155
  OldPagePath,
3156
+ PageId,
3024
3157
  PageName,
3025
3158
  PagePath,
3026
3159
  PageRedirect,
@@ -3087,12 +3220,17 @@ export {
3087
3220
  generateObjectExpression,
3088
3221
  generatePageMeta,
3089
3222
  generateResources,
3223
+ getAllFolders,
3224
+ getAllPages,
3090
3225
  getAssetMime,
3091
3226
  getAssetUrl,
3092
3227
  getExpressionIdentifiers,
3228
+ getFolderById,
3229
+ getHomePage,
3093
3230
  getIndexesWithinAncestors,
3094
3231
  getMimeTypeByExtension,
3095
3232
  getMimeTypeByFilename,
3233
+ getPageById,
3096
3234
  getPagePath,
3097
3235
  getStaticSiteMapXml,
3098
3236
  getStyleDeclKey,
@@ -6,6 +6,11 @@ export declare const ROOT_FOLDER_ID = "root";
6
6
  export declare const isRootFolder: ({ id }: {
7
7
  id: Folder["id"];
8
8
  }) => boolean;
9
+ export declare const getPageById: (pages: Pages, pageId: Page["id"]) => Page | undefined;
10
+ export declare const getFolderById: (pages: Pages, folderId: Folder["id"]) => Folder | undefined;
11
+ export declare const getAllPages: (pages: Pages) => Page[];
12
+ export declare const getAllFolders: (pages: Pages) => Folder[];
13
+ export declare const getHomePage: (pages: Pages) => Page;
9
14
  /**
10
15
  * Find a page by id or path.
11
16
  */
@@ -13,7 +18,7 @@ export declare const findPageByIdOrPath: (idOrPath: string, pages: Pages) => Pag
13
18
  /**
14
19
  * Find a folder that has has that id in the children.
15
20
  */
16
- export declare const findParentFolderByChildId: (id: Folder["id"] | Page["id"], folders: Array<Folder>) => Folder | undefined;
21
+ export declare const findParentFolderByChildId: (id: Folder["id"] | Page["id"], folders: Iterable<Folder> | Map<Folder["id"], Folder>) => Folder | undefined;
17
22
  /**
18
23
  * Get a path from all folder slugs from root to the current folder or page.
19
24
  */