@aphexcms/cms-core 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/assets.d.ts +48 -0
- package/dist/api/assets.d.ts.map +1 -0
- package/dist/api/assets.js +52 -0
- package/dist/api/client.d.ts +37 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +125 -0
- package/dist/api/documents.d.ts +56 -0
- package/dist/api/documents.d.ts.map +1 -0
- package/dist/api/documents.js +77 -0
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +5 -0
- package/dist/api/organizations.d.ts +101 -0
- package/dist/api/organizations.d.ts.map +1 -0
- package/dist/api/organizations.js +92 -0
- package/dist/api/types.d.ts +23 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +1 -0
- package/dist/app.d.ts +19 -0
- package/dist/auth/MULTI_TENANCY_PLAN.md +1183 -0
- package/dist/auth/auth-errors.d.ts +7 -0
- package/dist/auth/auth-errors.d.ts.map +1 -0
- package/dist/auth/auth-errors.js +13 -0
- package/dist/auth/auth-hooks.d.ts +6 -0
- package/dist/auth/auth-hooks.d.ts.map +1 -0
- package/dist/auth/auth-hooks.js +108 -0
- package/dist/auth/provider.d.ts +17 -0
- package/dist/auth/provider.d.ts.map +1 -0
- package/dist/auth/provider.js +1 -0
- package/dist/client/index.d.ts +24 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +31 -0
- package/dist/components/AdminApp.svelte +1077 -0
- package/dist/components/AdminApp.svelte.d.ts +24 -0
- package/dist/components/AdminApp.svelte.d.ts.map +1 -0
- package/dist/components/admin/AdminLayout.svelte +115 -0
- package/dist/components/admin/AdminLayout.svelte.d.ts +15 -0
- package/dist/components/admin/AdminLayout.svelte.d.ts.map +1 -0
- package/dist/components/admin/DocumentEditor.svelte +795 -0
- package/dist/components/admin/DocumentEditor.svelte.d.ts +18 -0
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -0
- package/dist/components/admin/DocumentTypesList.svelte +97 -0
- package/dist/components/admin/DocumentTypesList.svelte.d.ts +14 -0
- package/dist/components/admin/DocumentTypesList.svelte.d.ts.map +1 -0
- package/dist/components/admin/ObjectModal.svelte +135 -0
- package/dist/components/admin/ObjectModal.svelte.d.ts +15 -0
- package/dist/components/admin/ObjectModal.svelte.d.ts.map +1 -0
- package/dist/components/admin/SchemaField.svelte +171 -0
- package/dist/components/admin/SchemaField.svelte.d.ts +19 -0
- package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/ArrayField.svelte +266 -0
- package/dist/components/admin/fields/ArrayField.svelte.d.ts +12 -0
- package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/BooleanField.svelte +35 -0
- package/dist/components/admin/fields/BooleanField.svelte.d.ts +13 -0
- package/dist/components/admin/fields/BooleanField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/ImageField.svelte +284 -0
- package/dist/components/admin/fields/ImageField.svelte.d.ts +15 -0
- package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/NumberField.svelte +82 -0
- package/dist/components/admin/fields/NumberField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/NumberField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/ReferenceField.svelte +260 -0
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts +12 -0
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/SlugField.svelte +74 -0
- package/dist/components/admin/fields/SlugField.svelte.d.ts +15 -0
- package/dist/components/admin/fields/SlugField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/StringField.svelte +40 -0
- package/dist/components/admin/fields/StringField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/StringField.svelte.d.ts.map +1 -0
- package/dist/components/admin/fields/TextareaField.svelte +40 -0
- package/dist/components/admin/fields/TextareaField.svelte.d.ts +14 -0
- package/dist/components/admin/fields/TextareaField.svelte.d.ts.map +1 -0
- package/dist/components/fields/index.d.ts +9 -0
- package/dist/components/fields/index.d.ts.map +1 -0
- package/dist/components/fields/index.js +9 -0
- package/dist/components/index.d.ts +7 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +12 -0
- package/dist/components/layout/OrganizationSwitcher.svelte +218 -0
- package/dist/components/layout/OrganizationSwitcher.svelte.d.ts +11 -0
- package/dist/components/layout/OrganizationSwitcher.svelte.d.ts.map +1 -0
- package/dist/components/layout/Sidebar.svelte +88 -0
- package/dist/components/layout/Sidebar.svelte.d.ts +14 -0
- package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -0
- package/dist/components/layout/sidebar/AppSidebar.svelte +63 -0
- package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +11 -0
- package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -0
- package/dist/components/layout/sidebar/NavMain.svelte +95 -0
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts +19 -0
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -0
- package/dist/components/layout/sidebar/NavSecondary.svelte +69 -0
- package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts +9 -0
- package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts.map +1 -0
- package/dist/components/layout/sidebar/NavUser.svelte +85 -0
- package/dist/components/layout/sidebar/NavUser.svelte.d.ts +9 -0
- package/dist/components/layout/sidebar/NavUser.svelte.d.ts.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +15 -0
- package/dist/db/adapters/index.d.ts +1 -0
- package/dist/db/adapters/index.d.ts.map +1 -0
- package/dist/db/adapters/index.js +4 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +4 -0
- package/dist/db/interfaces/asset.d.ts +51 -0
- package/dist/db/interfaces/asset.d.ts.map +1 -0
- package/dist/db/interfaces/asset.js +1 -0
- package/dist/db/interfaces/document.d.ts +36 -0
- package/dist/db/interfaces/document.d.ts.map +1 -0
- package/dist/db/interfaces/document.js +1 -0
- package/dist/db/interfaces/index.d.ts +73 -0
- package/dist/db/interfaces/index.d.ts.map +1 -0
- package/dist/db/interfaces/index.js +1 -0
- package/dist/db/interfaces/organization.d.ts +27 -0
- package/dist/db/interfaces/organization.d.ts.map +1 -0
- package/dist/db/interfaces/organization.js +1 -0
- package/dist/db/interfaces/schema.d.ts +21 -0
- package/dist/db/interfaces/schema.d.ts.map +1 -0
- package/dist/db/interfaces/schema.js +1 -0
- package/dist/db/interfaces/user.d.ts +15 -0
- package/dist/db/interfaces/user.d.ts.map +1 -0
- package/dist/db/interfaces/user.js +1 -0
- package/dist/db/utils/reference-resolver.d.ts +18 -0
- package/dist/db/utils/reference-resolver.d.ts.map +1 -0
- package/dist/db/utils/reference-resolver.js +80 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +4 -0
- package/dist/email/index.d.ts +2 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +4 -0
- package/dist/email/interfaces/email.d.ts +42 -0
- package/dist/email/interfaces/email.d.ts.map +1 -0
- package/dist/email/interfaces/email.js +1 -0
- package/dist/engine.d.ts +26 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +66 -0
- package/dist/field-validation/rule.d.ts +51 -0
- package/dist/field-validation/rule.d.ts.map +1 -0
- package/dist/field-validation/rule.js +221 -0
- package/dist/field-validation/utils.d.ts +21 -0
- package/dist/field-validation/utils.d.ts.map +1 -0
- package/dist/field-validation/utils.js +66 -0
- package/dist/hooks.d.ts +23 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +96 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/plugins/README.md +154 -0
- package/dist/routes/assets-by-id.d.ts +5 -0
- package/dist/routes/assets-by-id.d.ts.map +1 -0
- package/dist/routes/assets-by-id.js +138 -0
- package/dist/routes/assets-cdn.d.ts +3 -0
- package/dist/routes/assets-cdn.d.ts.map +1 -0
- package/dist/routes/assets-cdn.js +155 -0
- package/dist/routes/assets.d.ts +4 -0
- package/dist/routes/assets.d.ts.map +1 -0
- package/dist/routes/assets.js +94 -0
- package/dist/routes/documents-by-id.d.ts +5 -0
- package/dist/routes/documents-by-id.d.ts.map +1 -0
- package/dist/routes/documents-by-id.js +142 -0
- package/dist/routes/documents-publish.d.ts +4 -0
- package/dist/routes/documents-publish.d.ts.map +1 -0
- package/dist/routes/documents-publish.js +151 -0
- package/dist/routes/documents.d.ts +4 -0
- package/dist/routes/documents.d.ts.map +1 -0
- package/dist/routes/documents.js +131 -0
- package/dist/routes/index.d.ts +6 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +10 -0
- package/dist/routes/organizations-by-id.d.ts +5 -0
- package/dist/routes/organizations-by-id.d.ts.map +1 -0
- package/dist/routes/organizations-by-id.js +187 -0
- package/dist/routes/organizations-invitations.d.ts +4 -0
- package/dist/routes/organizations-invitations.d.ts.map +1 -0
- package/dist/routes/organizations-invitations.js +125 -0
- package/dist/routes/organizations-members.d.ts +5 -0
- package/dist/routes/organizations-members.d.ts.map +1 -0
- package/dist/routes/organizations-members.js +206 -0
- package/dist/routes/organizations-switch.d.ts +3 -0
- package/dist/routes/organizations-switch.d.ts.map +1 -0
- package/dist/routes/organizations-switch.js +53 -0
- package/dist/routes/organizations.d.ts +4 -0
- package/dist/routes/organizations.d.ts.map +1 -0
- package/dist/routes/organizations.js +108 -0
- package/dist/routes/schemas-by-type.d.ts +3 -0
- package/dist/routes/schemas-by-type.d.ts.map +1 -0
- package/dist/routes/schemas-by-type.js +25 -0
- package/dist/routes/schemas.d.ts +3 -0
- package/dist/routes/schemas.d.ts.map +1 -0
- package/dist/routes/schemas.js +11 -0
- package/dist/routes-exports.d.ts +14 -0
- package/dist/routes-exports.d.ts.map +1 -0
- package/dist/routes-exports.js +19 -0
- package/dist/schema-context.svelte.d.ts +10 -0
- package/dist/schema-context.svelte.d.ts.map +1 -0
- package/dist/schema-context.svelte.js +18 -0
- package/dist/schema-utils/cleanup.d.ts +21 -0
- package/dist/schema-utils/cleanup.d.ts.map +1 -0
- package/dist/schema-utils/cleanup.js +80 -0
- package/dist/schema-utils/index.d.ts +4 -0
- package/dist/schema-utils/index.d.ts.map +1 -0
- package/dist/schema-utils/index.js +4 -0
- package/dist/schema-utils/utils.d.ts +30 -0
- package/dist/schema-utils/utils.d.ts.map +1 -0
- package/dist/schema-utils/utils.js +37 -0
- package/dist/schema-utils/validator.d.ts +6 -0
- package/dist/schema-utils/validator.d.ts.map +1 -0
- package/dist/schema-utils/validator.js +45 -0
- package/dist/server/index.d.ts +16 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +28 -0
- package/dist/services/asset-service.d.ts +86 -0
- package/dist/services/asset-service.d.ts.map +1 -0
- package/dist/services/asset-service.js +187 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +4 -0
- package/dist/storage/adapters/index.d.ts +2 -0
- package/dist/storage/adapters/index.d.ts.map +1 -0
- package/dist/storage/adapters/index.js +2 -0
- package/dist/storage/adapters/local-storage-adapter.d.ts +54 -0
- package/dist/storage/adapters/local-storage-adapter.d.ts.map +1 -0
- package/dist/storage/adapters/local-storage-adapter.js +187 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +6 -0
- package/dist/storage/interfaces/index.d.ts +2 -0
- package/dist/storage/interfaces/index.d.ts.map +1 -0
- package/dist/storage/interfaces/index.js +2 -0
- package/dist/storage/interfaces/storage.d.ts +91 -0
- package/dist/storage/interfaces/storage.d.ts.map +1 -0
- package/dist/storage/interfaces/storage.js +1 -0
- package/dist/storage/providers/storage.d.ts +43 -0
- package/dist/storage/providers/storage.d.ts.map +1 -0
- package/dist/storage/providers/storage.js +64 -0
- package/dist/types/asset.d.ts +73 -0
- package/dist/types/asset.d.ts.map +1 -0
- package/dist/types/asset.js +2 -0
- package/dist/types/auth.d.ts +50 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +41 -0
- package/dist/types/config.d.ts +47 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +1 -0
- package/dist/types/document.d.ts +34 -0
- package/dist/types/document.d.ts.map +1 -0
- package/dist/types/document.js +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/organization.d.ts +105 -0
- package/dist/types/organization.d.ts.map +1 -0
- package/dist/types/organization.js +3 -0
- package/dist/types/schemas.d.ts +114 -0
- package/dist/types/schemas.d.ts.map +1 -0
- package/dist/types/schemas.js +1 -0
- package/dist/types/sidebar.d.ts +33 -0
- package/dist/types/sidebar.d.ts.map +1 -0
- package/dist/types/sidebar.js +1 -0
- package/dist/types/user.d.ts +14 -0
- package/dist/types/user.d.ts.map +1 -0
- package/dist/types/user.js +1 -0
- package/dist/utils/content-hash.d.ts +22 -0
- package/dist/utils/content-hash.d.ts.map +1 -0
- package/dist/utils/content-hash.js +67 -0
- package/dist/utils/image-url.d.ts +88 -0
- package/dist/utils/image-url.d.ts.map +1 -0
- package/dist/utils/image-url.js +165 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/slug.d.ts +13 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/slug.js +30 -0
- package/package.json +11 -41
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Aphex CMS Document by ID API Handlers
|
|
2
|
+
import { json } from '@sveltejs/kit';
|
|
3
|
+
import { canWrite } from '../types/auth.js';
|
|
4
|
+
// GET /api/documents/[id] - Get document by ID
|
|
5
|
+
export const GET = async ({ params, url, locals }) => {
|
|
6
|
+
try {
|
|
7
|
+
const { databaseAdapter, auth: authProvider } = locals.aphexCMS;
|
|
8
|
+
const auth = locals.auth;
|
|
9
|
+
const { id } = params;
|
|
10
|
+
if (!auth) {
|
|
11
|
+
return json({ success: false, error: 'Unauthorized' }, { status: 401 });
|
|
12
|
+
}
|
|
13
|
+
if (!id) {
|
|
14
|
+
return json({ success: false, error: 'Document ID is required' }, { status: 400 });
|
|
15
|
+
}
|
|
16
|
+
// Parse depth parameter
|
|
17
|
+
const depthParam = url.searchParams.get('depth');
|
|
18
|
+
const depth = depthParam ? parseInt(depthParam) : 0;
|
|
19
|
+
const clampedDepth = isNaN(depth) ? 0 : Math.max(0, Math.min(depth, 5)); // Clamp between 0-5
|
|
20
|
+
const document = await databaseAdapter.findByDocId(auth.organizationId, id, clampedDepth);
|
|
21
|
+
if (!document) {
|
|
22
|
+
return json({ success: false, error: 'Document not found' }, { status: 404 });
|
|
23
|
+
}
|
|
24
|
+
// Populate createdBy user info if available
|
|
25
|
+
if (document.createdBy && authProvider) {
|
|
26
|
+
try {
|
|
27
|
+
if (typeof document.createdBy === 'string') {
|
|
28
|
+
const user = await authProvider.getUserById(document.createdBy);
|
|
29
|
+
if (user) {
|
|
30
|
+
document.createdBy = {
|
|
31
|
+
id: user.id,
|
|
32
|
+
name: user.name,
|
|
33
|
+
email: user.email
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// If user fetch fails, keep the user ID
|
|
40
|
+
console.warn('[documents-by-id] Failed to populate createdBy user:', err);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return json({
|
|
44
|
+
success: true,
|
|
45
|
+
data: document
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('Failed to fetch document:', error);
|
|
50
|
+
return json({
|
|
51
|
+
success: false,
|
|
52
|
+
error: 'Failed to fetch document',
|
|
53
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
54
|
+
}, { status: 500 });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
// PUT /api/documents/[id] - Update document
|
|
58
|
+
export const PUT = async ({ params, request, locals }) => {
|
|
59
|
+
try {
|
|
60
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
61
|
+
const auth = locals.auth;
|
|
62
|
+
const { id } = params;
|
|
63
|
+
const body = await request.json();
|
|
64
|
+
if (!auth) {
|
|
65
|
+
return json({ success: false, error: 'Unauthorized' }, { status: 401 });
|
|
66
|
+
}
|
|
67
|
+
// Check write permissions (viewers are read-only)
|
|
68
|
+
if (!canWrite(auth)) {
|
|
69
|
+
return json({
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Forbidden',
|
|
72
|
+
message: 'You do not have permission to update documents. Viewers have read-only access.'
|
|
73
|
+
}, { status: 403 });
|
|
74
|
+
}
|
|
75
|
+
const documentData = body.draftData;
|
|
76
|
+
if (!id) {
|
|
77
|
+
return json({ success: false, error: 'Document ID is required' }, { status: 400 });
|
|
78
|
+
}
|
|
79
|
+
let updatedDocument;
|
|
80
|
+
// NO VALIDATION FOR DRAFTS - Sanity-style: drafts can have any state
|
|
81
|
+
// Validation only happens on publish
|
|
82
|
+
if (auth.type == 'session') {
|
|
83
|
+
updatedDocument = await databaseAdapter.updateDocDraft(auth.organizationId, id, documentData, auth.user.id);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
updatedDocument = await databaseAdapter.updateDocDraft(auth.organizationId, id, documentData, auth.keyId);
|
|
87
|
+
}
|
|
88
|
+
if (!updatedDocument) {
|
|
89
|
+
return json({ success: false, error: 'Document not found' }, { status: 404 });
|
|
90
|
+
}
|
|
91
|
+
return json({
|
|
92
|
+
success: true,
|
|
93
|
+
data: updatedDocument
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error('Failed to update document:', error);
|
|
98
|
+
return json({
|
|
99
|
+
success: false,
|
|
100
|
+
error: 'Failed to update document',
|
|
101
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
102
|
+
}, { status: 500 });
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
// DELETE /api/documents/[id] - Delete document
|
|
106
|
+
export const DELETE = async ({ params, locals }) => {
|
|
107
|
+
try {
|
|
108
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
109
|
+
const auth = locals.auth;
|
|
110
|
+
const { id } = params;
|
|
111
|
+
if (!auth) {
|
|
112
|
+
return json({ success: false, error: 'Unauthorized' }, { status: 401 });
|
|
113
|
+
}
|
|
114
|
+
// Check write permissions (viewers are read-only)
|
|
115
|
+
if (!canWrite(auth)) {
|
|
116
|
+
return json({
|
|
117
|
+
success: false,
|
|
118
|
+
error: 'Forbidden',
|
|
119
|
+
message: 'You do not have permission to delete documents. Viewers have read-only access.'
|
|
120
|
+
}, { status: 403 });
|
|
121
|
+
}
|
|
122
|
+
if (!id) {
|
|
123
|
+
return json({ success: false, error: 'Document ID is required' }, { status: 400 });
|
|
124
|
+
}
|
|
125
|
+
const success = await databaseAdapter.deleteDocById(auth.organizationId, id);
|
|
126
|
+
if (!success) {
|
|
127
|
+
return json({ success: false, error: 'Document not found' }, { status: 404 });
|
|
128
|
+
}
|
|
129
|
+
return json({
|
|
130
|
+
success: true,
|
|
131
|
+
message: 'Document deleted successfully'
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Failed to delete document:', error);
|
|
136
|
+
return json({
|
|
137
|
+
success: false,
|
|
138
|
+
error: 'Failed to delete document',
|
|
139
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
140
|
+
}, { status: 500 });
|
|
141
|
+
}
|
|
142
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents-publish.d.ts","sourceRoot":"","sources":["../../src/lib/routes/documents-publish.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,eAAO,MAAM,IAAI,EAAE,cAkIlB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAsEpB,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Aphex CMS Document Publish API Handlers
|
|
2
|
+
import { json } from '@sveltejs/kit';
|
|
3
|
+
import { validateField } from '../field-validation/utils.js';
|
|
4
|
+
import { canWrite } from '../types/auth.js';
|
|
5
|
+
// POST /api/documents/[id]/publish - Publish document
|
|
6
|
+
export const POST = async ({ params, locals }) => {
|
|
7
|
+
try {
|
|
8
|
+
const { databaseAdapter, cmsEngine } = locals.aphexCMS;
|
|
9
|
+
const auth = locals.auth;
|
|
10
|
+
const { id } = params;
|
|
11
|
+
if (!auth) {
|
|
12
|
+
return json({
|
|
13
|
+
success: false,
|
|
14
|
+
error: 'Unauthorized',
|
|
15
|
+
message: 'Authentication required'
|
|
16
|
+
}, { status: 401 });
|
|
17
|
+
}
|
|
18
|
+
// Check write permissions (viewers are read-only)
|
|
19
|
+
if (!canWrite(auth)) {
|
|
20
|
+
return json({
|
|
21
|
+
success: false,
|
|
22
|
+
error: 'Forbidden',
|
|
23
|
+
message: 'You do not have permission to publish documents. Viewers have read-only access.'
|
|
24
|
+
}, { status: 403 });
|
|
25
|
+
}
|
|
26
|
+
if (!id) {
|
|
27
|
+
return json({
|
|
28
|
+
success: false,
|
|
29
|
+
error: 'Missing document ID',
|
|
30
|
+
message: 'Document ID is required'
|
|
31
|
+
}, { status: 400 });
|
|
32
|
+
}
|
|
33
|
+
// Get document to validate
|
|
34
|
+
const document = await databaseAdapter.findByDocId(auth.organizationId, id);
|
|
35
|
+
if (!document || !document.draftData) {
|
|
36
|
+
return json({
|
|
37
|
+
success: false,
|
|
38
|
+
error: 'Document not found or cannot be published',
|
|
39
|
+
message: 'Document may not exist or may not have draft content'
|
|
40
|
+
}, { status: 404 });
|
|
41
|
+
}
|
|
42
|
+
// Get schema for validation (from config to preserve validation functions)
|
|
43
|
+
const schema = cmsEngine.getSchemaTypeByName(document.type);
|
|
44
|
+
if (!schema) {
|
|
45
|
+
return json({
|
|
46
|
+
success: false,
|
|
47
|
+
error: 'Invalid document type',
|
|
48
|
+
message: `Schema type '${document.type}' not found`
|
|
49
|
+
}, { status: 400 });
|
|
50
|
+
}
|
|
51
|
+
// VALIDATE before publishing - block if errors exist
|
|
52
|
+
const validationErrors = [];
|
|
53
|
+
for (const field of schema.fields) {
|
|
54
|
+
const value = document.draftData[field.name];
|
|
55
|
+
const result = await validateField(field, value, document.draftData);
|
|
56
|
+
if (!result.isValid) {
|
|
57
|
+
const errorMessages = result.errors
|
|
58
|
+
.filter((e) => e.level === 'error')
|
|
59
|
+
.map((e) => e.message);
|
|
60
|
+
if (errorMessages.length > 0) {
|
|
61
|
+
validationErrors.push({
|
|
62
|
+
field: field.name,
|
|
63
|
+
errors: errorMessages
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Block publishing if validation errors exist
|
|
69
|
+
if (validationErrors.length > 0) {
|
|
70
|
+
return json({
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Cannot publish: validation errors',
|
|
73
|
+
message: 'Please fix all validation errors before publishing',
|
|
74
|
+
validationErrors
|
|
75
|
+
}, { status: 400 });
|
|
76
|
+
}
|
|
77
|
+
// All validation passed - proceed with publish
|
|
78
|
+
const publishedDocument = await databaseAdapter.publishDoc(auth.organizationId, id);
|
|
79
|
+
if (!publishedDocument) {
|
|
80
|
+
return json({
|
|
81
|
+
success: false,
|
|
82
|
+
error: 'Document not found or cannot be published',
|
|
83
|
+
message: 'Document may not exist or may not have draft content'
|
|
84
|
+
}, { status: 404 });
|
|
85
|
+
}
|
|
86
|
+
return json({
|
|
87
|
+
success: true,
|
|
88
|
+
data: publishedDocument,
|
|
89
|
+
message: 'Document published successfully'
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('Failed to publish document:', error);
|
|
94
|
+
return json({
|
|
95
|
+
success: false,
|
|
96
|
+
error: 'Failed to publish document',
|
|
97
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
98
|
+
}, { status: 500 });
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
// DELETE /api/documents/[id]/publish - Unpublish document
|
|
102
|
+
export const DELETE = async ({ params, locals }) => {
|
|
103
|
+
try {
|
|
104
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
105
|
+
const auth = locals.auth;
|
|
106
|
+
const { id } = params;
|
|
107
|
+
if (!auth) {
|
|
108
|
+
return json({
|
|
109
|
+
success: false,
|
|
110
|
+
error: 'Unauthorized',
|
|
111
|
+
message: 'Authentication required'
|
|
112
|
+
}, { status: 401 });
|
|
113
|
+
}
|
|
114
|
+
// Check write permissions (viewers are read-only)
|
|
115
|
+
if (!canWrite(auth)) {
|
|
116
|
+
return json({
|
|
117
|
+
success: false,
|
|
118
|
+
error: 'Forbidden',
|
|
119
|
+
message: 'You do not have permission to unpublish documents. Viewers have read-only access.'
|
|
120
|
+
}, { status: 403 });
|
|
121
|
+
}
|
|
122
|
+
if (!id) {
|
|
123
|
+
return json({
|
|
124
|
+
success: false,
|
|
125
|
+
error: 'Missing document ID',
|
|
126
|
+
message: 'Document ID is required'
|
|
127
|
+
}, { status: 400 });
|
|
128
|
+
}
|
|
129
|
+
const unpublishedDocument = await databaseAdapter.unpublishDoc(auth.organizationId, id);
|
|
130
|
+
if (!unpublishedDocument) {
|
|
131
|
+
return json({
|
|
132
|
+
success: false,
|
|
133
|
+
error: 'Document not found',
|
|
134
|
+
message: `No document found with ID: ${id}`
|
|
135
|
+
}, { status: 404 });
|
|
136
|
+
}
|
|
137
|
+
return json({
|
|
138
|
+
success: true,
|
|
139
|
+
data: unpublishedDocument,
|
|
140
|
+
message: 'Document unpublished successfully'
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error('Failed to unpublish document:', error);
|
|
145
|
+
return json({
|
|
146
|
+
success: false,
|
|
147
|
+
error: 'Failed to unpublish document',
|
|
148
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
149
|
+
}, { status: 500 });
|
|
150
|
+
}
|
|
151
|
+
};
|
|
@@ -0,0 +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;AAQpD,eAAO,MAAM,GAAG,EAAE,cAsEjB,CAAC;AAGF,eAAO,MAAM,IAAI,EAAE,cAwFlB,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// Aphex CMS Document API Handlers
|
|
2
|
+
import { json } from '@sveltejs/kit';
|
|
3
|
+
import { canWrite } from '../types/auth.js';
|
|
4
|
+
// Default values for API
|
|
5
|
+
const DEFAULT_API_LIMIT = 20;
|
|
6
|
+
const DEFAULT_API_OFFSET = 0;
|
|
7
|
+
// GET /api/documents - List documents with filtering
|
|
8
|
+
export const GET = async ({ url, locals }) => {
|
|
9
|
+
try {
|
|
10
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
11
|
+
const auth = locals.auth;
|
|
12
|
+
if (!auth) {
|
|
13
|
+
return json({
|
|
14
|
+
success: false,
|
|
15
|
+
error: 'Unauthorized',
|
|
16
|
+
message: 'Authentication required'
|
|
17
|
+
}, { status: 401 });
|
|
18
|
+
}
|
|
19
|
+
const docType = url.searchParams.get('docType');
|
|
20
|
+
const status = url.searchParams.get('status') || undefined;
|
|
21
|
+
const limitParam = url.searchParams.get('limit');
|
|
22
|
+
const offsetParam = url.searchParams.get('offset');
|
|
23
|
+
const depthParam = url.searchParams.get('depth');
|
|
24
|
+
const organizationIdsParam = url.searchParams.get('organizationIds'); // Comma-separated list
|
|
25
|
+
// Parse with defaults
|
|
26
|
+
const limit = limitParam ? parseInt(limitParam) : DEFAULT_API_LIMIT;
|
|
27
|
+
const offset = offsetParam ? parseInt(offsetParam) : DEFAULT_API_OFFSET;
|
|
28
|
+
const depth = depthParam ? parseInt(depthParam) : 0;
|
|
29
|
+
// Parse organizationIds if provided
|
|
30
|
+
const filterOrganizationIds = organizationIdsParam
|
|
31
|
+
? organizationIdsParam
|
|
32
|
+
.split(',')
|
|
33
|
+
.map((id) => id.trim())
|
|
34
|
+
.filter(Boolean)
|
|
35
|
+
: undefined;
|
|
36
|
+
const filters = {
|
|
37
|
+
...(docType && { type: docType }),
|
|
38
|
+
...(status && { status }),
|
|
39
|
+
...(filterOrganizationIds && { filterOrganizationIds }),
|
|
40
|
+
limit: isNaN(limit) ? DEFAULT_API_LIMIT : limit,
|
|
41
|
+
offset: isNaN(offset) ? DEFAULT_API_OFFSET : offset,
|
|
42
|
+
depth: isNaN(depth) ? 0 : Math.max(0, Math.min(depth, 5)) // Clamp between 0-5 for safety
|
|
43
|
+
};
|
|
44
|
+
const documents = await databaseAdapter.findManyDoc(auth.organizationId, filters);
|
|
45
|
+
return json({
|
|
46
|
+
success: true,
|
|
47
|
+
data: documents,
|
|
48
|
+
meta: {
|
|
49
|
+
count: documents.length,
|
|
50
|
+
limit: filters.limit,
|
|
51
|
+
offset: filters.offset,
|
|
52
|
+
filters: {
|
|
53
|
+
docType,
|
|
54
|
+
status
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error('Failed to fetch documents:', error);
|
|
61
|
+
return json({
|
|
62
|
+
success: false,
|
|
63
|
+
error: 'Failed to fetch documents',
|
|
64
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
65
|
+
}, { status: 500 });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
// POST /api/documents - Create new document
|
|
69
|
+
export const POST = async ({ request, locals }) => {
|
|
70
|
+
try {
|
|
71
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
72
|
+
const auth = locals.auth;
|
|
73
|
+
if (!auth) {
|
|
74
|
+
return json({
|
|
75
|
+
success: false,
|
|
76
|
+
error: 'Unauthorized',
|
|
77
|
+
message: 'Authentication required'
|
|
78
|
+
}, { status: 401 });
|
|
79
|
+
}
|
|
80
|
+
// Check write permissions (viewers are read-only)
|
|
81
|
+
if (!canWrite(auth)) {
|
|
82
|
+
return json({
|
|
83
|
+
success: false,
|
|
84
|
+
error: 'Forbidden',
|
|
85
|
+
message: 'You do not have permission to create documents. Viewers have read-only access.'
|
|
86
|
+
}, { status: 403 });
|
|
87
|
+
}
|
|
88
|
+
const body = await request.json();
|
|
89
|
+
// Validate required fields (support both old and new format)
|
|
90
|
+
const documentType = body.type;
|
|
91
|
+
const documentData = body.draftData || body.data;
|
|
92
|
+
if (!documentType || !documentData) {
|
|
93
|
+
return json({
|
|
94
|
+
success: false,
|
|
95
|
+
error: 'Missing required fields',
|
|
96
|
+
message: 'Document type and data are required'
|
|
97
|
+
}, { status: 400 });
|
|
98
|
+
}
|
|
99
|
+
// Validate document type exists
|
|
100
|
+
const { cmsEngine } = locals.aphexCMS;
|
|
101
|
+
const schema = cmsEngine.getSchemaTypeByName(documentType);
|
|
102
|
+
if (!schema) {
|
|
103
|
+
return json({
|
|
104
|
+
success: false,
|
|
105
|
+
error: 'Invalid document type',
|
|
106
|
+
message: `Schema type '${documentType}' not found`
|
|
107
|
+
}, { status: 400 });
|
|
108
|
+
}
|
|
109
|
+
// NO VALIDATION FOR DRAFTS - Sanity-style: drafts can have any state
|
|
110
|
+
// Validation only happens on publish
|
|
111
|
+
// Create document (always starts as draft)
|
|
112
|
+
const newDocument = await databaseAdapter.createDocument({
|
|
113
|
+
type: documentType,
|
|
114
|
+
draftData: documentData,
|
|
115
|
+
organizationId: auth.organizationId,
|
|
116
|
+
createdBy: auth.type === 'session' ? auth.user.id : undefined
|
|
117
|
+
});
|
|
118
|
+
return json({
|
|
119
|
+
success: true,
|
|
120
|
+
data: newDocument
|
|
121
|
+
}, { status: 201 });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('Failed to create document:', error);
|
|
125
|
+
return json({
|
|
126
|
+
success: false,
|
|
127
|
+
error: 'Failed to create document',
|
|
128
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
129
|
+
}, { status: 500 });
|
|
130
|
+
}
|
|
131
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * as documents from './documents.js';
|
|
2
|
+
export * as documentsById from './documents-by-id.js';
|
|
3
|
+
export * as assets from './assets.js';
|
|
4
|
+
export * as schemas from './schemas.js';
|
|
5
|
+
export * as schemasByType from './schemas-by-type.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/routes/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAGtC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Aphex CMS API Route Handlers
|
|
2
|
+
// These will be imported and re-exported by your app's API routes
|
|
3
|
+
// Document management routes
|
|
4
|
+
export * as documents from './documents.js';
|
|
5
|
+
export * as documentsById from './documents-by-id.js';
|
|
6
|
+
// Asset management routes
|
|
7
|
+
export * as assets from './assets.js';
|
|
8
|
+
// Schema information routes
|
|
9
|
+
export * as schemas from './schemas.js';
|
|
10
|
+
export * as schemasByType from './schemas-by-type.js';
|
|
@@ -0,0 +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;AAGpD,eAAO,MAAM,GAAG,EAAE,cAmEjB,CAAC;AAGF,eAAO,MAAM,KAAK,EAAE,cAgGnB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAmFpB,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Aphex CMS Organization by ID API Handlers
|
|
2
|
+
import { json } from '@sveltejs/kit';
|
|
3
|
+
// GET /api/organizations/[id] - Get organization by ID
|
|
4
|
+
export const GET = async ({ params, locals }) => {
|
|
5
|
+
try {
|
|
6
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
7
|
+
const auth = locals.auth;
|
|
8
|
+
const { id } = params;
|
|
9
|
+
if (!auth || auth.type !== 'session') {
|
|
10
|
+
return json({
|
|
11
|
+
success: false,
|
|
12
|
+
error: 'Unauthorized',
|
|
13
|
+
message: 'Session authentication required'
|
|
14
|
+
}, { status: 401 });
|
|
15
|
+
}
|
|
16
|
+
if (!id) {
|
|
17
|
+
return json({
|
|
18
|
+
success: false,
|
|
19
|
+
error: 'Missing required field',
|
|
20
|
+
message: 'Organization ID is required'
|
|
21
|
+
}, { status: 400 });
|
|
22
|
+
}
|
|
23
|
+
// Check if user is a member of this organization
|
|
24
|
+
const membership = await databaseAdapter.findUserMembership(auth.user.id, id);
|
|
25
|
+
if (!membership) {
|
|
26
|
+
return json({
|
|
27
|
+
success: false,
|
|
28
|
+
error: 'Forbidden',
|
|
29
|
+
message: 'You are not a member of this organization'
|
|
30
|
+
}, { status: 403 });
|
|
31
|
+
}
|
|
32
|
+
const organization = await databaseAdapter.findOrganizationById(id);
|
|
33
|
+
if (!organization) {
|
|
34
|
+
return json({
|
|
35
|
+
success: false,
|
|
36
|
+
error: 'Organization not found'
|
|
37
|
+
}, { status: 404 });
|
|
38
|
+
}
|
|
39
|
+
return json({
|
|
40
|
+
success: true,
|
|
41
|
+
data: organization
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
console.error('Failed to fetch organization:', error);
|
|
46
|
+
return json({
|
|
47
|
+
success: false,
|
|
48
|
+
error: 'Failed to fetch organization',
|
|
49
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
50
|
+
}, { status: 500 });
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
// PATCH /api/organizations/[id] - Update organization
|
|
54
|
+
export const PATCH = async ({ params, request, locals }) => {
|
|
55
|
+
try {
|
|
56
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
57
|
+
const auth = locals.auth;
|
|
58
|
+
const { id } = params;
|
|
59
|
+
if (!auth || auth.type !== 'session') {
|
|
60
|
+
return json({
|
|
61
|
+
success: false,
|
|
62
|
+
error: 'Unauthorized',
|
|
63
|
+
message: 'Session authentication required'
|
|
64
|
+
}, { status: 401 });
|
|
65
|
+
}
|
|
66
|
+
if (!id) {
|
|
67
|
+
return json({
|
|
68
|
+
success: false,
|
|
69
|
+
error: 'Missing required field',
|
|
70
|
+
message: 'Organization ID is required'
|
|
71
|
+
}, { status: 400 });
|
|
72
|
+
}
|
|
73
|
+
// Check if user is owner or admin of this organization
|
|
74
|
+
const membership = await databaseAdapter.findUserMembership(auth.user.id, id);
|
|
75
|
+
if (!membership || (membership.role !== 'owner' && membership.role !== 'admin')) {
|
|
76
|
+
return json({
|
|
77
|
+
success: false,
|
|
78
|
+
error: 'Forbidden',
|
|
79
|
+
message: 'Only owners and admins can update organization settings'
|
|
80
|
+
}, { status: 403 });
|
|
81
|
+
}
|
|
82
|
+
const body = await request.json();
|
|
83
|
+
// Validate: if slug is being changed, check it's not already taken
|
|
84
|
+
if (body.slug) {
|
|
85
|
+
const existingOrg = await databaseAdapter.findOrganizationBySlug(body.slug);
|
|
86
|
+
if (existingOrg && existingOrg.id !== id) {
|
|
87
|
+
return json({
|
|
88
|
+
success: false,
|
|
89
|
+
error: 'Slug already exists',
|
|
90
|
+
message: `Organization with slug '${body.slug}' already exists`
|
|
91
|
+
}, { status: 409 });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Update organization
|
|
95
|
+
const updateData = {};
|
|
96
|
+
if (body.name !== undefined)
|
|
97
|
+
updateData.name = body.name;
|
|
98
|
+
if (body.slug !== undefined)
|
|
99
|
+
updateData.slug = body.slug;
|
|
100
|
+
if (body.metadata !== undefined)
|
|
101
|
+
updateData.metadata = body.metadata;
|
|
102
|
+
const updatedOrganization = await databaseAdapter.updateOrganization(id, updateData);
|
|
103
|
+
if (!updatedOrganization) {
|
|
104
|
+
return json({
|
|
105
|
+
success: false,
|
|
106
|
+
error: 'Organization not found'
|
|
107
|
+
}, { status: 404 });
|
|
108
|
+
}
|
|
109
|
+
return json({
|
|
110
|
+
success: true,
|
|
111
|
+
data: updatedOrganization
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error('Failed to update organization:', error);
|
|
116
|
+
return json({
|
|
117
|
+
success: false,
|
|
118
|
+
error: 'Failed to update organization',
|
|
119
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
120
|
+
}, { status: 500 });
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
// DELETE /api/organizations/[id] - Delete an organization
|
|
124
|
+
export const DELETE = async ({ params, locals }) => {
|
|
125
|
+
try {
|
|
126
|
+
const { databaseAdapter } = locals.aphexCMS;
|
|
127
|
+
const auth = locals.auth;
|
|
128
|
+
const { id } = params;
|
|
129
|
+
if (!auth || auth.type !== 'session') {
|
|
130
|
+
return json({
|
|
131
|
+
success: false,
|
|
132
|
+
error: 'Unauthorized',
|
|
133
|
+
message: 'Session authentication required'
|
|
134
|
+
}, { status: 401 });
|
|
135
|
+
}
|
|
136
|
+
if (!id) {
|
|
137
|
+
return json({
|
|
138
|
+
success: false,
|
|
139
|
+
error: 'Missing required field',
|
|
140
|
+
message: 'Organization ID is required'
|
|
141
|
+
}, { status: 400 });
|
|
142
|
+
}
|
|
143
|
+
// Only owners can delete an organization
|
|
144
|
+
const membership = await databaseAdapter.findUserMembership(auth.user.id, id);
|
|
145
|
+
if (!membership || membership.role !== 'owner') {
|
|
146
|
+
return json({
|
|
147
|
+
success: false,
|
|
148
|
+
error: 'Forbidden',
|
|
149
|
+
message: 'Only owners can delete an organization'
|
|
150
|
+
}, { status: 403 });
|
|
151
|
+
}
|
|
152
|
+
// Get all members of the organization
|
|
153
|
+
const members = await databaseAdapter.findOrganizationMembers(id);
|
|
154
|
+
// Handle member lifecycle
|
|
155
|
+
for (const member of members) {
|
|
156
|
+
const userSession = await databaseAdapter.findUserSession(member.userId);
|
|
157
|
+
if (userSession?.activeOrganizationId === id) {
|
|
158
|
+
const otherOrgs = await databaseAdapter.findUserOrganizations(member.userId);
|
|
159
|
+
const remainingOrgs = otherOrgs.filter((org) => org.organization.id !== id);
|
|
160
|
+
if (remainingOrgs.length > 0 && remainingOrgs[0]) {
|
|
161
|
+
await databaseAdapter.updateUserSession(member.userId, remainingOrgs[0].organization.id);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
await databaseAdapter.deleteUserSession(member.userId);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Delete all members from the organization
|
|
169
|
+
await databaseAdapter.removeAllMembers(id);
|
|
170
|
+
// Delete all invitations for the organization
|
|
171
|
+
await databaseAdapter.removeAllInvitations(id);
|
|
172
|
+
// Delete the organization
|
|
173
|
+
await databaseAdapter.deleteOrganization(id);
|
|
174
|
+
return json({
|
|
175
|
+
success: true,
|
|
176
|
+
message: 'Organization deleted successfully'
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.error('Failed to delete organization:', error);
|
|
181
|
+
return json({
|
|
182
|
+
success: false,
|
|
183
|
+
error: 'Failed to delete organization',
|
|
184
|
+
message: error instanceof Error ? error.message : 'Unknown error'
|
|
185
|
+
}, { status: 500 });
|
|
186
|
+
}
|
|
187
|
+
};
|
|
@@ -0,0 +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;AAGpD,eAAO,MAAM,IAAI,EAAE,cAyGlB,CAAC;AAGF,eAAO,MAAM,MAAM,EAAE,cAqEpB,CAAC"}
|