@aphexcms/cms-core 0.1.12 → 0.1.14

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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api/documents.d.ts +1 -0
  3. package/dist/api/documents.d.ts.map +1 -1
  4. package/dist/api/documents.js +9 -1
  5. package/dist/api/types.d.ts +24 -2
  6. package/dist/api/types.d.ts.map +1 -1
  7. package/dist/auth/auth-hooks.d.ts.map +1 -1
  8. package/dist/auth/auth-hooks.js +18 -4
  9. package/dist/cli/generate-types.js +218 -0
  10. package/dist/cli/index.js +86 -0
  11. package/dist/components/AdminApp.svelte +15 -12
  12. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  13. package/dist/components/admin/DocumentEditor.svelte +60 -14
  14. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  15. package/dist/components/admin/fields/ImageField.svelte +22 -13
  16. package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -1
  17. package/dist/components/admin/fields/ReferenceField.svelte +2 -3
  18. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
  19. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +8 -1
  20. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -1
  21. package/dist/db/interfaces/asset.d.ts +22 -0
  22. package/dist/db/interfaces/asset.d.ts.map +1 -1
  23. package/dist/db/interfaces/document.d.ts +25 -0
  24. package/dist/db/interfaces/document.d.ts.map +1 -1
  25. package/dist/field-validation/utils.d.ts +19 -1
  26. package/dist/field-validation/utils.d.ts.map +1 -1
  27. package/dist/field-validation/utils.js +33 -0
  28. package/dist/hooks.d.ts +2 -0
  29. package/dist/hooks.d.ts.map +1 -1
  30. package/dist/hooks.js +80 -12
  31. package/dist/lib/auth/provider.js +1 -0
  32. package/dist/lib/db/index.js +4 -0
  33. package/dist/lib/db/interfaces/asset.js +1 -0
  34. package/dist/lib/db/interfaces/document.js +1 -0
  35. package/dist/lib/db/interfaces/index.js +1 -0
  36. package/dist/lib/db/interfaces/organization.js +1 -0
  37. package/dist/lib/db/interfaces/schema.js +1 -0
  38. package/dist/lib/db/interfaces/user.js +1 -0
  39. package/dist/lib/email/index.js +4 -0
  40. package/dist/lib/email/interfaces/email.js +1 -0
  41. package/dist/lib/field-validation/rule.js +221 -0
  42. package/dist/lib/field-validation/utils.js +99 -0
  43. package/dist/lib/storage/interfaces/index.js +2 -0
  44. package/dist/lib/storage/interfaces/storage.js +1 -0
  45. package/dist/lib/types/asset.js +2 -0
  46. package/dist/lib/types/auth.js +41 -0
  47. package/dist/lib/types/config.js +1 -0
  48. package/dist/lib/types/document.js +1 -0
  49. package/dist/lib/types/filters.js +5 -0
  50. package/dist/lib/types/index.js +9 -0
  51. package/dist/lib/types/organization.js +3 -0
  52. package/dist/lib/types/schemas.js +1 -0
  53. package/dist/lib/types/sidebar.js +1 -0
  54. package/dist/lib/types/user.js +1 -0
  55. package/dist/local-api/auth-helpers.d.ts +65 -0
  56. package/dist/local-api/auth-helpers.d.ts.map +1 -0
  57. package/dist/local-api/auth-helpers.js +102 -0
  58. package/dist/local-api/collection-api.d.ts +138 -0
  59. package/dist/local-api/collection-api.d.ts.map +1 -0
  60. package/dist/local-api/collection-api.js +276 -0
  61. package/dist/local-api/index.d.ts +108 -0
  62. package/dist/local-api/index.d.ts.map +1 -0
  63. package/dist/local-api/index.js +157 -0
  64. package/dist/local-api/permissions.d.ts +45 -0
  65. package/dist/local-api/permissions.d.ts.map +1 -0
  66. package/dist/local-api/permissions.js +117 -0
  67. package/dist/local-api/types.d.ts +65 -0
  68. package/dist/local-api/types.d.ts.map +1 -0
  69. package/dist/local-api/types.js +4 -0
  70. package/dist/routes/documents-by-id.d.ts.map +1 -1
  71. package/dist/routes/documents-by-id.js +84 -63
  72. package/dist/routes/documents-publish.d.ts.map +1 -1
  73. package/dist/routes/documents-publish.js +57 -72
  74. package/dist/routes/documents-query.d.ts +24 -0
  75. package/dist/routes/documents-query.d.ts.map +1 -0
  76. package/dist/routes/documents-query.js +95 -0
  77. package/dist/routes/documents.d.ts.map +1 -1
  78. package/dist/routes/documents.js +80 -75
  79. package/dist/routes/index.d.ts +2 -0
  80. package/dist/routes/index.d.ts.map +1 -1
  81. package/dist/routes/index.js +2 -0
  82. package/dist/server/index.d.ts +1 -0
  83. package/dist/server/index.d.ts.map +1 -1
  84. package/dist/server/index.js +2 -0
  85. package/dist/types/config.d.ts +18 -1
  86. package/dist/types/config.d.ts.map +1 -1
  87. package/dist/types/document.d.ts +1 -0
  88. package/dist/types/document.d.ts.map +1 -1
  89. package/dist/types/filters.d.ts +173 -0
  90. package/dist/types/filters.d.ts.map +1 -0
  91. package/dist/types/filters.js +5 -0
  92. package/dist/types/index.d.ts +1 -0
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/index.js +1 -0
  95. package/package.json +101 -95
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Benjamin Sinidol
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -2,6 +2,7 @@ import type { Document, DocumentListParams, CreateDocumentData, UpdateDocumentDa
2
2
  export declare class DocumentsApi {
3
3
  /**
4
4
  * List documents with optional filtering
5
+ * NOTE: Requires 'type' parameter - use getByType() for convenience
5
6
  */
6
7
  static list(params?: DocumentListParams): Promise<ApiResponse<Document[]>>;
7
8
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/lib/api/documents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,MAAM,SAAS,CAAC;AAEjB,qBAAa,YAAY;IACxB;;OAEG;WACU,IAAI,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAIpF;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIhE;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAI7E;;OAEG;WACU,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAI7F;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIhE;;OAEG;WACU,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIlE;;OAEG;WACU,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAI/D;;OAEG;WACU,SAAS,CACrB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAM,GAC9C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAInC;;OAEG;WACU,YAAY,CACxB,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAInC;;OAEG;WACU,SAAS,CACrB,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;CAGnC;AAGD,eAAO,MAAM,SAAS;;;;;;;;;;;CAWrB,CAAC"}
1
+ {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/lib/api/documents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,QAAQ,EACR,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,MAAM,SAAS,CAAC;AAEjB,qBAAa,YAAY;IACxB;;;OAGG;WACU,IAAI,CAAC,MAAM,GAAE,kBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAYpF;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIhE;;OAEG;WACU,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAI7E;;OAEG;WACU,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAI7F;;OAEG;WACU,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIhE;;OAEG;WACU,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAIlE;;OAEG;WACU,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAI/D;;OAEG;WACU,SAAS,CACrB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAM,GAC9C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAInC;;OAEG;WACU,YAAY,CACxB,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;IAInC;;OAEG;WACU,SAAS,CACrB,MAAM,GAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAM,GAC7C,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC;CAGnC;AAGD,eAAO,MAAM,SAAS;;;;;;;;;;;CAWrB,CAAC"}
@@ -3,9 +3,17 @@ import { apiClient } from './client.js';
3
3
  export class DocumentsApi {
4
4
  /**
5
5
  * List documents with optional filtering
6
+ * NOTE: Requires 'type' parameter - use getByType() for convenience
6
7
  */
7
8
  static async list(params = {}) {
8
- return apiClient.get('/documents', params);
9
+ // Support both 'type' and legacy 'docType' parameter
10
+ const queryParams = {
11
+ ...params,
12
+ type: params.type || params.docType
13
+ };
14
+ // Remove docType to avoid confusion
15
+ delete queryParams.docType;
16
+ return apiClient.get('/documents', queryParams);
9
17
  }
10
18
  /**
11
19
  * Get document by ID
@@ -1,9 +1,18 @@
1
1
  import type { Document, NewDocument } from '../types/index.js';
2
+ export interface PaginationMeta {
3
+ total: number;
4
+ page: number;
5
+ pageSize: number;
6
+ totalPages: number;
7
+ hasNextPage: boolean;
8
+ hasPrevPage: boolean;
9
+ }
2
10
  export interface ApiResponse<T> {
3
11
  success: boolean;
4
12
  data?: T;
5
13
  error?: string;
6
14
  message?: string;
15
+ pagination?: PaginationMeta;
7
16
  meta?: {
8
17
  count: number;
9
18
  limit: number;
@@ -12,12 +21,25 @@ export interface ApiResponse<T> {
12
21
  };
13
22
  }
14
23
  export interface DocumentListParams {
24
+ type?: string;
15
25
  docType?: string;
16
26
  status?: string;
27
+ page?: number;
28
+ pageSize?: number;
17
29
  limit?: number;
18
30
  offset?: number;
31
+ depth?: number;
32
+ sort?: string;
33
+ perspective?: 'draft' | 'published';
34
+ }
35
+ export interface CreateDocumentData {
36
+ type: string;
37
+ data: Record<string, any>;
38
+ publish?: boolean;
39
+ }
40
+ export interface UpdateDocumentData {
41
+ data: Record<string, any>;
42
+ publish?: boolean;
19
43
  }
20
- export type CreateDocumentData = Omit<NewDocument, 'id' | 'createdAt' | 'updatedAt' | 'publishedAt'>;
21
- export type UpdateDocumentData = Partial<Pick<Document, 'draftData' | 'status'>>;
22
44
  export type { Document, NewDocument };
23
45
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/api/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC7B,CAAC;CACF;AAGD,MAAM,WAAW,kBAAkB;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACpC,WAAW,EACX,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,aAAa,CAChD,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC;AAGjF,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/api/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG5D,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACrB;AAGD,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,cAAc,CAAC;IAE5B,IAAI,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC7B,CAAC;CACF;AAGD,MAAM,WAAW,kBAAkB;IAElC,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;CACpC;AAGD,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAGD,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAGD,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"auth-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/auth/auth-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAQ,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,wBAAsB,cAAc,CACnC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,eAAe,GACjB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAuH1B"}
1
+ {"version":3,"file":"auth-hooks.d.ts","sourceRoot":"","sources":["../../src/lib/auth/auth-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAQ,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,wBAAsB,cAAc,CACnC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,SAAS,EACjB,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,eAAe,GACjB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAoI1B"}
@@ -50,11 +50,17 @@ export async function handleAuthHook(event, config, authProvider, db) {
50
50
  // Otherwise, try session (for admin UI making API calls)
51
51
  auth = await authProvider.getSession(event.request, db);
52
52
  }
53
- // Dynamically find the GraphQL endpoint from plugins
53
+ // Check if GraphQL plugin is configured
54
54
  let graphqlEndpoint;
55
- const graphqlPlugin = config.plugins?.find((p) => p.name === '@aphexcms/graphql-plugin');
56
- if (graphqlPlugin && graphqlPlugin.routes) {
57
- graphqlEndpoint = Object.keys(graphqlPlugin.routes)[0];
55
+ const hasGraphQLPlugin = config.plugins?.some((p) => {
56
+ if (typeof p === 'string')
57
+ return p === '@aphexcms/graphql-plugin';
58
+ if (typeof p === 'object')
59
+ return p.name === '@aphexcms/graphql-plugin';
60
+ return false;
61
+ });
62
+ if (hasGraphQLPlugin) {
63
+ graphqlEndpoint = '/api/graphql'; // Standard GraphQL endpoint
58
64
  }
59
65
  // Require authentication for protected API routes
60
66
  const protectedApiRoutes = [
@@ -104,5 +110,13 @@ export async function handleAuthHook(event, config, authProvider, db) {
104
110
  event.locals.auth = auth;
105
111
  }
106
112
  }
113
+ // 4. All other routes - try to populate auth if session exists (optional auth)
114
+ // This allows public pages to detect if user is logged in (like WordPress admin bar)
115
+ if (!event.locals.auth) {
116
+ const auth = await authProvider.getSession(event.request, db);
117
+ if (auth) {
118
+ event.locals.auth = auth;
119
+ }
120
+ }
107
121
  return null; // Tell the main hook to continue
108
122
  }
@@ -0,0 +1,218 @@
1
+ import { isFieldRequired } from '../lib/field-validation/utils.js';
2
+ /**
3
+ * Map Aphex field types to TypeScript types
4
+ */
5
+ function mapFieldTypeToTS(field, schemaMap) {
6
+ switch (field.type) {
7
+ case 'string':
8
+ case 'text':
9
+ case 'slug':
10
+ return 'string';
11
+ case 'number':
12
+ return 'number';
13
+ case 'boolean':
14
+ return 'boolean';
15
+ case 'image':
16
+ // Image fields store reference to asset
17
+ return 'string'; // Asset ID
18
+ case 'array': {
19
+ if (!('of' in field) || !field.of || field.of.length === 0) {
20
+ return 'unknown[]';
21
+ }
22
+ // Union of all possible array item types
23
+ const types = field.of
24
+ .map((ref) => {
25
+ const refSchema = schemaMap.get(ref.type);
26
+ if (refSchema && refSchema.type === 'object') {
27
+ return pascalCase(ref.type);
28
+ }
29
+ return 'unknown';
30
+ })
31
+ .filter((t) => t !== 'unknown');
32
+ if (types.length === 0) {
33
+ return 'unknown[]';
34
+ }
35
+ return types.length === 1 ? `${types[0]}[]` : `Array<${types.join(' | ')}>`;
36
+ }
37
+ case 'object': {
38
+ if (!('fields' in field) || !field.fields) {
39
+ return 'Record<string, unknown>';
40
+ }
41
+ // Generate inline interface for object fields
42
+ const props = field.fields
43
+ .map((f) => {
44
+ const tsType = mapFieldTypeToTS(f, schemaMap);
45
+ const optional = isFieldOptional(f) ? '?' : '';
46
+ return ` ${f.name}${optional}: ${tsType};`;
47
+ })
48
+ .join('\n');
49
+ return `{\n${props}\n}`;
50
+ }
51
+ case 'reference': {
52
+ // References store document ID as string
53
+ return 'string';
54
+ }
55
+ default:
56
+ return 'unknown';
57
+ }
58
+ }
59
+ /**
60
+ * Convert kebab-case or snake_case to PascalCase
61
+ */
62
+ function pascalCase(str) {
63
+ return str
64
+ .split(/[-_]/)
65
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
66
+ .join('');
67
+ }
68
+ /**
69
+ * Determine if a field is optional based on validation rules
70
+ */
71
+ function isFieldOptional(field) {
72
+ return !isFieldRequired(field);
73
+ }
74
+ /**
75
+ * Generate TypeScript interface for a schema type
76
+ */
77
+ function generateInterface(schema, schemaMap) {
78
+ const interfaceName = pascalCase(schema.name);
79
+ const fields = schema.fields
80
+ .map((field) => {
81
+ const tsType = mapFieldTypeToTS(field, schemaMap);
82
+ const optional = isFieldOptional(field) ? '?' : '';
83
+ const comment = field.description ? ` /** ${field.description} */\n` : '';
84
+ return `${comment} ${field.name}${optional}: ${tsType};`;
85
+ })
86
+ .join('\n');
87
+ // Add id and _meta fields for document types
88
+ const isDocument = schema.type === 'document';
89
+ const metadataFields = isDocument
90
+ ? ` /** Document ID */
91
+ id: string;
92
+ ${fields}
93
+ /** Document metadata */
94
+ _meta?: {
95
+ type: string;
96
+ status: 'draft' | 'published';
97
+ organizationId: string;
98
+ createdAt: Date | null;
99
+ updatedAt: Date | null;
100
+ createdBy?: string;
101
+ updatedBy?: string;
102
+ publishedAt?: Date | null;
103
+ publishedHash?: string | null;
104
+ };`
105
+ : fields;
106
+ return `export interface ${interfaceName} {\n${metadataFields}\n}`;
107
+ }
108
+ /**
109
+ * Generate the Collections interface augmentation
110
+ */
111
+ function generateCollectionsAugmentation(documentSchemas) {
112
+ const mappings = documentSchemas
113
+ .map((schema) => {
114
+ const interfaceName = pascalCase(schema.name);
115
+ return ` ${schema.name}: CollectionAPI<${interfaceName}>;`;
116
+ })
117
+ .join('\n');
118
+ return `declare module '@aphexcms/cms-core/server' {
119
+ interface Collections {
120
+ ${mappings}
121
+ }
122
+ }`;
123
+ }
124
+ /**
125
+ * Generate complete TypeScript types file with module augmentation
126
+ */
127
+ export function generateTypes(schemas) {
128
+ // Create schema map for lookups
129
+ const schemaMap = new Map(schemas.map((s) => [s.name, s]));
130
+ // Separate document and object types
131
+ const documentSchemas = schemas.filter((s) => s.type === 'document');
132
+ const objectSchemas = schemas.filter((s) => s.type === 'object');
133
+ // Generate interfaces for all schemas
134
+ const objectInterfaces = objectSchemas.map((s) => generateInterface(s, schemaMap)).join('\n\n');
135
+ const documentInterfaces = documentSchemas.map((s) => generateInterface(s, schemaMap)).join('\n\n');
136
+ // Generate Collections interface augmentation
137
+ const collectionsAugmentation = generateCollectionsAugmentation(documentSchemas);
138
+ // Build the complete file
139
+ const output = `/**
140
+ * Generated types for Aphex CMS
141
+ * This file is auto-generated - DO NOT EDIT manually
142
+ */
143
+ import type { CollectionAPI } from '@aphexcms/cms-core/server';
144
+
145
+ // ============================================================================
146
+ // Object Types (nested in documents)
147
+ // ============================================================================
148
+
149
+ ${objectInterfaces}
150
+
151
+ // ============================================================================
152
+ // Document Types (collections)
153
+ // ============================================================================
154
+
155
+ ${documentInterfaces}
156
+
157
+ // ============================================================================
158
+ // Module Augmentation - Extends Collections interface globally
159
+ // ============================================================================
160
+
161
+ ${collectionsAugmentation}
162
+ `;
163
+ return output;
164
+ }
165
+ /**
166
+ * CLI helper to generate types from schema file
167
+ */
168
+ export async function generateTypesFromConfig(schemaPath, outputPath) {
169
+ try {
170
+ // Resolve paths relative to current working directory
171
+ const path = await import('path');
172
+ const { pathToFileURL } = await import('url');
173
+ const fs = await import('fs/promises');
174
+ const absoluteSchemaPath = path.resolve(process.cwd(), schemaPath);
175
+ const absoluteOutputPath = path.resolve(process.cwd(), outputPath);
176
+ // If the schema file is TypeScript, compile it with esbuild first
177
+ let schemaModulePath = absoluteSchemaPath;
178
+ let tempFile = null;
179
+ if (absoluteSchemaPath.endsWith('.ts')) {
180
+ const { build } = await import('esbuild');
181
+ const tempOutFile = path.join(path.dirname(absoluteSchemaPath), '.temp-schema.mjs');
182
+ await build({
183
+ entryPoints: [absoluteSchemaPath],
184
+ bundle: true,
185
+ format: 'esm',
186
+ platform: 'node',
187
+ outfile: tempOutFile,
188
+ external: ['@aphexcms/*']
189
+ });
190
+ schemaModulePath = tempOutFile;
191
+ tempFile = tempOutFile;
192
+ }
193
+ // Dynamic import the schema types
194
+ // Use file:// URL for proper ESM import
195
+ const schemaModule = await import(pathToFileURL(schemaModulePath).href);
196
+ const schemas = schemaModule.schemaTypes || schemaModule.default;
197
+ // Clean up temp file if created
198
+ if (tempFile) {
199
+ try {
200
+ await fs.unlink(tempFile);
201
+ }
202
+ catch {
203
+ // Ignore cleanup errors
204
+ }
205
+ }
206
+ if (!schemas || !Array.isArray(schemas)) {
207
+ throw new Error('Invalid schema file: expected schemaTypes array export');
208
+ }
209
+ const generatedTypes = generateTypes(schemas);
210
+ // Write to output file
211
+ await fs.writeFile(absoluteOutputPath, generatedTypes, 'utf-8');
212
+ console.log(`✅ Types generated successfully at: ${absoluteOutputPath}`);
213
+ }
214
+ catch (error) {
215
+ console.error('❌ Failed to generate types:', error);
216
+ throw error;
217
+ }
218
+ }
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Aphex CMS CLI
4
+ * Uses cac for command parsing + clack for interactive prompts
5
+ */
6
+ import { intro, outro, spinner, text, cancel, isCancel } from '@clack/prompts';
7
+ import { cac } from 'cac';
8
+ import pc from 'picocolors';
9
+ import { generateTypesFromConfig } from './generate-types.js';
10
+ const cli = cac('aphex');
11
+ // Version from package.json
12
+ const version = '0.1.14';
13
+ // ASCII Art Banner
14
+ function printBanner() {
15
+ console.log(pc.cyan(`${pc.bold('⚡ Aphex CMS')}\n${pc.dim('A modern headless CMS')}`));
16
+ }
17
+ /**
18
+ * aphex generate:types [schema-path] [output-path]
19
+ * Generate TypeScript types from schema
20
+ */
21
+ cli
22
+ .command('generate:types [schema-path] [output-path]', 'Generate TypeScript types from schema')
23
+ .action(async (schemaPath, outputPath) => {
24
+ intro(pc.cyan('⚡ Aphex CMS - Type Generator'));
25
+ try {
26
+ // If paths not provided, prompt for them
27
+ if (!schemaPath) {
28
+ const result = await text({
29
+ message: 'Schema file path:',
30
+ placeholder: './src/lib/schemaTypes/index.ts',
31
+ defaultValue: './src/lib/schemaTypes/index.ts'
32
+ });
33
+ if (isCancel(result)) {
34
+ cancel('Operation cancelled.');
35
+ process.exit(0);
36
+ }
37
+ schemaPath = result;
38
+ }
39
+ if (!outputPath) {
40
+ const result = await text({
41
+ message: 'Output file path:',
42
+ placeholder: './src/lib/generated-types.ts',
43
+ defaultValue: './src/lib/generated-types.ts'
44
+ });
45
+ if (isCancel(result)) {
46
+ cancel('Operation cancelled.');
47
+ process.exit(0);
48
+ }
49
+ outputPath = result;
50
+ }
51
+ const s = spinner();
52
+ s.start('Generating types...');
53
+ await generateTypesFromConfig(schemaPath, outputPath);
54
+ s.stop(pc.green('✅ Types generated successfully!'));
55
+ outro(pc.dim(`Output: ${pc.cyan(outputPath)}`));
56
+ }
57
+ catch (error) {
58
+ cancel(pc.red('Failed to generate types'));
59
+ console.error(error);
60
+ process.exit(1);
61
+ }
62
+ });
63
+ /**
64
+ * aphex help
65
+ */
66
+ cli.help();
67
+ /**
68
+ * aphex --version
69
+ */
70
+ cli.version(version);
71
+ /**
72
+ * Default command - show banner and help
73
+ */
74
+ cli.on('command:*', () => {
75
+ printBanner();
76
+ console.log(pc.red(`Unknown command: ${cli.args.join(' ')}\n`));
77
+ console.log(`Run ${pc.cyan('aphex --help')} to see available commands.`);
78
+ process.exit(1);
79
+ });
80
+ // Parse CLI args
81
+ cli.parse();
82
+ // If no command provided, show banner and help
83
+ if (!process.argv.slice(2).length) {
84
+ printBanner();
85
+ cli.outputHelp();
86
+ }
@@ -574,29 +574,32 @@
574
574
  const previewConfig = schema?.preview;
575
575
 
576
576
  documentsList = result.data.map((doc: any) => {
577
- const docData = doc.draftData || doc.publishedData || {};
577
+ // With LocalAPI, data is already flattened at top level (not in draftData)
578
+ // The document itself IS the data, with _meta containing metadata
578
579
 
579
580
  // Use preview config if available
580
581
  const title = previewConfig?.select?.title
581
- ? docData[previewConfig.select.title] || `Untitled`
582
- : docData.title || `Untitled`;
582
+ ? doc[previewConfig.select.title] || `Untitled`
583
+ : doc.title || `Untitled`;
583
584
 
584
585
  const subtitle = previewConfig?.select?.subtitle
585
- ? docData[previewConfig.select.subtitle]
586
+ ? doc[previewConfig.select.subtitle]
586
587
  : undefined;
587
588
 
589
+ // Metadata is in _meta field (from LocalAPI transformation)
590
+ const meta = doc._meta || {};
591
+
588
592
  return {
589
593
  id: doc.id,
590
594
  title,
591
595
  subtitle,
592
- status: doc.status,
593
- publishedAt: doc.publishedAt ? new Date(doc.publishedAt) : null,
594
- updatedAt: doc.updatedAt ? new Date(doc.updatedAt) : null,
595
- createdAt: doc.createdAt ? new Date(doc.createdAt) : null,
596
- hasChanges:
597
- doc.status === 'published' &&
598
- doc.draftData !== null &&
599
- JSON.stringify(doc.draftData) !== JSON.stringify(doc.publishedData)
596
+ status: meta.status || 'draft',
597
+ publishedAt: meta.publishedAt ? new Date(meta.publishedAt) : null,
598
+ updatedAt: meta.updatedAt ? new Date(meta.updatedAt) : null,
599
+ createdAt: meta.createdAt ? new Date(meta.createdAt) : null,
600
+ // hasChanges is tracked via publishedHash comparison
601
+ // If publishedHash is null, it's never been published or has unpublished changes
602
+ hasChanges: meta.status === 'published' && meta.publishedHash === null
600
603
  };
601
604
  });
602
605
  } else {
@@ -1 +1 @@
1
- {"version":3,"file":"AdminApp.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AdminApp.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAShD,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAA;KAAE,CAAC;IAC9C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAg8BF,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"AdminApp.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AdminApp.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAShD,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAA;KAAE,CAAC;IAC9C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAm8BF,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -73,7 +73,7 @@
73
73
 
74
74
  // Hash-based state tracking
75
75
  const hasUnpublishedContent = $derived(
76
- hasUnpublishedChanges(documentData, fullDocument?.publishedHash || null)
76
+ hasUnpublishedChanges(documentData, fullDocument?._meta?.publishedHash || null)
77
77
  );
78
78
  const canPublish = $derived(
79
79
  hasUnpublishedContent && !saving && documentId && !hasValidationErrors
@@ -198,15 +198,20 @@
198
198
  // Store full document for hash comparison
199
199
  fullDocument = response.data;
200
200
 
201
- // Load the draft data if available, otherwise published data
202
- const data = response.data.draftData || response.data.publishedData || {};
203
- console.log('📄 Loaded document data:', data);
204
- console.log('📄 Published hash:', response.data.publishedHash);
201
+ // With LocalAPI, data is flattened at top level (not in draftData)
202
+ // Extract all fields except id and _meta
203
+ const { id, _meta, ...data } = response.data;
204
+ console.log('📄 Full response.data:', response.data);
205
+ console.log('📄 Extracted data (after destructuring):', data);
206
+ console.log('📄 Keys in extracted data:', Object.keys(data));
207
+ console.log('📄 Published hash:', _meta?.publishedHash);
205
208
 
206
209
  documentData = { ...data };
210
+ console.log('📄 documentData after assignment:', documentData);
211
+ console.log('📄 Keys in documentData:', Object.keys(documentData));
207
212
  hasUnsavedChanges = false; // Just loaded, so no unsaved changes
208
213
  } else {
209
- console.error('❌ Failed to load document data:', response.error);
214
+ console.log('❌ Failed to load document data:', response.error);
210
215
  saveError = response.error || 'Failed to load document';
211
216
  }
212
217
  } catch (err) {
@@ -249,13 +254,47 @@
249
254
  });
250
255
  }
251
256
 
257
+ // Check if current data differs from last saved draft
258
+ function hasChangesFromSaved(): boolean {
259
+ if (!fullDocument) return true; // No saved version = has changes
260
+
261
+ // Extract saved draft data from fullDocument (same as we do in loadDocumentData)
262
+ const { id, _meta, ...savedData } = fullDocument;
263
+
264
+ // Compare current documentData with saved data using stable JSON
265
+ const currentJson = JSON.stringify(sortObjectForComparison(documentData));
266
+ const savedJson = JSON.stringify(sortObjectForComparison(savedData));
267
+
268
+ return currentJson !== savedJson;
269
+ }
270
+
271
+ // Helper to recursively sort object keys for stable comparison
272
+ function sortObjectForComparison(item: any): any {
273
+ if (item === null || typeof item !== 'object') return item;
274
+
275
+ if (Array.isArray(item)) {
276
+ return item.map(sortObjectForComparison);
277
+ }
278
+
279
+ const sortedKeys = Object.keys(item).sort();
280
+ const sortedObj: any = {};
281
+ for (const key of sortedKeys) {
282
+ sortedObj[key] = sortObjectForComparison(item[key]);
283
+ }
284
+ return sortedObj;
285
+ }
286
+
252
287
  // Watch for changes to trigger auto-save (debounced)
253
288
  $effect(() => {
254
289
  const hasContent = hasMeaningfulContent(documentData);
290
+ const hasChanges = hasChangesFromSaved();
255
291
 
256
- // Only set hasUnsavedChanges if we actually have meaningful data
257
- if (hasContent) {
292
+ // Only set hasUnsavedChanges if we actually have meaningful data AND it differs from saved
293
+ if (hasContent && hasChanges) {
258
294
  hasUnsavedChanges = true;
295
+ } else if (!hasChanges) {
296
+ // If there are no changes from saved, mark as not having unsaved changes
297
+ hasUnsavedChanges = false;
259
298
  }
260
299
 
261
300
  if (autoSaveTimer) {
@@ -263,12 +302,14 @@
263
302
  }
264
303
 
265
304
  // Debounced auto-save - waits for 800ms pause in typing (like Notion/modern apps)
266
- // Only auto-save if there's meaningful content and not in read-only mode
267
- if (hasContent && schema && !isReadOnly) {
305
+ // Only auto-save if there's meaningful content, data has changed, and not in read-only mode
306
+ if (hasContent && hasChanges && schema && !isReadOnly) {
268
307
  autoSaveTimer = setTimeout(() => {
269
- console.log('🔄 Auto-saving after typing pause...', { documentId });
308
+ console.log('🔄 Auto-saving after typing pause (data changed)...', { documentId });
270
309
  saveDocument(true); // auto-save
271
310
  }, 1200); // Shorter delay - saves faster but still waits for typing pauses
311
+ } else if (!hasChanges) {
312
+ console.log('⏭️ Skipping auto-save - no changes from saved data');
272
313
  }
273
314
 
274
315
  return () => {
@@ -292,11 +333,11 @@
292
333
  // Create new document
293
334
  console.log('🔄 Creating new document with data:', {
294
335
  type: documentType,
295
- draftData: documentData
336
+ data: documentData
296
337
  });
297
338
  response = await documents.create({
298
339
  type: documentType,
299
- draftData: documentData
340
+ data: documentData
300
341
  });
301
342
 
302
343
  console.log('📝 Document creation response:', response);
@@ -315,8 +356,13 @@
315
356
  } else if (documentId) {
316
357
  // Update existing document
317
358
  response = await documents.updateById(documentId, {
318
- draftData: documentData
359
+ data: documentData
319
360
  });
361
+
362
+ // Update fullDocument with the response to keep saved data in sync
363
+ if (response?.success && response.data) {
364
+ fullDocument = response.data;
365
+ }
320
366
  }
321
367
 
322
368
  if (response?.success) {
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/admin/DocumentEditor.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAM1D,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAwsBF,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"DocumentEditor.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/admin/DocumentEditor.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAM1D,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAsvBF,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}