@aphexcms/cms-core 8.0.0 → 9.0.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.
Files changed (205) hide show
  1. package/dist/api/api-keys.d.ts +8 -3
  2. package/dist/api/api-keys.d.ts.map +1 -1
  3. package/dist/api/schemas/assets.js +1 -1
  4. package/dist/api/schemas/documents.d.ts +0 -2
  5. package/dist/api/schemas/documents.d.ts.map +1 -1
  6. package/dist/api/schemas/documents.js +2 -8
  7. package/dist/api/schemas/instance.d.ts +6 -0
  8. package/dist/api/schemas/instance.d.ts.map +1 -0
  9. package/dist/api/schemas/instance.js +7 -0
  10. package/dist/api/schemas/user.js +1 -1
  11. package/dist/auth/auth-hooks.d.ts.map +1 -1
  12. package/dist/auth/auth-hooks.js +9 -3
  13. package/dist/cli/generate-types.d.ts.map +1 -1
  14. package/dist/cli/generate-types.js +1 -3
  15. package/dist/cli/generate-types.js.map +1 -1
  16. package/dist/components/AdminApp.svelte +43 -19
  17. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  18. package/dist/components/admin/DocumentEditor.svelte +47 -49
  19. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  20. package/dist/components/admin/MediaBrowser.svelte +7 -7
  21. package/dist/components/admin/fields/ArrayField.svelte +4 -2
  22. package/dist/components/admin/fields/FileField.svelte +1 -1
  23. package/dist/components/admin/fields/ImageField.svelte +1 -1
  24. package/dist/components/admin/fields/ReferenceField.svelte +5 -3
  25. package/dist/components/layout/OrganizationSwitcher.svelte +1 -1
  26. package/dist/components/layout/sidebar/NavMain.svelte +9 -1
  27. package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -1
  28. package/dist/db/interfaces/asset.d.ts +2 -4
  29. package/dist/db/interfaces/asset.d.ts.map +1 -1
  30. package/dist/db/interfaces/organization.d.ts +1 -1
  31. package/dist/db/interfaces/organization.d.ts.map +1 -1
  32. package/dist/field-access.d.ts.map +1 -1
  33. package/dist/field-access.js +5 -1
  34. package/dist/graphql/depth-limit.d.ts +8 -0
  35. package/dist/graphql/depth-limit.d.ts.map +1 -0
  36. package/dist/graphql/depth-limit.js +79 -0
  37. package/dist/graphql/index.d.ts.map +1 -1
  38. package/dist/graphql/index.js +12 -1
  39. package/dist/graphql/resolvers.d.ts.map +1 -1
  40. package/dist/graphql/resolvers.js +9 -11
  41. package/dist/hooks.d.ts +2 -0
  42. package/dist/hooks.d.ts.map +1 -1
  43. package/dist/hooks.js +5 -2
  44. package/dist/lib/api/api-keys.d.ts +8 -3
  45. package/dist/lib/api/api-keys.d.ts.map +1 -1
  46. package/dist/lib/api/api-keys.js.map +1 -1
  47. package/dist/lib/api/schemas/assets.js +1 -1
  48. package/dist/lib/api/schemas/assets.js.map +1 -1
  49. package/dist/lib/api/schemas/documents.d.ts +0 -2
  50. package/dist/lib/api/schemas/documents.d.ts.map +1 -1
  51. package/dist/lib/api/schemas/documents.js +2 -8
  52. package/dist/lib/api/schemas/documents.js.map +1 -1
  53. package/dist/lib/api/schemas/instance.d.ts +6 -0
  54. package/dist/lib/api/schemas/instance.d.ts.map +1 -0
  55. package/dist/lib/api/schemas/instance.js +8 -0
  56. package/dist/lib/api/schemas/instance.js.map +1 -0
  57. package/dist/lib/api/schemas/user.js +1 -1
  58. package/dist/lib/auth/auth-hooks.d.ts.map +1 -1
  59. package/dist/lib/auth/auth-hooks.js +9 -3
  60. package/dist/lib/auth/auth-hooks.js.map +1 -1
  61. package/dist/lib/db/interfaces/asset.d.ts +2 -4
  62. package/dist/lib/db/interfaces/asset.d.ts.map +1 -1
  63. package/dist/lib/db/interfaces/organization.d.ts +1 -1
  64. package/dist/lib/db/interfaces/organization.d.ts.map +1 -1
  65. package/dist/lib/field-access.d.ts.map +1 -1
  66. package/dist/lib/field-access.js +5 -1
  67. package/dist/lib/field-access.js.map +1 -1
  68. package/dist/lib/graphql/depth-limit.d.ts +8 -0
  69. package/dist/lib/graphql/depth-limit.d.ts.map +1 -0
  70. package/dist/lib/graphql/depth-limit.js +80 -0
  71. package/dist/lib/graphql/depth-limit.js.map +1 -0
  72. package/dist/lib/graphql/index.d.ts.map +1 -1
  73. package/dist/lib/graphql/index.js +12 -1
  74. package/dist/lib/graphql/index.js.map +1 -1
  75. package/dist/lib/graphql/resolvers.d.ts.map +1 -1
  76. package/dist/lib/graphql/resolvers.js +9 -11
  77. package/dist/lib/graphql/resolvers.js.map +1 -1
  78. package/dist/lib/hooks.d.ts +2 -0
  79. package/dist/lib/hooks.d.ts.map +1 -1
  80. package/dist/lib/hooks.js +5 -2
  81. package/dist/lib/hooks.js.map +1 -1
  82. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  83. package/dist/lib/local-api/collection-api.js +7 -9
  84. package/dist/lib/local-api/collection-api.js.map +1 -1
  85. package/dist/lib/local-api/index.d.ts +5 -1
  86. package/dist/lib/local-api/index.d.ts.map +1 -1
  87. package/dist/lib/local-api/index.js +12 -4
  88. package/dist/lib/local-api/index.js.map +1 -1
  89. package/dist/lib/routes/assets-cdn.d.ts.map +1 -1
  90. package/dist/lib/routes/assets-cdn.js +8 -3
  91. package/dist/lib/routes/assets-cdn.js.map +1 -1
  92. package/dist/lib/server/api/index.d.ts.map +1 -1
  93. package/dist/lib/server/api/index.js +18 -0
  94. package/dist/lib/server/api/index.js.map +1 -1
  95. package/dist/lib/server/api/routes/assets-bulk.d.ts.map +1 -1
  96. package/dist/lib/server/api/routes/assets-bulk.js +4 -0
  97. package/dist/lib/server/api/routes/assets-bulk.js.map +1 -1
  98. package/dist/lib/server/api/routes/assets-by-id.d.ts.map +1 -1
  99. package/dist/lib/server/api/routes/assets-by-id.js +7 -0
  100. package/dist/lib/server/api/routes/assets-by-id.js.map +1 -1
  101. package/dist/lib/server/api/routes/assets.d.ts.map +1 -1
  102. package/dist/lib/server/api/routes/assets.js +18 -9
  103. package/dist/lib/server/api/routes/assets.js.map +1 -1
  104. package/dist/lib/server/api/routes/document-versions.d.ts.map +1 -1
  105. package/dist/lib/server/api/routes/document-versions.js +8 -0
  106. package/dist/lib/server/api/routes/document-versions.js.map +1 -1
  107. package/dist/lib/server/api/routes/documents-by-id.d.ts.map +1 -1
  108. package/dist/lib/server/api/routes/documents-by-id.js +3 -3
  109. package/dist/lib/server/api/routes/documents-by-id.js.map +1 -1
  110. package/dist/lib/server/api/routes/documents-publish.d.ts.map +1 -1
  111. package/dist/lib/server/api/routes/documents-publish.js +2 -2
  112. package/dist/lib/server/api/routes/documents-publish.js.map +1 -1
  113. package/dist/lib/server/api/routes/documents-query.d.ts.map +1 -1
  114. package/dist/lib/server/api/routes/documents-query.js +2 -3
  115. package/dist/lib/server/api/routes/documents-query.js.map +1 -1
  116. package/dist/lib/server/api/routes/documents.d.ts.map +1 -1
  117. package/dist/lib/server/api/routes/documents.js +3 -5
  118. package/dist/lib/server/api/routes/documents.js.map +1 -1
  119. package/dist/lib/server/api/routes/organizations-invitations.d.ts.map +1 -1
  120. package/dist/lib/server/api/routes/organizations-invitations.js +1 -1
  121. package/dist/lib/server/api/routes/organizations-invitations.js.map +1 -1
  122. package/dist/lib/server/api/routes/organizations-members.d.ts.map +1 -1
  123. package/dist/lib/server/api/routes/organizations-members.js.map +1 -1
  124. package/dist/lib/server/index.d.ts +1 -0
  125. package/dist/lib/server/index.d.ts.map +1 -1
  126. package/dist/lib/server/index.js +2 -0
  127. package/dist/lib/server/index.js.map +1 -1
  128. package/dist/lib/services/asset-service.d.ts.map +1 -1
  129. package/dist/lib/services/asset-service.js +4 -2
  130. package/dist/lib/services/asset-service.js.map +1 -1
  131. package/dist/lib/services/references-service.d.ts.map +1 -1
  132. package/dist/lib/services/references-service.js.map +1 -1
  133. package/dist/lib/storage/adapters/local-storage-adapter.d.ts +4 -0
  134. package/dist/lib/storage/adapters/local-storage-adapter.d.ts.map +1 -1
  135. package/dist/lib/storage/adapters/local-storage-adapter.js +28 -6
  136. package/dist/lib/storage/adapters/local-storage-adapter.js.map +1 -1
  137. package/dist/lib/types/capabilities.d.ts +1 -0
  138. package/dist/lib/types/capabilities.d.ts.map +1 -1
  139. package/dist/lib/types/capabilities.js +3 -0
  140. package/dist/lib/types/capabilities.js.map +1 -1
  141. package/dist/lib/types/config.d.ts +16 -1
  142. package/dist/lib/types/config.d.ts.map +1 -1
  143. package/dist/lib/utils/logger.d.ts +8 -6
  144. package/dist/lib/utils/logger.d.ts.map +1 -1
  145. package/dist/lib/utils/logger.js +11 -2
  146. package/dist/lib/utils/logger.js.map +1 -1
  147. package/dist/lib/utils/mime-detect.d.ts.map +1 -1
  148. package/dist/lib/utils/mime-detect.js +21 -6
  149. package/dist/lib/utils/mime-detect.js.map +1 -1
  150. package/dist/lib/utils/reference-walk.js +4 -0
  151. package/dist/lib/utils/reference-walk.js.map +1 -1
  152. package/dist/lib/vite/index.d.ts.map +1 -1
  153. package/dist/lib/vite/index.js +4 -5
  154. package/dist/lib/vite/index.js.map +1 -1
  155. package/dist/local-api/collection-api.d.ts.map +1 -1
  156. package/dist/local-api/collection-api.js +7 -9
  157. package/dist/local-api/index.d.ts +5 -1
  158. package/dist/local-api/index.d.ts.map +1 -1
  159. package/dist/local-api/index.js +12 -4
  160. package/dist/routes/assets-cdn.d.ts.map +1 -1
  161. package/dist/routes/assets-cdn.js +8 -3
  162. package/dist/server/api/index.d.ts.map +1 -1
  163. package/dist/server/api/index.js +18 -0
  164. package/dist/server/api/routes/assets-bulk.d.ts.map +1 -1
  165. package/dist/server/api/routes/assets-bulk.js +4 -0
  166. package/dist/server/api/routes/assets-by-id.d.ts.map +1 -1
  167. package/dist/server/api/routes/assets-by-id.js +7 -0
  168. package/dist/server/api/routes/assets.d.ts.map +1 -1
  169. package/dist/server/api/routes/assets.js +18 -9
  170. package/dist/server/api/routes/document-versions.d.ts.map +1 -1
  171. package/dist/server/api/routes/document-versions.js +8 -0
  172. package/dist/server/api/routes/documents-by-id.d.ts.map +1 -1
  173. package/dist/server/api/routes/documents-by-id.js +3 -3
  174. package/dist/server/api/routes/documents-publish.d.ts.map +1 -1
  175. package/dist/server/api/routes/documents-publish.js +2 -2
  176. package/dist/server/api/routes/documents-query.d.ts.map +1 -1
  177. package/dist/server/api/routes/documents-query.js +2 -3
  178. package/dist/server/api/routes/documents.d.ts.map +1 -1
  179. package/dist/server/api/routes/documents.js +3 -5
  180. package/dist/server/api/routes/organizations-invitations.d.ts.map +1 -1
  181. package/dist/server/api/routes/organizations-invitations.js +1 -1
  182. package/dist/server/api/routes/organizations-members.d.ts.map +1 -1
  183. package/dist/server/index.d.ts +1 -0
  184. package/dist/server/index.d.ts.map +1 -1
  185. package/dist/server/index.js +2 -0
  186. package/dist/services/asset-service.d.ts.map +1 -1
  187. package/dist/services/asset-service.js +4 -2
  188. package/dist/services/references-service.d.ts.map +1 -1
  189. package/dist/storage/adapters/local-storage-adapter.d.ts +4 -0
  190. package/dist/storage/adapters/local-storage-adapter.d.ts.map +1 -1
  191. package/dist/storage/adapters/local-storage-adapter.js +28 -6
  192. package/dist/types/capabilities.d.ts +1 -0
  193. package/dist/types/capabilities.d.ts.map +1 -1
  194. package/dist/types/capabilities.js +3 -0
  195. package/dist/types/config.d.ts +16 -1
  196. package/dist/types/config.d.ts.map +1 -1
  197. package/dist/utils/logger.d.ts +8 -6
  198. package/dist/utils/logger.d.ts.map +1 -1
  199. package/dist/utils/logger.js +11 -2
  200. package/dist/utils/mime-detect.d.ts.map +1 -1
  201. package/dist/utils/mime-detect.js +21 -6
  202. package/dist/utils/reference-walk.js +4 -0
  203. package/dist/vite/index.d.ts.map +1 -1
  204. package/dist/vite/index.js +4 -5
  205. package/package.json +4 -5
