@aphexcms/cms-core 2.0.8 → 2.0.10

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 (167) hide show
  1. package/dist/api/api-keys.d.ts +4 -7
  2. package/dist/api/api-keys.d.ts.map +1 -1
  3. package/dist/api/assets.d.ts +7 -22
  4. package/dist/api/assets.d.ts.map +1 -1
  5. package/dist/api/assets.js +1 -10
  6. package/dist/api/documents.d.ts +17 -16
  7. package/dist/api/documents.d.ts.map +1 -1
  8. package/dist/api/documents.js +2 -2
  9. package/dist/api/organizations.d.ts +15 -35
  10. package/dist/api/organizations.d.ts.map +1 -1
  11. package/dist/api/schemas/api-keys.d.ts +16 -0
  12. package/dist/api/schemas/api-keys.d.ts.map +1 -0
  13. package/dist/api/schemas/api-keys.js +9 -0
  14. package/dist/api/schemas/assets.d.ts +174 -0
  15. package/dist/api/schemas/assets.d.ts.map +1 -0
  16. package/dist/api/schemas/assets.js +99 -0
  17. package/dist/api/schemas/documents.d.ts +325 -0
  18. package/dist/api/schemas/documents.d.ts.map +1 -0
  19. package/dist/api/schemas/documents.js +161 -0
  20. package/dist/api/schemas/organizations.d.ts +59 -0
  21. package/dist/api/schemas/organizations.d.ts.map +1 -0
  22. package/dist/api/schemas/organizations.js +45 -0
  23. package/dist/api/schemas/user.d.ts +10 -0
  24. package/dist/api/schemas/user.d.ts.map +1 -0
  25. package/dist/api/schemas/user.js +11 -0
  26. package/dist/api/user.d.ts +4 -6
  27. package/dist/api/user.d.ts.map +1 -1
  28. package/dist/auth/provider.d.ts +5 -0
  29. package/dist/auth/provider.d.ts.map +1 -1
  30. package/dist/client/index.d.ts +2 -0
  31. package/dist/client/index.d.ts.map +1 -1
  32. package/dist/client/index.js +3 -0
  33. package/dist/components/AdminApp.svelte +8 -4
  34. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  35. package/dist/components/admin/DocumentEditor.svelte +23 -18
  36. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  37. package/dist/components/admin/DocumentVersionPanel.svelte +18 -31
  38. package/dist/components/admin/DocumentVersionPanel.svelte.d.ts.map +1 -1
  39. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte +37 -0
  40. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts +19 -0
  41. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts.map +1 -0
  42. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
  43. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
  44. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.js +29 -0
  45. package/dist/hooks.d.ts.map +1 -1
  46. package/dist/hooks.js +4 -0
  47. package/dist/lib/api/api-keys.d.ts +4 -7
  48. package/dist/lib/api/api-keys.d.ts.map +1 -1
  49. package/dist/lib/api/api-keys.js.map +1 -1
  50. package/dist/lib/api/assets.d.ts +7 -22
  51. package/dist/lib/api/assets.d.ts.map +1 -1
  52. package/dist/lib/api/assets.js +1 -10
  53. package/dist/lib/api/assets.js.map +1 -1
  54. package/dist/lib/api/documents.d.ts +17 -16
  55. package/dist/lib/api/documents.d.ts.map +1 -1
  56. package/dist/lib/api/documents.js +2 -2
  57. package/dist/lib/api/documents.js.map +1 -1
  58. package/dist/lib/api/organizations.d.ts +15 -35
  59. package/dist/lib/api/organizations.d.ts.map +1 -1
  60. package/dist/lib/api/organizations.js.map +1 -1
  61. package/dist/lib/api/schemas/api-keys.d.ts +16 -0
  62. package/dist/lib/api/schemas/api-keys.d.ts.map +1 -0
  63. package/dist/lib/api/schemas/api-keys.js +10 -0
  64. package/dist/lib/api/schemas/api-keys.js.map +1 -0
  65. package/dist/lib/api/schemas/assets.d.ts +174 -0
  66. package/dist/lib/api/schemas/assets.d.ts.map +1 -0
  67. package/dist/lib/api/schemas/assets.js +100 -0
  68. package/dist/lib/api/schemas/assets.js.map +1 -0
  69. package/dist/lib/api/schemas/documents.d.ts +325 -0
  70. package/dist/lib/api/schemas/documents.d.ts.map +1 -0
  71. package/dist/lib/api/schemas/documents.js +162 -0
  72. package/dist/lib/api/schemas/documents.js.map +1 -0
  73. package/dist/lib/api/schemas/organizations.d.ts +59 -0
  74. package/dist/lib/api/schemas/organizations.d.ts.map +1 -0
  75. package/dist/lib/api/schemas/organizations.js +46 -0
  76. package/dist/lib/api/schemas/organizations.js.map +1 -0
  77. package/dist/lib/api/schemas/user.d.ts +10 -0
  78. package/dist/lib/api/schemas/user.d.ts.map +1 -0
  79. package/dist/lib/api/schemas/user.js +12 -0
  80. package/dist/lib/api/schemas/user.js.map +1 -0
  81. package/dist/lib/api/user.d.ts +4 -6
  82. package/dist/lib/api/user.d.ts.map +1 -1
  83. package/dist/lib/api/user.js.map +1 -1
  84. package/dist/lib/auth/provider.d.ts +5 -0
  85. package/dist/lib/auth/provider.d.ts.map +1 -1
  86. package/dist/lib/client/index.d.ts +2 -0
  87. package/dist/lib/client/index.d.ts.map +1 -1
  88. package/dist/lib/client/index.js +3 -0
  89. package/dist/lib/client/index.js.map +1 -1
  90. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
  91. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
  92. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js +30 -0
  93. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js.map +1 -0
  94. package/dist/lib/hooks.d.ts.map +1 -1
  95. package/dist/lib/hooks.js +4 -0
  96. package/dist/lib/hooks.js.map +1 -1
  97. package/dist/lib/routes/assets-bulk.d.ts.map +1 -1
  98. package/dist/lib/routes/assets-bulk.js +10 -3
  99. package/dist/lib/routes/assets-bulk.js.map +1 -1
  100. package/dist/lib/routes/assets-by-id.d.ts.map +1 -1
  101. package/dist/lib/routes/assets-by-id.js +11 -1
  102. package/dist/lib/routes/assets-by-id.js.map +1 -1
  103. package/dist/lib/routes/assets-references-counts.d.ts.map +1 -1
  104. package/dist/lib/routes/assets-references-counts.js +12 -2
  105. package/dist/lib/routes/assets-references-counts.js.map +1 -1
  106. package/dist/lib/routes/assets.d.ts.map +1 -1
  107. package/dist/lib/routes/assets.js +14 -13
  108. package/dist/lib/routes/assets.js.map +1 -1
  109. package/dist/lib/routes/document-versions.d.ts.map +1 -1
  110. package/dist/lib/routes/document-versions.js +16 -2
  111. package/dist/lib/routes/document-versions.js.map +1 -1
  112. package/dist/lib/routes/documents-by-id.d.ts.map +1 -1
  113. package/dist/lib/routes/documents-by-id.js +15 -3
  114. package/dist/lib/routes/documents-by-id.js.map +1 -1
  115. package/dist/lib/routes/documents-query.d.ts.map +1 -1
  116. package/dist/lib/routes/documents-query.js +13 -10
  117. package/dist/lib/routes/documents-query.js.map +1 -1
  118. package/dist/lib/routes/documents.d.ts.map +1 -1
  119. package/dist/lib/routes/documents.js +29 -26
  120. package/dist/lib/routes/documents.js.map +1 -1
  121. package/dist/lib/routes/organizations-by-id.d.ts.map +1 -1
  122. package/dist/lib/routes/organizations-by-id.js +11 -1
  123. package/dist/lib/routes/organizations-by-id.js.map +1 -1
  124. package/dist/lib/routes/organizations-invitations.d.ts.map +1 -1
  125. package/dist/lib/routes/organizations-invitations.js +32 -12
  126. package/dist/lib/routes/organizations-invitations.js.map +1 -1
  127. package/dist/lib/routes/organizations-members.d.ts.map +1 -1
  128. package/dist/lib/routes/organizations-members.js +14 -16
  129. package/dist/lib/routes/organizations-members.js.map +1 -1
  130. package/dist/lib/routes/organizations-switch.d.ts.map +1 -1
  131. package/dist/lib/routes/organizations-switch.js +7 -3
  132. package/dist/lib/routes/organizations-switch.js.map +1 -1
  133. package/dist/lib/routes/organizations.d.ts.map +1 -1
  134. package/dist/lib/routes/organizations.js +8 -5
  135. package/dist/lib/routes/organizations.js.map +1 -1
  136. package/dist/lib/routes/user-preferences.d.ts.map +1 -1
  137. package/dist/lib/routes/user-preferences.js +7 -13
  138. package/dist/lib/routes/user-preferences.js.map +1 -1
  139. package/dist/routes/assets-bulk.d.ts.map +1 -1
  140. package/dist/routes/assets-bulk.js +10 -3
  141. package/dist/routes/assets-by-id.d.ts.map +1 -1
  142. package/dist/routes/assets-by-id.js +11 -1
  143. package/dist/routes/assets-references-counts.d.ts.map +1 -1
  144. package/dist/routes/assets-references-counts.js +12 -2
  145. package/dist/routes/assets.d.ts.map +1 -1
  146. package/dist/routes/assets.js +14 -13
  147. package/dist/routes/document-versions.d.ts.map +1 -1
  148. package/dist/routes/document-versions.js +16 -2
  149. package/dist/routes/documents-by-id.d.ts.map +1 -1
  150. package/dist/routes/documents-by-id.js +15 -3
  151. package/dist/routes/documents-query.d.ts.map +1 -1
  152. package/dist/routes/documents-query.js +13 -10
  153. package/dist/routes/documents.d.ts.map +1 -1
  154. package/dist/routes/documents.js +29 -26
  155. package/dist/routes/organizations-by-id.d.ts.map +1 -1
  156. package/dist/routes/organizations-by-id.js +11 -1
  157. package/dist/routes/organizations-invitations.d.ts.map +1 -1
  158. package/dist/routes/organizations-invitations.js +32 -12
  159. package/dist/routes/organizations-members.d.ts.map +1 -1
  160. package/dist/routes/organizations-members.js +14 -16
  161. package/dist/routes/organizations-switch.d.ts.map +1 -1
  162. package/dist/routes/organizations-switch.js +7 -3
  163. package/dist/routes/organizations.d.ts.map +1 -1
  164. package/dist/routes/organizations.js +8 -5
  165. package/dist/routes/user-preferences.d.ts.map +1 -1
  166. package/dist/routes/user-preferences.js +7 -13
  167. package/package.json +5 -3
