@sonicjs-cms/core 3.0.0-beta.2 → 3.0.0-beta.20
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 +48 -49
- package/dist/admin-documents-form.template-DDSH6ROU.js +6 -0
- package/dist/{admin-documents-form.template-NLSI6Z42.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-WHJGSWWD.js.map → admin-documents-form.template-LSZKGA5J.cjs.map} +1 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.ts → admin-layout-catalyst.template-DrwDUfsE.d.cts} +25 -1
- package/dist/{filter-bar.template-DlVYMk-T.d.cts → 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-ZK5HD545.cjs.map → admin-layout-catalyst.template-KDHKVLXR.cjs.map} +1 -1
- package/dist/admin-layout-catalyst.template-YQ4EMF2J.js +7 -0
- package/dist/{admin-documents-form.template-KN7JF66Q.cjs.map → admin-layout-catalyst.template-YQ4EMF2J.js.map} +1 -1
- package/dist/{app-Bo0X1OWX.d.ts → app-01M0dIwt.d.ts} +1 -1
- package/dist/{app-Do66yCcV.d.cts → app-aj39TGHB.d.cts} +1 -1
- package/dist/{chunk-ZEZ245PW.js → chunk-2XAQTPAE.js} +4 -236
- package/dist/chunk-2XAQTPAE.js.map +1 -0
- package/dist/{chunk-BDDABDAB.cjs → chunk-36Z3AKX3.cjs} +3 -239
- package/dist/chunk-36Z3AKX3.cjs.map +1 -0
- package/dist/{chunk-VXE42MYF.cjs → chunk-3E7IROND.cjs} +695 -428
- package/dist/chunk-3E7IROND.cjs.map +1 -0
- package/dist/{chunk-BLMTL57B.js → chunk-3TMTYJAJ.js} +26 -4
- package/dist/chunk-3TMTYJAJ.js.map +1 -0
- package/dist/{chunk-AAWNRBRB.cjs → chunk-4SHNHNRP.cjs} +95 -20
- package/dist/chunk-4SHNHNRP.cjs.map +1 -0
- package/dist/{chunk-QAYFOER6.cjs → chunk-5ARIHAGN.cjs} +285 -3
- package/dist/chunk-5ARIHAGN.cjs.map +1 -0
- package/dist/{chunk-XW56B23A.cjs → chunk-5RSB5SEK.cjs} +4 -4
- package/dist/{chunk-XW56B23A.cjs.map → chunk-5RSB5SEK.cjs.map} +1 -1
- package/dist/{chunk-VD2EA3WT.js → chunk-5UCMLBRQ.js} +328 -62
- package/dist/chunk-5UCMLBRQ.js.map +1 -0
- package/dist/{chunk-3TB6AT6X.js → chunk-5V62WT6M.js} +35 -4
- package/dist/chunk-5V62WT6M.js.map +1 -0
- package/dist/{chunk-LRZIAW7U.cjs → chunk-AQJEMVAY.cjs} +3 -3
- package/dist/chunk-AQJEMVAY.cjs.map +1 -0
- package/dist/{chunk-WULONYGB.cjs → chunk-CRGUD4KC.cjs} +9 -9
- package/dist/{chunk-WULONYGB.cjs.map → chunk-CRGUD4KC.cjs.map} +1 -1
- package/dist/{chunk-NLJVSER2.js → chunk-DSXEVMOM.js} +3 -2
- package/dist/chunk-DSXEVMOM.js.map +1 -0
- package/dist/{chunk-H2AXVCLS.cjs → chunk-DTGCXWWM.cjs} +141 -74
- package/dist/chunk-DTGCXWWM.cjs.map +1 -0
- package/dist/{chunk-NUKJ54GA.cjs → chunk-GMMCCIQO.cjs} +6 -6
- package/dist/{chunk-NUKJ54GA.cjs.map → chunk-GMMCCIQO.cjs.map} +1 -1
- package/dist/{chunk-6OUHGKFD.js → chunk-GMZ5TGYP.js} +3 -3
- package/dist/{chunk-6OUHGKFD.js.map → chunk-GMZ5TGYP.js.map} +1 -1
- package/dist/{chunk-6JQOUUOB.js → chunk-JQISFW6U.js} +3 -3
- package/dist/{chunk-6JQOUUOB.js.map → chunk-JQISFW6U.js.map} +1 -1
- package/dist/{chunk-NAVPFIG5.cjs → chunk-K623Q6WD.cjs} +35 -3
- package/dist/chunk-K623Q6WD.cjs.map +1 -0
- package/dist/{chunk-JEQ7FLOD.cjs → chunk-KIGVVO6N.cjs} +16 -10
- package/dist/chunk-KIGVVO6N.cjs.map +1 -0
- package/dist/{chunk-2CB4KY7I.cjs → chunk-LTZ5WYOK.cjs} +29 -7
- package/dist/chunk-LTZ5WYOK.cjs.map +1 -0
- package/dist/{chunk-YHSQVQXX.js → chunk-MYQ7KZUQ.js} +135 -68
- package/dist/chunk-MYQ7KZUQ.js.map +1 -0
- package/dist/{chunk-DNQCEKUK.cjs → chunk-N32OWET6.cjs} +5 -5
- package/dist/{chunk-DNQCEKUK.cjs.map → chunk-N32OWET6.cjs.map} +1 -1
- package/dist/{chunk-HDWE5FRJ.js → chunk-OBA2RYZN.js} +3 -3
- package/dist/{chunk-HDWE5FRJ.js.map → chunk-OBA2RYZN.js.map} +1 -1
- package/dist/{chunk-MVIZJOO5.cjs → chunk-PXNTCCPE.cjs} +8 -8
- package/dist/{chunk-MVIZJOO5.cjs.map → chunk-PXNTCCPE.cjs.map} +1 -1
- package/dist/{chunk-ZGGXCFR6.js → chunk-RDH6PUOP.js} +282 -4
- package/dist/chunk-RDH6PUOP.js.map +1 -0
- package/dist/{chunk-EF2NQUIQ.js → chunk-RMRJGMDE.js} +3 -3
- package/dist/{chunk-EF2NQUIQ.js.map → chunk-RMRJGMDE.js.map} +1 -1
- package/dist/{chunk-IVPRUGTY.js → chunk-SOZUG52O.js} +4 -4
- package/dist/{chunk-IVPRUGTY.js.map → chunk-SOZUG52O.js.map} +1 -1
- package/dist/{chunk-DSA4UX5B.cjs → chunk-TQG5FNNR.cjs} +3 -2
- package/dist/chunk-TQG5FNNR.cjs.map +1 -0
- package/dist/{chunk-GCDZZNIN.js → chunk-UWUP2VMT.js} +16 -10
- package/dist/chunk-UWUP2VMT.js.map +1 -0
- package/dist/{chunk-IESEVHXL.js → chunk-VVYVFCML.js} +12 -3
- package/dist/chunk-VVYVFCML.js.map +1 -0
- package/dist/{chunk-NMPEMSU4.js → chunk-W53J3BJ2.js} +3 -3
- package/dist/chunk-W53J3BJ2.js.map +1 -0
- package/dist/{chunk-RZ6H7OZK.js → chunk-WCA4VENG.js} +87 -12
- package/dist/chunk-WCA4VENG.js.map +1 -0
- package/dist/{chunk-HIKBY7MS.cjs → chunk-XWVDSM2L.cjs} +12 -3
- package/dist/chunk-XWVDSM2L.cjs.map +1 -0
- package/dist/{collection-config-JgHOpFCG.d.ts → collection-config-BTzAvKt2.d.cts} +25 -0
- package/dist/{collection-config-JgHOpFCG.d.cts → collection-config-BTzAvKt2.d.ts} +25 -0
- package/dist/config-6FB2BXMP.js +6 -0
- package/dist/{config-HFXANXCC.js.map → config-6FB2BXMP.js.map} +1 -1
- package/dist/config-OCH7S4WK.cjs +19 -0
- package/dist/{config-ON6FNMYX.cjs.map → config-OCH7S4WK.cjs.map} +1 -1
- package/dist/{define-plugin-BzNHc1ZI.d.ts → define-plugin-BYIey6sp.d.ts} +1 -1
- package/dist/{define-plugin-IWDKYaVm.d.cts → define-plugin-DsKiGu1q.d.cts} +1 -1
- package/dist/document-projection-4HG75S5S.js +4 -0
- package/dist/{document-projection-YYMC6I4U.js.map → document-projection-4HG75S5S.js.map} +1 -1
- package/dist/document-projection-JQHSTSFD.cjs +13 -0
- package/dist/{document-projection-TDWRJX3Z.cjs.map → document-projection-JQHSTSFD.cjs.map} +1 -1
- package/dist/index.cjs +928 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -12
- package/dist/index.d.ts +200 -12
- package/dist/index.js +612 -75
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +37 -34
- package/dist/middleware.d.cts +2 -2
- package/dist/middleware.d.ts +2 -2
- package/dist/middleware.js +8 -5
- package/dist/migrations-HZJ6U6SX.js +4 -0
- package/dist/{migrations-WCAVBD7C.js.map → migrations-HZJ6U6SX.js.map} +1 -1
- package/dist/migrations-VQAFXMU7.cjs +13 -0
- package/dist/{migrations-NJJWQUKK.cjs.map → migrations-VQAFXMU7.cjs.map} +1 -1
- package/dist/{plugin-bootstrap-B8ThJU21.d.cts → plugin-bootstrap-BHWQ2df8.d.cts} +1 -1
- package/dist/{plugin-bootstrap-qu8hJgUt.d.ts → plugin-bootstrap-Bj4fxX1q.d.ts} +1 -1
- package/dist/plugins.cjs +40 -40
- package/dist/plugins.d.cts +2 -2
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +3 -3
- package/dist/rbac-7QZ4JZ2E.cjs +14 -0
- package/dist/{rbac-VONLJJKB.cjs.map → rbac-7QZ4JZ2E.cjs.map} +1 -1
- package/dist/rbac-Y43IEQOP.js +5 -0
- package/dist/{rbac-O73MFKDA.js.map → rbac-Y43IEQOP.js.map} +1 -1
- package/dist/routes.cjs +34 -34
- package/dist/routes.d.cts +2 -2
- package/dist/routes.d.ts +2 -2
- package/dist/routes.js +14 -14
- package/dist/services.cjs +42 -42
- package/dist/services.d.cts +16 -3
- package/dist/services.d.ts +16 -3
- package/dist/services.js +3 -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 -17
- package/dist/templates.d.cts +2 -24
- package/dist/templates.d.ts +2 -24
- package/dist/templates.js +3 -3
- package/dist/{types-Dea1eNxU.d.ts → types-DT7XN5TX.d.cts} +1 -1
- package/dist/{types-Dea1eNxU.d.cts → types-DT7XN5TX.d.ts} +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.ts +2 -2
- package/dist/utils.cjs +8 -8
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +2 -2
- package/package.json +1 -1
- package/dist/admin-documents-form.template-KN7JF66Q.cjs +0 -19
- package/dist/admin-documents-form.template-NLSI6Z42.js +0 -6
- package/dist/admin-layout-catalyst.template-WHJGSWWD.js +0 -7
- package/dist/admin-layout-catalyst.template-ZK5HD545.cjs +0 -17
- package/dist/chunk-2CB4KY7I.cjs.map +0 -1
- package/dist/chunk-3TB6AT6X.js.map +0 -1
- package/dist/chunk-AAWNRBRB.cjs.map +0 -1
- package/dist/chunk-BDDABDAB.cjs.map +0 -1
- package/dist/chunk-BLMTL57B.js.map +0 -1
- package/dist/chunk-DSA4UX5B.cjs.map +0 -1
- package/dist/chunk-GCDZZNIN.js.map +0 -1
- package/dist/chunk-H2AXVCLS.cjs.map +0 -1
- package/dist/chunk-HIKBY7MS.cjs.map +0 -1
- package/dist/chunk-IESEVHXL.js.map +0 -1
- package/dist/chunk-JEQ7FLOD.cjs.map +0 -1
- package/dist/chunk-LRZIAW7U.cjs.map +0 -1
- package/dist/chunk-NAVPFIG5.cjs.map +0 -1
- package/dist/chunk-NLJVSER2.js.map +0 -1
- package/dist/chunk-NMPEMSU4.js.map +0 -1
- package/dist/chunk-QAYFOER6.cjs.map +0 -1
- package/dist/chunk-RZ6H7OZK.js.map +0 -1
- package/dist/chunk-VD2EA3WT.js.map +0 -1
- package/dist/chunk-VXE42MYF.cjs.map +0 -1
- package/dist/chunk-YHSQVQXX.js.map +0 -1
- package/dist/chunk-ZEZ245PW.js.map +0 -1
- package/dist/chunk-ZGGXCFR6.js.map +0 -1
- package/dist/config-HFXANXCC.js +0 -6
- package/dist/config-ON6FNMYX.cjs +0 -19
- package/dist/document-projection-TDWRJX3Z.cjs +0 -13
- package/dist/document-projection-YYMC6I4U.js +0 -4
- package/dist/migrations-NJJWQUKK.cjs +0 -13
- package/dist/migrations-WCAVBD7C.js +0 -4
- package/dist/rbac-O73MFKDA.js +0 -5
- package/dist/rbac-VONLJJKB.cjs +0 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/auth/config.ts"],"names":["baHashPassword","baVerifyPassword"],"mappings":"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","file":"chunk-IVPRUGTY.js","sourcesContent":["/**\n * Better Auth configuration for SonicJS — via the better-auth-cloudflare shim.\n *\n * A fresh auth instance is built per request (Workers lifecycle). The existing\n * `auth_user` table is used as Better Auth's user model. Legacy SonicJS PBKDF2\n * hashes are verified and transparently upgraded to scrypt on first login. KV\n * (CACHE_KV) is used as session secondary storage so getSession does not hit D1\n * on every request.\n *\n * Extend via config.auth.extendBetterAuth in createSonicJSApp() to add social\n * providers, magic link, 2FA, etc.\n */\n/** Send an email via the SonicJS email plugin (Resend).\n * Loads apiKey/fromEmail/fromName from the `plugins` table at runtime.\n * Falls back to console.log when the plugin is unconfigured (local dev). */\nasync function sendViaEmailPlugin(\n db: D1Database,\n to: string,\n subject: string,\n html: string\n): Promise<void> {\n try {\n const row = (await db\n .prepare(\"SELECT settings FROM plugins WHERE id = 'email'\")\n .first()) as { settings: string } | null\n if (row?.settings) {\n const { apiKey, fromEmail, fromName } = JSON.parse(row.settings) as {\n apiKey?: string; fromEmail?: string; fromName?: string\n }\n if (apiKey && fromEmail) {\n await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n from: `${fromName ?? 'SonicJS'} <${fromEmail}>`,\n to: [to],\n subject,\n html,\n }),\n })\n return\n }\n }\n } catch { /* fall through to dev log */ }\n console.log(`[email-dev] To:${to} | Subject:${subject}`)\n}\n\nimport { betterAuth } from 'better-auth'\nimport { withCloudflare } from 'better-auth-cloudflare'\nimport { hashPassword as baHashPassword, verifyPassword as baVerifyPassword } from 'better-auth/crypto'\nimport { APIError } from 'better-auth/api'\nimport { magicLink } from 'better-auth/plugins/magic-link'\nimport { emailOTP } from 'better-auth/plugins/email-otp'\nimport { organization } from 'better-auth/plugins/organization'\nimport { drizzle } from 'drizzle-orm/d1'\nimport { authUser, authSession, authAccount, authVerification, authTenant, authTenantMember, authTenantInvitation, authTenantTeam } from '../db/schema'\nimport { isRegistrationEnabled, isFirstUserRegistration } from '../services/auth-validation'\nimport type { Bindings } from '../app'\n\n/**\n * Verify a password against a SonicJS legacy PBKDF2 hash:\n * pbkdf2:<iterations>:<saltHex>:<hashHex> (PBKDF2-SHA256, 256-bit)\n * Mirrors AuthManager.verifyPassword in middleware/auth.ts.\n */\nasync function verifyLegacyPbkdf2(password: string, stored: string): Promise<boolean> {\n const parts = stored.split(':')\n if (parts.length !== 4) return false\n const iterations = parseInt(parts[1]!, 10)\n const saltBytes = parts[2]!.match(/.{2}/g)\n if (!saltBytes || !Number.isFinite(iterations)) return false\n const salt = new Uint8Array(saltBytes.map((b) => parseInt(b, 16)))\n const km = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits'])\n const bits = await crypto.subtle.deriveBits({ name: 'PBKDF2', salt, iterations, hash: 'SHA-256' }, km, 256)\n const actual = Array.from(new Uint8Array(bits)).map((b) => b.toString(16).padStart(2, '0')).join('')\n const expected = parts[3]!\n if (actual.length !== expected.length) return false\n let diff = 0\n for (let i = 0; i < actual.length; i++) diff |= actual.charCodeAt(i) ^ expected.charCodeAt(i)\n return diff === 0\n}\n\n/**\n * Build the default Better Auth options used by SonicJS (through the CF shim).\n * Exported so apps can extend via config.auth.extendBetterAuth.\n */\nexport function getDefaultAuthOptions(env: Bindings, requestBaseURL?: string) {\n const db = drizzle(env.DB)\n\n return {\n secret: env.BETTER_AUTH_SECRET,\n baseURL: env.BETTER_AUTH_URL || requestBaseURL,\n appName: 'SonicJS',\n ...withCloudflare(\n {\n autoDetectIpAddress: true,\n geolocationTracking: false,\n cf: {},\n d1: {\n db,\n options: {\n // Keys MUST match modelName values — BA resolves by modelName, not by JS variable name.\n schema: { auth_user: authUser, auth_session: authSession, auth_account: authAccount, auth_verification: authVerification, auth_tenant: authTenant, auth_tenant_member: authTenantMember, auth_tenant_invitation: authTenantInvitation, auth_tenant_team: authTenantTeam },\n },\n },\n kv: env.CACHE_KV, // session secondary storage → getSession skips D1\n },\n {\n basePath: '/auth',\n emailAndPassword: {\n enabled: true,\n autoSignIn: true,\n // Transparent migration of SonicJS legacy PBKDF2 hashes: verify against\n // the old format on login, then re-hash to scrypt and persist. No\n // mass-rehash, no forced password resets.\n password: {\n verify: async ({ hash, password }: { hash: string; password: string }) => {\n if (hash.startsWith('pbkdf2:')) {\n const ok = await verifyLegacyPbkdf2(password, hash)\n if (ok) {\n const upgraded = await baHashPassword(password)\n await env.DB.prepare(\n \"UPDATE auth_account SET password = ?, updated_at = ? WHERE password = ? AND provider_id = 'credential'\"\n )\n .bind(upgraded, Math.floor(Date.now() / 1000), hash)\n .run()\n }\n return ok\n }\n return baVerifyPassword({ hash, password })\n },\n },\n },\n user: {\n modelName: 'auth_user',\n // Field-mapping values are Drizzle *property keys* (camelCase), which\n // already match Better Auth's defaults for emailVerified/createdAt/\n // updatedAt. Only `image` differs (SonicJS uses `avatar`).\n fields: {\n image: 'avatar',\n },\n additionalFields: {\n role: { type: 'string', required: false, defaultValue: 'viewer', input: false },\n firstName: { type: 'string', required: false, defaultValue: '', input: true },\n lastName: { type: 'string', required: false, defaultValue: '', input: true },\n isSuperAdmin: { type: 'boolean', required: false, defaultValue: false, input: false },\n },\n },\n session: {\n modelName: 'auth_session',\n // Drizzle property keys already match Better Auth defaults (userId,\n // expiresAt, ipAddress, …) — no field overrides needed.\n expiresIn: 60 * 60 * 24 * 7, // 7 days\n updateAge: 60 * 60 * 24, // refresh once per day\n },\n account: { modelName: 'auth_account' },\n verification: { modelName: 'auth_verification' },\n databaseHooks: {\n user: {\n create: {\n before: async (userData: Record<string, unknown>) => {\n const isFirst = await isFirstUserRegistration(env.DB)\n if (!isFirst) {\n const enabled = await isRegistrationEnabled(env.DB)\n if (!enabled) {\n throw new APIError('BAD_REQUEST', { message: 'Registration is currently disabled.' })\n }\n }\n const d = userData as {\n name?: string; email?: string; firstName?: string; lastName?: string\n }\n const name = (d.name ?? 'User').toString()\n const parts = name.trim().split(/\\s+/)\n // Prefer explicitly-provided fields (registration form); fall back\n // to values derived from name/email.\n const firstName = d.firstName || parts[0] || 'User'\n const lastName = d.lastName || parts.slice(1).join(' ') || firstName\n return { data: { ...userData, name, firstName, lastName, role: 'viewer' } }\n },\n after: async (user: { id: string }) => {\n // Assign dynamic RBAC membership. The first real user receives\n // Administrator so fresh installs can enter the portal; later\n // self-registered users receive Viewer.\n try {\n // RBAC roles/assignments are document-backed (services/rbac.ts).\n // First real portal admin → Administrator; later users → Viewer.\n // setUserRoles (via addUserRoleByName) also projects auth_user.role.\n const { RbacService } = await import('../services/rbac')\n const rbac = new RbacService(env.DB)\n const roleName = (await rbac.countPortalAdmins(user.id)) === 0 ? 'admin' : 'viewer'\n await rbac.addUserRoleByName(user.id, roleName)\n } catch {\n /* rbac docs may not be seeded yet on older schemas — non-fatal */\n }\n },\n },\n },\n },\n }\n ),\n\n // ── Phase 4: BA-native login methods ─────────────────────────────────────\n // Magic-link and Email-OTP replace the standalone SonicJS plugins that\n // minted JWT cookies. Social providers replace the bespoke oauth-providers\n // plugin. All are gated on the relevant env vars / email service config\n // so they activate only when configured.\n\n plugins: [\n // Magic-link passwordless auth. Sends a one-time link to the user's inbox;\n // the link resolves to a BA session. Requires a working email service.\n magicLink({\n sendMagicLink: async ({ email, url }: { email: string; url: string }, _request: any) => {\n await sendViaEmailPlugin(\n env.DB, email,\n 'Your sign-in link',\n `<div style=\"font-family:sans-serif;max-width:600px\">\n <h2>Sign in to SonicJS</h2>\n <p>Click the link below to sign in. Expires in 15 minutes.</p>\n <p><a href=\"${url}\" style=\"background:#465FFF;color:#fff;padding:12px 24px;border-radius:6px;text-decoration:none\">Sign in</a></p>\n <p style=\"color:#666;font-size:12px\">Or copy: ${url}</p>\n </div>`\n )\n },\n expiresIn: 15 * 60,\n }),\n\n // Email OTP — 6-digit code sent to inbox. Replaces the otp-login-plugin.\n emailOTP({\n sendVerificationOTP: async (params: { email: string; otp: string; type: string }, _request: any) => {\n await sendViaEmailPlugin(\n env.DB, params.email,\n 'Your sign-in code',\n `<div style=\"font-family:sans-serif;max-width:600px\">\n <h2>Your one-time code</h2>\n <p style=\"font-size:36px;font-weight:bold;letter-spacing:8px;color:#465FFF\">${params.otp}</p>\n <p style=\"color:#666\">Expires in 10 minutes. Do not share this code.</p>\n </div>`\n )\n },\n otpLength: 6,\n expiresIn: 10 * 60,\n }),\n\n organization({\n schema: {\n organization: {\n modelName: 'auth_tenant',\n additionalFields: {\n status: { type: 'string', required: false, defaultValue: 'active', input: true },\n domain: { type: 'string', required: false, input: true },\n notes: { type: 'string', required: false, defaultValue: '', input: true },\n },\n },\n member: {\n modelName: 'auth_tenant_member',\n fields: { organizationId: 'tenant_id' },\n },\n invitation: {\n modelName: 'auth_tenant_invitation',\n fields: { organizationId: 'tenant_id' },\n },\n team: {\n modelName: 'auth_tenant_team',\n fields: { organizationId: 'tenant_id' },\n },\n },\n }),\n ],\n\n // ── Phase 4: Social providers ─────────────────────────────────────────\n // Activated when the relevant env vars are set. Replaces the bespoke\n // oauth-providers SonicJS plugin. Set via wrangler secret put / .dev.vars.\n socialProviders: {\n ...(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET\n ? { github: { clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET } }\n : {}),\n ...(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET\n ? { google: { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET } }\n : {}),\n },\n }\n}\n\nexport type BetterAuthDefaultOptions = ReturnType<typeof getDefaultAuthOptions>\nexport type ExtendBetterAuth = (opts: BetterAuthDefaultOptions) => BetterAuthDefaultOptions\n\n/** Create a Better Auth instance for this request. */\nexport function createAuth(env: Bindings, extendBetterAuth?: ExtendBetterAuth, requestBaseURL?: string) {\n // Hard-fail rather than sign sessions with an undefined/blank secret. The\n // secret must be provided via `wrangler secret put BETTER_AUTH_SECRET`\n // (prod/preview) or a gitignored `.dev.vars` (local) — never committed.\n if (!env.BETTER_AUTH_SECRET || env.BETTER_AUTH_SECRET.length < 16) {\n throw new Error(\n 'BETTER_AUTH_SECRET is missing or too short. Set it as a Wrangler secret ' +\n '(wrangler secret put BETTER_AUTH_SECRET) or in a gitignored .dev.vars for local dev. ' +\n 'Refusing to initialize auth without a strong signing secret.'\n )\n }\n const defaults = getDefaultAuthOptions(env, requestBaseURL)\n const options = extendBetterAuth ? extendBetterAuth(defaults) : defaults\n return betterAuth(options as Parameters<typeof betterAuth>[0])\n}\n\nexport type SonicJSAuth = ReturnType<typeof createAuth>\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/auth/config.ts"],"names":["baHashPassword","baVerifyPassword"],"mappings":"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","file":"chunk-SOZUG52O.js","sourcesContent":["/**\n * Better Auth configuration for SonicJS — via the better-auth-cloudflare shim.\n *\n * A fresh auth instance is built per request (Workers lifecycle). The existing\n * `auth_user` table is used as Better Auth's user model. Legacy SonicJS PBKDF2\n * hashes are verified and transparently upgraded to scrypt on first login. KV\n * (CACHE_KV) is used as session secondary storage so getSession does not hit D1\n * on every request.\n *\n * Extend via config.auth.extendBetterAuth in createSonicJSApp() to add social\n * providers, magic link, 2FA, etc.\n */\n/** Send an email via the SonicJS email plugin (Resend).\n * Loads apiKey/fromEmail/fromName from the `plugins` table at runtime.\n * Falls back to console.log when the plugin is unconfigured (local dev). */\nasync function sendViaEmailPlugin(\n db: D1Database,\n to: string,\n subject: string,\n html: string\n): Promise<void> {\n try {\n const row = (await db\n .prepare(\"SELECT settings FROM plugins WHERE id = 'email'\")\n .first()) as { settings: string } | null\n if (row?.settings) {\n const { apiKey, fromEmail, fromName } = JSON.parse(row.settings) as {\n apiKey?: string; fromEmail?: string; fromName?: string\n }\n if (apiKey && fromEmail) {\n await fetch('https://api.resend.com/emails', {\n method: 'POST',\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({\n from: `${fromName ?? 'SonicJS'} <${fromEmail}>`,\n to: [to],\n subject,\n html,\n }),\n })\n return\n }\n }\n } catch { /* fall through to dev log */ }\n console.log(`[email-dev] To:${to} | Subject:${subject}`)\n}\n\nimport { betterAuth } from 'better-auth'\nimport { withCloudflare } from 'better-auth-cloudflare'\nimport { hashPassword as baHashPassword, verifyPassword as baVerifyPassword } from 'better-auth/crypto'\nimport { APIError } from 'better-auth/api'\nimport { magicLink } from 'better-auth/plugins/magic-link'\nimport { emailOTP } from 'better-auth/plugins/email-otp'\nimport { organization } from 'better-auth/plugins/organization'\nimport { drizzle } from 'drizzle-orm/d1'\nimport { authUser, authSession, authAccount, authVerification, authTenant, authTenantMember, authTenantInvitation, authTenantTeam } from '../db/schema'\nimport { isRegistrationEnabled, isFirstUserRegistration } from '../services/auth-validation'\nimport type { Bindings } from '../app'\n\n/**\n * Verify a password against a SonicJS legacy PBKDF2 hash:\n * pbkdf2:<iterations>:<saltHex>:<hashHex> (PBKDF2-SHA256, 256-bit)\n * Mirrors AuthManager.verifyPassword in middleware/auth.ts.\n */\nasync function verifyLegacyPbkdf2(password: string, stored: string): Promise<boolean> {\n const parts = stored.split(':')\n if (parts.length !== 4) return false\n const iterations = parseInt(parts[1]!, 10)\n const saltBytes = parts[2]!.match(/.{2}/g)\n if (!saltBytes || !Number.isFinite(iterations)) return false\n const salt = new Uint8Array(saltBytes.map((b) => parseInt(b, 16)))\n const km = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveBits'])\n const bits = await crypto.subtle.deriveBits({ name: 'PBKDF2', salt, iterations, hash: 'SHA-256' }, km, 256)\n const actual = Array.from(new Uint8Array(bits)).map((b) => b.toString(16).padStart(2, '0')).join('')\n const expected = parts[3]!\n if (actual.length !== expected.length) return false\n let diff = 0\n for (let i = 0; i < actual.length; i++) diff |= actual.charCodeAt(i) ^ expected.charCodeAt(i)\n return diff === 0\n}\n\n/**\n * Build the default Better Auth options used by SonicJS (through the CF shim).\n * Exported so apps can extend via config.auth.extendBetterAuth.\n */\nexport function getDefaultAuthOptions(env: Bindings, requestBaseURL?: string) {\n const db = drizzle(env.DB)\n\n return {\n secret: env.BETTER_AUTH_SECRET,\n baseURL: env.BETTER_AUTH_URL || requestBaseURL,\n appName: 'SonicJS',\n ...withCloudflare(\n {\n autoDetectIpAddress: true,\n geolocationTracking: false,\n cf: {},\n d1: {\n db,\n options: {\n // Keys MUST match modelName values — BA resolves by modelName, not by JS variable name.\n schema: { auth_user: authUser, auth_session: authSession, auth_account: authAccount, auth_verification: authVerification, auth_tenant: authTenant, auth_tenant_member: authTenantMember, auth_tenant_invitation: authTenantInvitation, auth_tenant_team: authTenantTeam },\n },\n },\n kv: env.CACHE_KV, // session secondary storage → getSession skips D1\n },\n {\n basePath: '/auth',\n emailAndPassword: {\n enabled: true,\n autoSignIn: true,\n // Transparent migration of SonicJS legacy PBKDF2 hashes: verify against\n // the old format on login, then re-hash to scrypt and persist. No\n // mass-rehash, no forced password resets.\n password: {\n verify: async ({ hash, password }: { hash: string; password: string }) => {\n if (hash.startsWith('pbkdf2:')) {\n const ok = await verifyLegacyPbkdf2(password, hash)\n if (ok) {\n const upgraded = await baHashPassword(password)\n await env.DB.prepare(\n \"UPDATE auth_account SET password = ?, updated_at = ? WHERE password = ? AND provider_id = 'credential'\"\n )\n .bind(upgraded, Math.floor(Date.now() / 1000), hash)\n .run()\n }\n return ok\n }\n return baVerifyPassword({ hash, password })\n },\n },\n },\n user: {\n modelName: 'auth_user',\n // Field-mapping values are Drizzle *property keys* (camelCase), which\n // already match Better Auth's defaults for emailVerified/createdAt/\n // updatedAt. Only `image` differs (SonicJS uses `avatar`).\n fields: {\n image: 'avatar',\n },\n additionalFields: {\n role: { type: 'string', required: false, defaultValue: 'viewer', input: false },\n firstName: { type: 'string', required: false, defaultValue: '', input: true },\n lastName: { type: 'string', required: false, defaultValue: '', input: true },\n isSuperAdmin: { type: 'boolean', required: false, defaultValue: false, input: false },\n },\n },\n session: {\n modelName: 'auth_session',\n // Drizzle property keys already match Better Auth defaults (userId,\n // expiresAt, ipAddress, …) — no field overrides needed.\n expiresIn: 60 * 60 * 24 * 7, // 7 days\n updateAge: 60 * 60 * 24, // refresh once per day\n },\n account: { modelName: 'auth_account' },\n verification: { modelName: 'auth_verification' },\n databaseHooks: {\n user: {\n create: {\n before: async (userData: Record<string, unknown>) => {\n const isFirst = await isFirstUserRegistration(env.DB)\n if (!isFirst) {\n const enabled = await isRegistrationEnabled(env.DB)\n if (!enabled) {\n throw new APIError('BAD_REQUEST', { message: 'Registration is currently disabled.' })\n }\n }\n const d = userData as {\n name?: string; email?: string; firstName?: string; lastName?: string\n }\n const name = (d.name ?? 'User').toString()\n const parts = name.trim().split(/\\s+/)\n // Prefer explicitly-provided fields (registration form); fall back\n // to values derived from name/email.\n const firstName = d.firstName || parts[0] || 'User'\n const lastName = d.lastName || parts.slice(1).join(' ') || firstName\n return { data: { ...userData, name, firstName, lastName, role: 'viewer' } }\n },\n after: async (user: { id: string }) => {\n // Assign dynamic RBAC membership. The first real user receives\n // Administrator so fresh installs can enter the portal; later\n // self-registered users receive Viewer.\n try {\n // RBAC roles/assignments are document-backed (services/rbac.ts).\n // First real portal admin → Administrator; later users → Viewer.\n // setUserRoles (via addUserRoleByName) also projects auth_user.role.\n const { RbacService } = await import('../services/rbac')\n const rbac = new RbacService(env.DB)\n const roleName = (await rbac.countPortalAdmins(user.id)) === 0 ? 'admin' : 'viewer'\n await rbac.addUserRoleByName(user.id, roleName)\n } catch {\n /* rbac docs may not be seeded yet on older schemas — non-fatal */\n }\n },\n },\n },\n },\n }\n ),\n\n // ── Phase 4: BA-native login methods ─────────────────────────────────────\n // Magic-link and Email-OTP replace the standalone SonicJS plugins that\n // minted JWT cookies. Social providers replace the bespoke oauth-providers\n // plugin. All are gated on the relevant env vars / email service config\n // so they activate only when configured.\n\n plugins: [\n // Magic-link passwordless auth. Sends a one-time link to the user's inbox;\n // the link resolves to a BA session. Requires a working email service.\n magicLink({\n sendMagicLink: async ({ email, url }: { email: string; url: string }, _request: any) => {\n await sendViaEmailPlugin(\n env.DB, email,\n 'Your sign-in link',\n `<div style=\"font-family:sans-serif;max-width:600px\">\n <h2>Sign in to SonicJS</h2>\n <p>Click the link below to sign in. Expires in 15 minutes.</p>\n <p><a href=\"${url}\" style=\"background:#465FFF;color:#fff;padding:12px 24px;border-radius:6px;text-decoration:none\">Sign in</a></p>\n <p style=\"color:#666;font-size:12px\">Or copy: ${url}</p>\n </div>`\n )\n },\n expiresIn: 15 * 60,\n }),\n\n // Email OTP — 6-digit code sent to inbox. Replaces the otp-login-plugin.\n emailOTP({\n sendVerificationOTP: async (params: { email: string; otp: string; type: string }, _request: any) => {\n await sendViaEmailPlugin(\n env.DB, params.email,\n 'Your sign-in code',\n `<div style=\"font-family:sans-serif;max-width:600px\">\n <h2>Your one-time code</h2>\n <p style=\"font-size:36px;font-weight:bold;letter-spacing:8px;color:#465FFF\">${params.otp}</p>\n <p style=\"color:#666\">Expires in 10 minutes. Do not share this code.</p>\n </div>`\n )\n },\n otpLength: 6,\n expiresIn: 10 * 60,\n }),\n\n organization({\n schema: {\n organization: {\n modelName: 'auth_tenant',\n additionalFields: {\n status: { type: 'string', required: false, defaultValue: 'active', input: true },\n domain: { type: 'string', required: false, input: true },\n notes: { type: 'string', required: false, defaultValue: '', input: true },\n },\n },\n member: {\n modelName: 'auth_tenant_member',\n fields: { organizationId: 'tenant_id' },\n },\n invitation: {\n modelName: 'auth_tenant_invitation',\n fields: { organizationId: 'tenant_id' },\n },\n team: {\n modelName: 'auth_tenant_team',\n fields: { organizationId: 'tenant_id' },\n },\n },\n }),\n ],\n\n // ── Phase 4: Social providers ─────────────────────────────────────────\n // Activated when the relevant env vars are set. Replaces the bespoke\n // oauth-providers SonicJS plugin. Set via wrangler secret put / .dev.vars.\n socialProviders: {\n ...(env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET\n ? { github: { clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET } }\n : {}),\n ...(env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET\n ? { google: { clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET } }\n : {}),\n },\n }\n}\n\nexport type BetterAuthDefaultOptions = ReturnType<typeof getDefaultAuthOptions>\nexport type ExtendBetterAuth = (opts: BetterAuthDefaultOptions) => BetterAuthDefaultOptions\n\n/** Create a Better Auth instance for this request. */\nexport function createAuth(env: Bindings, extendBetterAuth?: ExtendBetterAuth, requestBaseURL?: string) {\n // Hard-fail rather than sign sessions with an undefined/blank secret. The\n // secret must be provided via `wrangler secret put BETTER_AUTH_SECRET`\n // (prod/preview) or a gitignored `.dev.vars` (local) — never committed.\n if (!env.BETTER_AUTH_SECRET || env.BETTER_AUTH_SECRET.length < 16) {\n throw new Error(\n 'BETTER_AUTH_SECRET is missing or too short. Set it as a Wrangler secret ' +\n '(wrangler secret put BETTER_AUTH_SECRET) or in a gitignored .dev.vars for local dev. ' +\n 'Refusing to initialize auth without a strong signing secret.'\n )\n }\n const defaults = getDefaultAuthOptions(env, requestBaseURL)\n const options = extendBetterAuth ? extendBetterAuth(defaults) : defaults\n return betterAuth(options as Parameters<typeof betterAuth>[0])\n}\n\nexport type SonicJSAuth = ReturnType<typeof createAuth>\n"]}
|
|
@@ -82,6 +82,7 @@ var MigrationService = class {
|
|
|
82
82
|
constructor(db) {
|
|
83
83
|
this.db = db;
|
|
84
84
|
}
|
|
85
|
+
db;
|
|
85
86
|
/**
|
|
86
87
|
* Cloudflare D1 owns migration bookkeeping through `d1_migrations`.
|
|
87
88
|
* SonicJS intentionally does not create its own tracking table.
|
|
@@ -272,5 +273,5 @@ var MigrationService = class {
|
|
|
272
273
|
|
|
273
274
|
exports.MigrationService = MigrationService;
|
|
274
275
|
exports.ensureScalarSchema = ensureScalarSchema;
|
|
275
|
-
//# sourceMappingURL=chunk-
|
|
276
|
-
//# sourceMappingURL=chunk-
|
|
276
|
+
//# sourceMappingURL=chunk-TQG5FNNR.cjs.map
|
|
277
|
+
//# sourceMappingURL=chunk-TQG5FNNR.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/db/migrations-bundle.ts","../src/services/document-scalar-schema.ts","../src/services/migrations.ts"],"names":[],"mappings":"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","file":"chunk-TQG5FNNR.cjs","sourcesContent":["/**\n * AUTO-GENERATED FILE - DO NOT EDIT\n * Generated by: scripts/generate-migrations.ts\n * Generated at: 2026-06-30T02:35:30.716Z\n *\n * This file contains all migration SQL bundled for use in Cloudflare Workers\n * where filesystem access is not available at runtime.\n */\n\nexport interface BundledMigration {\n id: string\n name: string\n filename: string\n description: string\n sql: string\n}\n\nexport const bundledMigrations: BundledMigration[] = [\n {\n id: '0001',\n name: 'Core',\n filename: '0001_core.sql',\n description: 'Migration 0001: Core',\n sql: \"-- Migration 0001: Auth tables\\n-- auth_user, auth_session, auth_account, auth_verification + BA plugin tables + RBAC + auth support.\\n-- Only auth_* prefixed tables live here. All content lives in document_* tables (0002_documents.sql).\\n\\n-- ── auth_user ────────────────────────────────────────────────────────────────\\n-- BA user model + SonicJS domain columns as BA additionalFields.\\nCREATE TABLE IF NOT EXISTS auth_user (\\n id TEXT PRIMARY KEY,\\n name TEXT,\\n email TEXT NOT NULL UNIQUE,\\n email_verified INTEGER NOT NULL DEFAULT 0,\\n image TEXT,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL,\\n -- SonicJS additionalFields\\n first_name TEXT NOT NULL,\\n last_name TEXT NOT NULL,\\n role TEXT NOT NULL DEFAULT 'viewer',\\n -- Platform super-admin: bypasses the multi-tenant membership gate, uses global roles in every\\n -- tenant. Opt-in (default 0); intentionally NOT derived from the 'admin' role.\\n is_super_admin INTEGER NOT NULL DEFAULT 0,\\n avatar TEXT,\\n password_hash TEXT,\\n is_active INTEGER NOT NULL DEFAULT 1,\\n last_login_at INTEGER,\\n phone TEXT,\\n bio TEXT,\\n timezone TEXT DEFAULT 'UTC',\\n language TEXT DEFAULT 'en',\\n email_notifications INTEGER DEFAULT 1,\\n theme TEXT DEFAULT 'dark',\\n invitation_token TEXT,\\n invited_by TEXT,\\n invited_at INTEGER,\\n accepted_invitation_at INTEGER,\\n failed_login_count INTEGER NOT NULL DEFAULT 0,\\n locked_until INTEGER\\n);\\n\\nCREATE INDEX IF NOT EXISTS idx_auth_user_email ON auth_user(email);\\nCREATE INDEX IF NOT EXISTS idx_auth_user_role ON auth_user(role);\\nCREATE INDEX IF NOT EXISTS idx_auth_user_invitation_token ON auth_user(invitation_token);\\nCREATE INDEX IF NOT EXISTS idx_auth_user_locked_until ON auth_user(locked_until) WHERE locked_until IS NOT NULL;\\n\\n-- ── auth_session ─────────────────────────────────────────────────────────────\\nCREATE TABLE IF NOT EXISTS auth_session (\\n id TEXT PRIMARY KEY,\\n user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,\\n token TEXT NOT NULL UNIQUE,\\n expires_at INTEGER NOT NULL,\\n ip_address TEXT,\\n user_agent TEXT,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_session_user_id ON auth_session(user_id);\\nCREATE INDEX IF NOT EXISTS idx_auth_session_token ON auth_session(token);\\nCREATE INDEX IF NOT EXISTS idx_auth_session_expires_at ON auth_session(expires_at);\\n\\n-- ── auth_account ─────────────────────────────────────────────────────────────\\nCREATE TABLE IF NOT EXISTS auth_account (\\n id TEXT PRIMARY KEY,\\n user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,\\n account_id TEXT NOT NULL,\\n provider_id TEXT NOT NULL,\\n access_token TEXT,\\n refresh_token TEXT,\\n access_token_expires_at INTEGER,\\n refresh_token_expires_at INTEGER,\\n scope TEXT,\\n id_token TEXT,\\n password TEXT,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_account_user_id ON auth_account(user_id);\\nCREATE INDEX IF NOT EXISTS idx_auth_account_provider ON auth_account(provider_id, account_id);\\n\\n-- ── auth_verification ────────────────────────────────────────────────────────\\n-- Covers email verification, password reset, magic-link tokens, OTP codes.\\nCREATE TABLE IF NOT EXISTS auth_verification (\\n id TEXT PRIMARY KEY,\\n identifier TEXT NOT NULL,\\n value TEXT NOT NULL,\\n expires_at INTEGER NOT NULL,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_verification_identifier ON auth_verification(identifier);\\n\\n-- ── BA plugin tables ──────────────────────────────────────────────────────────\\n\\nCREATE TABLE IF NOT EXISTS auth_two_factor (\\n id TEXT PRIMARY KEY,\\n secret TEXT NOT NULL,\\n backup_codes TEXT NOT NULL,\\n user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,\\n verified INTEGER NOT NULL DEFAULT 1,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_two_factor_user_id ON auth_two_factor(user_id);\\n\\nCREATE TABLE IF NOT EXISTS auth_tenant (\\n id TEXT PRIMARY KEY,\\n name TEXT NOT NULL,\\n slug TEXT NOT NULL UNIQUE,\\n logo TEXT,\\n metadata TEXT,\\n -- SonicJS tenant-resolution fields (BA organization additionalFields):\\n status TEXT NOT NULL DEFAULT 'active',\\n domain TEXT,\\n notes TEXT NOT NULL DEFAULT '',\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_tenant_domain ON auth_tenant(domain);\\n\\nCREATE TABLE IF NOT EXISTS auth_tenant_member (\\n id TEXT PRIMARY KEY,\\n tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,\\n user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,\\n role TEXT NOT NULL DEFAULT 'member',\\n email TEXT,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL,\\n UNIQUE(tenant_id, user_id)\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_tenant_member_tenant ON auth_tenant_member(tenant_id);\\nCREATE INDEX IF NOT EXISTS idx_auth_tenant_member_user ON auth_tenant_member(user_id);\\n\\nCREATE TABLE IF NOT EXISTS auth_tenant_invitation (\\n id TEXT PRIMARY KEY,\\n tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,\\n email TEXT NOT NULL,\\n role TEXT NOT NULL DEFAULT 'member',\\n status TEXT NOT NULL DEFAULT 'pending',\\n expires_at INTEGER NOT NULL,\\n inviter_id TEXT REFERENCES auth_user(id) ON DELETE SET NULL,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_tenant_invitation_tenant ON auth_tenant_invitation(tenant_id);\\nCREATE INDEX IF NOT EXISTS idx_auth_tenant_invitation_email ON auth_tenant_invitation(email);\\n\\nCREATE TABLE IF NOT EXISTS auth_tenant_team (\\n id TEXT PRIMARY KEY,\\n name TEXT NOT NULL,\\n tenant_id TEXT NOT NULL REFERENCES auth_tenant(id) ON DELETE CASCADE,\\n created_at INTEGER NOT NULL,\\n updated_at INTEGER NOT NULL\\n);\\n\\n-- ── RBAC ─────────────────────────────────────────────────────────────────────\\n-- RBAC roles, verbs, and user-role assignments are document-backed (is_auth doc\\n-- types rbac_role / rbac_verb / rbac_user_roles — see services/rbac.ts). The\\n-- system roles/verbs/grants are seeded at bootstrap by RbacService.ensureSystemRbacSeed().\\n-- No auth_rbac_* tables.\\n\\n-- ── Auth support tables ───────────────────────────────────────────────────────\\nCREATE TABLE IF NOT EXISTS auth_password_history (\\n id TEXT PRIMARY KEY,\\n user_id TEXT NOT NULL REFERENCES auth_user(id) ON DELETE CASCADE,\\n password_hash TEXT NOT NULL,\\n created_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_password_history_user_id ON auth_password_history(user_id);\\n\\nCREATE TABLE IF NOT EXISTS auth_api_tokens (\\n id TEXT PRIMARY KEY,\\n name TEXT NOT NULL,\\n token TEXT NOT NULL UNIQUE,\\n user_id TEXT NOT NULL REFERENCES auth_user(id),\\n permissions TEXT NOT NULL,\\n expires_at INTEGER,\\n last_used_at INTEGER,\\n created_at INTEGER NOT NULL\\n);\\nCREATE INDEX IF NOT EXISTS idx_auth_api_tokens_user ON auth_api_tokens(user_id);\\nCREATE INDEX IF NOT EXISTS idx_auth_api_tokens_token ON auth_api_tokens(token);\\n\\n-- User profiles moved to the document model: a `user_profile` document (is_auth type),\\n-- one per user, addressed by slug = userId. See services/document-types-seed.ts and\\n-- plugins/core-plugins/user-profiles/user-profile-document.ts. No auth_user_profiles table.\\n\"\n },\n {\n id: '0002',\n name: 'Documents',\n filename: '0002_documents.sql',\n description: 'Migration 0002: Documents',\n sql: \"-- Migration 0002: Document Schema (v3 greenfield)\\n-- Contains only the new document data model tables, generated columns, and indexes.\\n\\n-- Document type registry\\nCREATE TABLE IF NOT EXISTS document_types (\\n id TEXT PRIMARY KEY,\\n name TEXT NOT NULL UNIQUE,\\n display_name TEXT NOT NULL,\\n description TEXT,\\n schema TEXT NOT NULL DEFAULT '{}',\\n queryable_fields TEXT NOT NULL DEFAULT '[]',\\n settings TEXT NOT NULL DEFAULT '{}',\\n plugin_id TEXT,\\n source TEXT NOT NULL DEFAULT 'code' CHECK (source IN ('code', 'plugin', 'system')),\\n schema_version INTEGER NOT NULL DEFAULT 1,\\n is_system INTEGER NOT NULL DEFAULT 0,\\n is_active INTEGER NOT NULL DEFAULT 1,\\n is_auth INTEGER NOT NULL DEFAULT 0,\\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\\n updated_at INTEGER NOT NULL DEFAULT (unixepoch())\\n);\\n\\nCREATE INDEX IF NOT EXISTS idx_document_types_plugin ON document_types(plugin_id);\\nCREATE INDEX IF NOT EXISTS idx_document_types_active ON document_types(is_active);\\n\\n-- Documents: canonical document rows and historical versions.\\nCREATE TABLE IF NOT EXISTS documents (\\n id TEXT PRIMARY KEY,\\n root_id TEXT NOT NULL,\\n type_id TEXT NOT NULL REFERENCES document_types(id),\\n type_version INTEGER NOT NULL DEFAULT 1,\\n\\n version_of_id TEXT REFERENCES documents(id),\\n version_number INTEGER NOT NULL DEFAULT 1,\\n\\n is_current_draft INTEGER NOT NULL DEFAULT 1,\\n is_published INTEGER NOT NULL DEFAULT 0,\\n status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'archived')),\\n\\n parent_root_id TEXT NOT NULL DEFAULT '',\\n slug TEXT,\\n path TEXT,\\n title TEXT,\\n zone TEXT,\\n sort_order INTEGER NOT NULL DEFAULT 0,\\n visible INTEGER NOT NULL DEFAULT 1,\\n\\n published_at INTEGER,\\n scheduled_at INTEGER,\\n expires_at INTEGER,\\n deleted_at INTEGER,\\n\\n tenant_id TEXT NOT NULL DEFAULT 'default',\\n locale TEXT NOT NULL DEFAULT 'default',\\n translation_group_id TEXT NOT NULL DEFAULT '',\\n\\n data TEXT NOT NULL DEFAULT '{}',\\n metadata TEXT NOT NULL DEFAULT '{}',\\n\\n owner_id TEXT,\\n created_by TEXT,\\n updated_by TEXT,\\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\\n updated_at INTEGER NOT NULL DEFAULT (unixepoch())\\n);\\n\\n-- Queryable scalar fields (VIRTUAL generated columns) and their q_* filter indexes\\n-- are AUTO-GENERATED at runtime from each document type's queryableFields config —\\n-- see DocumentTypeRegistry.register() -> ensureScalarSchema() (document-scalar-schema.ts).\\n-- Do not hand-add q_* columns/indexes here; declare the field in the type instead.\\n\\n-- Revision chain\\nCREATE INDEX IF NOT EXISTS idx_documents_root ON documents(root_id, version_number DESC);\\n\\n-- List / lifecycle\\nCREATE INDEX IF NOT EXISTS idx_documents_published ON documents(tenant_id, type_id, locale, is_published)\\n WHERE is_published = 1 AND deleted_at IS NULL;\\nCREATE INDEX IF NOT EXISTS idx_documents_drafts ON documents(tenant_id, type_id, status, is_current_draft)\\n WHERE is_current_draft = 1;\\nCREATE INDEX IF NOT EXISTS idx_documents_parent ON documents(tenant_id, parent_root_id, sort_order, is_published);\\nCREATE INDEX IF NOT EXISTS idx_documents_path ON documents(tenant_id, path);\\nCREATE INDEX IF NOT EXISTS idx_documents_translation ON documents(translation_group_id, locale);\\nCREATE INDEX IF NOT EXISTS idx_documents_deleted ON documents(deleted_at);\\nCREATE INDEX IF NOT EXISTS idx_documents_scheduled ON documents(scheduled_at) WHERE scheduled_at IS NOT NULL;\\nCREATE INDEX IF NOT EXISTS idx_documents_expires ON documents(expires_at) WHERE expires_at IS NOT NULL;\\n\\n-- Stable keyset/cursor pagination for published lists\\nCREATE INDEX IF NOT EXISTS idx_documents_published_cursor\\n ON documents(tenant_id, type_id, updated_at DESC, id DESC)\\n WHERE is_published = 1 AND deleted_at IS NULL;\\n\\n-- (q_* generated-column filter indexes are auto-created at runtime — see note above.)\\n\\n-- Partial unique indexes: the hard concurrency guarantees for draft/publish invariants.\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_documents_one_current_draft\\n ON documents(root_id) WHERE is_current_draft = 1;\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_documents_one_published\\n ON documents(root_id) WHERE is_published = 1;\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_documents_unique_version\\n ON documents(root_id, version_number);\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_documents_unique_slug\\n ON documents(tenant_id, locale, type_id, parent_root_id, slug)\\n WHERE is_current_draft = 1 AND deleted_at IS NULL AND slug IS NOT NULL;\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_documents_one_translation_per_locale\\n ON documents(tenant_id, translation_group_id, locale)\\n WHERE is_current_draft = 1 AND translation_group_id <> '';\\n\\n-- Document references: typed document-to-document edges.\\nCREATE TABLE IF NOT EXISTS document_references (\\n id TEXT PRIMARY KEY,\\n tenant_id TEXT NOT NULL,\\n from_root_id TEXT NOT NULL,\\n from_document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,\\n field_name TEXT NOT NULL,\\n ordinal INTEGER NOT NULL DEFAULT 0,\\n to_root_id TEXT NOT NULL,\\n ref_strength TEXT NOT NULL DEFAULT 'weak' CHECK (ref_strength IN ('strong', 'weak')),\\n created_at INTEGER NOT NULL DEFAULT (unixepoch())\\n);\\n\\nCREATE INDEX IF NOT EXISTS idx_docref_to ON document_references(tenant_id, to_root_id);\\nCREATE INDEX IF NOT EXISTS idx_docref_from ON document_references(from_document_id);\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_docref_unique\\n ON document_references(from_document_id, field_name, ordinal);\\n\\n-- Document facets: indexed rows for multi-valued scalar fields (e.g. tags arrays).\\nCREATE TABLE IF NOT EXISTS document_facets (\\n id TEXT PRIMARY KEY,\\n tenant_id TEXT NOT NULL,\\n document_id TEXT NOT NULL REFERENCES documents(id) ON DELETE CASCADE,\\n root_id TEXT NOT NULL,\\n type_id TEXT NOT NULL,\\n field_name TEXT NOT NULL,\\n ordinal INTEGER NOT NULL DEFAULT 0,\\n value_text TEXT,\\n value_number REAL,\\n created_at INTEGER NOT NULL DEFAULT (unixepoch())\\n);\\n\\nCREATE INDEX IF NOT EXISTS idx_facets_lookup ON document_facets(tenant_id, type_id, field_name, value_text);\\nCREATE INDEX IF NOT EXISTS idx_facets_doc ON document_facets(document_id);\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_facets_unique\\n ON document_facets(document_id, field_name, ordinal);\\n\\n-- Document permissions: per-document ACL overrides.\\nCREATE TABLE IF NOT EXISTS document_permissions (\\n id TEXT PRIMARY KEY,\\n tenant_id TEXT NOT NULL,\\n root_id TEXT NOT NULL,\\n principal_type TEXT NOT NULL CHECK (principal_type IN ('user', 'role', 'group', 'public', 'token')),\\n principal_id TEXT NOT NULL,\\n permission TEXT NOT NULL CHECK (permission IN ('read', 'create', 'update', 'delete', 'publish', 'manage')),\\n effect TEXT NOT NULL DEFAULT 'allow' CHECK (effect IN ('allow', 'deny')),\\n inherited INTEGER NOT NULL DEFAULT 0,\\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\\n created_by TEXT\\n);\\n\\nCREATE INDEX IF NOT EXISTS idx_document_permissions_root ON document_permissions(tenant_id, root_id);\\nCREATE INDEX IF NOT EXISTS idx_document_permissions_principal\\n ON document_permissions(tenant_id, principal_type, principal_id, permission);\\nCREATE UNIQUE INDEX IF NOT EXISTS idx_document_permissions_unique\\n ON document_permissions(root_id, principal_type, principal_id, permission);\\n\"\n }\n]\n\n// Map for quick lookup by ID\nexport const migrationsByIdMap = new Map<string, BundledMigration>(\n bundledMigrations.map(m => [m.id, m])\n)\n\n// Get migration SQL by ID\nexport function getMigrationSQLById(id: string): string | null {\n return migrationsByIdMap.get(id)?.sql ?? null\n}\n\n// Get all migration info (without SQL for lighter payloads)\nexport function getMigrationList(): Array<Omit<BundledMigration, 'sql'>> {\n return bundledMigrations.map(({ sql, ...rest }) => rest)\n}\n","import { D1Database } from '@cloudflare/workers-types'\nimport type { QueryableField } from '../schemas/document'\n\n// Identifiers and JSON paths are interpolated into DDL (they cannot be bound), so\n// they are format-guarded here. Source is trusted code config, not user input —\n// this is defense-in-depth, mirroring document-repository.ts.\nconst SAFE_IDENTIFIER = /^[a-z_][a-z0-9_]*$/\n\n/** Map a queryable field's logical type to a SQLite column affinity. */\nfunction affinity(type?: QueryableField['type']): 'TEXT' | 'INTEGER' | 'REAL' {\n if (type === 'number') return 'REAL'\n if (type === 'integer' || type === 'boolean' || type === 'date') return 'INTEGER'\n return 'TEXT'\n}\n\nconst slug = (s: string) => s.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '')\n\n/**\n * Authoritative generated-column name for a scalar field. An explicit `column`\n * always wins (back-compat with every existing type definition); otherwise it is\n * derived deterministically from the type id + field name. The repository reads\n * the same `column`/derivation when building filter SQL, so the two never drift.\n */\nexport function resolveColumn(typeId: string, f: QueryableField): string {\n if (f.column) return f.column\n const name = `q_${slug(typeId)}_${slug(f.name)}`\n return name.length <= 60 ? name : `q_${slug(typeId).slice(0, 20)}_${slug(f.name).slice(0, 20)}`\n}\n\n/**\n * Idempotently ensure the `documents` table has a VIRTUAL generated column and a\n * filter/sort index for each of a type's scalar queryable fields. Safe to call on\n * every registration and every bootstrap: existing columns/indexes are skipped,\n * and a concurrent add surfaces as a swallowed \"duplicate column name\".\n *\n * Facet and reference fields need no DDL (generic document_facets /\n * document_references tables), so they are ignored here.\n *\n * Returns the columns it actually created (empty when all already existed).\n */\nexport async function ensureScalarSchema(\n db: D1Database,\n typeId: string,\n fields: QueryableField[],\n): Promise<string[]> {\n const scalars = fields.filter((f) => f.kind === 'scalar')\n if (scalars.length === 0) return []\n\n // pragma_table_info does NOT list VIRTUAL generated columns — use table_xinfo, which does.\n let existing = new Set<string>()\n try {\n const info = await db.prepare(\"SELECT name FROM pragma_table_xinfo('documents')\").all()\n existing = new Set((info?.results ?? []).map((r: any) => r.name))\n } catch {\n // table_xinfo unavailable — fall back to attempting every ALTER (duplicate errors swallowed).\n }\n\n const added: string[] = []\n for (const f of scalars) {\n const col = resolveColumn(typeId, f)\n if (!SAFE_IDENTIFIER.test(col)) {\n console.error(`[scalar-schema] unsafe column name '${col}' for ${typeId}.${f.name} — skipped`)\n continue\n }\n const path = f.path ?? `$.${f.name}`\n if (path.includes(\"'\")) {\n console.error(`[scalar-schema] unsafe json path for ${col} (${typeId}.${f.name}) — skipped`)\n continue\n }\n\n if (!existing.has(col)) {\n try {\n await db\n .prepare(`ALTER TABLE documents ADD COLUMN ${col} ${affinity(f.type)} AS (json_extract(data, '${path}')) VIRTUAL`)\n .run()\n added.push(col)\n console.log(`[scalar-schema] added documents.${col} for type '${typeId}'`)\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n if (!msg.includes('duplicate column name')) {\n console.error(`[scalar-schema] failed to add documents.${col}:`, msg)\n continue\n }\n }\n }\n\n // One general index per column: the leading (tenant_id, type_id, col) prefix\n // serves every equality filter the repository builds; the trailing\n // (updated_at DESC, id DESC) matches the default keyset sort/cursor. Non-partial\n // so a single index covers both draft and published lists.\n try {\n await db\n .prepare(`CREATE INDEX IF NOT EXISTS idx_${col} ON documents(tenant_id, type_id, ${col}, updated_at DESC, id DESC)`)\n .run()\n } catch (error) {\n console.error(`[scalar-schema] failed to create idx_${col}:`, error instanceof Error ? error.message : String(error))\n }\n }\n return added\n}\n","import { D1Database } from '@cloudflare/workers-types'\nimport { bundledMigrations } from '../db/migrations-bundle'\nimport { ensureScalarSchema } from './document-scalar-schema'\nimport type { QueryableField } from '../schemas/document'\n\nexport interface Migration {\n id: string\n name: string\n filename: string\n description?: string\n applied: boolean\n appliedAt?: string\n size?: number\n}\n\nexport interface MigrationStatus {\n totalMigrations: number\n appliedMigrations: number\n pendingMigrations: number\n lastApplied?: string\n migrations: Migration[]\n}\n\nexport class MigrationService {\n constructor(private db: D1Database) {}\n\n /**\n * Cloudflare D1 owns migration bookkeeping through `d1_migrations`.\n * SonicJS intentionally does not create its own tracking table.\n */\n async initializeMigrationsTable(): Promise<void> {\n // Kept as a no-op for compatibility with older callers.\n }\n\n /**\n * Get all available migrations from the bundled migrations\n */\n async getAvailableMigrations(): Promise<Migration[]> {\n const migrations: Migration[] = []\n const appliedMigrations = await this.getD1AppliedMigrations()\n await this.ensureSchemaCompatibility()\n\n // Use bundled migrations as the source of truth\n for (const bundled of bundledMigrations) {\n const applied = appliedMigrations.has(bundled.id)\n const appliedData = appliedMigrations.get(bundled.id)\n\n migrations.push({\n id: bundled.id,\n name: bundled.name,\n filename: bundled.filename,\n description: bundled.description,\n applied,\n appliedAt: applied ? appliedData?.applied_at : undefined,\n size: bundled.sql.length\n })\n }\n\n return migrations\n }\n\n /**\n * Read Wrangler/D1's canonical migration table. If the table is absent, no\n * migrations have been applied by the supported migration runner yet.\n */\n private async getD1AppliedMigrations(): Promise<Map<string, any>> {\n try {\n const appliedResult = await this.db.prepare(\n 'SELECT name, applied_at FROM d1_migrations ORDER BY applied_at ASC'\n ).all()\n\n return new Map(\n (appliedResult.results ?? [])\n .map((row: any) => {\n const filename = String(row.name ?? '')\n const id = filename.match(/^(\\d+)/)?.[1]\n if (!id) return null\n return [id, {\n id,\n name: filename,\n filename,\n applied_at: row.applied_at\n }]\n })\n .filter((entry): entry is [string, any] => entry !== null)\n )\n } catch (error) {\n return new Map()\n }\n }\n\n /**\n * Run idempotent compatibility repairs that are safe outside migration state.\n */\n async ensureSchemaCompatibility(): Promise<void> {\n if (await this.checkTablesExist(['documents'])) {\n await this.ensureDocumentGeneratedColumns()\n }\n }\n\n /**\n * Ensure the `documents` table exposes every queryable VIRTUAL generated column + index (D45).\n * Data-driven repair: reconciles from each active type's `queryable_fields` rather than a hardcoded\n * list, so it stays in sync with whatever types are registered. Generation of these columns is owned\n * by DocumentTypeRegistry.register() (via ensureScalarSchema); this pass is a bootstrap safety net for\n * a DB that has document_types rows but lost columns (e.g. table rebuilt). Idempotent.\n */\n private async ensureDocumentGeneratedColumns(): Promise<void> {\n if (!(await this.checkTablesExist(['document_types']))) return\n const rows = await this.db\n .prepare('SELECT id, queryable_fields FROM document_types WHERE is_active = 1')\n .all<{ id: string; queryable_fields: string }>()\n for (const row of rows.results ?? []) {\n let fields: QueryableField[]\n try {\n fields = JSON.parse(row.queryable_fields)\n } catch {\n continue\n }\n await ensureScalarSchema(this.db, row.id, fields)\n }\n }\n\n /**\n * Check if specific tables exist in the database\n */\n private async checkTablesExist(tableNames: string[]): Promise<boolean> {\n try {\n for (const tableName of tableNames) {\n const result = await this.db.prepare(\n `SELECT name FROM sqlite_master WHERE type='table' AND name=?`\n ).bind(tableName).first()\n\n if (!result) {\n return false\n }\n }\n return true\n } catch (error) {\n return false\n }\n }\n\n /**\n * Check if a specific column exists in a table\n */\n private async checkColumnExists(tableName: string, columnName: string): Promise<boolean> {\n try {\n const result = await this.db.prepare(\n `SELECT * FROM pragma_table_info(?) WHERE name = ?`\n ).bind(tableName, columnName).first()\n\n return !!result\n } catch (error) {\n return false\n }\n }\n\n /**\n * Get migration status summary\n */\n async getMigrationStatus(): Promise<MigrationStatus> {\n const migrations = await this.getAvailableMigrations()\n const appliedMigrations = migrations.filter(m => m.applied)\n const pendingMigrations = migrations.filter(m => !m.applied)\n\n const lastApplied = appliedMigrations.length > 0\n ? appliedMigrations[appliedMigrations.length - 1]?.appliedAt\n : undefined\n\n return {\n totalMigrations: migrations.length,\n appliedMigrations: appliedMigrations.length,\n pendingMigrations: pendingMigrations.length,\n lastApplied,\n migrations\n }\n }\n\n /**\n * D1 migration state is managed by Wrangler.\n */\n async markMigrationApplied(migrationId: string, name: string, filename: string): Promise<void> {\n void migrationId\n void name\n void filename\n }\n\n /**\n * D1 migration state is managed by Wrangler.\n */\n async removeMigrationApplied(migrationId: string): Promise<void> {\n void migrationId\n }\n\n /**\n * Check if a specific migration has been applied\n */\n async isMigrationApplied(migrationId: string): Promise<boolean> {\n const appliedMigrations = await this.getD1AppliedMigrations()\n return appliedMigrations.has(migrationId)\n }\n\n /**\n * Get the last applied migration\n */\n async getLastAppliedMigration(): Promise<Migration | null> {\n const migrations = await this.getAvailableMigrations()\n return migrations.filter(m => m.applied).at(-1) ?? null\n }\n\n /**\n * Run pending migrations\n */\n async runPendingMigrations(): Promise<{ success: boolean; message: string; applied: string[]; errors: string[] }> {\n return {\n success: false,\n message: 'Migrations are managed by Cloudflare D1. Run `wrangler d1 migrations apply DB --local` or `wrangler d1 migrations apply DB --remote`.',\n applied: [],\n errors: []\n }\n }\n\n /**\n * Validate database schema\n */\n async validateSchema(): Promise<{ valid: boolean; issues: string[] }> {\n const issues: string[] = []\n\n // Basic table existence checks\n const requiredTables = [\n 'users', 'documents', 'document_types'\n ]\n\n for (const table of requiredTables) {\n try {\n await this.db.prepare(`SELECT COUNT(*) FROM ${table} LIMIT 1`).first()\n } catch (error) {\n issues.push(`Missing table: ${table}`)\n }\n }\n\n return {\n valid: issues.length === 0,\n issues\n }\n }\n}\n"]}
|
|
@@ -10,14 +10,19 @@ var POOL_SIZE_MULTIPLIER = 128;
|
|
|
10
10
|
var pool;
|
|
11
11
|
var poolOffset;
|
|
12
12
|
var fillPool = (bytes) => {
|
|
13
|
-
if (bytes < 0
|
|
14
|
-
|
|
15
|
-
pool
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
if (bytes < 0) throw new RangeError("Wrong ID size");
|
|
14
|
+
try {
|
|
15
|
+
if (!pool || pool.length < bytes) {
|
|
16
|
+
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
17
|
+
crypto.randomFillSync(pool);
|
|
18
|
+
poolOffset = 0;
|
|
19
|
+
} else if (poolOffset + bytes > pool.length) {
|
|
20
|
+
crypto.randomFillSync(pool);
|
|
21
|
+
poolOffset = 0;
|
|
22
|
+
}
|
|
23
|
+
} catch (e) {
|
|
24
|
+
pool = void 0;
|
|
25
|
+
throw e;
|
|
21
26
|
}
|
|
22
27
|
poolOffset += bytes;
|
|
23
28
|
};
|
|
@@ -43,6 +48,7 @@ var DocumentProjection = class {
|
|
|
43
48
|
constructor(db) {
|
|
44
49
|
this.db = db;
|
|
45
50
|
}
|
|
51
|
+
db;
|
|
46
52
|
// Build D1 PreparedStatement arrays for inserting facets/references for a document.
|
|
47
53
|
// Returns raw D1 PreparedStatement objects suitable for inclusion in db.batch([...]).
|
|
48
54
|
buildDerivedInsertStatements(doc, queryableFields, now) {
|
|
@@ -188,5 +194,5 @@ function rowToDocument(row) {
|
|
|
188
194
|
}
|
|
189
195
|
|
|
190
196
|
export { DocumentProjection, nanoid };
|
|
191
|
-
//# sourceMappingURL=chunk-
|
|
192
|
-
//# sourceMappingURL=chunk-
|
|
197
|
+
//# sourceMappingURL=chunk-UWUP2VMT.js.map
|
|
198
|
+
//# sourceMappingURL=chunk-UWUP2VMT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/nanoid/url-alphabet/index.js","../../../node_modules/nanoid/index.js","../src/services/document-projection.ts"],"names":[],"mappings":"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","file":"chunk-UWUP2VMT.js","sourcesContent":["let urlAlphabet =\n 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'\n\nexport { urlAlphabet }\n","import crypto from 'crypto'\n\nimport { urlAlphabet } from './url-alphabet/index.js'\n\nconst POOL_SIZE_MULTIPLIER = 128\nlet pool, poolOffset\n\nlet fillPool = bytes => {\n if (bytes < 0) throw new RangeError('Wrong ID size')\n try {\n if (!pool || pool.length < bytes) {\n pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n crypto.randomFillSync(pool)\n poolOffset = 0\n } else if (poolOffset + bytes > pool.length) {\n crypto.randomFillSync(pool)\n poolOffset = 0\n }\n } catch (e) {\n pool = undefined\n throw e\n }\n poolOffset += bytes\n}\n\nlet random = bytes => {\n fillPool((bytes |= 0))\n return pool.subarray(poolOffset - bytes, poolOffset)\n}\n\nlet customRandom = (alphabet, defaultSize, getRandom) => {\n let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1\n\n\n let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)\n\n return (size = defaultSize) => {\n let id = ''\n while (true) {\n let bytes = getRandom(step)\n let i = step\n while (i--) {\n id += alphabet[bytes[i] & mask] || ''\n if (id.length === size) return id\n }\n }\n }\n}\n\nlet customAlphabet = (alphabet, size = 21) =>\n customRandom(alphabet, size, random)\n\nlet nanoid = (size = 21) => {\n fillPool((size |= 0))\n let id = ''\n for (let i = poolOffset - size; i < poolOffset; i++) {\n id += urlAlphabet[pool[i] & 63]\n }\n return id\n}\n\nexport { nanoid, customAlphabet, customRandom, urlAlphabet, random }\n","import { D1Database } from '@cloudflare/workers-types'\nimport { nanoid } from 'nanoid'\nimport type { Document, QueryableField, DocumentRow } from '../schemas/document'\n\n// D1 hard limit: 100 bound parameters per statement. Keep under 90 for safety.\nconst MAX_PARAMS = 90\n\nfunction chunkArray<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = []\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size))\n }\n return chunks\n}\n\ninterface FacetInsert {\n id: string\n tenant_id: string\n document_id: string\n root_id: string\n type_id: string\n field_name: string\n ordinal: number\n value_text: string | null\n value_number: number | null\n now: number\n}\n\ninterface ReferenceInsert {\n id: string\n tenant_id: string\n from_root_id: string\n from_document_id: string\n field_name: string\n ordinal: number\n to_root_id: string\n ref_strength: string\n now: number\n}\n\nexport class DocumentProjection {\n constructor(private db: D1Database) {}\n\n // Build D1 PreparedStatement arrays for inserting facets/references for a document.\n // Returns raw D1 PreparedStatement objects suitable for inclusion in db.batch([...]).\n buildDerivedInsertStatements(\n doc: Document,\n queryableFields: QueryableField[],\n now: number,\n ): D1PreparedStatement[] {\n const statements: D1PreparedStatement[] = []\n const facets: FacetInsert[] = []\n const refs: ReferenceInsert[] = []\n\n for (const field of queryableFields) {\n const rawValue = this.extractPath(doc.data, field.path ?? `$.${field.name}`)\n\n if (field.kind === 'facet') {\n const values = Array.isArray(rawValue) ? rawValue : rawValue != null ? [rawValue] : []\n values.forEach((v, ordinal) => {\n const isNum = typeof v === 'number'\n facets.push({\n id: nanoid(),\n tenant_id: doc.tenantId,\n document_id: doc.id,\n root_id: doc.rootId,\n type_id: doc.typeId,\n field_name: field.name,\n ordinal,\n value_text: isNum ? null : String(v),\n value_number: isNum ? v : null,\n now,\n })\n })\n } else if (field.kind === 'reference') {\n const roots = Array.isArray(rawValue) ? rawValue : rawValue != null ? [rawValue] : []\n roots.forEach((rootId, ordinal) => {\n refs.push({\n id: nanoid(),\n tenant_id: doc.tenantId,\n from_root_id: doc.rootId,\n from_document_id: doc.id,\n field_name: field.name,\n ordinal,\n to_root_id: String(rootId),\n ref_strength: field.refStrength ?? 'weak',\n now,\n })\n })\n }\n // 'scalar' fields are VIRTUAL generated columns; no derived rows needed.\n }\n\n // Insert facets in chunks to respect the 100-param D1 limit (9 params per row).\n const FACET_COLS = 10\n for (const chunk of chunkArray(facets, Math.floor(MAX_PARAMS / FACET_COLS))) {\n const placeholders = chunk.map(() => '(?,?,?,?,?,?,?,?,?,?)').join(',')\n const params: (string | number | null)[] = []\n for (const f of chunk) {\n params.push(f.id, f.tenant_id, f.document_id, f.root_id, f.type_id, f.field_name, f.ordinal, f.value_text, f.value_number, f.now)\n }\n statements.push(\n this.db.prepare(\n `INSERT INTO document_facets (id, tenant_id, document_id, root_id, type_id, field_name, ordinal, value_text, value_number, created_at) VALUES ${placeholders}`,\n ).bind(...params),\n )\n }\n\n // Insert references in chunks (9 params per row).\n const REF_COLS = 9\n for (const chunk of chunkArray(refs, Math.floor(MAX_PARAMS / REF_COLS))) {\n const placeholders = chunk.map(() => '(?,?,?,?,?,?,?,?,?)').join(',')\n const params: (string | number | null)[] = []\n for (const r of chunk) {\n params.push(r.id, r.tenant_id, r.from_root_id, r.from_document_id, r.field_name, r.ordinal, r.to_root_id, r.ref_strength, r.now)\n }\n statements.push(\n this.db.prepare(\n `INSERT INTO document_references (id, tenant_id, from_root_id, from_document_id, field_name, ordinal, to_root_id, ref_strength, created_at) VALUES ${placeholders}`,\n ).bind(...params),\n )\n }\n\n return statements\n }\n\n buildDerivedDeleteStatements(documentId: string): D1PreparedStatement[] {\n return [\n this.db.prepare('DELETE FROM document_facets WHERE document_id = ?').bind(documentId),\n this.db.prepare('DELETE FROM document_references WHERE from_document_id = ?').bind(documentId),\n ]\n }\n\n // Rebuild derived rows for all current-draft and published rows of a type.\n // One bounded admin action; not chunked cron orchestration.\n async reindexType(typeId: string, tenantId: string, queryableFields: QueryableField[]): Promise<number> {\n // Only reindex rows that participate in queries (current-draft or published).\n const result = await this.db\n .prepare(\n `SELECT * FROM documents\n WHERE type_id = ? AND tenant_id = ? AND (is_current_draft = 1 OR is_published = 1) AND deleted_at IS NULL`,\n )\n .bind(typeId, tenantId)\n .all<DocumentRow>()\n\n const rows = result.results ?? []\n if (rows.length === 0) return 0\n\n const now = Math.floor(Date.now() / 1000)\n let rebuilt = 0\n\n // Process in batches of 20 documents to stay well under D1's 1000-rows-per-batch guidance.\n for (const chunk of chunkArray(rows, 20)) {\n const statements: D1PreparedStatement[] = []\n\n for (const row of chunk) {\n const doc = rowToDocument(row)\n statements.push(...this.buildDerivedDeleteStatements(doc.id))\n statements.push(...this.buildDerivedInsertStatements(doc, queryableFields, now))\n }\n\n if (statements.length > 0) {\n await this.db.batch(statements)\n rebuilt += chunk.length\n }\n }\n\n return rebuilt\n }\n\n private extractPath(data: Record<string, unknown>, path: string): unknown {\n // Supports simple $.<key> paths only; full JSONPath is overkill for the POC.\n if (path.startsWith('$.')) {\n const key = path.slice(2)\n return data[key] ?? null\n }\n return null\n }\n}\n\nfunction rowToDocument(row: DocumentRow): Document {\n return {\n id: row.id,\n rootId: row.root_id,\n typeId: row.type_id,\n typeVersion: row.type_version,\n versionOfId: row.version_of_id,\n versionNumber: row.version_number,\n isCurrentDraft: row.is_current_draft === 1,\n isPublished: row.is_published === 1,\n status: row.status,\n parentRootId: row.parent_root_id,\n slug: row.slug,\n path: row.path,\n title: row.title,\n zone: row.zone,\n sortOrder: row.sort_order,\n visible: row.visible === 1,\n publishedAt: row.published_at,\n scheduledAt: row.scheduled_at,\n expiresAt: row.expires_at,\n deletedAt: row.deleted_at,\n tenantId: row.tenant_id,\n locale: row.locale,\n translationGroupId: row.translation_group_id,\n data: JSON.parse(row.data),\n metadata: JSON.parse(row.metadata),\n ownerId: row.owner_id,\n createdBy: row.created_by,\n updatedBy: row.updated_by,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n }\n}\n"]}
|
|
@@ -32,8 +32,17 @@ async function isFirstUserRegistration(db) {
|
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
var emailSchema = z.string().email("Valid email is required").refine(
|
|
36
|
+
(value) => {
|
|
37
|
+
const at = value.lastIndexOf("@");
|
|
38
|
+
if (at < 0) return false;
|
|
39
|
+
const domain = value.slice(at + 1);
|
|
40
|
+
return domain.split(".").every((label) => label.length > 0 && !label.startsWith("-") && !label.endsWith("-"));
|
|
41
|
+
},
|
|
42
|
+
{ message: "Valid email is required" }
|
|
43
|
+
);
|
|
35
44
|
var baseRegistrationSchema = z.object({
|
|
36
|
-
email:
|
|
45
|
+
email: emailSchema,
|
|
37
46
|
password: z.string().min(8, "Password must be at least 8 characters"),
|
|
38
47
|
firstName: z.string().min(1, "First name is required").optional(),
|
|
39
48
|
lastName: z.string().min(1, "Last name is required").optional()
|
|
@@ -62,5 +71,5 @@ var authValidationService = {
|
|
|
62
71
|
};
|
|
63
72
|
|
|
64
73
|
export { authValidationService, isFirstUserRegistration, isRegistrationEnabled };
|
|
65
|
-
//# sourceMappingURL=chunk-
|
|
66
|
-
//# sourceMappingURL=chunk-
|
|
74
|
+
//# sourceMappingURL=chunk-VVYVFCML.js.map
|
|
75
|
+
//# sourceMappingURL=chunk-VVYVFCML.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/auth-validation.ts"],"names":[],"mappings":"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","file":"chunk-VVYVFCML.js","sourcesContent":["/**\n * Auth Validation Service\n *\n * Provides validation schemas for authentication operations\n */\n\nimport { z } from 'zod'\nimport type { D1Database } from '@cloudflare/workers-types'\n\n// In-memory cache for admin existence check (lazy initialization pattern)\nlet adminExistsCache: boolean | null = null\n\nexport interface AuthSettings {\n enablePasswordLogin?: boolean\n enableOAuthLogin?: boolean\n requireEmailVerification?: boolean\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any\n}\n\n/**\n * Check if user registration is enabled in the auth plugin settings\n * @param db - D1 database instance\n * @returns true if registration is enabled, false if disabled\n */\nexport async function isRegistrationEnabled(db: D1Database): Promise<boolean> {\n // Plugin settings live on the plugin's document (type_id='plugin', slug=pluginId) since the\n // document-model migration — the legacy `plugins` table no longer exists on greenfield. The\n // /admin/plugins/core-auth/settings write goes through PluginService.updatePluginSettings (doc model),\n // so the read must come from the same place or \"disable registration\" silently no-ops.\n try {\n const row = await db\n .prepare(\n \"SELECT data FROM documents WHERE slug = 'core-auth' AND type_id = 'plugin' AND tenant_id = 'default' AND is_current_draft = 1 AND deleted_at IS NULL\",\n )\n .first() as { data: string } | null\n if (row?.data) {\n const data = typeof row.data === 'string' ? JSON.parse(row.data) : row.data\n const enabled = data?.settings?.registration?.enabled\n return enabled !== false && enabled !== 0\n }\n } catch {\n // fall through to the legacy table for installs that still have it\n }\n\n // Legacy fallback: the dropped `plugins` table (guarded — absent on greenfield).\n try {\n const plugin = await db.prepare('SELECT settings FROM plugins WHERE id = ?')\n .bind('core-auth')\n .first() as { settings: string } | null\n if (plugin?.settings) {\n // SQLite stores booleans as 0/1, so check for both false and 0.\n const settings = JSON.parse(plugin.settings)\n const enabled = settings?.registration?.enabled\n return enabled !== false && enabled !== 0\n }\n } catch {\n // no legacy table either\n }\n\n return true // Default to enabled when no setting is found\n}\n\n/**\n * Check if this would be the first user registration (bootstrap scenario)\n * The first user should always be allowed to register even if registration is disabled\n * @param db - D1 database instance\n * @returns true if no users exist in the database\n */\nexport async function isFirstUserRegistration(db: D1Database): Promise<boolean> {\n try {\n const result = await db.prepare('SELECT COUNT(*) as count FROM auth_user').first() as { count: number } | null\n return result?.count === 0\n } catch {\n return false // Default to not first user on error\n }\n}\n\n/**\n * Check if an admin user exists in the database (with in-memory caching)\n * Uses lazy initialization - only queries DB on first call, then caches result\n * @param db - D1 database instance\n * @returns true if an admin user exists\n */\nexport async function checkAdminUserExists(db: D1Database): Promise<boolean> {\n // Return cached value if already checked\n if (adminExistsCache !== null) {\n return adminExistsCache\n }\n\n try {\n const result = await db.prepare('SELECT id FROM auth_user WHERE role = ?')\n .bind('admin')\n .first()\n adminExistsCache = !!result\n return adminExistsCache\n } catch {\n // On error (e.g., table doesn't exist yet), assume no admin exists\n return false\n }\n}\n\n/**\n * Set the admin exists cache to true\n * Call this after successfully creating the first admin user\n */\nexport function setAdminExists(): void {\n adminExistsCache = true\n}\n\n/**\n * Reset the admin exists cache (for testing purposes)\n */\nexport function resetAdminExistsCache(): void {\n adminExistsCache = null\n}\n\n/**\n * Auth Validation Service\n * Provides dynamic validation schemas for registration based on database settings\n */\n/**\n * Email schema. Zod's `.email()` already rejects the common malformed shapes\n * (spaces, double-quoted local parts, consecutive dots, leading dots, commas),\n * but it *accepts* domain labels that begin or end with a hyphen (e.g.\n * `user@example-.com`), which are invalid per RFC 1035. The refine closes that\n * gap so registration validation matches stricter CMS auth suites.\n */\nexport const emailSchema = z\n .string()\n .email('Valid email is required')\n .refine(\n (value) => {\n const at = value.lastIndexOf('@')\n if (at < 0) return false\n const domain = value.slice(at + 1)\n // No domain label may start or end with a hyphen.\n return domain.split('.').every((label) => label.length > 0 && !label.startsWith('-') && !label.endsWith('-'))\n },\n { message: 'Valid email is required' }\n )\n\nconst baseRegistrationSchema = z.object({\n email: emailSchema,\n password: z.string().min(8, 'Password must be at least 8 characters'),\n firstName: z.string().min(1, 'First name is required').optional(),\n lastName: z.string().min(1, 'Last name is required').optional()\n})\n\nexport type RegistrationSchema = typeof baseRegistrationSchema\nexport type RegistrationData = z.infer<RegistrationSchema>\n\nexport const authValidationService = {\n /**\n * Build registration schema dynamically based on auth settings\n * For now, returns a static schema with standard fields\n */\n async buildRegistrationSchema(_db: D1Database): Promise<RegistrationSchema> {\n // TODO: Load settings from database to make fields optional/required dynamically\n // For now, use a static schema with common registration fields\n return baseRegistrationSchema\n },\n\n /**\n * Generate default values for optional fields\n */\n generateDefaultValue(field: string, data: any): string {\n switch (field) {\n case 'firstName':\n return 'User'\n case 'lastName':\n return data.email ? data.email.split('@')[0] : 'Account'\n default:\n return ''\n }\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@sonicjs-cms/core",
|
|
4
|
-
version: "3.0.0-beta.
|
|
4
|
+
version: "3.0.0-beta.20",
|
|
5
5
|
description: "Core framework for SonicJS headless CMS - Edge-first, TypeScript-native CMS built for Cloudflare Workers",
|
|
6
6
|
type: "module",
|
|
7
7
|
main: "./dist/index.cjs",
|
|
@@ -150,5 +150,5 @@ function getCoreVersion() {
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
export { SONICJS_VERSION, getCoreVersion, package_default };
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
154
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-W53J3BJ2.js.map
|
|
154
|
+
//# sourceMappingURL=chunk-W53J3BJ2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/utils/version.ts"],"names":[],"mappings":"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","file":"chunk-W53J3BJ2.js","sourcesContent":["{\n \"name\": \"@sonicjs-cms/core\",\n \"version\": \"3.0.0-beta.20\",\n \"description\": \"Core framework for SonicJS headless CMS - Edge-first, TypeScript-native CMS built for Cloudflare Workers\",\n \"type\": \"module\",\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"sonicjs-db-reset\": \"./bin/db-reset.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./services\": {\n \"types\": \"./dist/services.d.ts\",\n \"import\": \"./dist/services.js\",\n \"require\": \"./dist/services.cjs\"\n },\n \"./middleware\": {\n \"types\": \"./dist/middleware.d.ts\",\n \"import\": \"./dist/middleware.js\",\n \"require\": \"./dist/middleware.cjs\"\n },\n \"./routes\": {\n \"types\": \"./dist/routes.d.ts\",\n \"import\": \"./dist/routes.js\",\n \"require\": \"./dist/routes.cjs\"\n },\n \"./templates\": {\n \"types\": \"./dist/templates.d.ts\",\n \"import\": \"./dist/templates.js\",\n \"require\": \"./dist/templates.cjs\"\n },\n \"./plugins\": {\n \"types\": \"./dist/plugins.d.ts\",\n \"import\": \"./dist/plugins.js\",\n \"require\": \"./dist/plugins.cjs\"\n },\n \"./utils\": {\n \"types\": \"./dist/utils.d.ts\",\n \"import\": \"./dist/utils.js\",\n \"require\": \"./dist/utils.cjs\"\n },\n \"./types\": {\n \"types\": \"./dist/types.d.ts\",\n \"import\": \"./dist/types.js\",\n \"require\": \"./dist/types.cjs\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"bin\",\n \"dist\",\n \"migrations\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"generate:migrations\": \"npx tsx scripts/generate-migrations.ts\",\n \"prebuild\": \"npm run generate:migrations\",\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"type-check\": \"tsc --noEmit\",\n \"lint\": \"eslint src/\",\n \"lint:fix\": \"eslint src/ --fix\",\n \"test\": \"vitest run\",\n \"test:cov\": \"vitest run --coverage\",\n \"test:watch\": \"vitest\",\n \"prepublishOnly\": \"npm run build\",\n \"prepare\": \"npm run build\"\n },\n \"keywords\": [\n \"cms\",\n \"headless-cms\",\n \"cloudflare\",\n \"workers\",\n \"edge\",\n \"typescript\",\n \"hono\",\n \"content-management\",\n \"api\",\n \"sonicjs\"\n ],\n \"author\": \"SonicJS Team\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/sonicjs/sonicjs.git\",\n \"directory\": \"packages/core\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/sonicjs/sonicjs/issues\"\n },\n \"homepage\": \"https://sonicjs.com\",\n \"peerDependencies\": {\n \"@cloudflare/workers-types\": \"^4.0.0\",\n \"drizzle-orm\": \"^0.44.0\",\n \"hono\": \"^4.0.0\",\n \"zod\": \"^3.0.0 || ^4.0.0\"\n },\n \"dependencies\": {\n \"@cf-wasm/resvg\": \"^0.3.3\",\n \"better-auth\": \"^1.6.13\",\n \"better-auth-cloudflare\": \"^0.3.0\",\n \"csv-parse\": \"^6.2.1\",\n \"drizzle-zod\": \"^0.8.3\",\n \"highlight.js\": \"^11.11.1\",\n \"linkedom\": \"^0.18.12\",\n \"marked\": \"^16.4.1\",\n \"qrcode-svg\": \"^1.1.0\",\n \"semver\": \"^7.7.3\",\n \"tiny-lru\": \"^13.0.0\"\n },\n \"devDependencies\": {\n \"@cloudflare/workers-types\": \"^4.20251014.0\",\n \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/node\": \"^24.9.2\",\n \"@types/qrcode-svg\": \"^1.1.5\",\n \"@typescript-eslint/eslint-plugin\": \"^8.50.0\",\n \"@typescript-eslint/parser\": \"^8.50.0\",\n \"@vitest/coverage-v8\": \"^4.1.9\",\n \"better-sqlite3\": \"^12.10.0\",\n \"drizzle-orm\": \"^0.45.2\",\n \"eslint\": \"^9.39.2\",\n \"glob\": \"^10.5.0\",\n \"hono\": \"^4.12.26\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.9\",\n \"zod\": \"^4.1.12\"\n },\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n }\n}\n","/**\n * Version utility\n *\n * Provides the current version of @sonicjs-cms/core package\n */\n\nimport pkg from '../../package.json'\n\nexport const SONICJS_VERSION = pkg.version\n\n/**\n * Get the current SonicJS core version\n */\nexport function getCoreVersion(): string {\n return SONICJS_VERSION\n}\n"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { RbacService } from './chunk-
|
|
2
|
-
import { loadCollectionConfigs, getCollectionRegistry, PluginBootstrapService } from './chunk-
|
|
3
|
-
import { ensureScalarSchema, MigrationService } from './chunk-
|
|
1
|
+
import { RbacService } from './chunk-3TMTYJAJ.js';
|
|
2
|
+
import { loadCollectionConfigs, getCollectionRegistry, PluginBootstrapService, getTelemetryService } from './chunk-RDH6PUOP.js';
|
|
3
|
+
import { ensureScalarSchema, MigrationService } from './chunk-DSXEVMOM.js';
|
|
4
|
+
import { init_admin_layout_catalyst_template, setBranchLabel } from './chunk-5V62WT6M.js';
|
|
4
5
|
import { hasHookSystem, getHookSystem } from './chunk-RNZFGN4R.js';
|
|
5
6
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
7
|
+
import { SONICJS_VERSION } from './chunk-W53J3BJ2.js';
|
|
6
8
|
import { z } from 'zod';
|
|
7
9
|
import { sign, verify } from 'hono/jwt';
|
|
8
10
|
import { getCookie, setCookie } from 'hono/cookie';
|
|
@@ -31,6 +33,7 @@ var DocumentTypeRegistry = class {
|
|
|
31
33
|
constructor(db) {
|
|
32
34
|
this.db = db;
|
|
33
35
|
}
|
|
36
|
+
db;
|
|
34
37
|
cache = /* @__PURE__ */ new Map();
|
|
35
38
|
// Register or update a document type. Idempotent: bumps schema_version only when schema changes.
|
|
36
39
|
async register(def) {
|
|
@@ -265,6 +268,26 @@ async function bootstrapDocumentTypes(db) {
|
|
|
265
268
|
{ name: "blocked", kind: "scalar", type: "integer", column: "q_sa_blocked" }
|
|
266
269
|
]
|
|
267
270
|
});
|
|
271
|
+
await registry.register({
|
|
272
|
+
id: "api_key",
|
|
273
|
+
name: "api_key",
|
|
274
|
+
displayName: "API Key",
|
|
275
|
+
description: "Programmatic API access key (auth-owned; only the secret hash is stored)",
|
|
276
|
+
source: "system",
|
|
277
|
+
isAuth: true,
|
|
278
|
+
schema: anyObject,
|
|
279
|
+
settings: {
|
|
280
|
+
internal: true,
|
|
281
|
+
maxVersionsPerRoot: 1,
|
|
282
|
+
pii: true,
|
|
283
|
+
baseGrants: { admin: ["read", "create", "update", "delete", "manage"] }
|
|
284
|
+
},
|
|
285
|
+
queryableFields: [
|
|
286
|
+
{ name: "keyHash", kind: "scalar", type: "text", column: "q_apikey_hash" },
|
|
287
|
+
{ name: "userId", kind: "scalar", type: "text", column: "q_apikey_user_id" },
|
|
288
|
+
{ name: "revoked", kind: "scalar", type: "integer", column: "q_apikey_revoked" }
|
|
289
|
+
]
|
|
290
|
+
});
|
|
268
291
|
await registry.register({
|
|
269
292
|
id: "analytics_event",
|
|
270
293
|
name: "analytics_event",
|
|
@@ -333,6 +356,12 @@ async function autoRegisterCollectionDocumentTypes(db) {
|
|
|
333
356
|
if (collection.internal) continue;
|
|
334
357
|
if (collection.name === "blog_post") continue;
|
|
335
358
|
try {
|
|
359
|
+
const defaultGrants = {
|
|
360
|
+
admin: ["read", "create", "update", "delete", "publish", "manage"],
|
|
361
|
+
editor: ["read", "create", "update", "publish"],
|
|
362
|
+
viewer: ["read"]
|
|
363
|
+
};
|
|
364
|
+
const baseGrants = collection.access ? { ...defaultGrants, ...collection.access } : defaultGrants;
|
|
336
365
|
await registry.register({
|
|
337
366
|
id: collection.name,
|
|
338
367
|
name: collection.name,
|
|
@@ -341,12 +370,7 @@ async function autoRegisterCollectionDocumentTypes(db) {
|
|
|
341
370
|
source: "system",
|
|
342
371
|
schema: anyObject,
|
|
343
372
|
settings: {
|
|
344
|
-
baseGrants
|
|
345
|
-
public: ["read"],
|
|
346
|
-
admin: ["read", "create", "update", "delete", "publish", "manage"],
|
|
347
|
-
editor: ["read", "create", "update", "publish"],
|
|
348
|
-
viewer: ["read"]
|
|
349
|
-
},
|
|
373
|
+
baseGrants,
|
|
350
374
|
maxVersionsPerRoot: 50,
|
|
351
375
|
...collection.versioning ? { versioning: true } : {}
|
|
352
376
|
},
|
|
@@ -361,6 +385,7 @@ async function autoRegisterCollectionDocumentTypes(db) {
|
|
|
361
385
|
}
|
|
362
386
|
|
|
363
387
|
// src/middleware/bootstrap.ts
|
|
388
|
+
init_admin_layout_catalyst_template();
|
|
364
389
|
var bootstrapComplete = false;
|
|
365
390
|
function verifySecurityConfig(env) {
|
|
366
391
|
const warnings = [];
|
|
@@ -411,6 +436,10 @@ function bootstrapMiddleware(config = {}) {
|
|
|
411
436
|
if (path.startsWith("/images/") || path.startsWith("/assets/") || path === "/health" || path.endsWith(".js") || path.endsWith(".css") || path.endsWith(".png") || path.endsWith(".jpg") || path.endsWith(".ico")) {
|
|
412
437
|
return next();
|
|
413
438
|
}
|
|
439
|
+
const host = c.req.header("host") || "";
|
|
440
|
+
const isLocalhost = host.includes("localhost") || host.includes("127.0.0.1");
|
|
441
|
+
const gitBranch = c.env.GIT_BRANCH;
|
|
442
|
+
setBranchLabel(isLocalhost && gitBranch ? gitBranch : void 0);
|
|
414
443
|
try {
|
|
415
444
|
console.log("[Bootstrap] Starting system initialization...");
|
|
416
445
|
console.log("[Bootstrap] Checking schema compatibility...");
|
|
@@ -445,7 +474,7 @@ function bootstrapMiddleware(config = {}) {
|
|
|
445
474
|
console.error("[Bootstrap] Error repairing credential accounts:", error);
|
|
446
475
|
}
|
|
447
476
|
try {
|
|
448
|
-
const { RbacService: RbacService2 } = await import('./rbac-
|
|
477
|
+
const { RbacService: RbacService2 } = await import('./rbac-Y43IEQOP.js');
|
|
449
478
|
await new RbacService2(c.env.DB, c.env.CACHE_KV).ensureSystemRbacSeed();
|
|
450
479
|
} catch (error) {
|
|
451
480
|
console.error("[Bootstrap] Error seeding RBAC documents:", error);
|
|
@@ -468,6 +497,52 @@ function bootstrapMiddleware(config = {}) {
|
|
|
468
497
|
}
|
|
469
498
|
bootstrapComplete = true;
|
|
470
499
|
console.log("[Bootstrap] System initialization completed");
|
|
500
|
+
try {
|
|
501
|
+
const registry = getCollectionRegistry();
|
|
502
|
+
const collections = registry.listActive();
|
|
503
|
+
const countResult = await c.env.DB.prepare(
|
|
504
|
+
`SELECT type_id, COUNT(*) AS cnt FROM documents
|
|
505
|
+
WHERE is_current_draft = 1 AND deleted_at IS NULL GROUP BY type_id`
|
|
506
|
+
).all();
|
|
507
|
+
const countMap = {};
|
|
508
|
+
let docTotal = 0;
|
|
509
|
+
for (const row of countResult.results ?? []) {
|
|
510
|
+
countMap[row.type_id] = row.cnt;
|
|
511
|
+
docTotal += row.cnt;
|
|
512
|
+
}
|
|
513
|
+
const fieldTypeHistogram = {};
|
|
514
|
+
for (const col of collections) {
|
|
515
|
+
const props = col.schema?.properties ?? {};
|
|
516
|
+
for (const field of Object.values(props)) {
|
|
517
|
+
const ft = field?.type ?? "unknown";
|
|
518
|
+
fieldTypeHistogram[ft] = (fieldTypeHistogram[ft] ?? 0) + 1;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const activePlugins = (config.plugins?.register ?? []).map((p) => p.name ?? "unknown");
|
|
522
|
+
let installationId = "unknown";
|
|
523
|
+
try {
|
|
524
|
+
const kv = c.env.KV;
|
|
525
|
+
if (kv) {
|
|
526
|
+
installationId = await kv.get("_sonicjs_installation_id") ?? "";
|
|
527
|
+
if (!installationId) {
|
|
528
|
+
installationId = crypto.randomUUID();
|
|
529
|
+
await kv.put("_sonicjs_installation_id", installationId);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
} catch {
|
|
533
|
+
}
|
|
534
|
+
const telemetry = getTelemetryService();
|
|
535
|
+
await telemetry.trackProjectSnapshot({
|
|
536
|
+
installation_id: installationId,
|
|
537
|
+
collection_names: collections.map((c2) => c2.name),
|
|
538
|
+
collection_counts: countMap,
|
|
539
|
+
active_plugins: activePlugins,
|
|
540
|
+
field_type_histogram: fieldTypeHistogram,
|
|
541
|
+
doc_total: docTotal,
|
|
542
|
+
sonicjs_version: SONICJS_VERSION
|
|
543
|
+
});
|
|
544
|
+
} catch {
|
|
545
|
+
}
|
|
471
546
|
} catch (error) {
|
|
472
547
|
console.error("[Bootstrap] Error during system initialization:", error);
|
|
473
548
|
}
|
|
@@ -1130,5 +1205,5 @@ var logActivity = () => {
|
|
|
1130
1205
|
};
|
|
1131
1206
|
|
|
1132
1207
|
export { AuthManager, DocumentTypeRegistry, PermissionManager, bootstrapDocumentTypes, bootstrapMiddleware, cacheHeaders, compressionMiddleware, csrfProtection, detailedLoggingMiddleware, generateCsrfToken, getActivePlugins, getJwtExpirySeconds, getJwtExpirySecondsFromDb, getJwtRefreshGraceSecondsFromDb, isPluginActive, logActivity, loggingMiddleware, metricsMiddleware, optionalAuth, performanceLoggingMiddleware, rateLimit, requireActivePlugin, requireActivePlugins, requireAnyPermission, requireAuth, requirePermission, requireRbac, requireRole, securityHeadersMiddleware, securityLoggingMiddleware, validateCsrfToken, verifySecurityConfig };
|
|
1133
|
-
//# sourceMappingURL=chunk-
|
|
1134
|
-
//# sourceMappingURL=chunk-
|
|
1208
|
+
//# sourceMappingURL=chunk-WCA4VENG.js.map
|
|
1209
|
+
//# sourceMappingURL=chunk-WCA4VENG.js.map
|