@aphexcms/cms-core 0.1.10 → 0.1.11
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/package.json +2 -2
- package/src/lib/api/assets.ts +75 -0
- package/src/lib/api/client.ts +150 -0
- package/src/lib/api/documents.ts +102 -0
- package/src/lib/api/index.ts +7 -0
- package/src/lib/api/organizations.ts +154 -0
- package/src/lib/api/types.ts +34 -0
- package/src/lib/auth/auth-errors.ts +23 -0
- package/src/lib/auth/auth-hooks.ts +132 -0
- package/src/lib/auth/provider.ts +25 -0
- package/{dist/client/index.js → src/lib/client/index.ts} +18 -7
- package/{dist → src/lib}/components/AdminApp.svelte +43 -11
- package/{dist/components/index.js → src/lib/components/index.ts} +5 -1
- package/src/lib/config.ts +18 -0
- package/{dist/db/adapters/index.js → src/lib/db/adapters/index.ts} +0 -1
- package/{dist/db/index.js → src/lib/db/index.ts} +2 -1
- package/src/lib/db/interfaces/asset.ts +61 -0
- package/src/lib/db/interfaces/document.ts +53 -0
- package/src/lib/db/interfaces/index.ts +98 -0
- package/src/lib/db/interfaces/organization.ts +51 -0
- package/src/lib/db/interfaces/schema.ts +13 -0
- package/src/lib/db/interfaces/user.ts +16 -0
- package/src/lib/db/utils/reference-resolver.ts +119 -0
- package/src/lib/define.ts +7 -0
- package/{dist/email/index.js → src/lib/email/index.ts} +2 -1
- package/src/lib/email/interfaces/email.ts +45 -0
- package/src/lib/engine.ts +85 -0
- package/src/lib/field-validation/rule.ts +287 -0
- package/src/lib/field-validation/utils.ts +91 -0
- package/src/lib/hooks.ts +142 -0
- package/{dist/index.js → src/lib/index.ts} +2 -1
- package/{dist/is-mobile.svelte.js → src/lib/is-mobile.svelte.ts} +5 -3
- package/src/lib/routes/assets-by-id.ts +161 -0
- package/src/lib/routes/assets-cdn.ts +185 -0
- package/src/lib/routes/assets.ts +116 -0
- package/src/lib/routes/documents-by-id.ts +188 -0
- package/src/lib/routes/documents-publish.ts +211 -0
- package/src/lib/routes/documents.ts +172 -0
- package/src/lib/routes/index.ts +13 -0
- package/src/lib/routes/organizations-by-id.ts +258 -0
- package/src/lib/routes/organizations-invitations.ts +183 -0
- package/src/lib/routes/organizations-members.ts +301 -0
- package/src/lib/routes/organizations-switch.ts +74 -0
- package/src/lib/routes/organizations.ts +147 -0
- package/src/lib/routes/schemas-by-type.ts +35 -0
- package/src/lib/routes/schemas.ts +19 -0
- package/src/lib/routes-exports.ts +42 -0
- package/src/lib/schema-context.svelte.ts +24 -0
- package/src/lib/schema-utils/cleanup.ts +116 -0
- package/src/lib/schema-utils/index.ts +4 -0
- package/src/lib/schema-utils/utils.ts +47 -0
- package/src/lib/schema-utils/validator.ts +58 -0
- package/src/lib/server/index.ts +40 -0
- package/src/lib/services/asset-service.ts +256 -0
- package/src/lib/services/index.ts +6 -0
- package/src/lib/storage/adapters/index.ts +2 -0
- package/src/lib/storage/adapters/local-storage-adapter.ts +215 -0
- package/{dist/storage/index.js → src/lib/storage/index.ts} +4 -2
- package/src/lib/storage/interfaces/index.ts +2 -0
- package/src/lib/storage/interfaces/storage.ts +114 -0
- package/src/lib/storage/providers/storage.ts +83 -0
- package/src/lib/types/asset.ts +81 -0
- package/src/lib/types/auth.ts +80 -0
- package/src/lib/types/config.ts +45 -0
- package/src/lib/types/document.ts +38 -0
- package/src/lib/types/index.ts +8 -0
- package/src/lib/types/organization.ts +119 -0
- package/src/lib/types/schemas.ts +156 -0
- package/src/lib/types/sidebar.ts +37 -0
- package/src/lib/types/user.ts +17 -0
- package/src/lib/utils/content-hash.ts +75 -0
- package/src/lib/utils/image-url.ts +204 -0
- package/src/lib/utils/index.ts +12 -0
- package/src/lib/utils/slug.ts +33 -0
- package/src/lib/utils.ts +13 -0
- package/dist/api/assets.d.ts +0 -48
- package/dist/api/assets.d.ts.map +0 -1
- package/dist/api/assets.js +0 -52
- package/dist/api/client.d.ts +0 -37
- package/dist/api/client.d.ts.map +0 -1
- package/dist/api/client.js +0 -125
- package/dist/api/documents.d.ts +0 -56
- package/dist/api/documents.d.ts.map +0 -1
- package/dist/api/documents.js +0 -77
- package/dist/api/index.d.ts +0 -7
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -5
- package/dist/api/organizations.d.ts +0 -101
- package/dist/api/organizations.d.ts.map +0 -1
- package/dist/api/organizations.js +0 -92
- package/dist/api/types.d.ts +0 -23
- package/dist/api/types.d.ts.map +0 -1
- package/dist/api/types.js +0 -1
- package/dist/auth/auth-errors.d.ts +0 -7
- package/dist/auth/auth-errors.d.ts.map +0 -1
- package/dist/auth/auth-errors.js +0 -13
- package/dist/auth/auth-hooks.d.ts +0 -6
- package/dist/auth/auth-hooks.d.ts.map +0 -1
- package/dist/auth/auth-hooks.js +0 -108
- package/dist/auth/provider.d.ts +0 -17
- package/dist/auth/provider.d.ts.map +0 -1
- package/dist/auth/provider.js +0 -1
- package/dist/client/index.d.ts +0 -24
- package/dist/client/index.d.ts.map +0 -1
- package/dist/components/AdminApp.svelte.d.ts +0 -24
- package/dist/components/AdminApp.svelte.d.ts.map +0 -1
- package/dist/components/admin/AdminLayout.svelte.d.ts +0 -15
- package/dist/components/admin/AdminLayout.svelte.d.ts.map +0 -1
- package/dist/components/admin/DocumentEditor.svelte.d.ts +0 -18
- package/dist/components/admin/DocumentEditor.svelte.d.ts.map +0 -1
- package/dist/components/admin/DocumentTypesList.svelte.d.ts +0 -14
- package/dist/components/admin/DocumentTypesList.svelte.d.ts.map +0 -1
- package/dist/components/admin/ObjectModal.svelte.d.ts +0 -15
- package/dist/components/admin/ObjectModal.svelte.d.ts.map +0 -1
- package/dist/components/admin/SchemaField.svelte.d.ts +0 -19
- package/dist/components/admin/SchemaField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/ArrayField.svelte.d.ts +0 -12
- package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/BooleanField.svelte.d.ts +0 -13
- package/dist/components/admin/fields/BooleanField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/ImageField.svelte.d.ts +0 -15
- package/dist/components/admin/fields/ImageField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/NumberField.svelte.d.ts +0 -14
- package/dist/components/admin/fields/NumberField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts +0 -12
- package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/SlugField.svelte.d.ts +0 -15
- package/dist/components/admin/fields/SlugField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/StringField.svelte.d.ts +0 -14
- package/dist/components/admin/fields/StringField.svelte.d.ts.map +0 -1
- package/dist/components/admin/fields/TextareaField.svelte.d.ts +0 -14
- package/dist/components/admin/fields/TextareaField.svelte.d.ts.map +0 -1
- package/dist/components/fields/index.d.ts +0 -9
- package/dist/components/fields/index.d.ts.map +0 -1
- package/dist/components/index.d.ts +0 -7
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/layout/OrganizationSwitcher.svelte.d.ts +0 -11
- package/dist/components/layout/OrganizationSwitcher.svelte.d.ts.map +0 -1
- package/dist/components/layout/Sidebar.svelte.d.ts +0 -14
- package/dist/components/layout/Sidebar.svelte.d.ts.map +0 -1
- package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +0 -4
- package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +0 -1
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts +0 -19
- package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +0 -1
- package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts +0 -9
- package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts.map +0 -1
- package/dist/components/layout/sidebar/NavUser.svelte.d.ts +0 -9
- package/dist/components/layout/sidebar/NavUser.svelte.d.ts.map +0 -1
- package/dist/config.d.ts +0 -3
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -15
- package/dist/db/adapters/index.d.ts +0 -1
- package/dist/db/adapters/index.d.ts.map +0 -1
- package/dist/db/index.d.ts +0 -2
- package/dist/db/index.d.ts.map +0 -1
- package/dist/db/interfaces/asset.d.ts +0 -51
- package/dist/db/interfaces/asset.d.ts.map +0 -1
- package/dist/db/interfaces/asset.js +0 -1
- package/dist/db/interfaces/document.d.ts +0 -36
- package/dist/db/interfaces/document.d.ts.map +0 -1
- package/dist/db/interfaces/document.js +0 -1
- package/dist/db/interfaces/index.d.ts +0 -73
- package/dist/db/interfaces/index.d.ts.map +0 -1
- package/dist/db/interfaces/index.js +0 -1
- package/dist/db/interfaces/organization.d.ts +0 -27
- package/dist/db/interfaces/organization.d.ts.map +0 -1
- package/dist/db/interfaces/organization.js +0 -1
- package/dist/db/interfaces/schema.d.ts +0 -21
- package/dist/db/interfaces/schema.d.ts.map +0 -1
- package/dist/db/interfaces/schema.js +0 -1
- package/dist/db/interfaces/user.d.ts +0 -15
- package/dist/db/interfaces/user.d.ts.map +0 -1
- package/dist/db/interfaces/user.js +0 -1
- package/dist/db/utils/reference-resolver.d.ts +0 -18
- package/dist/db/utils/reference-resolver.d.ts.map +0 -1
- package/dist/db/utils/reference-resolver.js +0 -80
- package/dist/define.d.ts +0 -3
- package/dist/define.d.ts.map +0 -1
- package/dist/define.js +0 -4
- package/dist/email/index.d.ts +0 -2
- package/dist/email/index.d.ts.map +0 -1
- package/dist/email/interfaces/email.d.ts +0 -42
- package/dist/email/interfaces/email.d.ts.map +0 -1
- package/dist/email/interfaces/email.js +0 -1
- package/dist/engine.d.ts +0 -26
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -66
- package/dist/field-validation/rule.d.ts +0 -51
- package/dist/field-validation/rule.d.ts.map +0 -1
- package/dist/field-validation/rule.js +0 -221
- package/dist/field-validation/utils.d.ts +0 -21
- package/dist/field-validation/utils.d.ts.map +0 -1
- package/dist/field-validation/utils.js +0 -66
- package/dist/hooks.d.ts +0 -23
- package/dist/hooks.d.ts.map +0 -1
- package/dist/hooks.js +0 -96
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +0 -1
- package/dist/is-mobile.svelte.d.ts +0 -5
- package/dist/is-mobile.svelte.d.ts.map +0 -1
- package/dist/routes/assets-by-id.d.ts +0 -5
- package/dist/routes/assets-by-id.d.ts.map +0 -1
- package/dist/routes/assets-by-id.js +0 -138
- package/dist/routes/assets-cdn.d.ts +0 -3
- package/dist/routes/assets-cdn.d.ts.map +0 -1
- package/dist/routes/assets-cdn.js +0 -155
- package/dist/routes/assets.d.ts +0 -4
- package/dist/routes/assets.d.ts.map +0 -1
- package/dist/routes/assets.js +0 -94
- package/dist/routes/documents-by-id.d.ts +0 -5
- package/dist/routes/documents-by-id.d.ts.map +0 -1
- package/dist/routes/documents-by-id.js +0 -142
- package/dist/routes/documents-publish.d.ts +0 -4
- package/dist/routes/documents-publish.d.ts.map +0 -1
- package/dist/routes/documents-publish.js +0 -151
- package/dist/routes/documents.d.ts +0 -4
- package/dist/routes/documents.d.ts.map +0 -1
- package/dist/routes/documents.js +0 -131
- package/dist/routes/index.d.ts +0 -6
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/index.js +0 -10
- package/dist/routes/organizations-by-id.d.ts +0 -5
- package/dist/routes/organizations-by-id.d.ts.map +0 -1
- package/dist/routes/organizations-by-id.js +0 -187
- package/dist/routes/organizations-invitations.d.ts +0 -4
- package/dist/routes/organizations-invitations.d.ts.map +0 -1
- package/dist/routes/organizations-invitations.js +0 -125
- package/dist/routes/organizations-members.d.ts +0 -5
- package/dist/routes/organizations-members.d.ts.map +0 -1
- package/dist/routes/organizations-members.js +0 -206
- package/dist/routes/organizations-switch.d.ts +0 -3
- package/dist/routes/organizations-switch.d.ts.map +0 -1
- package/dist/routes/organizations-switch.js +0 -53
- package/dist/routes/organizations.d.ts +0 -4
- package/dist/routes/organizations.d.ts.map +0 -1
- package/dist/routes/organizations.js +0 -109
- package/dist/routes/schemas-by-type.d.ts +0 -3
- package/dist/routes/schemas-by-type.d.ts.map +0 -1
- package/dist/routes/schemas-by-type.js +0 -25
- package/dist/routes/schemas.d.ts +0 -3
- package/dist/routes/schemas.d.ts.map +0 -1
- package/dist/routes/schemas.js +0 -11
- package/dist/routes-exports.d.ts +0 -14
- package/dist/routes-exports.d.ts.map +0 -1
- package/dist/routes-exports.js +0 -19
- package/dist/schema-context.svelte.d.ts +0 -10
- package/dist/schema-context.svelte.d.ts.map +0 -1
- package/dist/schema-context.svelte.js +0 -18
- package/dist/schema-utils/cleanup.d.ts +0 -21
- package/dist/schema-utils/cleanup.d.ts.map +0 -1
- package/dist/schema-utils/cleanup.js +0 -80
- package/dist/schema-utils/index.d.ts +0 -4
- package/dist/schema-utils/index.d.ts.map +0 -1
- package/dist/schema-utils/index.js +0 -4
- package/dist/schema-utils/utils.d.ts +0 -30
- package/dist/schema-utils/utils.d.ts.map +0 -1
- package/dist/schema-utils/utils.js +0 -37
- package/dist/schema-utils/validator.d.ts +0 -6
- package/dist/schema-utils/validator.d.ts.map +0 -1
- package/dist/schema-utils/validator.js +0 -45
- package/dist/server/index.d.ts +0 -16
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js +0 -28
- package/dist/services/asset-service.d.ts +0 -86
- package/dist/services/asset-service.d.ts.map +0 -1
- package/dist/services/asset-service.js +0 -187
- package/dist/services/index.d.ts +0 -3
- package/dist/services/index.d.ts.map +0 -1
- package/dist/services/index.js +0 -4
- package/dist/storage/adapters/index.d.ts +0 -2
- package/dist/storage/adapters/index.d.ts.map +0 -1
- package/dist/storage/adapters/index.js +0 -2
- package/dist/storage/adapters/local-storage-adapter.d.ts +0 -54
- package/dist/storage/adapters/local-storage-adapter.d.ts.map +0 -1
- package/dist/storage/adapters/local-storage-adapter.js +0 -187
- package/dist/storage/index.d.ts +0 -3
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/interfaces/index.d.ts +0 -2
- package/dist/storage/interfaces/index.d.ts.map +0 -1
- package/dist/storage/interfaces/index.js +0 -2
- package/dist/storage/interfaces/storage.d.ts +0 -91
- package/dist/storage/interfaces/storage.d.ts.map +0 -1
- package/dist/storage/interfaces/storage.js +0 -1
- package/dist/storage/providers/storage.d.ts +0 -43
- package/dist/storage/providers/storage.d.ts.map +0 -1
- package/dist/storage/providers/storage.js +0 -64
- package/dist/types/asset.d.ts +0 -73
- package/dist/types/asset.d.ts.map +0 -1
- package/dist/types/asset.js +0 -2
- package/dist/types/auth.d.ts +0 -50
- package/dist/types/auth.d.ts.map +0 -1
- package/dist/types/auth.js +0 -41
- package/dist/types/config.d.ts +0 -47
- package/dist/types/config.d.ts.map +0 -1
- package/dist/types/config.js +0 -1
- package/dist/types/document.d.ts +0 -34
- package/dist/types/document.d.ts.map +0 -1
- package/dist/types/document.js +0 -1
- package/dist/types/index.d.ts +0 -9
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -8
- package/dist/types/organization.d.ts +0 -105
- package/dist/types/organization.d.ts.map +0 -1
- package/dist/types/organization.js +0 -3
- package/dist/types/schemas.d.ts +0 -114
- package/dist/types/schemas.d.ts.map +0 -1
- package/dist/types/schemas.js +0 -1
- package/dist/types/sidebar.d.ts +0 -33
- package/dist/types/sidebar.d.ts.map +0 -1
- package/dist/types/sidebar.js +0 -1
- package/dist/types/user.d.ts +0 -14
- package/dist/types/user.d.ts.map +0 -1
- package/dist/types/user.js +0 -1
- package/dist/utils/content-hash.d.ts +0 -22
- package/dist/utils/content-hash.d.ts.map +0 -1
- package/dist/utils/content-hash.js +0 -67
- package/dist/utils/image-url.d.ts +0 -88
- package/dist/utils/image-url.d.ts.map +0 -1
- package/dist/utils/image-url.js +0 -165
- package/dist/utils/index.d.ts +0 -6
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -9
- package/dist/utils/slug.d.ts +0 -13
- package/dist/utils/slug.d.ts.map +0 -1
- package/dist/utils/slug.js +0 -30
- package/dist/utils.d.ts +0 -13
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -5
- /package/{dist → src/lib}/app.d.ts +0 -0
- /package/{dist → src/lib}/auth/MULTI_TENANCY_PLAN.md +0 -0
- /package/{dist → src/lib}/components/admin/AdminLayout.svelte +0 -0
- /package/{dist → src/lib}/components/admin/DocumentEditor.svelte +0 -0
- /package/{dist → src/lib}/components/admin/DocumentTypesList.svelte +0 -0
- /package/{dist → src/lib}/components/admin/ObjectModal.svelte +0 -0
- /package/{dist → src/lib}/components/admin/SchemaField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/ArrayField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/BooleanField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/ImageField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/NumberField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/ReferenceField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/SlugField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/StringField.svelte +0 -0
- /package/{dist → src/lib}/components/admin/fields/TextareaField.svelte +0 -0
- /package/{dist/components/fields/index.js → src/lib/components/fields/index.ts} +0 -0
- /package/{dist → src/lib}/components/layout/OrganizationSwitcher.svelte +0 -0
- /package/{dist → src/lib}/components/layout/Sidebar.svelte +0 -0
- /package/{dist → src/lib}/components/layout/sidebar/AppSidebar.svelte +0 -0
- /package/{dist → src/lib}/components/layout/sidebar/NavMain.svelte +0 -0
- /package/{dist → src/lib}/components/layout/sidebar/NavSecondary.svelte +0 -0
- /package/{dist → src/lib}/components/layout/sidebar/NavUser.svelte +0 -0
- /package/{dist → src/lib}/plugins/README.md +0 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// packages/cms-core/src/auth/provider.ts
|
|
2
|
+
import type { SessionAuth, ApiKeyAuth } from '../types/index';
|
|
3
|
+
import type { DatabaseAdapter } from '../db/interfaces/index';
|
|
4
|
+
|
|
5
|
+
export interface AuthProvider {
|
|
6
|
+
// Session auth (browser, admin UI)
|
|
7
|
+
getSession(request: Request, db: DatabaseAdapter): Promise<SessionAuth | null>;
|
|
8
|
+
requireSession(request: Request, db: DatabaseAdapter): Promise<SessionAuth>;
|
|
9
|
+
|
|
10
|
+
// API key auth (programmatic access)
|
|
11
|
+
validateApiKey(request: Request, db: DatabaseAdapter): Promise<ApiKeyAuth | null>;
|
|
12
|
+
requireApiKey(
|
|
13
|
+
request: Request,
|
|
14
|
+
db: DatabaseAdapter,
|
|
15
|
+
permission?: 'read' | 'write'
|
|
16
|
+
): Promise<ApiKeyAuth>;
|
|
17
|
+
|
|
18
|
+
// User management
|
|
19
|
+
getUserById(userId: string): Promise<{ id: string; name?: string; email: string } | null>;
|
|
20
|
+
changeUserName(userId: string, name: string): Promise<void>;
|
|
21
|
+
|
|
22
|
+
// Password reset
|
|
23
|
+
requestPasswordReset(email: string, redirectTo?: string): Promise<void>;
|
|
24
|
+
resetPassword(token: string, newPassword: string): Promise<void>;
|
|
25
|
+
}
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
// Aphex CMS Core - Client-side exports
|
|
2
2
|
// These are safe to import in the browser (no Node.js dependencies)
|
|
3
|
+
|
|
3
4
|
// Core types (shared between client and server)
|
|
4
|
-
export * from '../types/index
|
|
5
|
+
export * from '../types/index';
|
|
6
|
+
export type { SidebarUser, SidebarNavItem, SidebarBranding, SidebarData } from '../types/sidebar';
|
|
7
|
+
|
|
5
8
|
// Field validation (client-side validation)
|
|
6
|
-
export * from '../field-validation/rule
|
|
7
|
-
export * from '../field-validation/utils
|
|
9
|
+
export * from '../field-validation/rule';
|
|
10
|
+
export * from '../field-validation/utils';
|
|
11
|
+
|
|
8
12
|
// Content hashing utilities (for client-side change detection)
|
|
9
|
-
export { createContentHash, hasUnpublishedChanges } from '../utils/content-hash
|
|
13
|
+
export { createContentHash, hasUnpublishedChanges } from '../utils/content-hash';
|
|
14
|
+
|
|
10
15
|
// Schema context (for providing schemas to components)
|
|
11
16
|
export { setSchemaContext, getSchemaContext } from '../schema-context.svelte';
|
|
17
|
+
|
|
12
18
|
// Schema utilities (for working with schemas)
|
|
13
|
-
export * from '../schema-utils/index
|
|
19
|
+
export * from '../schema-utils/index';
|
|
20
|
+
|
|
14
21
|
// Components (UI components for the admin interface)
|
|
15
22
|
export { default as DocumentEditor } from '../components/admin/DocumentEditor.svelte';
|
|
16
23
|
export { default as DocumentTypesList } from '../components/admin/DocumentTypesList.svelte';
|
|
17
24
|
export { default as SchemaField } from '../components/admin/SchemaField.svelte';
|
|
18
25
|
export { default as AdminApp } from '../components/AdminApp.svelte';
|
|
19
26
|
export { default as Sidebar } from '../components/layout/Sidebar.svelte';
|
|
27
|
+
|
|
20
28
|
// Field components
|
|
21
29
|
export { default as StringField } from '../components/admin/fields/StringField.svelte';
|
|
22
30
|
export { default as TextareaField } from '../components/admin/fields/TextareaField.svelte';
|
|
@@ -26,6 +34,9 @@ export { default as ImageField } from '../components/admin/fields/ImageField.sve
|
|
|
26
34
|
export { default as SlugField } from '../components/admin/fields/SlugField.svelte';
|
|
27
35
|
export { default as ArrayField } from '../components/admin/fields/ArrayField.svelte';
|
|
28
36
|
export { default as ReferenceField } from '../components/admin/fields/ReferenceField.svelte';
|
|
37
|
+
|
|
29
38
|
// Utility functions (browser-safe)
|
|
30
|
-
export * from '../utils/index
|
|
31
|
-
|
|
39
|
+
export * from '../utils/index';
|
|
40
|
+
|
|
41
|
+
export * from '../api/index';
|
|
42
|
+
export type { ApiResponse } from '../api/index';
|
|
@@ -13,12 +13,13 @@
|
|
|
13
13
|
import DocumentEditor from './admin/DocumentEditor.svelte';
|
|
14
14
|
import type { DocumentType } from '../types/index';
|
|
15
15
|
import { documents } from '../api/index';
|
|
16
|
+
import { FileText } from 'lucide-svelte';
|
|
16
17
|
|
|
17
|
-
type InitDocumentType = Pick<DocumentType, 'name' | 'title' | 'description'>;
|
|
18
|
+
type InitDocumentType = Pick<DocumentType, 'name' | 'title' | 'description' | 'icon'>;
|
|
18
19
|
|
|
19
20
|
interface Props {
|
|
20
21
|
schemas: SchemaType[];
|
|
21
|
-
documentTypes:
|
|
22
|
+
documentTypes: Array<{ name: string; title: string; description?: string }>;
|
|
22
23
|
schemaError?: { message: string } | null;
|
|
23
24
|
title?: string;
|
|
24
25
|
graphqlSettings?: { endpoint: string; enableGraphiQL: boolean } | null;
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
|
|
30
31
|
let {
|
|
31
32
|
schemas,
|
|
32
|
-
documentTypes,
|
|
33
|
+
documentTypes: documentTypesFromServer,
|
|
33
34
|
schemaError = null,
|
|
34
35
|
title = 'Aphex CMS',
|
|
35
36
|
graphqlSettings = null,
|
|
@@ -38,7 +39,16 @@
|
|
|
38
39
|
handleTabChange = () => {}
|
|
39
40
|
}: Props = $props();
|
|
40
41
|
|
|
41
|
-
//
|
|
42
|
+
// Merge document types with schema icons (schemas have icons, server data doesn't)
|
|
43
|
+
const documentTypes = $derived(
|
|
44
|
+
documentTypesFromServer.map((docType) => {
|
|
45
|
+
const schema = schemas.find((s) => s.name === docType.name);
|
|
46
|
+
return {
|
|
47
|
+
...docType,
|
|
48
|
+
icon: schema?.icon
|
|
49
|
+
};
|
|
50
|
+
})
|
|
51
|
+
);
|
|
42
52
|
|
|
43
53
|
const hasDocumentTypes = $derived(documentTypes.length > 0);
|
|
44
54
|
|
|
@@ -730,7 +740,12 @@
|
|
|
730
740
|
>
|
|
731
741
|
<div class="flex items-center gap-3">
|
|
732
742
|
<div class="flex h-6 w-6 items-center justify-center">
|
|
733
|
-
|
|
743
|
+
{#if docType.icon}
|
|
744
|
+
{@const Icon = docType.icon}
|
|
745
|
+
<Icon class="text-muted-foreground h-4 w-4" />
|
|
746
|
+
{:else}
|
|
747
|
+
<FileText class="text-muted-foreground h-4 w-4" />
|
|
748
|
+
{/if}
|
|
734
749
|
</div>
|
|
735
750
|
<div>
|
|
736
751
|
<h3 class="text-sm font-medium">{docType.title}s</h3>
|
|
@@ -763,7 +778,7 @@
|
|
|
763
778
|
<div
|
|
764
779
|
class="bg-muted/50 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
|
|
765
780
|
>
|
|
766
|
-
<
|
|
781
|
+
<FileText class="text-muted-foreground h-8 w-8" />
|
|
767
782
|
</div>
|
|
768
783
|
<h3 class="mb-2 font-medium">No content types found</h3>
|
|
769
784
|
<p class="text-muted-foreground mb-4 text-sm">
|
|
@@ -806,19 +821,26 @@
|
|
|
806
821
|
</div>
|
|
807
822
|
</button>
|
|
808
823
|
{:else}
|
|
824
|
+
{@const currentDocType = documentTypes.find(
|
|
825
|
+
(t) => t.name === selectedDocumentType
|
|
826
|
+
)}
|
|
809
827
|
<div class="border-border bg-muted/20 border-b p-3">
|
|
810
828
|
<div class="flex items-center justify-between">
|
|
811
829
|
<div class="flex items-center gap-3">
|
|
812
830
|
{#if windowWidth > 620}
|
|
813
831
|
<!-- Desktop: Icon -->
|
|
814
832
|
<div class="flex h-6 w-6 items-center justify-center">
|
|
815
|
-
|
|
833
|
+
{#if currentDocType?.icon}
|
|
834
|
+
{@const Icon = currentDocType.icon}
|
|
835
|
+
<Icon class="text-muted-foreground h-4 w-4" />
|
|
836
|
+
{:else}
|
|
837
|
+
<FileText class="text-muted-foreground h-4 w-4" />
|
|
838
|
+
{/if}
|
|
816
839
|
</div>
|
|
817
840
|
{/if}
|
|
818
841
|
<div>
|
|
819
842
|
<h3 class="text-sm font-medium">
|
|
820
|
-
{(
|
|
821
|
-
selectedDocumentType) + 's'}
|
|
843
|
+
{(currentDocType?.title || selectedDocumentType) + 's'}
|
|
822
844
|
</h3>
|
|
823
845
|
<p class="text-muted-foreground text-xs">
|
|
824
846
|
{documentsList.length} document{documentsList.length !== 1 ? 's' : ''}
|
|
@@ -870,7 +892,12 @@
|
|
|
870
892
|
>
|
|
871
893
|
<div class="flex min-w-0 flex-1 items-center gap-3">
|
|
872
894
|
<div class="flex h-6 w-6 items-center justify-center">
|
|
873
|
-
|
|
895
|
+
{#if currentDocType?.icon}
|
|
896
|
+
{@const Icon = currentDocType.icon}
|
|
897
|
+
<Icon class="text-muted-foreground h-4 w-4" />
|
|
898
|
+
{:else}
|
|
899
|
+
<FileText class="text-muted-foreground h-4 w-4" />
|
|
900
|
+
{/if}
|
|
874
901
|
</div>
|
|
875
902
|
<div class="min-w-0 flex-1">
|
|
876
903
|
<h3 class="truncate text-sm font-medium">{doc.title}</h3>
|
|
@@ -895,7 +922,12 @@
|
|
|
895
922
|
<div
|
|
896
923
|
class="bg-muted/50 mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full"
|
|
897
924
|
>
|
|
898
|
-
|
|
925
|
+
{#if currentDocType?.icon}
|
|
926
|
+
{@const Icon = currentDocType.icon}
|
|
927
|
+
<Icon class="text-muted-foreground h-8 w-8" />
|
|
928
|
+
{:else}
|
|
929
|
+
<FileText class="text-muted-foreground h-8 w-8" />
|
|
930
|
+
{/if}
|
|
899
931
|
</div>
|
|
900
932
|
<h3 class="mb-2 font-medium">No documents found</h3>
|
|
901
933
|
<p class="text-muted-foreground text-sm">
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// Aphex CMS Components
|
|
2
2
|
// All admin interface components -- is this being used?
|
|
3
|
+
|
|
3
4
|
// Main admin app
|
|
4
5
|
export { default as AdminApp } from './AdminApp.svelte';
|
|
6
|
+
|
|
5
7
|
// Sidebar
|
|
6
8
|
export { default as Sidebar } from './layout/Sidebar.svelte';
|
|
9
|
+
|
|
7
10
|
// Admin components (will be migrated from your current structure)
|
|
8
11
|
export { default as DocumentEditor } from './admin/DocumentEditor.svelte';
|
|
9
12
|
export { default as DocumentTypesList } from './admin/DocumentTypesList.svelte';
|
|
10
13
|
export { default as SchemaField } from './admin/SchemaField.svelte';
|
|
14
|
+
|
|
11
15
|
// Field components
|
|
12
|
-
export * from './fields/index
|
|
16
|
+
export * from './fields/index';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Aphex CMS Configuration System
|
|
2
|
+
import type { CMSConfig } from './types/index';
|
|
3
|
+
|
|
4
|
+
export function createCMSConfig(config: CMSConfig): CMSConfig {
|
|
5
|
+
return {
|
|
6
|
+
// Start with the user's config and apply defaults for missing properties
|
|
7
|
+
...config,
|
|
8
|
+
storage: config.storage ?? null, // Default to null if not provided
|
|
9
|
+
customization: {
|
|
10
|
+
branding: {
|
|
11
|
+
title: 'Aphex CMS',
|
|
12
|
+
...config.customization?.branding
|
|
13
|
+
},
|
|
14
|
+
...config.customization
|
|
15
|
+
},
|
|
16
|
+
plugins: config.plugins ?? []
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Asset interface for asset operations
|
|
2
|
+
import type { Asset } from '../../types/index';
|
|
3
|
+
|
|
4
|
+
export interface AssetFilters {
|
|
5
|
+
organizationId: string; // Required for multi-tenancy (user's current org for RLS context)
|
|
6
|
+
assetType?: 'image' | 'file';
|
|
7
|
+
mimeType?: string;
|
|
8
|
+
search?: string;
|
|
9
|
+
limit?: number;
|
|
10
|
+
offset?: number;
|
|
11
|
+
filterOrganizationIds?: string[]; // Optional: Filter to specific org(s). RLS still enforces access.
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CreateAssetData {
|
|
15
|
+
organizationId: string; // Required for multi-tenancy
|
|
16
|
+
assetType: 'image' | 'file';
|
|
17
|
+
filename: string;
|
|
18
|
+
originalFilename: string;
|
|
19
|
+
mimeType: string;
|
|
20
|
+
size: number;
|
|
21
|
+
url: string;
|
|
22
|
+
path: string;
|
|
23
|
+
storageAdapter: string; // Which storage adapter was used
|
|
24
|
+
width?: number;
|
|
25
|
+
height?: number;
|
|
26
|
+
metadata?: any;
|
|
27
|
+
title?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
alt?: string;
|
|
30
|
+
creditLine?: string;
|
|
31
|
+
createdBy?: string; // User ID (optional for backward compatibility)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UpdateAssetData {
|
|
35
|
+
url?: string; // Allow updating URL (for local storage after asset creation)
|
|
36
|
+
title?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
alt?: string;
|
|
39
|
+
creditLine?: string;
|
|
40
|
+
updatedBy?: string; // User ID (optional for backward compatibility)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Asset adapter interface for asset-specific operations
|
|
45
|
+
*/
|
|
46
|
+
export interface AssetAdapter {
|
|
47
|
+
// Asset CRUD operations
|
|
48
|
+
createAsset(data: CreateAssetData): Promise<Asset>;
|
|
49
|
+
findAssetById(organizationId: string, id: string): Promise<Asset | null>;
|
|
50
|
+
findAssets(
|
|
51
|
+
organizationId: string,
|
|
52
|
+
filters?: Omit<AssetFilters, 'organizationId'>
|
|
53
|
+
): Promise<Asset[]>;
|
|
54
|
+
updateAsset(organizationId: string, id: string, data: UpdateAssetData): Promise<Asset | null>;
|
|
55
|
+
deleteAsset(organizationId: string, id: string): Promise<boolean>;
|
|
56
|
+
|
|
57
|
+
// Asset analytics
|
|
58
|
+
countAssets(organizationId: string): Promise<number>;
|
|
59
|
+
countAssetsByType(organizationId: string): Promise<Record<string, number>>;
|
|
60
|
+
getTotalAssetsSize(organizationId: string): Promise<number>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Document interface for document operations
|
|
2
|
+
import type { Document } from '../../types/index';
|
|
3
|
+
|
|
4
|
+
export interface DocumentFilters {
|
|
5
|
+
organizationId: string; // Required for multi-tenancy (user's current org for RLS context)
|
|
6
|
+
type?: string;
|
|
7
|
+
status?: string;
|
|
8
|
+
limit?: number;
|
|
9
|
+
offset?: number;
|
|
10
|
+
depth?: number; // How deep to resolve nested references (0 = no resolution, default = 0)
|
|
11
|
+
filterOrganizationIds?: string[]; // Optional: Filter to specific org(s). RLS still enforces access.
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CreateDocumentData {
|
|
15
|
+
organizationId: string; // Required for multi-tenancy
|
|
16
|
+
type: string;
|
|
17
|
+
draftData: any;
|
|
18
|
+
createdBy?: string; // User ID (optional for backward compatibility)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface UpdateDocumentData {
|
|
22
|
+
draftData?: any;
|
|
23
|
+
status?: string;
|
|
24
|
+
updatedBy?: string; // User ID (optional for backward compatibility)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Document adapter interface for document-specific operations
|
|
29
|
+
*/
|
|
30
|
+
export interface DocumentAdapter {
|
|
31
|
+
// Document CRUD operations
|
|
32
|
+
findManyDoc(
|
|
33
|
+
organizationId: string,
|
|
34
|
+
filters?: Omit<DocumentFilters, 'organizationId'>
|
|
35
|
+
): Promise<Document[]>;
|
|
36
|
+
findByDocId(organizationId: string, id: string, depth?: number): Promise<Document | null>;
|
|
37
|
+
createDocument(data: CreateDocumentData): Promise<Document>;
|
|
38
|
+
updateDocDraft(
|
|
39
|
+
organizationId: string,
|
|
40
|
+
id: string,
|
|
41
|
+
data: any,
|
|
42
|
+
updatedBy?: string
|
|
43
|
+
): Promise<Document | null>;
|
|
44
|
+
deleteDocById(organizationId: string, id: string): Promise<boolean>;
|
|
45
|
+
|
|
46
|
+
// Publishing operations
|
|
47
|
+
publishDoc(organizationId: string, id: string): Promise<Document | null>;
|
|
48
|
+
unpublishDoc(organizationId: string, id: string): Promise<Document | null>;
|
|
49
|
+
|
|
50
|
+
// Analytics/counts
|
|
51
|
+
countDocsByType(organizationId: string, type: string): Promise<number>;
|
|
52
|
+
getDocCountsByType(organizationId: string): Promise<Record<string, number>>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Combined database interface
|
|
2
|
+
import type { DocumentAdapter } from './document';
|
|
3
|
+
import type { AssetAdapter } from './asset';
|
|
4
|
+
import type { UserProfileAdapter } from './user';
|
|
5
|
+
import type { SchemaAdapter } from './schema';
|
|
6
|
+
import type { OrganizationAdapter } from './organization';
|
|
7
|
+
|
|
8
|
+
// Re-export individual interfaces
|
|
9
|
+
export type {
|
|
10
|
+
DocumentAdapter,
|
|
11
|
+
DocumentFilters,
|
|
12
|
+
CreateDocumentData,
|
|
13
|
+
UpdateDocumentData
|
|
14
|
+
} from './document';
|
|
15
|
+
export type { AssetAdapter, CreateAssetData, UpdateAssetData } from './asset';
|
|
16
|
+
export type { UserProfileAdapter, NewUserProfileData } from './user';
|
|
17
|
+
export type { SchemaAdapter } from './schema';
|
|
18
|
+
export type { OrganizationAdapter } from './organization';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Combined database adapter interface
|
|
22
|
+
* Extends all entity-specific adapters for full database functionality
|
|
23
|
+
*/
|
|
24
|
+
export interface DatabaseAdapter
|
|
25
|
+
extends DocumentAdapter,
|
|
26
|
+
AssetAdapter,
|
|
27
|
+
UserProfileAdapter,
|
|
28
|
+
SchemaAdapter,
|
|
29
|
+
OrganizationAdapter {
|
|
30
|
+
// Connection management
|
|
31
|
+
connect?(): Promise<void>;
|
|
32
|
+
disconnect?(): Promise<void>;
|
|
33
|
+
|
|
34
|
+
// Health check
|
|
35
|
+
isHealthy(): Promise<boolean>;
|
|
36
|
+
|
|
37
|
+
// Multi-tenancy RLS methods (optional - only for adapters that support RLS)
|
|
38
|
+
/**
|
|
39
|
+
* Initialize RLS (enable/disable) on tables - call after migrations
|
|
40
|
+
*/
|
|
41
|
+
initializeRLS?(): Promise<void>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Execute a function within a transaction with organization context set for RLS
|
|
45
|
+
* Ensures proper isolation with connection pooling
|
|
46
|
+
*/
|
|
47
|
+
withOrgContext?<T>(organizationId: string, fn: () => Promise<T>): Promise<T>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get all child organizations for a parent (for hierarchy support)
|
|
51
|
+
*/
|
|
52
|
+
getChildOrganizations?(parentOrganizationId: string): Promise<string[]>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Check if any user profiles exist in the system (for first-user detection)
|
|
56
|
+
*/
|
|
57
|
+
hasAnyUserProfiles?(): Promise<boolean>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Database provider factory interface
|
|
62
|
+
* Providers are pre-configured and create adapters on demand
|
|
63
|
+
*/
|
|
64
|
+
export interface DatabaseProvider {
|
|
65
|
+
name: string;
|
|
66
|
+
createAdapter(): DatabaseAdapter;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Generic database configuration
|
|
71
|
+
*/
|
|
72
|
+
export interface DatabaseConfig {
|
|
73
|
+
connectionString?: string; // Optional if client is provided
|
|
74
|
+
client?: any; // Pre-initialized database client (recommended for database agnosticism)
|
|
75
|
+
options?: {
|
|
76
|
+
maxConnections?: number;
|
|
77
|
+
timeout?: number;
|
|
78
|
+
ssl?: boolean;
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Database transaction interface (optional for advanced providers)
|
|
85
|
+
*/
|
|
86
|
+
export interface DatabaseTransaction {
|
|
87
|
+
commit(): Promise<void>;
|
|
88
|
+
rollback(): Promise<void>;
|
|
89
|
+
isActive(): boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Extended database adapter with transaction support
|
|
94
|
+
*/
|
|
95
|
+
export interface TransactionalDatabaseAdapter extends DatabaseAdapter {
|
|
96
|
+
beginTransaction(): Promise<DatabaseTransaction>;
|
|
97
|
+
withTransaction<T>(fn: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
|
|
98
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Organization adapter interface for multi-tenancy operations
|
|
2
|
+
import type {
|
|
3
|
+
Organization,
|
|
4
|
+
NewOrganization,
|
|
5
|
+
OrganizationMember,
|
|
6
|
+
NewOrganizationMember,
|
|
7
|
+
Invitation,
|
|
8
|
+
NewInvitation,
|
|
9
|
+
UserSession,
|
|
10
|
+
OrganizationMembership
|
|
11
|
+
} from '../../types/organization';
|
|
12
|
+
|
|
13
|
+
export interface OrganizationAdapter {
|
|
14
|
+
// Organization CRUD
|
|
15
|
+
createOrganization(data: NewOrganization): Promise<Organization>;
|
|
16
|
+
findOrganizationById(id: string): Promise<Organization | null>;
|
|
17
|
+
findOrganizationBySlug(slug: string): Promise<Organization | null>;
|
|
18
|
+
updateOrganization(
|
|
19
|
+
id: string,
|
|
20
|
+
data: Partial<Omit<Organization, 'id' | 'createdAt' | 'createdBy'>>
|
|
21
|
+
): Promise<Organization | null>;
|
|
22
|
+
deleteOrganization(id: string): Promise<boolean>;
|
|
23
|
+
|
|
24
|
+
// Member management
|
|
25
|
+
addMember(data: NewOrganizationMember): Promise<OrganizationMember>;
|
|
26
|
+
removeMember(organizationId: string, userId: string): Promise<boolean>;
|
|
27
|
+
removeAllMembers(organizationId: string): Promise<boolean>;
|
|
28
|
+
updateMemberRole(
|
|
29
|
+
organizationId: string,
|
|
30
|
+
userId: string,
|
|
31
|
+
role: 'owner' | 'admin' | 'editor' | 'viewer'
|
|
32
|
+
): Promise<OrganizationMember | null>;
|
|
33
|
+
findUserMembership(userId: string, organizationId: string): Promise<OrganizationMember | null>;
|
|
34
|
+
findUserOrganizations(userId: string): Promise<OrganizationMembership[]>;
|
|
35
|
+
findOrganizationMembers(organizationId: string): Promise<OrganizationMember[]>;
|
|
36
|
+
|
|
37
|
+
// Invitation management
|
|
38
|
+
createInvitation(data: NewInvitation): Promise<Invitation>;
|
|
39
|
+
findInvitationByToken(token: string): Promise<Invitation | null>;
|
|
40
|
+
findOrganizationInvitations(organizationId: string): Promise<Invitation[]>;
|
|
41
|
+
findInvitationsByEmail(email: string): Promise<Invitation[]>;
|
|
42
|
+
acceptInvitation(token: string, userId: string): Promise<OrganizationMember>;
|
|
43
|
+
deleteInvitation(id: string): Promise<boolean>;
|
|
44
|
+
removeAllInvitations(organizationId: string): Promise<boolean>;
|
|
45
|
+
cleanupExpiredInvitations(): Promise<number>;
|
|
46
|
+
|
|
47
|
+
// User session management
|
|
48
|
+
updateUserSession(userId: string, organizationId: string): Promise<void>;
|
|
49
|
+
findUserSession(userId: string): Promise<UserSession | null>;
|
|
50
|
+
deleteUserSession(userId: string): Promise<boolean>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SchemaType } from '../../types/index';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines database operations for managing schemas.
|
|
5
|
+
*/
|
|
6
|
+
export interface SchemaAdapter {
|
|
7
|
+
registerSchemaType(schemaType: SchemaType): Promise<void>;
|
|
8
|
+
getSchemaType(name: string): Promise<SchemaType | null>;
|
|
9
|
+
listSchemas(): Promise<SchemaType[]>;
|
|
10
|
+
listDocumentTypes(): Promise<Array<{ name: string; title: string; description?: string }>>;
|
|
11
|
+
listObjectTypes(): Promise<Array<{ name: string; title: string; description?: string }>>;
|
|
12
|
+
deleteSchemaType(name: string): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { UserProfile } from '../../types/index';
|
|
2
|
+
|
|
3
|
+
export interface NewUserProfileData {
|
|
4
|
+
userId: string;
|
|
5
|
+
role?: 'super_admin' | 'admin' | 'editor' | 'viewer';
|
|
6
|
+
preferences?: Record<string, any>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Defines database operations for managing user profiles.
|
|
11
|
+
*/
|
|
12
|
+
export interface UserProfileAdapter {
|
|
13
|
+
createUserProfile(data: NewUserProfileData): Promise<UserProfile>;
|
|
14
|
+
findUserProfileById(userId: string): Promise<UserProfile | null>;
|
|
15
|
+
deleteUserProfile(userId: string): Promise<boolean>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Reference resolution utility for resolving nested document references
|
|
2
|
+
import type { Document } from '../../types/index';
|
|
3
|
+
import type { DocumentAdapter } from '../interfaces/document';
|
|
4
|
+
|
|
5
|
+
interface ResolveOptions {
|
|
6
|
+
depth: number;
|
|
7
|
+
currentDepth?: number;
|
|
8
|
+
visited?: Set<string>; // Track visited documents to prevent circular references
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Recursively resolves reference fields in a document
|
|
13
|
+
* @param document - The document to resolve references for
|
|
14
|
+
* @param adapter - Document adapter for fetching referenced documents
|
|
15
|
+
* @param organizationId - Organization ID for filtering referenced documents
|
|
16
|
+
* @param options - Resolution options (depth, tracking)
|
|
17
|
+
* @returns Document with resolved references
|
|
18
|
+
*/
|
|
19
|
+
export async function resolveReferences(
|
|
20
|
+
document: Document,
|
|
21
|
+
adapter: DocumentAdapter,
|
|
22
|
+
organizationId: string,
|
|
23
|
+
options: ResolveOptions
|
|
24
|
+
): Promise<Document> {
|
|
25
|
+
const { depth, currentDepth = 0, visited = new Set() } = options;
|
|
26
|
+
|
|
27
|
+
// Base case: no more depth to resolve or already visited (circular reference)
|
|
28
|
+
if (currentDepth >= depth || visited.has(document.id)) {
|
|
29
|
+
return document;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Mark as visited
|
|
33
|
+
visited.add(document.id);
|
|
34
|
+
|
|
35
|
+
// Clone the document to avoid mutations
|
|
36
|
+
const resolvedDocument = { ...document };
|
|
37
|
+
|
|
38
|
+
// Resolve references in draftData
|
|
39
|
+
if (document.draftData) {
|
|
40
|
+
resolvedDocument.draftData = await resolveDataReferences(
|
|
41
|
+
document.draftData,
|
|
42
|
+
adapter,
|
|
43
|
+
organizationId,
|
|
44
|
+
{
|
|
45
|
+
depth,
|
|
46
|
+
currentDepth: currentDepth + 1,
|
|
47
|
+
visited
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Resolve references in publishedData
|
|
53
|
+
if (document.publishedData) {
|
|
54
|
+
resolvedDocument.publishedData = await resolveDataReferences(
|
|
55
|
+
document.publishedData,
|
|
56
|
+
adapter,
|
|
57
|
+
organizationId,
|
|
58
|
+
{
|
|
59
|
+
depth,
|
|
60
|
+
currentDepth: currentDepth + 1,
|
|
61
|
+
visited
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return resolvedDocument;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolves references within document data (recursive)
|
|
71
|
+
*/
|
|
72
|
+
async function resolveDataReferences(
|
|
73
|
+
data: any,
|
|
74
|
+
adapter: DocumentAdapter,
|
|
75
|
+
organizationId: string,
|
|
76
|
+
options: ResolveOptions
|
|
77
|
+
): Promise<any> {
|
|
78
|
+
if (!data || typeof data !== 'object') {
|
|
79
|
+
return data;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Handle arrays
|
|
83
|
+
if (Array.isArray(data)) {
|
|
84
|
+
return Promise.all(
|
|
85
|
+
data.map((item) => resolveDataReferences(item, adapter, organizationId, options))
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Clone object
|
|
90
|
+
const resolved: any = {};
|
|
91
|
+
|
|
92
|
+
for (const [key, value] of Object.entries(data)) {
|
|
93
|
+
// Check if this looks like a reference field (string ID)
|
|
94
|
+
if (typeof value === 'string' && key !== '_type' && key !== '_key') {
|
|
95
|
+
// Try to fetch the referenced document
|
|
96
|
+
try {
|
|
97
|
+
const referencedDoc = await adapter.findByDocId(organizationId, value);
|
|
98
|
+
if (referencedDoc) {
|
|
99
|
+
// Recursively resolve nested references
|
|
100
|
+
resolved[key] = await resolveReferences(referencedDoc, adapter, organizationId, options);
|
|
101
|
+
} else {
|
|
102
|
+
// Reference not found, keep the ID
|
|
103
|
+
resolved[key] = value;
|
|
104
|
+
}
|
|
105
|
+
} catch (error) {
|
|
106
|
+
// On error, keep the original value
|
|
107
|
+
resolved[key] = value;
|
|
108
|
+
}
|
|
109
|
+
} else if (value && typeof value === 'object') {
|
|
110
|
+
// Recursively resolve nested objects/arrays
|
|
111
|
+
resolved[key] = await resolveDataReferences(value, adapter, organizationId, options);
|
|
112
|
+
} else {
|
|
113
|
+
// Primitive value, keep as is
|
|
114
|
+
resolved[key] = value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return resolved;
|
|
119
|
+
}
|