@@ -1,6 +1,7 @@
1
1
  // Aphex CMS User Preferences API Handler
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { cmsLogger } from '../utils/logger.js';
4
+ import { updateUserPreferencesRequest } from '../api/schemas/user.js';
4
5
  // GET /api/user/preferences - Get user preferences
5
6
  export const GET = async ({ locals }) => {
6
7
  try {
@@ -40,24 +41,17 @@ export const PATCH = async ({ request, locals }) => {
40
41
  message: 'Session authentication required'
41
42
  }, { status: 401 });
42
43
  }
43
- const body = (await request.json());
44
- // Validate the preferences object
45
- if (typeof body !== 'object' || body === null) {
44
+ const rawBody = await request.json();
45
+ const parsed = updateUserPreferencesRequest.safeParse(rawBody);
46
+ if (!parsed.success) {
46
47
  return json({
47
48
  success: false,
48
49
  error: 'Invalid request body',
49
- message: 'Expected an object with preference values'
50
- }, { status: 400 });
51
- }
52
- // Validate individual preference types
53
- if (body.includeChildOrganizations !== undefined &&
54
- typeof body.includeChildOrganizations !== 'boolean') {
55
- return json({
56
- success: false,
57
- error: 'Invalid preference value',
58
- message: 'includeChildOrganizations must be a boolean'
50
+ message: 'Invalid preference values',
51
+ issues: parsed.error.issues
59
52
  }, { status: 400 });
60
53
  }
54
+ const body = parsed.data;
61
55
  // Update preferences
62
56
  await databaseAdapter.updateUserPreferences(auth.user.id, body);
63
57
  // Get updated profile
@@ -1 +1 @@
1
- {"version":3,"file":"user-preferences.js","sourceRoot":"","sources":["../../../src/lib/routes/user-preferences.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-preferences.js","sourceRoot":"","sources":["../../../src/lib/routes/user-preferences.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"assets-bulk.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-bulk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,eAAO,MAAM,MAAM,EAAE,cAwDpB,CAAC"}
1
+ {"version":3,"file":"assets-bulk.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-bulk.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,MAAM,EAAE,cAgEpB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { json } from '@sveltejs/kit';
2
2
  import { cmsLogger } from '../utils/logger.js';
3
+ import { bulkDeleteAssetsRequest } from '../api/schemas/assets.js';
3
4
  export const DELETE = async ({ request, locals }) => {
4
5
  try {
5
6
  const { assetService, databaseAdapter } = locals.aphexCMS;
@@ -7,10 +8,16 @@ export const DELETE = async ({ request, locals }) => {
7
8
  if (!auth || auth.type === 'partial_session') {
8
9
  return json({ success: false, error: 'Unauthorized' }, { status: 401 });
9
10
  }
10
- const { ids } = await request.json();
11
- if (!Array.isArray(ids) || ids.length === 0) {
12
- return json({ success: false, error: 'No asset IDs provided' }, { status: 400 });
11
+ const rawBody = await request.json();
12
+ const parsed = bulkDeleteAssetsRequest.safeParse(rawBody);
13
+ if (!parsed.success) {
14
+ return json({
15
+ success: false,
16
+ error: 'No asset IDs provided',
17
+ issues: parsed.error.issues
18
+ }, { status: 400 });
13
19
  }
20
+ const { ids } = parsed.data;
14
21
  // Check for references before deleting
15
22
  let referencedIds = [];
16
23
  if (databaseAdapter.countDocumentReferencesForAssets) {
@@ -1 +1 @@
1
- {"version":3,"file":"assets-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-by-id.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,GAAG,EAAE,cA6BjB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,cA0CpB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,cAiDnB,CAAC"}
1
+ {"version":3,"file":"assets-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-by-id.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cA6BjB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,cA0CpB,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,cA6DnB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { json } from '@sveltejs/kit';
2
2
  import { cmsLogger } from '../utils/logger.js';
3
+ import { updateAssetRequest } from '../api/schemas/assets.js';
3
4
  export const GET = async ({ params, locals }) => {
4
5
  try {
5
6
  const { assetService } = locals.aphexCMS;
@@ -69,7 +70,16 @@ export const PATCH = async ({ params, locals, request }) => {
69
70
  if (!id) {
70
71
  return json({ success: false, error: 'Asset ID is required' }, { status: 400 });
71
72
  }
72
- const { title, description, alt, creditLine } = await request.json();
73
+ const rawBody = await request.json();
74
+ const parsed = updateAssetRequest.safeParse(rawBody);
75
+ if (!parsed.success) {
76
+ return json({
77
+ success: false,
78
+ error: 'Invalid request body',
79
+ issues: parsed.error.issues
80
+ }, { status: 400 });
81
+ }
82
+ const { title, description, alt, creditLine } = parsed.data;
73
83
  let updatedAsset;
74
84
  if (auth.type == 'session') {
75
85
  updatedAsset = await assetService.updateAssetMetadata(auth.organizationId, id, {
@@ -1 +1 @@
1
- {"version":3,"file":"assets-references-counts.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-references-counts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,cA4BlB,CAAC"}
1
+ {"version":3,"file":"assets-references-counts.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets-references-counts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD;;;GAGG;AACH,eAAO,MAAM,IAAI,EAAE,cAwClB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { json } from '@sveltejs/kit';
2
2
  import { cmsLogger } from '../utils/logger.js';
3
+ import { assetReferenceCountsRequest } from '../api/schemas/assets.js';
3
4
  /**
4
5
  * POST /api/assets/references/counts
5
6
  * Get reference counts for multiple asset IDs in batch
@@ -11,8 +12,17 @@ export const POST = async ({ request, locals }) => {
11
12
  if (!auth || auth.type === 'partial_session') {
12
13
  return json({ success: false, error: 'Unauthorized' }, { status: 401 });
13
14
  }
14
- const { ids } = await request.json();
15
- if (!Array.isArray(ids) || ids.length === 0) {
15
+ const rawBody = await request.json();
16
+ const parsed = assetReferenceCountsRequest.safeParse(rawBody);
17
+ if (!parsed.success) {
18
+ return json({
19
+ success: false,
20
+ error: 'Invalid request body',
21
+ issues: parsed.error.issues
22
+ }, { status: 400 });
23
+ }
24
+ const { ids } = parsed.data;
25
+ if (ids.length === 0) {
16
26
  return json({ success: true, data: {} });
17
27
  }
18
28
  if (!databaseAdapter.countDocumentReferencesForAssets) {
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,IAAI,EAAE,cAuFlB,CAAC;AAEF,eAAO,MAAM,GAAG,EAAE,cAiEjB,CAAC"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/lib/routes/assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,IAAI,EAAE,cAuFlB,CAAC;AAEF,eAAO,MAAM,GAAG,EAAE,cAqEjB,CAAC"}
@@ -2,6 +2,7 @@
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { cmsLogger } from '../utils/logger.js';
4
4
  import { validateFile } from '../utils/mime-detect.js';
5
+ import { listAssetsQuery } from '../api/schemas/assets.js';
5
6
  export const POST = async ({ request, locals }) => {
6
7
  try {
7
8
  const { assetService } = locals.aphexCMS;
@@ -82,20 +83,20 @@ export const GET = async ({ url, locals }) => {
82
83
  if (!auth || auth.type === 'partial_session') {
83
84
  return json({ success: false, error: 'Unauthorized' }, { status: 401 });
84
85
  }
85
- // Parse query parameters
86
- const assetType = url.searchParams.get('assetType');
87
- const mimeType = url.searchParams.get('mimeType') || undefined;
88
- const search = url.searchParams.get('search') || undefined;
89
- const limitParam = url.searchParams.get('limit');
90
- const offsetParam = url.searchParams.get('offset');
91
- const limit = limitParam ? parseInt(limitParam) : 20;
92
- const offset = offsetParam ? parseInt(offsetParam) : 0;
86
+ const parsedQuery = listAssetsQuery.safeParse(Object.fromEntries(url.searchParams.entries()));
87
+ if (!parsedQuery.success) {
88
+ return json({
89
+ success: false,
90
+ error: 'Invalid query parameters',
91
+ issues: parsedQuery.error.issues
92
+ }, { status: 400 });
93
+ }
93
94
  const filters = {
94
- assetType,
95
- mimeType,
96
- search,
97
- limit: isNaN(limit) ? 20 : limit,
98
- offset: isNaN(offset) ? 0 : offset
95
+ assetType: parsedQuery.data.assetType,
96
+ mimeType: parsedQuery.data.mimeType,
97
+ search: parsedQuery.data.search,
98
+ limit: parsedQuery.data.limit ?? 20,
99
+ offset: parsedQuery.data.offset ?? 0
99
100
  };
100
101
  // Fetch assets and total count in parallel
101
102
  const [fetchedAssets, totalAssets] = await Promise.all([
@@ -1 +1 @@
1
- {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../src/lib/routes/document-versions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cAuDjB,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,cAuCxB,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,cA4C5B,CAAC"}
1
+ {"version":3,"file":"document-versions.d.ts","sourceRoot":"","sources":["../../src/lib/routes/document-versions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAMpD,eAAO,MAAM,GAAG,EAAE,cAyEjB,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,cAuCxB,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,cA4C5B,CAAC"}
@@ -2,6 +2,7 @@
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { authToContext } from '../local-api/auth-helpers.js';
4
4
  import { cmsLogger } from '../utils/logger.js';
5
+ import { listVersionsQuery } from '../api/schemas/documents.js';
5
6
  // GET /api/documents/[id]/versions - List version history
6
7
  export const GET = async ({ params, url, locals }) => {
7
8
  try {
@@ -11,14 +12,27 @@ export const GET = async ({ params, url, locals }) => {
11
12
  if (!id) {
12
13
  return json({ success: false, error: 'Document ID is required' }, { status: 400 });
13
14
  }
14
- const limit = parseInt(url.searchParams.get('limit') || '25');
15
- const offset = parseInt(url.searchParams.get('offset') || '0');
15
+ const parsedQuery = listVersionsQuery.safeParse(Object.fromEntries(url.searchParams.entries()));
16
+ if (!parsedQuery.success) {
17
+ return json({
18
+ success: false,
19
+ error: 'Invalid query parameters',
20
+ issues: parsedQuery.error.issues
21
+ }, { status: 400 });
22
+ }
23
+ const limit = parsedQuery.data.limit ?? 25;
24
+ const offset = parsedQuery.data.offset ?? 0;
16
25
  const result = await localAPI.versionService.listVersions(databaseAdapter, context.organizationId, id, { limit, offset });
17
26
  // Resolve user names for createdBy IDs
18
27
  const userIds = [...new Set(result.versions.map((v) => v.createdBy).filter(Boolean))];
19
28
  const userMap = new Map();
20
29
  if (userIds.length > 0 && locals.aphexCMS.auth) {
21
30
  await Promise.all(userIds.map(async (userId) => {
31
+ // API key actions are stored as "apikey:<id>" — resolve to a friendly label
32
+ if (userId.startsWith('apikey:')) {
33
+ userMap.set(userId, 'API Key');
34
+ return;
35
+ }
22
36
  try {
23
37
  const user = await locals.aphexCMS.auth.getUserById(userId);
24
38
  if (user) {
@@ -1 +1 @@
1
- {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents-by-id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAOpD,eAAO,MAAM,GAAG,EAAE,cAuEjB,CAAC;AAIF,eAAO,MAAM,GAAG,EAAE,cAkFjB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cA+DpB,CAAC"}
1
+ {"version":3,"file":"documents-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents-by-id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAQpD,eAAO,MAAM,GAAG,EAAE,cAuEjB,CAAC;AAIF,eAAO,MAAM,GAAG,EAAE,cAiGjB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cA+DpB,CAAC"}
@@ -3,6 +3,7 @@ import { json } from '@sveltejs/kit';
3
3
  import { authToContext } from '../local-api/auth-helpers.js';
4
4
  import { PermissionError } from '../local-api/permissions.js';
5
5
  import { cmsLogger } from '../utils/logger.js';
6
+ import { updateDocumentRequest } from '../api/schemas/documents.js';
6
7
  // GET /api/documents/[id] - Get document by ID
7
8
  // TODO ENABLE CHILDREN ORG ACCESS BY DEFAULT - BECAUSE IF A PARENT ORG IS TRYING TO ACCESS A CHILD ORG. It should already have access to said id.
8
9
  export const GET = async ({ params, url, locals }) => {
@@ -67,12 +68,23 @@ export const PUT = async ({ params, request, locals }) => {
67
68
  const { localAPI } = locals.aphexCMS;
68
69
  const context = authToContext(locals.auth);
69
70
  const { id } = params;
70
- const body = await request.json();
71
71
  if (!id) {
72
72
  return json({ success: false, error: 'Document ID is required' }, { status: 400 });
73
73
  }
74
- const documentData = body.draftData || body.data;
75
- const shouldPublish = body.publish || false;
74
+ const rawBody = await request.json();
75
+ const parsed = updateDocumentRequest.safeParse(rawBody);
76
+ if (!parsed.success) {
77
+ return json({
78
+ success: false,
79
+ error: 'Invalid request body',
80
+ issues: parsed.error.issues
81
+ }, { status: 400 });
82
+ }
83
+ const documentData = parsed.data.draftData ?? parsed.data.data;
84
+ if (!documentData) {
85
+ return json({ success: false, error: 'Document data is required' }, { status: 400 });
86
+ }
87
+ const shouldPublish = parsed.data.publish ?? false;
76
88
  // Fetch document to get its type (hierarchy-aware, no RLS transaction)
77
89
  const found = await localAPI.findDocumentById(context, id);
78
90
  if (!found) {
@@ -1 +1 @@
1
- {"version":3,"file":"documents-query.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents-query.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAUpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,IAAI,EAAE,cAuFlB,CAAC"}
1
+ {"version":3,"file":"documents-query.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents-query.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAWpD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,IAAI,EAAE,cAyFlB,CAAC"}
@@ -3,6 +3,7 @@ import { json } from '@sveltejs/kit';
3
3
  import { authToContext } from '../local-api/auth-helpers.js';
4
4
  import { PermissionError } from '../local-api/permissions.js';
5
5
  import { cmsLogger } from '../utils/logger.js';
6
+ import { queryDocumentsRequest } from '../api/schemas/documents.js';
6
7
  // Default values
7
8
  const DEFAULT_PAGE_SIZE = 20;
8
9
  const DEFAULT_PAGE = 1;
@@ -33,16 +34,18 @@ export const POST = async ({ request, locals }) => {
33
34
  try {
34
35
  const { localAPI } = locals.aphexCMS;
35
36
  const context = authToContext(locals.auth);
36
- const body = await request.json();
37
- // Extract document type
38
- const documentType = body.type;
39
- if (!documentType) {
37
+ const rawBody = await request.json();
38
+ const parsed = queryDocumentsRequest.safeParse(rawBody);
39
+ if (!parsed.success) {
40
40
  return json({
41
41
  success: false,
42
42
  error: 'Bad Request',
43
- message: 'Document type is required in request body'
43
+ message: 'Document type is required in request body',
44
+ issues: parsed.error.issues
44
45
  }, { status: 400 });
45
46
  }
47
+ const body = parsed.data;
48
+ const documentType = body.type;
46
49
  // Check if collection exists
47
50
  if (!localAPI.hasCollection(documentType)) {
48
51
  return json({
@@ -52,18 +55,18 @@ export const POST = async ({ request, locals }) => {
52
55
  }, { status: 400 });
53
56
  }
54
57
  // Parse pagination - support both page-based and offset-based
55
- const page = body.page ? Math.max(1, parseInt(body.page)) : DEFAULT_PAGE;
56
- const pageSize = body.pageSize || body.limit || DEFAULT_PAGE_SIZE;
58
+ const page = body.page ?? DEFAULT_PAGE;
59
+ const pageSize = body.pageSize ?? body.limit ?? DEFAULT_PAGE_SIZE;
57
60
  const offset = body.offset !== undefined ? body.offset : (page - 1) * pageSize;
58
61
  // Build FindOptions from request body
59
62
  const findOptions = {
60
63
  where: body.where,
61
64
  limit: pageSize,
62
- offset: offset,
65
+ offset,
63
66
  sort: body.sort,
64
- depth: body.depth !== undefined ? Math.max(0, Math.min(body.depth, 5)) : 0,
67
+ depth: body.depth ?? 0,
65
68
  select: body.select,
66
- perspective: body.perspective || 'draft',
69
+ perspective: body.perspective ?? 'draft',
67
70
  includeChildOrganizations: body.includeChildOrganizations,
68
71
  filterOrganizationIds: body.filterOrganizationIds
69
72
  };
@@ -1 +1 @@
1
- {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAUpD,eAAO,MAAM,GAAG,EAAE,cAwGjB,CAAC;AAGF,eAAO,MAAM,IAAI,EAAE,cAmFlB,CAAC"}
1
+ {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAWpD,eAAO,MAAM,GAAG,EAAE,cA6GjB,CAAC;AAGF,eAAO,MAAM,IAAI,EAAE,cAkFlB,CAAC"}
@@ -3,6 +3,7 @@ import { json } from '@sveltejs/kit';
3
3
  import { authToContext } from '../local-api/auth-helpers.js';
4
4
  import { PermissionError } from '../local-api/permissions.js';
5
5
  import { cmsLogger } from '../utils/logger.js';
6
+ import { createDocumentRequest, listDocumentsQuery } from '../api/schemas/documents.js';
6
7
  // Default values for API
7
8
  const DEFAULT_PAGE_SIZE = 20;
8
9
  const DEFAULT_PAGE = 1;
@@ -11,25 +12,27 @@ export const GET = async ({ url, locals }) => {
11
12
  try {
12
13
  const { localAPI } = locals.aphexCMS;
13
14
  const context = authToContext(locals.auth);
14
- // Parse query params
15
- const docType = url.searchParams.get('type') || url.searchParams.get('docType');
16
- const status = url.searchParams.get('status');
17
- const pageParam = url.searchParams.get('page');
18
- const pageSizeParam = url.searchParams.get('pageSize') || url.searchParams.get('limit');
19
- const depthParam = url.searchParams.get('depth');
20
- const sortParam = url.searchParams.get('sort');
21
- const perspective = url.searchParams.get('perspective') || 'draft';
22
- const includeChildOrganizations = url.searchParams.get('includeChildOrganizations') === 'true';
23
- const filterOrganizationIds = url.searchParams
24
- .get('filterOrganizationIds')
25
- ?.split(',')
26
- .filter(Boolean);
27
- // Parse pagination
28
- const page = pageParam ? Math.max(1, parseInt(pageParam)) : DEFAULT_PAGE;
29
- const pageSize = pageSizeParam ? parseInt(pageSizeParam) : DEFAULT_PAGE_SIZE;
15
+ // Parse + validate query params with zod
16
+ const rawQuery = Object.fromEntries(url.searchParams.entries());
17
+ const parsedQuery = listDocumentsQuery.safeParse(rawQuery);
18
+ if (!parsedQuery.success) {
19
+ return json({
20
+ success: false,
21
+ error: 'Invalid query parameters',
22
+ issues: parsedQuery.error.issues
23
+ }, { status: 400 });
24
+ }
25
+ const q = parsedQuery.data;
26
+ const docType = q.type ?? q.docType;
27
+ const status = q.status;
28
+ const sortParam = Array.isArray(q.sort) ? q.sort.join(',') : q.sort;
29
+ const perspective = q.perspective ?? 'draft';
30
+ const includeChildOrganizations = q.includeChildOrganizations;
31
+ const filterOrganizationIds = q.filterOrganizationIds;
32
+ const page = q.page ?? DEFAULT_PAGE;
33
+ const pageSize = q.pageSize ?? q.limit ?? DEFAULT_PAGE_SIZE;
30
34
  const offset = (page - 1) * pageSize;
31
- // Parse depth (clamp between 0-5)
32
- const depth = depthParam ? Math.max(0, Math.min(parseInt(depthParam), 5)) : 0;
35
+ const depth = q.depth ?? 0;
33
36
  if (!docType) {
34
37
  return json({
35
38
  success: false,
@@ -96,18 +99,18 @@ export const POST = async ({ request, locals }) => {
96
99
  try {
97
100
  const { localAPI } = locals.aphexCMS;
98
101
  const context = authToContext(locals.auth);
99
- const body = await request.json();
100
- // Validate required fields (support both old and new format)
101
- const documentType = body.type;
102
- const documentData = body.draftData || body.data;
103
- const shouldPublish = body.publish || false;
104
- if (!documentType || !documentData) {
102
+ const rawBody = await request.json();
103
+ const parsed = createDocumentRequest.safeParse(rawBody);
104
+ if (!parsed.success) {
105
105
  return json({
106
106
  success: false,
107
- error: 'Missing required fields',
108
- message: 'Document type and data are required'
107
+ error: 'Invalid request body',
108
+ issues: parsed.error.issues
109
109
  }, { status: 400 });
110
110
  }
111
+ const documentType = parsed.data.type;
112
+ const documentData = (parsed.data.draftData ?? parsed.data.data);
113
+ const shouldPublish = parsed.data.publish ?? false;
111
114
  // Get collection API (TypeScript-safe)
112
115
  const collection = localAPI.collections[documentType];
113
116
  if (!collection) {
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-by-id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,GAAG,EAAE,cAmEjB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cAgGnB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAmFpB,CAAC"}
1
+ {"version":3,"file":"organizations-by-id.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-by-id.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cAmEjB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cA4GnB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAmFpB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  // Aphex CMS Organization by ID API Handlers
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { cmsLogger } from '../utils/logger.js';
4
+ import { updateOrganizationRequest } from '../api/schemas/organizations.js';
4
5
  // GET /api/organizations/[id] - Get organization by ID
5
6
  export const GET = async ({ params, locals }) => {
6
7
  try {
@@ -80,7 +81,16 @@ export const PATCH = async ({ params, request, locals }) => {
80
81
  message: 'Only owners and admins can update organization settings'
81
82
  }, { status: 403 });
82
83
  }
83
- const body = await request.json();
84
+ const rawBody = await request.json();
85
+ const parsed = updateOrganizationRequest.safeParse(rawBody);
86
+ if (!parsed.success) {
87
+ return json({
88
+ success: false,
89
+ error: 'Invalid request body',
90
+ issues: parsed.error.issues
91
+ }, { status: 400 });
92
+ }
93
+ const body = parsed.data;
84
94
  // Validate: if slug is being changed, check it's not already taken
85
95
  if (body.slug) {
86
96
  const existingOrg = await databaseAdapter.findOrganizationBySlug(body.slug);
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-invitations.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-invitations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,IAAI,EAAE,cAyGlB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAqEpB,CAAC"}
1
+ {"version":3,"file":"organizations-invitations.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-invitations.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,IAAI,EAAE,cA+HlB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAuEpB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  // Aphex CMS Organization Invitations API Handlers
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { cmsLogger } from '../utils/logger.js';
4
+ import { inviteMemberRequest, cancelInvitationRequest } from '../api/schemas/organizations.js';
4
5
  // POST /api/organizations/invitations - Create/send an invitation
5
6
  export const POST = async ({ request, locals }) => {
6
7
  try {
@@ -21,23 +22,39 @@ export const POST = async ({ request, locals }) => {
21
22
  message: 'Only owners and admins can invite members'
22
23
  }, { status: 403 });
23
24
  }
24
- const body = await request.json();
25
- if (!body.email || !body.role) {
25
+ const rawBody = await request.json();
26
+ const parsed = inviteMemberRequest.safeParse(rawBody);
27
+ if (!parsed.success) {
26
28
  return json({
27
29
  success: false,
28
- error: 'Missing required fields',
29
- message: 'email and role are required'
30
+ error: 'Invalid request body',
31
+ message: 'email and role (admin|editor|viewer) are required',
32
+ issues: parsed.error.issues
30
33
  }, { status: 400 });
31
34
  }
32
- // Validate role
33
- const validRoles = ['admin', 'editor', 'viewer'];
34
- if (!validRoles.includes(body.role)) {
35
+ const body = parsed.data;
36
+ // Reject self-invitation
37
+ if (body.email.toLowerCase() === auth.user.email.toLowerCase()) {
35
38
  return json({
36
39
  success: false,
37
- error: 'Invalid role',
38
- message: 'Role must be one of: admin, editor, viewer'
40
+ error: 'Invalid invitation',
41
+ message: 'You cannot invite yourself'
39
42
  }, { status: 400 });
40
43
  }
44
+ // Reject if the invitee is already a member of the organization
45
+ if (locals.aphexCMS.auth) {
46
+ const existingUser = await locals.aphexCMS.auth.getUserByEmail(body.email);
47
+ if (existingUser) {
48
+ const existingMembership = await databaseAdapter.findUserMembership(existingUser.id, auth.organizationId);
49
+ if (existingMembership) {
50
+ return json({
51
+ success: false,
52
+ error: 'Already a member',
53
+ message: 'This user is already a member of the organization'
54
+ }, { status: 400 });
55
+ }
56
+ }
57
+ }
41
58
  // Check if there's already a pending invitation for this email
42
59
  const existingInvitations = await databaseAdapter.findOrganizationInvitations(auth.organizationId);
43
60
  const pendingInvitation = existingInvitations.find((inv) => inv.email.toLowerCase() === body.email.toLowerCase() && inv.acceptedAt === null);
@@ -94,14 +111,17 @@ export const DELETE = async ({ request, locals }) => {
94
111
  message: 'Only owners and admins can cancel invitations'
95
112
  }, { status: 403 });
96
113
  }
97
- const body = await request.json();
98
- if (!body.invitationId) {
114
+ const rawBody = await request.json();
115
+ const parsed = cancelInvitationRequest.safeParse(rawBody);
116
+ if (!parsed.success) {
99
117
  return json({
100
118
  success: false,
101
119
  error: 'Missing required field',
102
- message: 'invitationId is required'
120
+ message: 'invitationId is required',
121
+ issues: parsed.error.issues
103
122
  }, { status: 400 });
104
123
  }
124
+ const body = parsed.data;
105
125
  // Delete the invitation
106
126
  const deleted = await databaseAdapter.deleteInvitation(body.invitationId);
107
127
  if (!deleted) {
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-members.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,GAAG,EAAE,cAkCjB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAmIpB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cA4HnB,CAAC"}
1
+ {"version":3,"file":"organizations-members.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-members.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,GAAG,EAAE,cAkCjB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAqIpB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cAiHnB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  // Aphex CMS Organization Members API Handlers
2
2
  import { json } from '@sveltejs/kit';
3
3
  import { cmsLogger } from '../utils/logger.js';
4
+ import { removeMemberRequest, updateMemberRoleRequest } from '../api/schemas/organizations.js';
4
5
  // GET /api/organizations/members - List organization members
5
6
  export const GET = async ({ locals }) => {
6
7
  try {
@@ -49,14 +50,17 @@ export const DELETE = async ({ request, locals }) => {
49
50
  message: 'Only owners and admins can remove members'
50
51
  }, { status: 403 });
51
52
  }
52
- const body = await request.json();
53
- if (!body.userId) {
53
+ const rawBody = await request.json();
54
+ const parsed = removeMemberRequest.safeParse(rawBody);
55
+ if (!parsed.success) {
54
56
  return json({
55
57
  success: false,
56
58
  error: 'Missing required field',
57
- message: 'userId is required'
59
+ message: 'userId is required',
60
+ issues: parsed.error.issues
58
61
  }, { status: 400 });
59
62
  }
63
+ const body = parsed.data;
60
64
  // Prevent removing yourself
61
65
  if (body.userId === auth.user.id) {
62
66
  return json({
@@ -141,23 +145,17 @@ export const PATCH = async ({ request, locals }) => {
141
145
  message: 'Only owners and admins can update member roles'
142
146
  }, { status: 403 });
143
147
  }
144
- const body = await request.json();
145
- if (!body.userId || !body.role) {
148
+ const rawBody = await request.json();
149
+ const parsed = updateMemberRoleRequest.safeParse(rawBody);
150
+ if (!parsed.success) {
146
151
  return json({
147
152
  success: false,
148
- error: 'Missing required fields',
149
- message: 'userId and role are required'
150
- }, { status: 400 });
151
- }
152
- // Validate role
153
- const validRoles = ['owner', 'admin', 'editor', 'viewer'];
154
- if (!validRoles.includes(body.role)) {
155
- return json({
156
- success: false,
157
- error: 'Invalid role',
158
- message: 'Role must be one of: owner, admin, editor, viewer'
153
+ error: 'Invalid request body',
154
+ message: 'userId and role (owner|admin|editor|viewer) are required',
155
+ issues: parsed.error.issues
159
156
  }, { status: 400 });
160
157
  }
158
+ const body = parsed.data;
161
159
  // Prevent changing your own role
162
160
  if (body.userId === auth.user.id) {
163
161
  return json({
@@ -1 +1 @@
1
- {"version":3,"file":"organizations-switch.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-switch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,IAAI,EAAE,cAoElB,CAAC"}
1
+ {"version":3,"file":"organizations-switch.d.ts","sourceRoot":"","sources":["../../src/lib/routes/organizations-switch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,IAAI,EAAE,cAsElB,CAAC"}