@sonicjs-cms/core 2.18.1 → 3.0.0-beta.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.
- package/README.md +52 -52
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-layout-catalyst.template-UMTIN66R.js.map → admin-documents-form.template-DDSH6ROU.js.map} +1 -1
- package/dist/admin-documents-form.template-LSZKGA5J.cjs +19 -0
- package/dist/{admin-layout-catalyst.template-HFD37TY5.cjs.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.ts} +25 -1
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs +21 -0
- package/dist/admin-layout-catalyst.template-KDHKVLXR.cjs.map +1 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js.map +1 -0
- package/dist/app-Bo0X1OWX.d.ts +1268 -0
- package/dist/app-Do66yCcV.d.cts +1268 -0
- package/dist/cache-DDARE4QE.js +4 -0
- package/dist/cache-DDARE4QE.js.map +1 -0
- package/dist/cache-LVYS4BPL.cjs +33 -0
- package/dist/cache-LVYS4BPL.cjs.map +1 -0
- package/dist/chunk-2CB4KY7I.cjs +771 -0
- package/dist/chunk-2CB4KY7I.cjs.map +1 -0
- package/dist/{chunk-ABB34XUS.cjs → chunk-3KYKEXV7.cjs} +667 -19
- package/dist/chunk-3KYKEXV7.cjs.map +1 -0
- package/dist/chunk-4BTBSXMR.cjs +912 -0
- package/dist/chunk-4BTBSXMR.cjs.map +1 -0
- package/dist/{chunk-55RDMDOP.js → chunk-5V62WT6M.js} +181 -57
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/{chunk-XXDFQERJ.js → chunk-6OC6MF3C.js} +7192 -9806
- package/dist/chunk-6OC6MF3C.js.map +1 -0
- package/dist/chunk-AI663NBO.js +821 -0
- package/dist/chunk-AI663NBO.js.map +1 -0
- package/dist/chunk-ALDRXTUO.js +273 -0
- package/dist/chunk-ALDRXTUO.js.map +1 -0
- package/dist/{chunk-TFNTM3OA.js → chunk-ATUPB6MN.js} +645 -15
- package/dist/chunk-ATUPB6MN.js.map +1 -0
- package/dist/chunk-BLMTL57B.js +767 -0
- package/dist/chunk-BLMTL57B.js.map +1 -0
- package/dist/{chunk-4ZSNJDLS.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/chunk-CRGUD4KC.cjs.map +1 -0
- package/dist/chunk-F67UK75A.cjs +158 -0
- package/dist/chunk-F67UK75A.cjs.map +1 -0
- package/dist/chunk-GCDZZNIN.js +192 -0
- package/dist/chunk-GCDZZNIN.js.map +1 -0
- package/dist/chunk-HIKBY7MS.cjs +70 -0
- package/dist/chunk-HIKBY7MS.cjs.map +1 -0
- package/dist/chunk-IDCZBF35.js +1186 -0
- package/dist/chunk-IDCZBF35.js.map +1 -0
- package/dist/chunk-IESEVHXL.js +66 -0
- package/dist/chunk-IESEVHXL.js.map +1 -0
- package/dist/chunk-IGADDMXH.js +387 -0
- package/dist/chunk-IGADDMXH.js.map +1 -0
- package/dist/chunk-IHTXB7AT.cjs +276 -0
- package/dist/chunk-IHTXB7AT.cjs.map +1 -0
- package/dist/chunk-IVPRUGTY.js +242 -0
- package/dist/chunk-IVPRUGTY.js.map +1 -0
- package/dist/{chunk-SQ6FNXU2.cjs → chunk-IXUHXTHW.cjs} +2 -151
- package/dist/chunk-IXUHXTHW.cjs.map +1 -0
- package/dist/chunk-J6JTWD2A.cjs +100 -0
- package/dist/chunk-J6JTWD2A.cjs.map +1 -0
- package/dist/chunk-JEQ7FLOD.cjs +199 -0
- package/dist/chunk-JEQ7FLOD.cjs.map +1 -0
- package/dist/{chunk-ON5ZMSU4.js → chunk-JQISFW6U.js} +3 -3
- package/dist/chunk-JQISFW6U.js.map +1 -0
- package/dist/chunk-K25XHMM3.js +566 -0
- package/dist/chunk-K25XHMM3.js.map +1 -0
- package/dist/{chunk-UYJ6TJHX.cjs → chunk-K623Q6WD.cjs} +181 -56
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/chunk-MUNO67TT.cjs +1219 -0
- package/dist/chunk-MUNO67TT.cjs.map +1 -0
- package/dist/chunk-N32OWET6.cjs +327 -0
- package/dist/chunk-N32OWET6.cjs.map +1 -0
- package/dist/chunk-NUKJ54GA.cjs +245 -0
- package/dist/chunk-NUKJ54GA.cjs.map +1 -0
- package/dist/{chunk-XWIA3HVX.js → chunk-OBA2RYZN.js} +6 -1249
- package/dist/chunk-OBA2RYZN.js.map +1 -0
- package/dist/chunk-PMGOBS6X.cjs +408 -0
- package/dist/chunk-PMGOBS6X.cjs.map +1 -0
- package/dist/{chunk-OHYBNCVL.cjs → chunk-PXNTCCPE.cjs} +10 -1256
- package/dist/chunk-PXNTCCPE.cjs.map +1 -0
- package/dist/chunk-PYVFXCSD.js +1828 -0
- package/dist/chunk-PYVFXCSD.js.map +1 -0
- package/dist/{chunk-MGFRZO24.js → chunk-QZGABF2M.js} +3 -149
- package/dist/chunk-QZGABF2M.js.map +1 -0
- package/dist/{chunk-T3Q5V33G.cjs → chunk-R4ILO3W6.cjs} +876 -829
- package/dist/chunk-R4ILO3W6.cjs.map +1 -0
- package/dist/chunk-RMRJGMDE.js +323 -0
- package/dist/chunk-RMRJGMDE.js.map +1 -0
- package/dist/chunk-RNZFGN4R.js +88 -0
- package/dist/chunk-RNZFGN4R.js.map +1 -0
- package/dist/chunk-RQ6N3FTV.js +900 -0
- package/dist/chunk-RQ6N3FTV.js.map +1 -0
- package/dist/{chunk-SXXTQETM.cjs → chunk-TO6EY4P7.cjs} +8722 -11323
- package/dist/chunk-TO6EY4P7.cjs.map +1 -0
- package/dist/chunk-V464XBYS.js +154 -0
- package/dist/chunk-V464XBYS.js.map +1 -0
- package/dist/chunk-YA3TJ65D.cjs +575 -0
- package/dist/chunk-YA3TJ65D.cjs.map +1 -0
- package/dist/chunk-YP7GW2G5.cjs +866 -0
- package/dist/chunk-YP7GW2G5.cjs.map +1 -0
- package/dist/{collection-config-B4PG-AaF.d.cts → collection-config-JgHOpFCG.d.cts} +30 -2
- package/dist/{collection-config-B4PG-AaF.d.ts → collection-config-JgHOpFCG.d.ts} +30 -2
- package/dist/config-HFXANXCC.js +6 -0
- package/dist/config-HFXANXCC.js.map +1 -0
- package/dist/config-ON6FNMYX.cjs +19 -0
- package/dist/config-ON6FNMYX.cjs.map +1 -0
- package/dist/define-plugin-BzNHc1ZI.d.ts +1321 -0
- package/dist/define-plugin-IWDKYaVm.d.cts +1321 -0
- package/dist/document-projection-TDWRJX3Z.cjs +13 -0
- package/dist/document-projection-TDWRJX3Z.cjs.map +1 -0
- package/dist/document-projection-YYMC6I4U.js +4 -0
- package/dist/document-projection-YYMC6I4U.js.map +1 -0
- package/dist/index.cjs +13737 -4327
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +331 -493
- package/dist/index.d.ts +331 -493
- package/dist/index.js +13456 -4068
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +38 -32
- package/dist/middleware.d.cts +69 -7
- package/dist/middleware.d.ts +69 -7
- package/dist/middleware.js +9 -3
- package/dist/migrations-2XHQEGOQ.cjs +13 -0
- package/dist/{migrations-IYNTWDC6.cjs.map → migrations-2XHQEGOQ.cjs.map} +1 -1
- package/dist/migrations-PE3CDVSM.js +4 -0
- package/dist/{migrations-R337UD46.js.map → migrations-PE3CDVSM.js.map} +1 -1
- package/dist/{plugin-bootstrap-DfVerYV4.d.cts → plugin-bootstrap-B8ThJU21.d.cts} +4315 -1661
- package/dist/{plugin-bootstrap-P_ciLp_C.d.ts → plugin-bootstrap-qu8hJgUt.d.ts} +4315 -1661
- package/dist/plugins.cjs +171 -12
- package/dist/plugins.d.cts +36 -2
- package/dist/plugins.d.ts +36 -2
- package/dist/plugins.js +5 -2
- package/dist/rbac-O73MFKDA.js +5 -0
- package/dist/rbac-O73MFKDA.js.map +1 -0
- package/dist/rbac-VONLJJKB.cjs +14 -0
- package/dist/rbac-VONLJJKB.cjs.map +1 -0
- package/dist/routes.cjs +42 -46
- package/dist/routes.d.cts +56 -146
- package/dist/routes.d.ts +56 -146
- package/dist/routes.js +18 -10
- package/dist/services.cjs +43 -76
- package/dist/services.d.cts +93 -55
- package/dist/services.d.ts +93 -55
- package/dist/services.js +6 -3
- package/dist/{telemetry-B9vIV4wh.d.cts → telemetry-Cku1ax74.d.cts} +1 -1
- package/dist/{telemetry-B9vIV4wh.d.ts → telemetry-Cku1ax74.d.ts} +1 -1
- package/dist/templates.cjs +17 -29
- package/dist/templates.d.cts +2 -89
- package/dist/templates.d.ts +2 -89
- package/dist/templates.js +3 -3
- package/dist/types-Dea1eNxU.d.cts +286 -0
- package/dist/types-Dea1eNxU.d.ts +286 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +21 -20
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +3 -2
- package/migrations/0001_core.sql +184 -0
- package/migrations/0002_documents.sql +163 -0
- package/package.json +12 -7
- package/dist/admin-layout-catalyst.template-HFD37TY5.cjs +0 -17
- package/dist/admin-layout-catalyst.template-UMTIN66R.js +0 -7
- package/dist/app-C9esKLmh.d.cts +0 -112
- package/dist/app-C9esKLmh.d.ts +0 -112
- package/dist/chunk-4R3NOOL3.js +0 -2217
- package/dist/chunk-4R3NOOL3.js.map +0 -1
- package/dist/chunk-4ZSNJDLS.cjs.map +0 -1
- package/dist/chunk-55RDMDOP.js.map +0 -1
- package/dist/chunk-635JAMSE.cjs +0 -653
- package/dist/chunk-635JAMSE.cjs.map +0 -1
- package/dist/chunk-ABB34XUS.cjs.map +0 -1
- package/dist/chunk-C54YUA23.cjs +0 -2219
- package/dist/chunk-C54YUA23.cjs.map +0 -1
- package/dist/chunk-DSUJ5YQH.cjs +0 -722
- package/dist/chunk-DSUJ5YQH.cjs.map +0 -1
- package/dist/chunk-EW5NOBVU.js +0 -1783
- package/dist/chunk-EW5NOBVU.js.map +0 -1
- package/dist/chunk-EXNEW5US.js +0 -648
- package/dist/chunk-EXNEW5US.js.map +0 -1
- package/dist/chunk-I2H5NGJQ.js +0 -692
- package/dist/chunk-I2H5NGJQ.js.map +0 -1
- package/dist/chunk-MGFRZO24.js.map +0 -1
- package/dist/chunk-OHYBNCVL.cjs.map +0 -1
- package/dist/chunk-ON5ZMSU4.js.map +0 -1
- package/dist/chunk-QFWHAFEO.js +0 -1843
- package/dist/chunk-QFWHAFEO.js.map +0 -1
- package/dist/chunk-SQ6FNXU2.cjs.map +0 -1
- package/dist/chunk-SXXTQETM.cjs.map +0 -1
- package/dist/chunk-T3Q5V33G.cjs.map +0 -1
- package/dist/chunk-TFNTM3OA.js.map +0 -1
- package/dist/chunk-UYJ6TJHX.cjs.map +0 -1
- package/dist/chunk-WAEQXGCX.cjs +0 -1898
- package/dist/chunk-WAEQXGCX.cjs.map +0 -1
- package/dist/chunk-XWIA3HVX.js.map +0 -1
- package/dist/chunk-XXDFQERJ.js.map +0 -1
- package/dist/migrations-IYNTWDC6.cjs +0 -13
- package/dist/migrations-R337UD46.js +0 -4
- package/dist/plugin-manager-BoM3Q7o7.d.cts +0 -328
- package/dist/plugin-manager-Efx9RyDX.d.ts +0 -328
- package/migrations/001_initial_schema.sql +0 -170
- package/migrations/002_faq_plugin.sql +0 -86
- package/migrations/003_stage5_enhancements.sql +0 -121
- package/migrations/004_stage6_user_management.sql +0 -183
- package/migrations/005_stage7_workflow_automation.sql +0 -294
- package/migrations/006_plugin_system.sql +0 -155
- package/migrations/007_demo_login_plugin.sql +0 -23
- package/migrations/008_fix_slug_validation.sql +0 -22
- package/migrations/009_system_logging.sql +0 -57
- package/migrations/011_config_managed_collections.sql +0 -15
- package/migrations/012_testimonials_plugin.sql +0 -80
- package/migrations/013_code_examples_plugin.sql +0 -177
- package/migrations/014_fix_plugin_registry.sql +0 -88
- package/migrations/015_add_remaining_plugins.sql +0 -89
- package/migrations/016_remove_duplicate_cache_plugin.sql +0 -17
- package/migrations/017_auth_configurable_fields.sql +0 -49
- package/migrations/018_settings_table.sql +0 -23
- package/migrations/019_remove_blog_posts_collection.sql +0 -15
- package/migrations/020_add_email_plugin.sql +0 -22
- package/migrations/021_add_magic_link_auth_plugin.sql +0 -42
- package/migrations/022_add_tinymce_plugin.sql +0 -25
- package/migrations/023_add_easy_mdx_plugin.sql +0 -25
- package/migrations/024_add_quill_editor_plugin.sql +0 -25
- package/migrations/025_add_easymde_plugin.sql +0 -25
- package/migrations/026_add_otp_login.sql +0 -42
- package/migrations/027_fix_slug_field_type.sql +0 -18
- package/migrations/028_fix_slug_field_type_in_schemas.sql +0 -30
- package/migrations/029_add_forms_system.sql +0 -184
- package/migrations/030_add_turnstile_to_forms.sql +0 -14
- package/migrations/031_ai_search_plugin.sql +0 -45
- package/migrations/032_user_profiles.sql +0 -37
- package/migrations/033_form_content_integration.sql +0 -19
- package/migrations/034_security_audit_plugin.sql +0 -27
- package/migrations/035_user_profiles_data_column.sql +0 -16
- package/migrations/036_analytics_events.sql +0 -22
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed hook event catalog
|
|
3
|
+
*
|
|
4
|
+
* The single source of truth for which lifecycle events a plugin may subscribe
|
|
5
|
+
* to, and the payload shape each one carries. Subscribing through the typed
|
|
6
|
+
* facade (`createTypedHooks`) gives a plugin the narrowed payload type with no
|
|
7
|
+
* casting — TypeScript rejects a wrong field name at the `.on()` call site.
|
|
8
|
+
*
|
|
9
|
+
* Scope note: this catalog lists the events that are (or are being) dispatched
|
|
10
|
+
* in production. The legacy string-keyed `HOOKS` map in `../types` declared many
|
|
11
|
+
* more events than were ever fired; reconciling that list down to what actually
|
|
12
|
+
* dispatches is tracked in the plugin-overhaul plan. Add an event here only when
|
|
13
|
+
* a real dispatch site exists (or is landing in the same change).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The acting user on a hook event. ONE canonical shape across every event —
|
|
17
|
+
* always `id` (never `userId`), so a plugin reading `payload.user.id` works on
|
|
18
|
+
* content events and auth events alike.
|
|
19
|
+
*/
|
|
20
|
+
interface HookActor {
|
|
21
|
+
id: string;
|
|
22
|
+
email: string;
|
|
23
|
+
role?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Common shape for content lifecycle events. */
|
|
26
|
+
interface ContentEventPayload {
|
|
27
|
+
/** Collection / content-type slug the event is about. */
|
|
28
|
+
collection: string;
|
|
29
|
+
/** Content row id, when known (absent for pre-create events). */
|
|
30
|
+
id?: string;
|
|
31
|
+
/** The content data being read/written. Mutable by `before` handlers in the chain. */
|
|
32
|
+
data: Record<string, unknown>;
|
|
33
|
+
/** The acting user, when the event originates from an authenticated request. */
|
|
34
|
+
user?: HookActor;
|
|
35
|
+
}
|
|
36
|
+
/** Emitted after a user completes self-registration. */
|
|
37
|
+
interface AuthRegistrationCompletedPayload {
|
|
38
|
+
user: HookActor;
|
|
39
|
+
}
|
|
40
|
+
/** Emitted when a password reset is requested (carries the reset token internally). */
|
|
41
|
+
interface AuthPasswordResetRequestedPayload {
|
|
42
|
+
user: HookActor;
|
|
43
|
+
/** Single-use reset token. Never expose this in an API response. */
|
|
44
|
+
resetToken: string;
|
|
45
|
+
}
|
|
46
|
+
/** Emitted after a password reset is confirmed. */
|
|
47
|
+
interface AuthPasswordResetCompletedPayload {
|
|
48
|
+
user: HookActor;
|
|
49
|
+
}
|
|
50
|
+
/** Emitted after a magic-link sign-in link is successfully consumed. */
|
|
51
|
+
interface AuthMagicLinkConsumedPayload {
|
|
52
|
+
user: HookActor;
|
|
53
|
+
}
|
|
54
|
+
/** Emitted after an OTP code is successfully verified. */
|
|
55
|
+
interface AuthOtpVerifiedPayload {
|
|
56
|
+
user: HookActor;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The catalog: event name → payload type.
|
|
60
|
+
*
|
|
61
|
+
* Keep keys in sync with `HookEventName` (derived below) and with the dispatch
|
|
62
|
+
* sites. This is an interface (not a const) so it participates in type-level
|
|
63
|
+
* lookups and can be augmented via declaration merging if a downstream package
|
|
64
|
+
* needs to extend it.
|
|
65
|
+
*/
|
|
66
|
+
interface HookEventPayloads {
|
|
67
|
+
'content:read': ContentEventPayload;
|
|
68
|
+
'content:before:create': ContentEventPayload;
|
|
69
|
+
'content:before:update': ContentEventPayload;
|
|
70
|
+
'content:before:delete': ContentEventPayload;
|
|
71
|
+
'content:after:create': ContentEventPayload;
|
|
72
|
+
'content:after:update': ContentEventPayload;
|
|
73
|
+
'content:after:delete': ContentEventPayload;
|
|
74
|
+
'content:after:publish': ContentEventPayload;
|
|
75
|
+
'auth:registration:completed': AuthRegistrationCompletedPayload;
|
|
76
|
+
'auth:password-reset:requested': AuthPasswordResetRequestedPayload;
|
|
77
|
+
'auth:password-reset:completed': AuthPasswordResetCompletedPayload;
|
|
78
|
+
'auth:magic-link:consumed': AuthMagicLinkConsumedPayload;
|
|
79
|
+
'auth:otp:verified': AuthOtpVerifiedPayload;
|
|
80
|
+
}
|
|
81
|
+
/** Union of all catalog event names. */
|
|
82
|
+
type HookEventName = keyof HookEventPayloads;
|
|
83
|
+
/** The payload type for a given event name. */
|
|
84
|
+
type HookPayload<E extends HookEventName> = HookEventPayloads[E];
|
|
85
|
+
/**
|
|
86
|
+
* Runtime list of catalog event names.
|
|
87
|
+
*
|
|
88
|
+
* Useful for validation (e.g. "is this a known event?") and for diagnostics.
|
|
89
|
+
* Kept as a typed tuple so it can't silently drift from the interface: any new
|
|
90
|
+
* key added to `HookEventPayloads` should be added here too, and the
|
|
91
|
+
* `satisfies` check below fails the build if the list references an unknown
|
|
92
|
+
* event.
|
|
93
|
+
*/
|
|
94
|
+
declare const HOOK_EVENT_NAMES: readonly ["content:read", "content:before:create", "content:before:update", "content:before:delete", "content:after:create", "content:after:update", "content:after:delete", "content:after:publish", "auth:registration:completed", "auth:password-reset:requested", "auth:password-reset:completed", "auth:magic-link:consumed", "auth:otp:verified"];
|
|
95
|
+
/** True if `name` is a canonical catalog event. */
|
|
96
|
+
declare function isKnownHookEvent(name: string): name is HookEventName;
|
|
97
|
+
/** Deprecated event names mapped to their canonical payload type. */
|
|
98
|
+
interface LegacyHookEventPayloads {
|
|
99
|
+
'content:create': ContentEventPayload;
|
|
100
|
+
'content:update': ContentEventPayload;
|
|
101
|
+
'content:delete': ContentEventPayload;
|
|
102
|
+
'content:publish': ContentEventPayload;
|
|
103
|
+
/** No after-only successor; folded into update. */
|
|
104
|
+
'content:save': ContentEventPayload;
|
|
105
|
+
}
|
|
106
|
+
/** Map each deprecated name to the canonical name it resolves to. */
|
|
107
|
+
declare const LEGACY_EVENT_ALIASES: {
|
|
108
|
+
readonly 'content:create': "content:after:create";
|
|
109
|
+
readonly 'content:update': "content:after:update";
|
|
110
|
+
readonly 'content:delete': "content:after:delete";
|
|
111
|
+
readonly 'content:publish': "content:after:publish";
|
|
112
|
+
readonly 'content:save': "content:after:update";
|
|
113
|
+
};
|
|
114
|
+
/** A deprecated event name accepted (with a warning) at subscribe time. */
|
|
115
|
+
type LegacyHookEventName = keyof LegacyHookEventPayloads;
|
|
116
|
+
/** True if `name` is a deprecated alias. */
|
|
117
|
+
declare function isLegacyHookEvent(name: string): name is LegacyHookEventName;
|
|
118
|
+
/**
|
|
119
|
+
* Resolve a subscribe-time event name to its canonical form: returns the name
|
|
120
|
+
* itself if canonical, the aliased canonical name if deprecated, or `undefined`
|
|
121
|
+
* if unknown.
|
|
122
|
+
*/
|
|
123
|
+
declare function resolveHookEventName(name: string): HookEventName | undefined;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Typed hook facade
|
|
127
|
+
*
|
|
128
|
+
* Wraps the (string-keyed, untyped) hook system in a catalog-aware API:
|
|
129
|
+
*
|
|
130
|
+
* const hooks = createTypedHooks(hookSystem)
|
|
131
|
+
* hooks.on('auth:registration:completed', (payload) => {
|
|
132
|
+
* payload.user.email // ✓ narrowed — no cast
|
|
133
|
+
* payload.user.nope // ✗ type error
|
|
134
|
+
* })
|
|
135
|
+
* await hooks.dispatch('auth:registration:completed', { user: {...} })
|
|
136
|
+
*
|
|
137
|
+
* The facade is intentionally structural about the underlying hook system (see
|
|
138
|
+
* `HookSystemLike`) so both `HookSystemImpl` and `ScopedHookSystem` — and the
|
|
139
|
+
* `src`/`dist` duplicate type identities — all satisfy it without casts.
|
|
140
|
+
*/
|
|
141
|
+
|
|
142
|
+
/** A name accepted at subscribe time: a canonical event or a deprecated alias. */
|
|
143
|
+
type SubscribableEvent = HookEventName | LegacyHookEventName;
|
|
144
|
+
/** The payload type for a subscribable name — canonical payload, even for aliases. */
|
|
145
|
+
type PayloadForEvent<E extends SubscribableEvent> = E extends HookEventName ? HookPayload<E> : E extends LegacyHookEventName ? LegacyHookEventPayloads[E] : never;
|
|
146
|
+
/**
|
|
147
|
+
* Minimal structural contract the typed facade needs from a hook system.
|
|
148
|
+
* Satisfied by `HookSystemImpl` and `ScopedHookSystem`.
|
|
149
|
+
*/
|
|
150
|
+
interface HookSystemLike {
|
|
151
|
+
register(hookName: string, handler: (data: any, context: any) => any, priority?: number): void;
|
|
152
|
+
execute(hookName: string, data: any, context?: any): Promise<any>;
|
|
153
|
+
unregister?(hookName: string, handler: (data: any, context: any) => any): void;
|
|
154
|
+
}
|
|
155
|
+
/** Context passed to a typed hook handler (kept loose; mirrors the legacy HookContext). */
|
|
156
|
+
interface TypedHookContext {
|
|
157
|
+
/** Plugin that registered the hook, if known. */
|
|
158
|
+
plugin?: string;
|
|
159
|
+
/** Cancel the remaining hook chain. */
|
|
160
|
+
cancel?: () => void;
|
|
161
|
+
[key: string]: unknown;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A typed hook handler. May mutate and return the payload (threaded to the next
|
|
165
|
+
* handler), or return nothing (the current payload is preserved).
|
|
166
|
+
*/
|
|
167
|
+
type TypedHookHandler<E extends HookEventName> = (payload: HookPayload<E>, context: TypedHookContext) => HookPayload<E> | void | Promise<HookPayload<E> | void>;
|
|
168
|
+
interface TypedHooks {
|
|
169
|
+
/**
|
|
170
|
+
* Subscribe to a catalog event. Accepts canonical names and (for one release)
|
|
171
|
+
* deprecated aliases — an alias resolves to its canonical name and emits a
|
|
172
|
+
* one-time deprecation warning. Lower priority runs earlier (default 10).
|
|
173
|
+
*/
|
|
174
|
+
on<E extends SubscribableEvent>(event: E, handler: (payload: PayloadForEvent<E>, context: TypedHookContext) => PayloadForEvent<E> | void | Promise<PayloadForEvent<E> | void>, priority?: number): void;
|
|
175
|
+
/**
|
|
176
|
+
* Dispatch a catalog event through the handler chain. Canonical names only —
|
|
177
|
+
* the host owns dispatch sites. Returns the (possibly mutated) payload.
|
|
178
|
+
*/
|
|
179
|
+
dispatch<E extends HookEventName>(event: E, payload: HookPayload<E>, context?: TypedHookContext): Promise<HookPayload<E>>;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Build a typed facade over a hook system.
|
|
183
|
+
*
|
|
184
|
+
* `on()` resolves deprecated aliases to canonical names (warning once), then
|
|
185
|
+
* registers under the canonical name so a legacy subscriber fires when the host
|
|
186
|
+
* dispatches the canonical event. Returning `void` from a handler preserves the
|
|
187
|
+
* current payload in the chain (the underlying `execute()` threads whatever each
|
|
188
|
+
* handler returns, so we coalesce `undefined` back to the incoming data).
|
|
189
|
+
*/
|
|
190
|
+
declare function createTypedHooks(hookSystem: HookSystemLike): TypedHooks;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Provider-agnostic email types
|
|
194
|
+
*
|
|
195
|
+
* The whole point of this layer: a SonicJS app sends mail through one
|
|
196
|
+
* `EmailService` chokepoint, and the *transport* is a swappable `EmailProvider`.
|
|
197
|
+
* Built-ins ship for Resend and SendGrid, but a developer can drop in any
|
|
198
|
+
* implementation of `EmailProvider` (Postmark, SES, an internal relay, a mock in
|
|
199
|
+
* tests) without touching call sites. Every send is recorded in `email_log`.
|
|
200
|
+
*/
|
|
201
|
+
/** A message as authored by a caller. `from` is optional (the service fills a default). */
|
|
202
|
+
interface EmailMessage {
|
|
203
|
+
to: string | string[];
|
|
204
|
+
subject: string;
|
|
205
|
+
html?: string;
|
|
206
|
+
text?: string;
|
|
207
|
+
/** Overrides the service's default from-address. */
|
|
208
|
+
from?: string;
|
|
209
|
+
replyTo?: string;
|
|
210
|
+
cc?: string | string[];
|
|
211
|
+
bcc?: string | string[];
|
|
212
|
+
/** Extra transport headers. */
|
|
213
|
+
headers?: Record<string, string>;
|
|
214
|
+
/**
|
|
215
|
+
* Logical flow this send belongs to (e.g. `'password-reset'`, `'otp'`,
|
|
216
|
+
* `'magic-link'`, `'welcome'`, `'test'`). Recorded in `email_log.flow` for
|
|
217
|
+
* observability; does not affect delivery.
|
|
218
|
+
*/
|
|
219
|
+
flow?: string;
|
|
220
|
+
/** Free-form metadata recorded (as JSON) in `email_log.metadata`. */
|
|
221
|
+
metadata?: Record<string, unknown>;
|
|
222
|
+
}
|
|
223
|
+
/** A message after the service has resolved defaults — what a provider receives. */
|
|
224
|
+
interface NormalizedEmailMessage extends Omit<EmailMessage, 'to' | 'cc' | 'bcc'> {
|
|
225
|
+
to: string[];
|
|
226
|
+
from: string;
|
|
227
|
+
cc?: string[];
|
|
228
|
+
bcc?: string[];
|
|
229
|
+
}
|
|
230
|
+
/** Outcome of a single send attempt. */
|
|
231
|
+
interface SendResult {
|
|
232
|
+
ok: boolean;
|
|
233
|
+
/** Provider that handled (or attempted) the send. */
|
|
234
|
+
provider: string;
|
|
235
|
+
/** Provider-side message id, when the transport returns one. */
|
|
236
|
+
providerId?: string;
|
|
237
|
+
/** Error message when `ok` is false. */
|
|
238
|
+
error?: string;
|
|
239
|
+
/** id of the `email_log` row written for this attempt, when logging is enabled. */
|
|
240
|
+
logId?: string;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A swappable email transport.
|
|
244
|
+
*
|
|
245
|
+
* Implement this to support any provider. `isConfigured()` lets the service (and
|
|
246
|
+
* `resolveEmailProvider`) decide whether a provider is usable before attempting a
|
|
247
|
+
* send — e.g. a Resend provider with no API key reports `false`.
|
|
248
|
+
*/
|
|
249
|
+
/**
|
|
250
|
+
* An email_log entry as seen by the reconciliation method.
|
|
251
|
+
* Derived from the documents row data JSON for type_id='email_log'.
|
|
252
|
+
* `id` is the document root_id used to identify the row.
|
|
253
|
+
*/
|
|
254
|
+
interface EmailLogRow {
|
|
255
|
+
id: string;
|
|
256
|
+
provider_id?: string | null;
|
|
257
|
+
provider: string;
|
|
258
|
+
status: 'sent' | 'failed' | string;
|
|
259
|
+
delivery_state?: string | null;
|
|
260
|
+
}
|
|
261
|
+
interface EmailProvider {
|
|
262
|
+
/** Stable identifier recorded in `email_log.provider` (e.g. `'resend'`). */
|
|
263
|
+
readonly name: string;
|
|
264
|
+
/** True if the provider has everything it needs to send (credentials, etc.). */
|
|
265
|
+
isConfigured(): boolean;
|
|
266
|
+
/** Attempt delivery. Must not throw for ordinary failures — return `ok: false`. */
|
|
267
|
+
send(message: NormalizedEmailMessage): Promise<SendResult>;
|
|
268
|
+
/**
|
|
269
|
+
* Optional: reconcile delivery state for a batch of recently-sent messages.
|
|
270
|
+
*
|
|
271
|
+
* Called by the core `email-reconciliation` cron. Providers that expose a
|
|
272
|
+
* delivery/event API (e.g. Cloudflare Email with delivery webhooks) implement
|
|
273
|
+
* this to backfill `delivery_state`. Providers without delivery status APIs
|
|
274
|
+
* (e.g. Resend, SendGrid at the current integration level) leave this undefined
|
|
275
|
+
* — those rows stay with `delivery_state = null`.
|
|
276
|
+
*
|
|
277
|
+
* Returning an array of `{ id, delivery_state }` updates the matching rows in
|
|
278
|
+
* `email_log`. Errors do not propagate (cron is fire-and-log).
|
|
279
|
+
*/
|
|
280
|
+
reconcile?(rows: EmailLogRow[]): Promise<Array<{
|
|
281
|
+
id: string;
|
|
282
|
+
delivery_state: string;
|
|
283
|
+
}>>;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export { type AuthMagicLinkConsumedPayload as A, type ContentEventPayload as C, type EmailProvider as E, HOOK_EVENT_NAMES as H, LEGACY_EVENT_ALIASES as L, type NormalizedEmailMessage as N, type PayloadForEvent as P, type SubscribableEvent as S, type TypedHookContext as T, type AuthOtpVerifiedPayload as a, type AuthPasswordResetCompletedPayload as b, type AuthPasswordResetRequestedPayload as c, type AuthRegistrationCompletedPayload as d, type HookActor as e, type HookEventName as f, type HookEventPayloads as g, type HookPayload as h, type HookSystemLike as i, type LegacyHookEventName as j, type LegacyHookEventPayloads as k, type TypedHookHandler as l, type TypedHooks as m, createTypedHooks as n, isKnownHookEvent as o, isLegacyHookEvent as p, type SendResult as q, resolveHookEventName as r, type EmailLogRow as s, type EmailMessage as t };
|
package/dist/types.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { B as BlockDefinition, a as BlockDefinitions, C as CollectionConfig, b as CollectionConfigModule, c as CollectionSchema, d as CollectionSyncResult, F as FieldConfig, e as FieldType } from './collection-config-
|
|
1
|
+
export { B as BlockDefinition, a as BlockDefinitions, C as CollectionConfig, b as CollectionConfigModule, c as CollectionSchema, d as CollectionSyncResult, F as FieldConfig, e as FieldType } from './collection-config-JgHOpFCG.cjs';
|
|
2
2
|
export { A as AuthService, C as ContentService, H as HOOKS, a as HookContext, b as HookHandler, c as HookName, d as HookSystem, M as MediaService, e as ModelRelationship, P as Plugin, f as PluginAdminPage, g as PluginBuilderOptions, h as PluginComponent, i as PluginConfig, j as PluginContext, k as PluginHook, l as PluginLogger, m as PluginManager, n as PluginMenuItem, o as PluginMiddleware, p as PluginModel, q as PluginRegistry, r as PluginRoutes, s as PluginService, t as PluginStatus, u as PluginValidationResult, v as PluginValidator, S as ScopedHookSystem } from './plugin-DDYetMF-.cjs';
|
|
3
3
|
export { P as PluginManifest } from './plugin-manifest-Dpy8wxIB.cjs';
|
|
4
|
-
export { T as TelemetryConfig, a as TelemetryEvent, b as TelemetryIdentity, c as TelemetryProperties } from './telemetry-
|
|
4
|
+
export { T as TelemetryConfig, a as TelemetryEvent, b as TelemetryIdentity, c as TelemetryProperties } from './telemetry-Cku1ax74.cjs';
|
|
5
5
|
import 'hono';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import '@cloudflare/workers-types';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { B as BlockDefinition, a as BlockDefinitions, C as CollectionConfig, b as CollectionConfigModule, c as CollectionSchema, d as CollectionSyncResult, F as FieldConfig, e as FieldType } from './collection-config-
|
|
1
|
+
export { B as BlockDefinition, a as BlockDefinitions, C as CollectionConfig, b as CollectionConfigModule, c as CollectionSchema, d as CollectionSyncResult, F as FieldConfig, e as FieldType } from './collection-config-JgHOpFCG.js';
|
|
2
2
|
export { A as AuthService, C as ContentService, H as HOOKS, a as HookContext, b as HookHandler, c as HookName, d as HookSystem, M as MediaService, e as ModelRelationship, P as Plugin, f as PluginAdminPage, g as PluginBuilderOptions, h as PluginComponent, i as PluginConfig, j as PluginContext, k as PluginHook, l as PluginLogger, m as PluginManager, n as PluginMenuItem, o as PluginMiddleware, p as PluginModel, q as PluginRegistry, r as PluginRoutes, s as PluginService, t as PluginStatus, u as PluginValidationResult, v as PluginValidator, S as ScopedHookSystem } from './plugin-DDYetMF-.js';
|
|
3
3
|
export { P as PluginManifest } from './plugin-manifest-Dpy8wxIB.js';
|
|
4
|
-
export { T as TelemetryConfig, a as TelemetryEvent, b as TelemetryIdentity, c as TelemetryProperties } from './telemetry-
|
|
4
|
+
export { T as TelemetryConfig, a as TelemetryEvent, b as TelemetryIdentity, c as TelemetryProperties } from './telemetry-Cku1ax74.js';
|
|
5
5
|
import 'hono';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import '@cloudflare/workers-types';
|
package/dist/utils.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var chunkP3XDZL6Q_cjs = require('./chunk-P3XDZL6Q.cjs');
|
|
3
|
+
var chunkIXUHXTHW_cjs = require('./chunk-IXUHXTHW.cjs');
|
|
5
4
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
5
|
+
var chunkP3XDZL6Q_cjs = require('./chunk-P3XDZL6Q.cjs');
|
|
6
|
+
var chunkF67UK75A_cjs = require('./chunk-F67UK75A.cjs');
|
|
6
7
|
var chunkMNWKYY5E_cjs = require('./chunk-MNWKYY5E.cjs');
|
|
7
8
|
require('./chunk-IGJUBJBW.cjs');
|
|
8
9
|
|
|
@@ -10,43 +11,39 @@ require('./chunk-IGJUBJBW.cjs');
|
|
|
10
11
|
|
|
11
12
|
Object.defineProperty(exports, "QueryFilterBuilder", {
|
|
12
13
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
14
|
-
});
|
|
15
|
-
Object.defineProperty(exports, "SONICJS_VERSION", {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return chunkSQ6FNXU2_cjs.SONICJS_VERSION; }
|
|
14
|
+
get: function () { return chunkIXUHXTHW_cjs.QueryFilterBuilder; }
|
|
18
15
|
});
|
|
19
16
|
Object.defineProperty(exports, "TemplateRenderer", {
|
|
20
17
|
enumerable: true,
|
|
21
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkIXUHXTHW_cjs.TemplateRenderer; }
|
|
22
19
|
});
|
|
23
20
|
Object.defineProperty(exports, "buildQuery", {
|
|
24
21
|
enumerable: true,
|
|
25
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkIXUHXTHW_cjs.buildQuery; }
|
|
26
23
|
});
|
|
27
24
|
Object.defineProperty(exports, "generateSlug", {
|
|
28
25
|
enumerable: true,
|
|
29
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkIXUHXTHW_cjs.generateSlug; }
|
|
30
27
|
});
|
|
31
28
|
Object.defineProperty(exports, "getBlocksFieldConfig", {
|
|
32
29
|
enumerable: true,
|
|
33
|
-
get: function () { return
|
|
34
|
-
});
|
|
35
|
-
Object.defineProperty(exports, "getCoreVersion", {
|
|
36
|
-
enumerable: true,
|
|
37
|
-
get: function () { return chunkSQ6FNXU2_cjs.getCoreVersion; }
|
|
30
|
+
get: function () { return chunkIXUHXTHW_cjs.getBlocksFieldConfig; }
|
|
38
31
|
});
|
|
39
32
|
Object.defineProperty(exports, "parseBlocksValue", {
|
|
40
33
|
enumerable: true,
|
|
41
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkIXUHXTHW_cjs.parseBlocksValue; }
|
|
42
35
|
});
|
|
43
36
|
Object.defineProperty(exports, "renderTemplate", {
|
|
44
37
|
enumerable: true,
|
|
45
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkIXUHXTHW_cjs.renderTemplate; }
|
|
46
39
|
});
|
|
47
40
|
Object.defineProperty(exports, "templateRenderer", {
|
|
48
41
|
enumerable: true,
|
|
49
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkIXUHXTHW_cjs.templateRenderer; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "metricsTracker", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkRCQ2HIQD_cjs.metricsTracker; }
|
|
50
47
|
});
|
|
51
48
|
Object.defineProperty(exports, "generateInstallationId", {
|
|
52
49
|
enumerable: true,
|
|
@@ -80,9 +77,13 @@ Object.defineProperty(exports, "shouldSkipEvent", {
|
|
|
80
77
|
enumerable: true,
|
|
81
78
|
get: function () { return chunkP3XDZL6Q_cjs.shouldSkipEvent; }
|
|
82
79
|
});
|
|
83
|
-
Object.defineProperty(exports, "
|
|
80
|
+
Object.defineProperty(exports, "SONICJS_VERSION", {
|
|
84
81
|
enumerable: true,
|
|
85
|
-
get: function () { return
|
|
82
|
+
get: function () { return chunkF67UK75A_cjs.SONICJS_VERSION; }
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "getCoreVersion", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () { return chunkF67UK75A_cjs.getCoreVersion; }
|
|
86
87
|
});
|
|
87
88
|
Object.defineProperty(exports, "escapeHtml", {
|
|
88
89
|
enumerable: true,
|
package/dist/utils.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { F as FilterCondition, a as FilterGroup, b as FilterOperator, Q as QueryFilter, c as QueryFilterBuilder, d as QueryResult, S as SONICJS_VERSION, T as TemplateRenderer, e as buildQuery, f as escapeHtml, g as getCoreVersion, m as metricsTracker, r as renderTemplate, s as sanitizeInput, h as sanitizeObject, t as templateRenderer } from './version-DFTyGfIH.cjs';
|
|
2
|
-
import { T as TelemetryConfig } from './telemetry-
|
|
3
|
-
import { a as BlockDefinitions } from './collection-config-
|
|
2
|
+
import { T as TelemetryConfig } from './telemetry-Cku1ax74.cjs';
|
|
3
|
+
import { a as BlockDefinitions } from './collection-config-JgHOpFCG.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Slug generation utilities for creating URL-friendly slugs
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { F as FilterCondition, a as FilterGroup, b as FilterOperator, Q as QueryFilter, c as QueryFilterBuilder, d as QueryResult, S as SONICJS_VERSION, T as TemplateRenderer, e as buildQuery, f as escapeHtml, g as getCoreVersion, m as metricsTracker, r as renderTemplate, s as sanitizeInput, h as sanitizeObject, t as templateRenderer } from './version-DFTyGfIH.js';
|
|
2
|
-
import { T as TelemetryConfig } from './telemetry-
|
|
3
|
-
import { a as BlockDefinitions } from './collection-config-
|
|
2
|
+
import { T as TelemetryConfig } from './telemetry-Cku1ax74.js';
|
|
3
|
+
import { a as BlockDefinitions } from './collection-config-JgHOpFCG.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Slug generation utilities for creating URL-friendly slugs
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { QueryFilterBuilder,
|
|
2
|
-
export { generateInstallationId, generateProjectId, getDefaultTelemetryConfig, getTelemetryConfig, isTelemetryEnabled, sanitizeErrorMessage, sanitizeRoute, shouldSkipEvent } from './chunk-X7ZAEI5S.js';
|
|
1
|
+
export { QueryFilterBuilder, TemplateRenderer, buildQuery, generateSlug, getBlocksFieldConfig, parseBlocksValue, renderTemplate, templateRenderer } from './chunk-QZGABF2M.js';
|
|
3
2
|
export { metricsTracker } from './chunk-FICTAGD4.js';
|
|
3
|
+
export { generateInstallationId, generateProjectId, getDefaultTelemetryConfig, getTelemetryConfig, isTelemetryEnabled, sanitizeErrorMessage, sanitizeRoute, shouldSkipEvent } from './chunk-X7ZAEI5S.js';
|
|
4
|
+
export { SONICJS_VERSION, getCoreVersion } from './chunk-V464XBYS.js';
|
|
4
5
|
export { escapeHtml, sanitizeInput, sanitizeObject } from './chunk-TQABQWOP.js';
|
|
5
6
|
import './chunk-V4OQ3NZ2.js';
|
|
6
7
|
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
-- Migration 0001: Auth tables
|
|
2
|
+
-- auth_user, auth_session, auth_account, auth_verification + BA plugin tables + RBAC + auth support.
|
|
3
|
+
-- Only auth_* prefixed tables live here. All content lives in document_* tables (0002_documents.sql).
|
|
4
|
+
|
|
5
|
+
-- ── auth_user ────────────────────────────────────────────────────────────────
|
|
6
|
+
-- BA user model + SonicJS domain columns as BA additionalFields.
|
|
7
|
+
CREATE TABLE IF NOT EXISTS auth_user (
|
|
8
|
+
id TEXT PRIMARY KEY,
|
|
9
|
+
name TEXT,
|
|
10
|
+
email TEXT NOT NULL UNIQUE,
|
|
11
|
+
email_verified INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
image TEXT,
|
|
13
|
+
created_at INTEGER NOT NULL,
|
|
14
|
+
updated_at INTEGER NOT NULL,
|
|
15
|
+
-- SonicJS additionalFields
|
|
16
|
+
first_name TEXT NOT NULL,
|
|
17
|
+
last_name TEXT NOT NULL,
|
|
18
|
+
role TEXT NOT NULL DEFAULT 'viewer',
|
|
19
|
+
-- Platform super-admin: bypasses the multi-tenant membership gate, uses global roles in every
|
|
20
|
+
-- tenant. Opt-in (default 0); intentionally NOT derived from the 'admin' role.
|
|
21
|
+
is_super_admin INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
avatar TEXT,
|
|
23
|
+
password_hash TEXT,
|
|
24
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
25
|
+
last_login_at INTEGER,
|
|
26
|
+
phone TEXT,
|
|
27
|
+
bio TEXT,
|
|
28
|
+
timezone TEXT DEFAULT 'UTC',
|
|
29
|
+
language TEXT DEFAULT 'en',
|
|
30
|
+
email_notifications INTEGER DEFAULT 1,
|
|
31
|
+
theme TEXT DEFAULT 'dark',
|
|
32
|
+
invitation_token TEXT,
|
|
33
|
+
invited_by TEXT,
|
|
34
|
+
invited_at INTEGER,
|
|
35
|
+
accepted_invitation_at INTEGER,
|
|
36
|
+
failed_login_count INTEGER NOT NULL DEFAULT 0,
|
|
37
|
+
locked_until INTEGER
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_auth_user_email ON auth_user(email);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_auth_user_role ON auth_user(role);
|
|
42
|
+
CREATE INDEX IF NOT EXISTS idx_auth_user_invitation_token ON auth_user(invitation_token);
|
|
43
|
+
CREATE INDEX IF NOT EXISTS idx_auth_user_locked_until ON auth_user(locked_until) WHERE locked_until IS NOT NULL;
|
|
44
|
+
|
|
45
|
+
-- ── auth_session ─────────────────────────────────────────────────────────────
|
|
46
|
+
CREATE TABLE IF NOT EXISTS auth_session (
|
|
47
|
+
id TEXT PRIMARY KEY,
|
|
48
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,
|
|
49
|
+
token TEXT NOT NULL UNIQUE,
|
|
50
|
+
expires_at INTEGER NOT NULL,
|
|
51
|
+
ip_address TEXT,
|
|
52
|
+
user_agent TEXT,
|
|
53
|
+
created_at INTEGER NOT NULL,
|
|
54
|
+
updated_at INTEGER NOT NULL
|
|
55
|
+
);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_auth_session_user_id ON auth_session(user_id);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_auth_session_token ON auth_session(token);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_auth_session_expires_at ON auth_session(expires_at);
|
|
59
|
+
|
|
60
|
+
-- ── auth_account ─────────────────────────────────────────────────────────────
|
|
61
|
+
CREATE TABLE IF NOT EXISTS auth_account (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,
|
|
64
|
+
account_id TEXT NOT NULL,
|
|
65
|
+
provider_id TEXT NOT NULL,
|
|
66
|
+
access_token TEXT,
|
|
67
|
+
refresh_token TEXT,
|
|
68
|
+
access_token_expires_at INTEGER,
|
|
69
|
+
refresh_token_expires_at INTEGER,
|
|
70
|
+
scope TEXT,
|
|
71
|
+
id_token TEXT,
|
|
72
|
+
password TEXT,
|
|
73
|
+
created_at INTEGER NOT NULL,
|
|
74
|
+
updated_at INTEGER NOT NULL
|
|
75
|
+
);
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_auth_account_user_id ON auth_account(user_id);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_auth_account_provider ON auth_account(provider_id, account_id);
|
|
78
|
+
|
|
79
|
+
-- ── auth_verification ────────────────────────────────────────────────────────
|
|
80
|
+
-- Covers email verification, password reset, magic-link tokens, OTP codes.
|
|
81
|
+
CREATE TABLE IF NOT EXISTS auth_verification (
|
|
82
|
+
id TEXT PRIMARY KEY,
|
|
83
|
+
identifier TEXT NOT NULL,
|
|
84
|
+
value TEXT NOT NULL,
|
|
85
|
+
expires_at INTEGER NOT NULL,
|
|
86
|
+
created_at INTEGER NOT NULL,
|
|
87
|
+
updated_at INTEGER NOT NULL
|
|
88
|
+
);
|
|
89
|
+
CREATE INDEX IF NOT EXISTS idx_auth_verification_identifier ON auth_verification(identifier);
|
|
90
|
+
|
|
91
|
+
-- ── BA plugin tables ──────────────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
CREATE TABLE IF NOT EXISTS auth_two_factor (
|
|
94
|
+
id TEXT PRIMARY KEY,
|
|
95
|
+
secret TEXT NOT NULL,
|
|
96
|
+
backup_codes TEXT NOT NULL,
|
|
97
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,
|
|
98
|
+
verified INTEGER NOT NULL DEFAULT 1,
|
|
99
|
+
created_at INTEGER NOT NULL,
|
|
100
|
+
updated_at INTEGER NOT NULL
|
|
101
|
+
);
|
|
102
|
+
CREATE INDEX IF NOT EXISTS idx_auth_two_factor_user_id ON auth_two_factor(user_id);
|
|
103
|
+
|
|
104
|
+
CREATE TABLE IF NOT EXISTS auth_tenant (
|
|
105
|
+
id TEXT PRIMARY KEY,
|
|
106
|
+
name TEXT NOT NULL,
|
|
107
|
+
slug TEXT NOT NULL UNIQUE,
|
|
108
|
+
logo TEXT,
|
|
109
|
+
metadata TEXT,
|
|
110
|
+
-- SonicJS tenant-resolution fields (BA organization additionalFields):
|
|
111
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
112
|
+
domain TEXT,
|
|
113
|
+
notes TEXT NOT NULL DEFAULT '',
|
|
114
|
+
created_at INTEGER NOT NULL,
|
|
115
|
+
updated_at INTEGER NOT NULL
|
|
116
|
+
);
|
|
117
|
+
CREATE INDEX IF NOT EXISTS idx_auth_tenant_domain ON auth_tenant(domain);
|
|
118
|
+
|
|
119
|
+
CREATE TABLE IF NOT EXISTS auth_tenant_member (
|
|
120
|
+
id TEXT PRIMARY KEY,
|
|
121
|
+
tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,
|
|
122
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,
|
|
123
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
124
|
+
email TEXT,
|
|
125
|
+
created_at INTEGER NOT NULL,
|
|
126
|
+
updated_at INTEGER NOT NULL,
|
|
127
|
+
UNIQUE(tenant_id, user_id)
|
|
128
|
+
);
|
|
129
|
+
CREATE INDEX IF NOT EXISTS idx_auth_tenant_member_tenant ON auth_tenant_member(tenant_id);
|
|
130
|
+
CREATE INDEX IF NOT EXISTS idx_auth_tenant_member_user ON auth_tenant_member(user_id);
|
|
131
|
+
|
|
132
|
+
CREATE TABLE IF NOT EXISTS auth_tenant_invitation (
|
|
133
|
+
id TEXT PRIMARY KEY,
|
|
134
|
+
tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,
|
|
135
|
+
email TEXT NOT NULL,
|
|
136
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
137
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
138
|
+
expires_at INTEGER NOT NULL,
|
|
139
|
+
inviter_id TEXT REFERENCES auth_user(id) ON DELETE SET NULL,
|
|
140
|
+
created_at INTEGER NOT NULL,
|
|
141
|
+
updated_at INTEGER NOT NULL
|
|
142
|
+
);
|
|
143
|
+
CREATE INDEX IF NOT EXISTS idx_auth_tenant_invitation_tenant ON auth_tenant_invitation(tenant_id);
|
|
144
|
+
CREATE INDEX IF NOT EXISTS idx_auth_tenant_invitation_email ON auth_tenant_invitation(email);
|
|
145
|
+
|
|
146
|
+
CREATE TABLE IF NOT EXISTS auth_tenant_team (
|
|
147
|
+
id TEXT PRIMARY KEY,
|
|
148
|
+
name TEXT NOT NULL,
|
|
149
|
+
tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,
|
|
150
|
+
created_at INTEGER NOT NULL,
|
|
151
|
+
updated_at INTEGER NOT NULL
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
-- ── RBAC ─────────────────────────────────────────────────────────────────────
|
|
155
|
+
-- RBAC roles, verbs, and user-role assignments are document-backed (is_auth doc
|
|
156
|
+
-- types rbac_role / rbac_verb / rbac_user_roles — see services/rbac.ts). The
|
|
157
|
+
-- system roles/verbs/grants are seeded at bootstrap by RbacService.ensureSystemRbacSeed().
|
|
158
|
+
-- No auth_rbac_* tables.
|
|
159
|
+
|
|
160
|
+
-- ── Auth support tables ───────────────────────────────────────────────────────
|
|
161
|
+
CREATE TABLE IF NOT EXISTS auth_password_history (
|
|
162
|
+
id TEXT PRIMARY KEY,
|
|
163
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,
|
|
164
|
+
password_hash TEXT NOT NULL,
|
|
165
|
+
created_at INTEGER NOT NULL
|
|
166
|
+
);
|
|
167
|
+
CREATE INDEX IF NOT EXISTS idx_auth_password_history_user_id ON auth_password_history(user_id);
|
|
168
|
+
|
|
169
|
+
CREATE TABLE IF NOT EXISTS auth_api_tokens (
|
|
170
|
+
id TEXT PRIMARY KEY,
|
|
171
|
+
name TEXT NOT NULL,
|
|
172
|
+
token TEXT NOT NULL UNIQUE,
|
|
173
|
+
user_id TEXT NOT NULL REFERENCES auth_user(id),
|
|
174
|
+
permissions TEXT NOT NULL,
|
|
175
|
+
expires_at INTEGER,
|
|
176
|
+
last_used_at INTEGER,
|
|
177
|
+
created_at INTEGER NOT NULL
|
|
178
|
+
);
|
|
179
|
+
CREATE INDEX IF NOT EXISTS idx_auth_api_tokens_user ON auth_api_tokens(user_id);
|
|
180
|
+
CREATE INDEX IF NOT EXISTS idx_auth_api_tokens_token ON auth_api_tokens(token);
|
|
181
|
+
|
|
182
|
+
-- User profiles moved to the document model: a `user_profile` document (is_auth type),
|
|
183
|
+
-- one per user, addressed by slug = userId. See services/document-types-seed.ts and
|
|
184
|
+
-- plugins/core-plugins/user-profiles/user-profile-document.ts. No auth_user_profiles table.
|