@@ -162,7 +162,10 @@ export class CollectionAPI {
162
162
  // callers always get one document back. Filters are intentionally
163
163
  // ignored — there is at most one row by definition.
164
164
  if (this._schema.singleton) {
165
- const doc = await this.get(context, { perspective: options.perspective, depth: options.depth });
165
+ const doc = await this.get(context, {
166
+ perspective: options.perspective,
167
+ depth: options.depth
168
+ });
166
169
  return {
167
170
  docs: [doc],
168
171
  totalDocs: 1,
@@ -459,8 +462,7 @@ export class CollectionAPI {
459
462
  // Protect the canonical singleton row. In-limbo random-uuid docs of
460
463
  // the same type (left over from before the schema was flipped to
461
464
  // singleton) remain deletable — only the deterministic id is locked.
462
- if (this._schema.singleton &&
463
- id === singletonId(this._schema.name, context.organizationId)) {
465
+ if (this._schema.singleton && id === singletonId(this._schema.name, context.organizationId)) {
464
466
  throw new SingletonOperationError(`Cannot delete the singleton document for '${this._schema.name}'. Remove the singleton flag from the schema first.`);
465
467
  }
466
468
  // Fetch the target so ownership policies have a doc to inspect. For
@@ -513,16 +515,12 @@ export class CollectionAPI {
513
515
  const refDoc = await this.databaseAdapter.findByDocIdAdvanced(context.organizationId, refId);
514
516
  if (refDoc && !refDoc.publishedData) {
515
517
  const data = refDoc.draftData;
516
- const title = data?.title ||
517
- data?.name ||
518
- refDoc.id;
518
+ const title = data?.title || data?.name || refDoc.id;
519
519
  unpublished.push({ id: refDoc.id, type: refDoc.type, title });
520
520
  }
521
521
  }
522
522
  if (unpublished.length > 0) {
523
- const names = unpublished
524
- .map((d) => `"${d.title}" (${d.type})`)
525
- .join(', ');
523
+ const names = unpublished.map((d) => `"${d.title}" (${d.type})`).join(', ');
526
524
  throw new Error(`Cannot publish — ${unpublished.length} referenced document(s) are not published: ${names}`);
527
525
  }
528
526
  }
@@ -11,7 +11,6 @@ import type { LocalAPIContext } from './types.js';
11
11
  * This interface is meant to be augmented by generated types
12
12
  */
13
13
  export interface Collections {
14
- [collectionName: string]: CollectionAPI<unknown>;
15
14
  }
16
15
  /**
17
16
  * Local API - provides a unified, type-safe interface for all CMS operations
@@ -46,6 +45,7 @@ export interface Collections {
46
45
  export declare class LocalAPI {
47
46
  private config;
48
47
  collections: Collections;
48
+ private _collections;
49
49
  private userAdapter;
50
50
  private systemAdapter;
51
51
  private documentCache;
@@ -72,6 +72,10 @@ export declare class LocalAPI {
72
72
  * Check if a collection exists
73
73
  */
74
74
  hasCollection(name: string): boolean;
75
+ /**
76
+ * Get a collection by name (for dynamic access in route handlers and resolvers)
77
+ */
78
+ getCollection(name: string): CollectionAPI<unknown> | undefined;
75
79
  /**
76
80
  * Get schema for a collection
77
81
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/local-api/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/local-api/index.ts"],"names":[],"mappings":"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"}
@@ -49,6 +49,7 @@ import { PermissionChecker } from './permissions.js';
49
49
  export class LocalAPI {
50
50
  config;
51
51
  collections = {};
52
+ _collections = new Map();
52
53
  userAdapter;
53
54
  systemAdapter;
54
55
  documentCache;
@@ -90,8 +91,7 @@ export class LocalAPI {
90
91
  // wrapper. They don't touch the database, so wrapping
91
92
  // would force callers to `await` what is actually a
92
93
  // synchronous compute (and break their return types).
93
- if (typeof method === 'function' &&
94
- SYNC_COLLECTION_METHODS.has(prop)) {
94
+ if (typeof method === 'function' && SYNC_COLLECTION_METHODS.has(prop)) {
95
95
  return method.bind(target);
96
96
  }
97
97
  if (typeof method === 'function') {
@@ -108,7 +108,9 @@ export class LocalAPI {
108
108
  return method;
109
109
  }
110
110
  });
111
- this.collections[schema.name] = collectionAPI;
111
+ this._collections.set(schema.name, collectionAPI);
112
+ this.collections[schema.name] =
113
+ collectionAPI;
112
114
  }
113
115
  }
114
116
  /**
@@ -133,6 +135,12 @@ export class LocalAPI {
133
135
  hasCollection(name) {
134
136
  return this.schemas.has(name);
135
137
  }
138
+ /**
139
+ * Get a collection by name (for dynamic access in route handlers and resolvers)
140
+ */
141
+ getCollection(name) {
142
+ return this._collections.get(name);
143
+ }
136
144
  /**
137
145
  * Get schema for a collection
138
146
  */
@@ -202,7 +210,7 @@ export class LocalAPI {
202
210
  const docs = await Promise.all(typeLookups.map(async (lookup) => {
203
211
  if (!lookup)
204
212
  return null;
205
- const collection = this.collections[lookup.type];
213
+ const collection = this.getCollection(lookup.type);
206
214
  if (!collection)
207
215
  return null;
208
216
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"assets-cdn.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-cdn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,eAAO,MAAM,GAAG,EAAE,cAkKjB,CAAC"}
1
+ {"version":3,"file":"assets-cdn.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-cdn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,eAAO,MAAM,GAAG,EAAE,cAyKjB,CAAC"}
@@ -116,12 +116,17 @@ export const GET = async ({ params, locals, setHeaders, request }) => {
116
116
  .replace(/[^\x20-\x7E]/g, '_') // strip anything outside printable ASCII
117
117
  .replace(/["\\]/g, ''); // drop quotes and backslashes that'd break the quoted-string
118
118
  const utf8Encoded = encodeURIComponent(rawFilename);
119
- // Set appropriate headers for the asset
119
+ const safeInlineTypes = ['image/', 'application/pdf', 'video/', 'audio/'];
120
+ const canInline = asset.mimeType &&
121
+ asset.mimeType !== 'image/svg+xml' &&
122
+ safeInlineTypes.some((t) => asset.mimeType.startsWith(t));
123
+ const disposition = canInline ? 'inline' : 'attachment';
120
124
  setHeaders({
121
125
  'Content-Type': asset.mimeType || 'application/octet-stream',
122
126
  'Content-Length': fileBuffer.length.toString(),
123
- 'Cache-Control': 'public, max-age=31536000, immutable', // Cache for 1 year
124
- 'Content-Disposition': `inline; filename="${asciiFallback}"; filename*=UTF-8''${utf8Encoded}`,
127
+ 'Cache-Control': 'public, max-age=31536000, immutable',
128
+ 'Content-Disposition': `${disposition}; filename="${asciiFallback}"; filename*=UTF-8''${utf8Encoded}`,
129
+ 'X-Content-Type-Options': 'nosniff',
125
130
  ...(asset.mimeType?.startsWith('image/') && {
126
131
  'Accept-Ranges': 'bytes'
127
132
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/server/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAoB7C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB,SAAS,EAAE;QACV,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE;QACT,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;KAClB,CAAC;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,kGAY7B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAsCrD;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC5B,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,IAEzC,GAAG,OAAO,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,uBAejD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/server/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAoB7C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB,SAAS,EAAE;QACV,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;KAClB,CAAC;IACF,QAAQ,EAAE;QACT,QAAQ,EAAE,YAAY,CAAC;QACvB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;KAClB,CAAC;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,kGAqB7B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAkDrD;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,IACtE,GAAG,OAAO,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,uBAejD"}
@@ -1,4 +1,5 @@
1
1
  import { Hono } from 'hono';
2
+ import { bodyLimit } from 'hono/body-limit';
2
3
  import { schemasRouter } from './routes/schemas.js';
3
4
  import { documentsRouter } from './routes/documents.js';
4
5
  import { documentsByIdRouter } from './routes/documents-by-id.js';
@@ -27,6 +28,11 @@ import { userRouter } from './routes/user.js';
27
28
  */
28
29
  export function createAphexApi() {
29
30
  const app = new Hono().basePath('/api');
31
+ // Reject oversized request bodies before they're fully buffered.
32
+ app.use('*', bodyLimit({
33
+ maxSize: 10 * 1024 * 1024, // 10MB for JSON endpoints
34
+ onError: (c) => c.json({ success: false, error: 'Request body too large (max 10MB)' }, 413)
35
+ }));
30
36
  // Bridge: lift values passed via app.fetch(req, env) onto c.var so
31
37
  // handlers can read c.var.aphexCMS / c.var.auth directly.
32
38
  app.use('*', async (c, next) => {
@@ -77,6 +83,18 @@ export function mountAphexBuiltins(app) {
77
83
  // Hono would try to match them under the wrong handler chain.
78
84
  app.route('/user', userPreferencesRouter);
79
85
  app.route('/user', userRouter);
86
+ // Health check — unauthenticated, used by load balancers and uptime monitors.
87
+ app.get('/aphex-health', async (c) => {
88
+ try {
89
+ const { databaseAdapter } = c.var.aphexCMS;
90
+ const dbHealthy = await databaseAdapter.isHealthy();
91
+ const status = dbHealthy ? 'healthy' : 'degraded';
92
+ return c.json({ status, database: dbHealthy }, dbHealthy ? 200 : 503);
93
+ }
94
+ catch {
95
+ return c.json({ status: 'unhealthy', database: false }, 503);
96
+ }
97
+ });
80
98
  }
81
99
  /**
82
100
  * Adapter: wrap a SvelteKit-style `RequestHandler` so it can be mounted
@@ -1 +1 @@
1
- {"version":3,"file":"assets-bulk.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets-bulk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAkE3C,CAAC"}
1
+ {"version":3,"file":"assets-bulk.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets-bulk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAyE3C,CAAC"}
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import { zValidator } from '@hono/zod-validator';
3
3
  import { cmsLogger } from '../../../utils/logger.js';
4
4
  import { bulkDeleteAssetsRequest } from '../../../api/schemas/assets.js';
5
+ import { hasCapability } from '../../../types/capabilities.js';
5
6
  export const assetsBulkRouter = new Hono().delete('/bulk', zValidator('json', bulkDeleteAssetsRequest, (result, c) => {
6
7
  if (!result.success) {
7
8
  return c.json({
@@ -17,6 +18,9 @@ export const assetsBulkRouter = new Hono().delete('/bulk', zValidator('json', bu
17
18
  if (!auth || auth.type === 'partial_session') {
18
19
  return c.json({ success: false, error: 'Unauthorized' }, 401);
19
20
  }
21
+ if (!hasCapability(auth, 'asset.delete')) {
22
+ return c.json({ success: false, error: 'Forbidden: asset.delete capability required' }, 403);
23
+ }
20
24
  const { ids } = c.req.valid('json');
21
25
  let referencedIds = [];
22
26
  if (databaseAdapter.countDocumentReferencesForAssets) {
@@ -1 +1 @@
1
- {"version":3,"file":"assets-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CA8HzC,CAAC"}
1
+ {"version":3,"file":"assets-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CA0I1C,CAAC"}
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import { zValidator } from '@hono/zod-validator';
3
3
  import { cmsLogger } from '../../../utils/logger.js';
4
4
  import { updateAssetRequest } from '../../../api/schemas/assets.js';
5
+ import { hasCapability } from '../../../types/capabilities.js';
5
6
  export const assetsByIdRouter = new Hono()
6
7
  .get('/:id', async (c) => {
7
8
  try {
@@ -33,6 +34,9 @@ export const assetsByIdRouter = new Hono()
33
34
  if (!auth || auth.type === 'partial_session') {
34
35
  return c.json({ success: false, error: 'Unauthorized' }, 401);
35
36
  }
37
+ if (!hasCapability(auth, 'asset.delete')) {
38
+ return c.json({ success: false, error: 'Forbidden: asset.delete capability required' }, 403);
39
+ }
36
40
  if (!id) {
37
41
  return c.json({ success: false, error: 'Asset ID is required' }, 400);
38
42
  }
@@ -72,6 +76,9 @@ export const assetsByIdRouter = new Hono()
72
76
  if (!auth || auth.type === 'partial_session') {
73
77
  return c.json({ success: false, error: 'Unauthorized' }, 401);
74
78
  }
79
+ if (!hasCapability(auth, 'asset.upload')) {
80
+ return c.json({ success: false, error: 'Forbidden: asset.upload capability required' }, 403);
81
+ }
75
82
  if (!id) {
76
83
  return c.json({ success: false, error: 'Asset ID is required' }, 400);
77
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,QAAQ,CA+IrC,CAAC"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,IAAI,CAAC,QAAQ,CA8JrC,CAAC"}
@@ -3,6 +3,7 @@ import { zValidator } from '@hono/zod-validator';
3
3
  import { cmsLogger } from '../../../utils/logger.js';
4
4
  import { validateFile } from '../../../utils/mime-detect.js';
5
5
  import { listAssetsQuery } from '../../../api/schemas/assets.js';
6
+ import { hasCapability } from '../../../types/capabilities.js';
6
7
  export const assetsRouter = new Hono()
7
8
  .get('/', zValidator('query', listAssetsQuery, (result, c) => {
8
9
  if (!result.success) {
@@ -27,15 +28,15 @@ export const assetsRouter = new Hono()
27
28
  limit: q.limit ?? 20,
28
29
  offset: q.offset ?? 0
29
30
  };
30
- const [fetchedAssets, totalAssets] = await Promise.all([
31
+ const { databaseAdapter } = c.var.aphexCMS;
32
+ const [fetchedAssets, total] = await Promise.all([
31
33
  assetService.findAssets(auth.organizationId, filters),
32
- assetService.findAssets(auth.organizationId, {
33
- ...filters,
34
- limit: 999999,
35
- offset: 0
34
+ databaseAdapter.countAssets(auth.organizationId, {
35
+ assetType: filters.assetType,
36
+ mimeType: filters.mimeType,
37
+ search: filters.search
36
38
  })
37
39
  ]);
38
- const total = totalAssets.length;
39
40
  const pageSize = filters.limit || 20;
40
41
  const currentPage = Math.floor(filters.offset / pageSize) + 1;
41
42
  const totalPages = Math.ceil(total / pageSize);
@@ -68,6 +69,9 @@ export const assetsRouter = new Hono()
68
69
  if (!auth || auth.type === 'partial_session') {
69
70
  return c.json({ success: false, error: 'Unauthorized' }, 401);
70
71
  }
72
+ if (!hasCapability(auth, 'asset.upload')) {
73
+ return c.json({ success: false, error: 'Forbidden: asset.upload capability required' }, 403);
74
+ }
71
75
  const formData = await c.req.formData();
72
76
  const file = formData.get('file');
73
77
  if (!file) {
@@ -75,10 +79,14 @@ export const assetsRouter = new Hono()
75
79
  }
76
80
  const arrayBuffer = await file.arrayBuffer();
77
81
  const buffer = Buffer.from(arrayBuffer);
82
+ const SERVER_MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB hard limit
78
83
  const allowedMimeTypesRaw = formData.get('allowedMimeTypes');
79
84
  const maxSizeRaw = formData.get('maxSize');
80
85
  const allowedMimeTypes = allowedMimeTypesRaw ? JSON.parse(allowedMimeTypesRaw) : undefined;
81
- const maxSize = maxSizeRaw ? parseInt(maxSizeRaw, 10) : undefined;
86
+ const clientMaxSize = maxSizeRaw ? parseInt(maxSizeRaw, 10) : undefined;
87
+ const maxSize = clientMaxSize
88
+ ? Math.min(clientMaxSize, SERVER_MAX_FILE_SIZE)
89
+ : SERVER_MAX_FILE_SIZE;
82
90
  const validation = validateFile(buffer, file.name, file.type, {
83
91
  allowedMimeTypes,
84
92
  maxSize
@@ -86,18 +94,19 @@ export const assetsRouter = new Hono()
86
94
  if (!validation.valid) {
87
95
  return c.json({ success: false, error: validation.error }, 400);
88
96
  }
97
+ const safeMimeType = validation.detectedMimeType || 'application/octet-stream';
89
98
  const title = formData.get('title') || undefined;
90
99
  const description = formData.get('description') || undefined;
91
100
  const alt = formData.get('alt') || undefined;
92
101
  const creditLine = formData.get('creditLine') || undefined;
93
102
  const schemaType = formData.get('schemaType') || undefined;
94
103
  const fieldPath = formData.get('fieldPath') || undefined;
95
- const targetOrganizationId = formData.get('organizationId') || auth.organizationId;
104
+ const targetOrganizationId = auth.organizationId;
96
105
  const uploadData = {
97
106
  organizationId: targetOrganizationId,
98
107
  buffer,
99
108
  originalFilename: file.name,
100
- mimeType: file.type,
109
+ mimeType: safeMimeType,
101
110
  size: file.size,
102
111
  title,
103
112
  description,
@@ -1 +1 @@
1
- {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/document-versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAqJ/C,CAAC"}
1
+ {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/document-versions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAiK/C,CAAC"}
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import { zValidator } from '@hono/zod-validator';
3
3
  import { authToContext } from '../../../local-api/auth-helpers.js';
4
4
  import { cmsLogger } from '../../../utils/logger.js';
5
+ import { hasCapability } from '../../../types/capabilities.js';
5
6
  import { listVersionsQuery } from '../../../api/schemas/documents.js';
6
7
  export const documentVersionsRouter = new Hono()
7
8
  .get('/:id/versions', zValidator('query', listVersionsQuery, (result, c) => {
@@ -84,6 +85,13 @@ export const documentVersionsRouter = new Hono()
84
85
  })
85
86
  .post('/:id/versions/:version/restore', async (c) => {
86
87
  try {
88
+ const auth = c.var.auth;
89
+ if (!auth || auth.type === 'partial_session') {
90
+ return c.json({ success: false, error: 'Unauthorized' }, 401);
91
+ }
92
+ if (!hasCapability(auth, 'document.update')) {
93
+ return c.json({ success: false, error: 'Forbidden: document.update capability required' }, 403);
94
+ }
87
95
  const { localAPI, databaseAdapter } = c.var.aphexCMS;
88
96
  const context = authToContext(c.var.auth);
89
97
  const id = c.req.param('id');
@@ -1 +1 @@
1
- {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CA6N5C,CAAC"}
1
+ {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-by-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAqN5C,CAAC"}
@@ -21,7 +21,7 @@ export const documentsByIdRouter = new Hono()
21
21
  if (!result) {
22
22
  return c.json({ success: false, error: 'Document not found' }, 404);
23
23
  }
24
- const collection = localAPI.collections[result.type];
24
+ const collection = localAPI.getCollection(result.type);
25
25
  if (!collection) {
26
26
  return c.json({
27
27
  success: false,
@@ -73,7 +73,7 @@ export const documentsByIdRouter = new Hono()
73
73
  if (!found) {
74
74
  return c.json({ success: false, error: 'Document not found' }, 404);
75
75
  }
76
- const collection = localAPI.collections[found.type];
76
+ const collection = localAPI.getCollection(found.type);
77
77
  if (!collection) {
78
78
  return c.json({
79
79
  success: false,
@@ -120,7 +120,7 @@ export const documentsByIdRouter = new Hono()
120
120
  if (!result) {
121
121
  return c.json({ success: false, error: 'Document not found' }, 404);
122
122
  }
123
- const collection = localAPI.collections[result.type];
123
+ const collection = localAPI.getCollection(result.type);
124
124
  if (!collection) {
125
125
  return c.json({
126
126
  success: false,
@@ -1 +1 @@
1
- {"version":3,"file":"documents-publish.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CAkK/C,CAAC"}
1
+ {"version":3,"file":"documents-publish.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,sBAAsB,EAAE,IAAI,CAAC,QAAQ,CA4J/C,CAAC"}
@@ -23,7 +23,7 @@ export const documentsPublishRouter = new Hono()
23
23
  message: 'Document may not exist'
24
24
  }, 404);
25
25
  }
26
- const collection = localAPI.collections[found.type];
26
+ const collection = localAPI.getCollection(found.type);
27
27
  if (!collection) {
28
28
  return c.json({
29
29
  success: false,
@@ -84,7 +84,7 @@ export const documentsPublishRouter = new Hono()
84
84
  message: `No document found with ID: ${id}`
85
85
  }, 404);
86
86
  }
87
- const collection = localAPI.collections[found.type];
87
+ const collection = localAPI.getCollection(found.type);
88
88
  if (!collection) {
89
89
  return c.json({
90
90
  success: false,
@@ -1 +1 @@
1
- {"version":3,"file":"documents-query.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CAiF/C,CAAC"}
1
+ {"version":3,"file":"documents-query.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CAAC,QAAQ,CA6E/C,CAAC"}
@@ -43,10 +43,9 @@ export const documentsQueryRouter = new Hono().post('/query', zValidator('json',
43
43
  depth: body.depth ?? 0,
44
44
  select: body.select,
45
45
  perspective: body.perspective ?? 'draft',
46
- includeChildOrganizations: body.includeChildOrganizations,
47
- filterOrganizationIds: body.filterOrganizationIds
46
+ includeChildOrganizations: body.includeChildOrganizations
48
47
  };
49
- const result = await localAPI.collections[documentType].find(context, findOptions);
48
+ const result = await localAPI.getCollection(documentType).find(context, findOptions);
50
49
  return c.json({
51
50
  success: true,
52
51
  data: result.docs,
@@ -1 +1 @@
1
- {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC,eAAO,MAAM,eAAe,EAAE,IAAI,CAAC,QAAQ,CAyMxC,CAAC"}
1
+ {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAU5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAKzC,eAAO,MAAM,eAAe,EAAE,IAAI,CAAC,QAAQ,CA6MzC,CAAC"}
@@ -25,7 +25,6 @@ export const documentsRouter = new Hono()
25
25
  const sortParam = Array.isArray(q.sort) ? q.sort.join(',') : q.sort;
26
26
  const perspective = q.perspective ?? 'draft';
27
27
  const includeChildOrganizations = q.includeChildOrganizations;
28
- const filterOrganizationIds = q.filterOrganizationIds;
29
28
  const page = q.page ?? DEFAULT_PAGE;
30
29
  const pageSize = q.pageSize ?? q.limit ?? DEFAULT_PAGE_SIZE;
31
30
  const offset = (page - 1) * pageSize;
@@ -37,7 +36,7 @@ export const documentsRouter = new Hono()
37
36
  message: 'Document type is required. Use ?type=page or ?docType=page'
38
37
  }, 400);
39
38
  }
40
- const collection = localAPI.collections[docType];
39
+ const collection = localAPI.getCollection(docType);
41
40
  if (!collection) {
42
41
  return c.json({
43
42
  success: false,
@@ -56,8 +55,7 @@ export const documentsRouter = new Hono()
56
55
  depth,
57
56
  sort: sortParam || undefined,
58
57
  perspective,
59
- includeChildOrganizations,
60
- filterOrganizationIds
58
+ includeChildOrganizations
61
59
  });
62
60
  return c.json({
63
61
  success: true,
@@ -128,7 +126,7 @@ export const documentsRouter = new Hono()
128
126
  const documentType = parsed.type;
129
127
  const documentData = (parsed.draftData ?? parsed.data);
130
128
  const shouldPublish = parsed.publish ?? false;
131
- const collection = localAPI.collections[documentType];
129
+ const collection = localAPI.getCollection(documentType);
132
130
  if (!collection) {
133
131
  return c.json({
134
132
  success: false,
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-invitations.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-invitations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,IAAI,CAAC,QAAQ,CA0MxD,CAAC"}
1
+ {"version":3,"file":"organizations-invitations.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-invitations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,IAAI,CAAC,QAAQ,CA4MxD,CAAC"}
@@ -127,7 +127,7 @@ export const organizationsInvitationsRouter = new Hono()
127
127
  }, 403);
128
128
  }
129
129
  const body = c.req.valid('json');
130
- const deleted = await databaseAdapter.deleteInvitation(body.invitationId);
130
+ const deleted = await databaseAdapter.deleteInvitation(body.invitationId, auth.organizationId);
131
131
  if (!deleted) {
132
132
  return c.json({ success: false, error: 'Invitation not found' }, 404);
133
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-members.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAQ5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CA+RpD,CAAC"}
1
+ {"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../../../src/lib/server/api/routes/organizations-members.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,eAAO,MAAM,0BAA0B,EAAE,IAAI,CAAC,QAAQ,CA4RpD,CAAC"}
@@ -4,6 +4,7 @@ export * from '../cache/index.js';
4
4
  export * from '../email/index.js';
5
5
  export { AuthError, type AuthErrorCode } from '../auth/auth-errors.js';
6
6
  export { createCMSConfig } from '../config.js';
7
+ export { cmsLogger, setLogger, type Logger } from '../utils/logger.js';
7
8
  export { CMSEngine } from '../engine.js';
8
9
  export { createCMSHook, __notifyAphexConfigChanged, type CMSInstances } from '../hooks.js';
9
10
  export * from '../db/interfaces/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/server/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAE/B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxF,cAAc,wBAAwB,CAAC;AAGvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAKzD,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI5D,OAAO,EACN,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,KAAK,QAAQ,EACb,MAAM,aAAa,CAAC;AAGrB,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,OAAO,EACN,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACN,QAAQ,EACR,cAAc,EACd,WAAW,EACX,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/server/index.ts"],"names":[],"mappings":"AAIA,cAAc,gBAAgB,CAAC;AAE/B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,gBAAgB,CAAC;AAG/B,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAE,0BAA0B,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxF,cAAc,wBAAwB,CAAC;AAGvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAKzD,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI5D,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG/F,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,OAAO,EACN,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACN,QAAQ,EACR,cAAc,EACd,WAAW,EACX,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EACjB,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,MAAM,oBAAoB,CAAC"}
@@ -9,6 +9,8 @@ export * from '../email/index.js';
9
9
  export { AuthError } from '../auth/auth-errors.js';
10
10
  // Configuration system
11
11
  export { createCMSConfig } from '../config.js';
12
+ // Logger
13
+ export { cmsLogger, setLogger } from '../utils/logger.js';
12
14
  // CMS Engine
13
15
  export { CMSEngine } from '../engine.js';
14
16
  // Hooks integration (SvelteKit server hooks)
@@ -1 +1 @@
1
- {"version":3,"file":"asset-service.d.ts","sourceRoot":"","sources":["../../src/lib/services/asset-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAG5C,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACnB,CAAC;CACF;AAED,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,YAAY;IAEvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;gBADR,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,eAAe;IAGlC;;OAEG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC;IAoFhF;;OAEG;IACG,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAI9E;;;OAGG;IACG,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAmB5D;;OAEG;IACG,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAItF;;;;;OAKG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BvE;;OAEG;IACG,mBAAmB,CACxB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACnB,GACC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIxB;;OAEG;IACG,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QACpD,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IAeF;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC;QAChC,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;KAClB,CAAC;CAWF"}
1
+ {"version":3,"file":"asset-service.d.ts","sourceRoot":"","sources":["../../src/lib/services/asset-service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAG5C,MAAM,WAAW,eAAe;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACnB,CAAC;CACF;AAED,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,YAAY;IAEvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ;gBADR,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,eAAe;IAGlC;;OAEG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC;IAsFhF;;OAEG;IACG,aAAa,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAI9E;;;OAGG;IACG,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAmB5D;;OAEG;IACG,UAAU,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAItF;;;;;OAKG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BvE;;OAEG;IACG,mBAAmB,CACxB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACnB,GACC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;IAIxB;;OAEG;IACG,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC;QACpD,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IAeF;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC;QAChC,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC;KAClB,CAAC;CAWF"}
@@ -27,7 +27,9 @@ export class AssetService {
27
27
  };
28
28
  if (assetType === 'image') {
29
29
  try {
30
- const imageMetadata = await sharp(data.buffer).metadata();
30
+ const imageMetadata = await sharp(data.buffer, {
31
+ limitInputPixels: 100_000_000
32
+ }).metadata();
31
33
  width = imageMetadata.width;
32
34
  height = imageMetadata.height;
33
35
  // Merge image metadata with field metadata
@@ -41,7 +43,7 @@ export class AssetService {
41
43
  hasAlpha: imageMetadata.hasAlpha
42
44
  };
43
45
  // Add dominant color
44
- const stats = await sharp(data.buffer).stats();
46
+ const stats = await sharp(data.buffer, { limitInputPixels: 100_000_000 }).stats();
45
47
  metadata.dominantColor = stats.dominant;
46
48
  }
47
49
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"references-service.d.ts","sourceRoot":"","sources":["../../src/lib/services/references-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IACjB,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,eAAe;IAEpD;;;OAGG;IACG,iBAAiB,CACtB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,QAAQ,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,IAAI,CAAC;IAShB;;;;;;;OAOG;IACG,eAAe,CACpB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,UAAU,EAAE,EACrB,gBAAgB,EAAE,MAAM,OAAO,CAC9B,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAClD,GACC,OAAO,CAAC,IAAI,CAAC;CAwBhB"}
1
+ {"version":3,"file":"references-service.d.ts","sourceRoot":"","sources":["../../src/lib/services/references-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD;;;;;;;;;GASG;AACH,qBAAa,iBAAiB;IACjB,OAAO,CAAC,eAAe;gBAAf,eAAe,EAAE,eAAe;IAEpD;;;OAGG;IACG,iBAAiB,CACtB,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,QAAQ,EAAE,UAAU,EAAE,GACpB,OAAO,CAAC,IAAI,CAAC;IAShB;;;;;;;OAOG;IACG,eAAe,CACpB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,UAAU,EAAE,EACrB,gBAAgB,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,GACjF,OAAO,CAAC,IAAI,CAAC;CAwBhB"}
@@ -6,6 +6,10 @@ export declare class LocalStorageAdapter implements StorageAdapter {
6
6
  readonly name = "local";
7
7
  private config;
8
8
  constructor(config: StorageConfig);
9
+ /**
10
+ * Strip path traversal sequences, keeping only the base filename.
11
+ */
12
+ private sanitizeFilename;
9
13
  /**
10
14
  * Generate unique filename preserving original name
11
15
  */
@@ -1 +1 @@
1
- {"version":3,"file":"local-storage-adapter.d.ts","sourceRoot":"","sources":["../../../src/lib/storage/adapters/local-storage-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,MAAM,uBAAuB,CAAC;AAK/B;;GAEG;AACH,qBAAa,mBAAoB,YAAW,cAAc;IACzD,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,EAAE,aAAa;IASjC;;OAEG;YACW,sBAAsB;IAcpC;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;YACW,gBAAgB;IAU9B;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAoCvD;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK9C;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5C;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS5C;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAM5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAyB/E;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAYnC"}
1
+ {"version":3,"file":"local-storage-adapter.d.ts","sourceRoot":"","sources":["../../../src/lib/storage/adapters/local-storage-adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACX,cAAc,EACd,aAAa,EACb,cAAc,EACd,WAAW,EACX,MAAM,uBAAuB,CAAC;AAK/B;;GAEG;AACH,qBAAa,mBAAoB,YAAW,cAAc;IACzD,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAA0B;gBAE5B,MAAM,EAAE,aAAa;IASjC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;YACW,sBAAsB;IAepC;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;YACW,gBAAgB;IAU9B;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAoCvD;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAU9C;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe5C;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAc5C;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAM5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAyB/E;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAYnC"}