emdash 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapters-BKSf3T9R.d.mts → adapters-DoNJiveC.d.mts} +1 -1
- package/dist/{adapters-BKSf3T9R.d.mts.map → adapters-DoNJiveC.d.mts.map} +1 -1
- package/dist/{apply-x0eMK1lX.mjs → apply-BzltprvY.mjs} +85 -135
- package/dist/apply-BzltprvY.mjs.map +1 -0
- package/dist/astro/index.d.mts +6 -6
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +110 -4
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +6 -7
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +16 -59
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +17 -12
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +9 -6
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +72 -124
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/types.d.mts +26 -10
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{base64-MBPo9ozB.mjs → base64-BRICGH2l.mjs} +1 -1
- package/dist/{base64-MBPo9ozB.mjs.map → base64-BRICGH2l.mjs.map} +1 -1
- package/dist/{byline-Chbr2GoP.mjs → byline-BSaNL1w7.mjs} +4 -4
- package/dist/{byline-Chbr2GoP.mjs.map → byline-BSaNL1w7.mjs.map} +1 -1
- package/dist/bylines-CvJ3PYz2.mjs +113 -0
- package/dist/bylines-CvJ3PYz2.mjs.map +1 -0
- package/dist/cache-C6N_hhN7.mjs +65 -0
- package/dist/cache-C6N_hhN7.mjs.map +1 -0
- package/dist/{chunks-HGz06Soa.mjs → chunks-NBQVDOci.mjs} +8 -2
- package/dist/{chunks-HGz06Soa.mjs.map → chunks-NBQVDOci.mjs.map} +1 -1
- package/dist/cli/index.mjs +224 -30
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +3 -3
- package/dist/client/index.mjs.map +1 -1
- package/dist/{config-BXwuX8Bx.mjs → config-BI0V3ICQ.mjs} +1 -1
- package/dist/{config-BXwuX8Bx.mjs.map → config-BI0V3ICQ.mjs.map} +1 -1
- package/dist/{content-BcQPYxdV.mjs → content-8lOYF0pr.mjs} +32 -15
- package/dist/{content-BcQPYxdV.mjs.map → content-8lOYF0pr.mjs.map} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/libsql.d.mts.map +1 -1
- package/dist/db/libsql.mjs +7 -2
- package/dist/db/libsql.mjs.map +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.d.mts.map +1 -1
- package/dist/db/sqlite.mjs +8 -3
- package/dist/db/sqlite.mjs.map +1 -1
- package/dist/{db-errors-l1Qh2RPR.mjs → db-errors-WRezodiz.mjs} +1 -1
- package/dist/{db-errors-l1Qh2RPR.mjs.map → db-errors-WRezodiz.mjs.map} +1 -1
- package/dist/{default-DCVqE5ib.mjs → default-D8ksjWhO.mjs} +1 -1
- package/dist/{default-DCVqE5ib.mjs.map → default-D8ksjWhO.mjs.map} +1 -1
- package/dist/{dialect-helpers-DhTzaUxP.mjs → dialect-helpers-BKCvISIQ.mjs} +19 -2
- package/dist/dialect-helpers-BKCvISIQ.mjs.map +1 -0
- package/dist/{error-zG5T1UGA.mjs → error-D_-tqP-I.mjs} +1 -1
- package/dist/{error-zG5T1UGA.mjs.map → error-D_-tqP-I.mjs.map} +1 -1
- package/dist/{index-DIb-CzNx.d.mts → index-BFRaVcD6.d.mts} +94 -34
- package/dist/index-BFRaVcD6.d.mts.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +29 -27
- package/dist/{load-CyEoextb.mjs → load-DDqMMvZL.mjs} +2 -2
- package/dist/{load-CyEoextb.mjs.map → load-DDqMMvZL.mjs.map} +1 -1
- package/dist/{loader-CndGj8kM.mjs → loader-CKLbBnhK.mjs} +27 -7
- package/dist/loader-CKLbBnhK.mjs.map +1 -0
- package/dist/{manifest-schema-DH9xhc6t.mjs → manifest-schema-DqWNC3lM.mjs} +33 -3
- package/dist/manifest-schema-DqWNC3lM.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +1 -1
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/media/local-runtime.mjs +3 -3
- package/dist/{media-D8FbNsl0.mjs → media-BW32b4gi.mjs} +2 -2
- package/dist/{media-D8FbNsl0.mjs.map → media-BW32b4gi.mjs.map} +1 -1
- package/dist/{mode-BnAOqItE.mjs → mode-ier8jbBk.mjs} +1 -1
- package/dist/{mode-BnAOqItE.mjs.map → mode-ier8jbBk.mjs.map} +1 -1
- package/dist/options-BVp3UsTS.mjs +117 -0
- package/dist/options-BVp3UsTS.mjs.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{placeholder-D29tWZ7o.d.mts → placeholder-BE4o_2dc.d.mts} +1 -1
- package/dist/{placeholder-D29tWZ7o.d.mts.map → placeholder-BE4o_2dc.d.mts.map} +1 -1
- package/dist/{placeholder-C-fk5hYI.mjs → placeholder-CIJejMlK.mjs} +1 -1
- package/dist/{placeholder-C-fk5hYI.mjs.map → placeholder-CIJejMlK.mjs.map} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +6 -5
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/public-url-DByxYjUw.mjs +51 -0
- package/dist/public-url-DByxYjUw.mjs.map +1 -0
- package/dist/{query-fqEdLFms.mjs → query-Cg9ZKRQ0.mjs} +114 -16
- package/dist/query-Cg9ZKRQ0.mjs.map +1 -0
- package/dist/{redirect-D_pshWdf.mjs → redirect-BhUBKRc1.mjs} +11 -6
- package/dist/redirect-BhUBKRc1.mjs.map +1 -0
- package/dist/{registry-C3Mr0ODu.mjs → registry-Dw70ChxB.mjs} +38 -4
- package/dist/registry-Dw70ChxB.mjs.map +1 -0
- package/dist/{request-cache-Ci7f5pBb.mjs → request-cache-B-bmkipQ.mjs} +1 -1
- package/dist/{request-cache-Ci7f5pBb.mjs.map → request-cache-B-bmkipQ.mjs.map} +1 -1
- package/dist/runner-Bnoj7vjK.d.mts +44 -0
- package/dist/runner-Bnoj7vjK.d.mts.map +1 -0
- package/dist/{runner-tQ7BJ4T7.mjs → runner-C7ADox5q.mjs} +185 -55
- package/dist/{runner-tQ7BJ4T7.mjs.map → runner-C7ADox5q.mjs.map} +1 -1
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +4 -4
- package/dist/{search-BoZYFuUk.mjs → search-dOGEccMa.mjs} +129 -83
- package/dist/search-dOGEccMa.mjs.map +1 -0
- package/dist/secrets-CW3reAnU.mjs +314 -0
- package/dist/secrets-CW3reAnU.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +15 -14
- package/dist/seo/index.d.mts +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{taxonomies-B4IAshV8.mjs → taxonomies-ZlRtD6AG.mjs} +14 -7
- package/dist/taxonomies-ZlRtD6AG.mjs.map +1 -0
- package/dist/{tokens-D9vnZqYS.mjs → tokens-D7zMmWi2.mjs} +2 -2
- package/dist/{tokens-D9vnZqYS.mjs.map → tokens-D7zMmWi2.mjs.map} +1 -1
- package/dist/{transport-C9ugt2Nr.mjs → transport-BeMCmin1.mjs} +6 -5
- package/dist/{transport-C9ugt2Nr.mjs.map → transport-BeMCmin1.mjs.map} +1 -1
- package/dist/{transport-CUnEL3Vs.d.mts → transport-DNEfeMaU.d.mts} +1 -1
- package/dist/{transport-CUnEL3Vs.d.mts.map → transport-DNEfeMaU.d.mts.map} +1 -1
- package/dist/types-4fVtCIm0.mjs +68 -0
- package/dist/types-4fVtCIm0.mjs.map +1 -0
- package/dist/{types-BmPPSUEx.d.mts → types-BSyXeCFW.d.mts} +24 -2
- package/dist/{types-BmPPSUEx.d.mts.map → types-BSyXeCFW.d.mts.map} +1 -1
- package/dist/{types-i36XcA_X.d.mts → types-BuBIptGk.d.mts} +65 -134
- package/dist/types-BuBIptGk.d.mts.map +1 -0
- package/dist/{types-CgqmmMJB.mjs → types-CDbKp7ND.mjs} +1 -1
- package/dist/{types-CgqmmMJB.mjs.map → types-CDbKp7ND.mjs.map} +1 -1
- package/dist/{types-Bm1dn-q3.mjs → types-CIOg5AR8.mjs} +1 -1
- package/dist/{types-Bm1dn-q3.mjs.map → types-CIOg5AR8.mjs.map} +1 -1
- package/dist/{types-BrA0xf5I.d.mts → types-CJsYGpco.d.mts} +1 -1
- package/dist/{types-BrA0xf5I.d.mts.map → types-CJsYGpco.d.mts.map} +1 -1
- package/dist/{types-BIgulNsW.mjs → types-CRxNbK-Z.mjs} +2 -2
- package/dist/{types-BIgulNsW.mjs.map → types-CRxNbK-Z.mjs.map} +1 -1
- package/dist/{types-CS8FIX7L.d.mts → types-CrtWgIvl.d.mts} +1 -1
- package/dist/{types-CS8FIX7L.d.mts.map → types-CrtWgIvl.d.mts.map} +1 -1
- package/dist/{types-DIMwPFub.d.mts → types-M78DQ1lx.d.mts} +1 -1
- package/dist/{types-DIMwPFub.d.mts.map → types-M78DQ1lx.d.mts.map} +1 -1
- package/dist/{validate-CxVsLehf.mjs → validate-Baqf0slj.mjs} +3 -3
- package/dist/{validate-CxVsLehf.mjs.map → validate-Baqf0slj.mjs.map} +1 -1
- package/dist/{validate-DHxmpFJt.d.mts → validate-BfQh_C_y.d.mts} +4 -4
- package/dist/{validate-DHxmpFJt.d.mts.map → validate-BfQh_C_y.d.mts.map} +1 -1
- package/dist/{validation-C-ZpN2GI.mjs → validation-BfEI7tNe.mjs} +6 -6
- package/dist/{validation-C-ZpN2GI.mjs.map → validation-BfEI7tNe.mjs.map} +1 -1
- package/dist/version-DoxrVdYf.mjs +7 -0
- package/dist/{version-Bbq8TCrz.mjs.map → version-DoxrVdYf.mjs.map} +1 -1
- package/dist/{zod-generator-CpwccCIv.mjs → zod-generator-CC0xNe_K.mjs} +4 -4
- package/dist/zod-generator-CC0xNe_K.mjs.map +1 -0
- package/locals.d.ts +1 -6
- package/package.json +9 -8
- package/src/api/handlers/comments.ts +6 -4
- package/src/api/handlers/content.ts +29 -1
- package/src/api/handlers/device-flow.ts +5 -0
- package/src/api/handlers/marketplace.ts +11 -4
- package/src/api/handlers/oauth-authorization.ts +72 -33
- package/src/api/handlers/revision.ts +23 -14
- package/src/api/handlers/taxonomies.ts +3 -6
- package/src/api/public-url.ts +48 -2
- package/src/api/schemas/comments.ts +2 -2
- package/src/api/schemas/content.ts +17 -0
- package/src/api/schemas/sections.ts +3 -3
- package/src/api/schemas/users.ts +1 -1
- package/src/api/types.ts +5 -1
- package/src/astro/integration/index.ts +17 -0
- package/src/astro/integration/runtime.ts +30 -0
- package/src/astro/integration/virtual-modules.ts +32 -2
- package/src/astro/integration/vite-config.ts +6 -1
- package/src/astro/middleware/auth.ts +13 -6
- package/src/astro/middleware/redirect.ts +29 -16
- package/src/astro/middleware/request-context.ts +15 -5
- package/src/astro/middleware.ts +23 -9
- package/src/astro/routes/api/auth/invite/complete.ts +6 -1
- package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
- package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
- package/src/astro/routes/api/auth/signup/complete.ts +6 -1
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
- package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
- package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
- package/src/astro/routes/api/import/wordpress/prepare.ts +7 -8
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
- package/src/astro/routes/api/manifest.ts +62 -45
- package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
- package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
- package/src/astro/routes/api/openapi.json.ts +27 -10
- package/src/astro/routes/api/redirects/404s/index.ts +10 -4
- package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
- package/src/astro/routes/api/redirects/[id].ts +10 -4
- package/src/astro/routes/api/redirects/index.ts +7 -3
- package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
- package/src/astro/routes/api/schema/collections/index.ts +1 -1
- package/src/astro/routes/api/search/index.ts +10 -2
- package/src/astro/routes/api/sections/[slug].ts +10 -4
- package/src/astro/routes/api/sections/index.ts +7 -3
- package/src/astro/routes/api/setup/admin-verify.ts +6 -1
- package/src/astro/routes/api/snapshot.ts +44 -18
- package/src/astro/routes/api/taxonomies/index.ts +0 -1
- package/src/astro/routes/api/themes/preview.ts +11 -5
- package/src/astro/types.ts +23 -3
- package/src/auth/allowed-origins.ts +168 -0
- package/src/auth/passkey-config.ts +35 -13
- package/src/bylines/index.ts +37 -88
- package/src/cli/commands/auth.ts +28 -6
- package/src/cli/commands/bundle-utils.ts +11 -2
- package/src/cli/commands/bundle.ts +28 -8
- package/src/cli/commands/content.ts +13 -0
- package/src/cli/commands/login.ts +8 -1
- package/src/cli/commands/publish.ts +24 -0
- package/src/cli/commands/secrets.ts +183 -0
- package/src/cli/credentials.ts +1 -1
- package/src/cli/index.ts +5 -1
- package/src/client/index.ts +4 -4
- package/src/client/transport.ts +17 -7
- package/src/components/Break.astro +2 -2
- package/src/components/EmDashHead.astro +18 -13
- package/src/components/Embed.astro +1 -1
- package/src/components/Gallery.astro +1 -1
- package/src/components/Image.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +104 -18
- package/src/config/secrets.ts +528 -0
- package/src/database/dialect-helpers.ts +50 -0
- package/src/database/migrations/034_published_at_index.ts +1 -1
- package/src/database/migrations/035_bounded_404_log.ts +56 -39
- package/src/database/migrations/runner.ts +156 -23
- package/src/database/repositories/content.ts +36 -12
- package/src/database/repositories/redirect.ts +14 -3
- package/src/database/repositories/taxonomy.ts +26 -0
- package/src/db/libsql.ts +1 -3
- package/src/db/sqlite.ts +2 -5
- package/src/emdash-runtime.ts +84 -159
- package/src/index.ts +9 -0
- package/src/loader.ts +24 -1
- package/src/mcp/server.ts +103 -36
- package/src/page/site-identity.ts +58 -0
- package/src/plugins/adapt-sandbox-entry.ts +22 -10
- package/src/plugins/context.ts +13 -10
- package/src/plugins/define-plugin.ts +40 -12
- package/src/plugins/hooks.ts +23 -19
- package/src/plugins/index.ts +9 -0
- package/src/plugins/manifest-schema.ts +37 -2
- package/src/plugins/types.ts +151 -11
- package/src/preview/urls.ts +23 -3
- package/src/query.ts +148 -5
- package/src/redirects/cache.ts +38 -18
- package/src/schema/registry.ts +56 -0
- package/src/schema/zod-generator.ts +27 -5
- package/src/seed/apply.ts +2 -0
- package/src/settings/index.ts +80 -6
- package/src/settings/types.ts +23 -1
- package/src/taxonomies/index.ts +11 -1
- package/dist/apply-x0eMK1lX.mjs.map +0 -1
- package/dist/bylines-CRNsVG88.mjs +0 -157
- package/dist/bylines-CRNsVG88.mjs.map +0 -1
- package/dist/cache-BkKBuIvS.mjs +0 -56
- package/dist/cache-BkKBuIvS.mjs.map +0 -1
- package/dist/chunk-ClPoSABd.mjs +0 -21
- package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
- package/dist/index-DIb-CzNx.d.mts.map +0 -1
- package/dist/loader-CndGj8kM.mjs.map +0 -1
- package/dist/manifest-schema-DH9xhc6t.mjs.map +0 -1
- package/dist/query-fqEdLFms.mjs.map +0 -1
- package/dist/redirect-D_pshWdf.mjs.map +0 -1
- package/dist/registry-C3Mr0ODu.mjs.map +0 -1
- package/dist/runner-OURCaApa.d.mts +0 -34
- package/dist/runner-OURCaApa.d.mts.map +0 -1
- package/dist/search-BoZYFuUk.mjs.map +0 -1
- package/dist/taxonomies-B4IAshV8.mjs.map +0 -1
- package/dist/types-i36XcA_X.d.mts.map +0 -1
- package/dist/version-Bbq8TCrz.mjs +0 -7
- package/dist/zod-generator-CpwccCIv.mjs.map +0 -1
|
@@ -1,8 +1,25 @@
|
|
|
1
|
-
import { t as __exportAll } from "./chunk-ClPoSABd.mjs";
|
|
2
1
|
import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
|
|
3
|
-
import {
|
|
2
|
+
import { c as listTablesLike, i as currentTimestampValue, n as columnExists, o as isSqlite, r as currentTimestamp, t as binaryType } from "./dialect-helpers-BKCvISIQ.mjs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
4
|
import { Migrator, sql } from "kysely";
|
|
5
5
|
|
|
6
|
+
//#region \0rolldown/runtime.js
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __exportAll = (all, no_symbols) => {
|
|
9
|
+
let target = {};
|
|
10
|
+
for (var name in all) {
|
|
11
|
+
__defProp(target, name, {
|
|
12
|
+
get: all[name],
|
|
13
|
+
enumerable: true
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
if (!no_symbols) {
|
|
17
|
+
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
18
|
+
}
|
|
19
|
+
return target;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
6
23
|
//#region src/database/migrations/001_initial.ts
|
|
7
24
|
var _001_initial_exports = /* @__PURE__ */ __exportAll({
|
|
8
25
|
down: () => down$33,
|
|
@@ -1404,7 +1421,7 @@ async function up$1(db) {
|
|
|
1404
1421
|
for (const tableName of tableNames) {
|
|
1405
1422
|
const table = { name: tableName };
|
|
1406
1423
|
await sql`
|
|
1407
|
-
CREATE INDEX ${sql.ref(`idx_${table.name}_deleted_published_id`)}
|
|
1424
|
+
CREATE INDEX IF NOT EXISTS ${sql.ref(`idx_${table.name}_deleted_published_id`)}
|
|
1408
1425
|
ON ${sql.ref(table.name)} (deleted_at, published_at DESC, id DESC)
|
|
1409
1426
|
`.execute(db);
|
|
1410
1427
|
}
|
|
@@ -1440,55 +1457,58 @@ var _035_bounded_404_log_exports = /* @__PURE__ */ __exportAll({
|
|
|
1440
1457
|
* - Adds a UNIQUE index on `path` so upsert semantics work
|
|
1441
1458
|
*/
|
|
1442
1459
|
async function up(db) {
|
|
1443
|
-
await db
|
|
1444
|
-
await db.schema.alterTable("_emdash_404_log").addColumn("
|
|
1460
|
+
const hitsExists = await columnExists(db, "_emdash_404_log", "hits");
|
|
1461
|
+
if (!hitsExists) await db.schema.alterTable("_emdash_404_log").addColumn("hits", "integer", (col) => col.notNull().defaultTo(1)).execute();
|
|
1462
|
+
if (!await columnExists(db, "_emdash_404_log", "last_seen_at")) await db.schema.alterTable("_emdash_404_log").addColumn("last_seen_at", "text").execute();
|
|
1445
1463
|
await sql`
|
|
1446
1464
|
UPDATE _emdash_404_log
|
|
1447
1465
|
SET last_seen_at = created_at
|
|
1448
1466
|
WHERE last_seen_at IS NULL
|
|
1449
1467
|
`.execute(db);
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
id,
|
|
1454
|
-
path,
|
|
1455
|
-
ROW_NUMBER() OVER (
|
|
1456
|
-
PARTITION BY path
|
|
1457
|
-
ORDER BY created_at DESC, id DESC
|
|
1458
|
-
) AS rn,
|
|
1459
|
-
COUNT(*) OVER (PARTITION BY path) AS path_count,
|
|
1460
|
-
MAX(created_at) OVER (PARTITION BY path) AS latest_created_at
|
|
1461
|
-
FROM _emdash_404_log
|
|
1462
|
-
)
|
|
1463
|
-
UPDATE _emdash_404_log
|
|
1464
|
-
SET
|
|
1465
|
-
hits = (SELECT path_count FROM ranked WHERE ranked.id = _emdash_404_log.id),
|
|
1466
|
-
last_seen_at = (SELECT latest_created_at FROM ranked WHERE ranked.id = _emdash_404_log.id)
|
|
1467
|
-
WHERE id IN (SELECT id FROM ranked WHERE rn = 1)
|
|
1468
|
-
`.execute(db);
|
|
1469
|
-
await sql`
|
|
1470
|
-
DELETE FROM _emdash_404_log
|
|
1471
|
-
WHERE id IN (
|
|
1472
|
-
SELECT id FROM (
|
|
1468
|
+
if (!hitsExists) {
|
|
1469
|
+
await sql`
|
|
1470
|
+
WITH ranked AS (
|
|
1473
1471
|
SELECT
|
|
1474
1472
|
id,
|
|
1473
|
+
path,
|
|
1475
1474
|
ROW_NUMBER() OVER (
|
|
1476
1475
|
PARTITION BY path
|
|
1477
1476
|
ORDER BY created_at DESC, id DESC
|
|
1478
|
-
) AS rn
|
|
1477
|
+
) AS rn,
|
|
1478
|
+
COUNT(*) OVER (PARTITION BY path) AS path_count,
|
|
1479
|
+
MAX(created_at) OVER (PARTITION BY path) AS latest_created_at
|
|
1479
1480
|
FROM _emdash_404_log
|
|
1480
|
-
)
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1481
|
+
)
|
|
1482
|
+
UPDATE _emdash_404_log
|
|
1483
|
+
SET
|
|
1484
|
+
hits = (SELECT path_count FROM ranked WHERE ranked.id = _emdash_404_log.id),
|
|
1485
|
+
last_seen_at = (SELECT latest_created_at FROM ranked WHERE ranked.id = _emdash_404_log.id)
|
|
1486
|
+
WHERE id IN (SELECT id FROM ranked WHERE rn = 1)
|
|
1487
|
+
`.execute(db);
|
|
1488
|
+
await sql`
|
|
1489
|
+
DELETE FROM _emdash_404_log
|
|
1490
|
+
WHERE id IN (
|
|
1491
|
+
SELECT id FROM (
|
|
1492
|
+
SELECT
|
|
1493
|
+
id,
|
|
1494
|
+
ROW_NUMBER() OVER (
|
|
1495
|
+
PARTITION BY path
|
|
1496
|
+
ORDER BY created_at DESC, id DESC
|
|
1497
|
+
) AS rn
|
|
1498
|
+
FROM _emdash_404_log
|
|
1499
|
+
) AS ranked
|
|
1500
|
+
WHERE rn > 1
|
|
1501
|
+
)
|
|
1502
|
+
`.execute(db);
|
|
1503
|
+
}
|
|
1504
|
+
await db.schema.createIndex("idx_404_log_path_unique").ifNotExists().on("_emdash_404_log").column("path").unique().execute();
|
|
1505
|
+
await db.schema.dropIndex("idx_404_log_path").ifExists().execute();
|
|
1506
|
+
await db.schema.createIndex("idx_404_log_last_seen").ifNotExists().on("_emdash_404_log").column("last_seen_at").execute();
|
|
1487
1507
|
}
|
|
1488
1508
|
async function down(db) {
|
|
1489
|
-
await db.schema.dropIndex("idx_404_log_last_seen").execute();
|
|
1490
|
-
await db.schema.dropIndex("idx_404_log_path_unique").execute();
|
|
1491
|
-
await db.schema.createIndex("idx_404_log_path").on("_emdash_404_log").column("path").execute();
|
|
1509
|
+
await db.schema.dropIndex("idx_404_log_last_seen").ifExists().execute();
|
|
1510
|
+
await db.schema.dropIndex("idx_404_log_path_unique").ifExists().execute();
|
|
1511
|
+
await db.schema.createIndex("idx_404_log_path").ifNotExists().on("_emdash_404_log").column("path").execute();
|
|
1492
1512
|
await db.schema.alterTable("_emdash_404_log").dropColumn("last_seen_at").execute();
|
|
1493
1513
|
await db.schema.alterTable("_emdash_404_log").dropColumn("hits").execute();
|
|
1494
1514
|
}
|
|
@@ -1564,22 +1584,130 @@ async function getMigrationStatus(db) {
|
|
|
1564
1584
|
pending
|
|
1565
1585
|
};
|
|
1566
1586
|
}
|
|
1587
|
+
/** Pattern for escaping special regex characters. Matches the shared helper in `database/repositories/content.ts`. */
|
|
1588
|
+
const REGEX_ESCAPE_PATTERN = /[.*+?^${}()|[\]\\]/g;
|
|
1589
|
+
/** Escape special regex characters so a string can be embedded literally in `new RegExp()`. */
|
|
1590
|
+
function escapeRegExp(value) {
|
|
1591
|
+
return value.replace(REGEX_ESCAPE_PATTERN, "\\$&");
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Pattern used to detect the concurrent-migration race. The Kysely
|
|
1595
|
+
* `SqliteAdapter.acquireMigrationLock` is a no-op (inherited by `kysely-d1`
|
|
1596
|
+
* and our `EmDashD1Dialect`), so two isolates running migrations against the
|
|
1597
|
+
* same database can both attempt `INSERT INTO _emdash_migrations` for the
|
|
1598
|
+
* same migration name. The losing insert fails with a UNIQUE constraint
|
|
1599
|
+
* error, which is benign: the other isolate is applying the same schema.
|
|
1600
|
+
*
|
|
1601
|
+
* We match on the table name (not the full error text) because different
|
|
1602
|
+
* SQLite drivers phrase the message differently
|
|
1603
|
+
* (`UNIQUE constraint failed: _emdash_migrations.name` for better-sqlite3,
|
|
1604
|
+
* `D1_ERROR: UNIQUE constraint failed: _emdash_migrations.name: SQLITE_CONSTRAINT`
|
|
1605
|
+
* for D1, etc.). The pattern is built from `MIGRATION_TABLE` so a rename
|
|
1606
|
+
* cannot silently disable race detection.
|
|
1607
|
+
*/
|
|
1608
|
+
const MIGRATION_RACE_PATTERN = new RegExp(`UNIQUE constraint failed: ${escapeRegExp(MIGRATION_TABLE)}\\.name`, "i");
|
|
1609
|
+
/** How long to wait for a concurrent migrator to finish before giving up. */
|
|
1610
|
+
const MIGRATION_RACE_WAIT_MS = 1e4;
|
|
1611
|
+
/** Polling interval while waiting for a concurrent migrator. */
|
|
1612
|
+
const MIGRATION_RACE_POLL_MS = 100;
|
|
1613
|
+
/**
|
|
1614
|
+
* Pattern used to detect "table does not exist" errors across the dialects
|
|
1615
|
+
* EmDash supports. The phrasing differs by driver:
|
|
1616
|
+
*
|
|
1617
|
+
* - better-sqlite3: `no such table: _emdash_migrations`
|
|
1618
|
+
* - D1: `D1_ERROR: no such table: _emdash_migrations: SQLITE_ERROR`
|
|
1619
|
+
* - PostgreSQL: `relation "_emdash_migrations" does not exist`
|
|
1620
|
+
* (also occasionally `table "_emdash_migrations" does not exist`)
|
|
1621
|
+
*
|
|
1622
|
+
* We deliberately match on the migration table name (rather than using the
|
|
1623
|
+
* generic `isMissingTableError` helper) so an unexpected missing-table error
|
|
1624
|
+
* naming a different table — implausible today since
|
|
1625
|
+
* `getAppliedMigrationCount` only references `MIGRATION_TABLE`, but cheap
|
|
1626
|
+
* insurance against future edits — is not silently swallowed. The pattern is
|
|
1627
|
+
* built from `MIGRATION_TABLE` so a rename cannot drift.
|
|
1628
|
+
*/
|
|
1629
|
+
const MIGRATION_TABLE_MISSING_PATTERN = new RegExp(`(?:no such table:\\s*${escapeRegExp(MIGRATION_TABLE)}\\b|(?:relation|table)\\s+"?${escapeRegExp(MIGRATION_TABLE)}"?\\s+does(?:n't| not) exist\\b)`, "i");
|
|
1630
|
+
/**
|
|
1631
|
+
* Read the count of applied migrations.
|
|
1632
|
+
*
|
|
1633
|
+
* Returns `null` only when the migration table does not exist yet (which is
|
|
1634
|
+
* the normal state on a fresh database before the first migration runs).
|
|
1635
|
+
* Any other error is rethrown so callers — particularly
|
|
1636
|
+
* `waitForConcurrentMigrator` — don't silently mask connection failures,
|
|
1637
|
+
* permission errors, or other unexpected driver problems behind a 10s wait
|
|
1638
|
+
* and a bogus "we're done" verdict.
|
|
1639
|
+
*/
|
|
1640
|
+
async function getAppliedMigrationCount(db) {
|
|
1641
|
+
try {
|
|
1642
|
+
const result = await sql`
|
|
1643
|
+
SELECT COUNT(*) as count FROM ${sql.ref(MIGRATION_TABLE)}
|
|
1644
|
+
`.execute(db);
|
|
1645
|
+
return Number(result.rows[0]?.count ?? 0);
|
|
1646
|
+
} catch (error) {
|
|
1647
|
+
if (MIGRATION_TABLE_MISSING_PATTERN.test(deepErrorMessage(error))) return null;
|
|
1648
|
+
throw error;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Wait for a concurrent migrator to finish applying all migrations.
|
|
1653
|
+
*
|
|
1654
|
+
* Resolves to `true` once the migration table contains at least
|
|
1655
|
+
* `MIGRATION_COUNT` rows (i.e. every migration this build knows about has
|
|
1656
|
+
* been recorded), `false` if the deadline elapses first. We use `>=` rather
|
|
1657
|
+
* than `===` so that an old isolate observing a database that has already
|
|
1658
|
+
* been migrated by a newer build still treats the wait as settled instead
|
|
1659
|
+
* of timing out.
|
|
1660
|
+
*/
|
|
1661
|
+
async function waitForConcurrentMigrator(db) {
|
|
1662
|
+
const deadline = Date.now() + MIGRATION_RACE_WAIT_MS;
|
|
1663
|
+
while (Date.now() < deadline) {
|
|
1664
|
+
const count = await getAppliedMigrationCount(db);
|
|
1665
|
+
if (count !== null && count >= MIGRATION_COUNT) return true;
|
|
1666
|
+
await new Promise((resolve) => setTimeout(resolve, MIGRATION_RACE_POLL_MS));
|
|
1667
|
+
}
|
|
1668
|
+
const finalCount = await getAppliedMigrationCount(db);
|
|
1669
|
+
return finalCount !== null && finalCount >= MIGRATION_COUNT;
|
|
1670
|
+
}
|
|
1671
|
+
/** Extract the deepest error message available from a thrown value. */
|
|
1672
|
+
function deepErrorMessage(error) {
|
|
1673
|
+
if (error instanceof Error) {
|
|
1674
|
+
const own = error.message ?? "";
|
|
1675
|
+
if (error.cause) {
|
|
1676
|
+
const causeMsg = deepErrorMessage(error.cause);
|
|
1677
|
+
return own ? `${own}: ${causeMsg}` : causeMsg;
|
|
1678
|
+
}
|
|
1679
|
+
return own;
|
|
1680
|
+
}
|
|
1681
|
+
if (typeof error === "string") return error;
|
|
1682
|
+
try {
|
|
1683
|
+
return JSON.stringify(error);
|
|
1684
|
+
} catch {
|
|
1685
|
+
return String(error);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1567
1688
|
/**
|
|
1568
1689
|
* Run all pending migrations.
|
|
1569
1690
|
*
|
|
1570
1691
|
* Includes a fast-path: if the migration table already exists and contains
|
|
1571
|
-
*
|
|
1572
|
-
* skip the Kysely Migrator entirely. This avoids
|
|
1573
|
-
* `pragma_table_info` introspection that Kysely runs for
|
|
1574
|
-
* database (twice!) just to check if the migration
|
|
1575
|
-
* On D1 with ~57 tables, that's ~116 queries saved per init.
|
|
1692
|
+
* at least MIGRATION_COUNT rows, all migrations this build knows about have
|
|
1693
|
+
* been applied and we can skip the Kysely Migrator entirely. This avoids
|
|
1694
|
+
* the expensive `pragma_table_info` introspection that Kysely runs for
|
|
1695
|
+
* every table in the database (twice!) just to check if the migration
|
|
1696
|
+
* tables exist. On D1 with ~57 tables, that's ~116 queries saved per init.
|
|
1697
|
+
*
|
|
1698
|
+
* Concurrent-migration safety: the Kysely Migrator's `acquireMigrationLock`
|
|
1699
|
+
* is a no-op for SQLite (and therefore D1), so two callers running this
|
|
1700
|
+
* concurrently against the same database will both try to apply pending
|
|
1701
|
+
* migrations. SQLite serializes the writes, but the loser still surfaces a
|
|
1702
|
+
* `UNIQUE constraint failed: _emdash_migrations.name` error. We treat that
|
|
1703
|
+
* specific error as benign: another caller is already applying the same
|
|
1704
|
+
* schema. We wait for the concurrent migrator to finish, then return
|
|
1705
|
+
* success. This matches the user-observable expectation that running
|
|
1706
|
+
* migrations twice in a row is a no-op.
|
|
1576
1707
|
*/
|
|
1577
1708
|
async function runMigrations(db) {
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
SELECT COUNT(*) as count FROM ${sql.ref(MIGRATION_TABLE)}
|
|
1581
|
-
`.execute(db)).rows[0]?.count === MIGRATION_COUNT) return { applied: [] };
|
|
1582
|
-
} catch {}
|
|
1709
|
+
const initialCount = await getAppliedMigrationCount(db);
|
|
1710
|
+
if (initialCount !== null && initialCount >= MIGRATION_COUNT) return { applied: [] };
|
|
1583
1711
|
const { error, results } = await new Migrator({
|
|
1584
1712
|
db,
|
|
1585
1713
|
provider: new StaticMigrationProvider(),
|
|
@@ -1588,11 +1716,13 @@ async function runMigrations(db) {
|
|
|
1588
1716
|
}).migrateToLatest();
|
|
1589
1717
|
const applied = results?.filter((r) => r.status === "Success").map((r) => r.migrationName) ?? [];
|
|
1590
1718
|
if (error) {
|
|
1591
|
-
|
|
1592
|
-
if (!msg && error instanceof Error && error.cause) msg = error.cause instanceof Error ? error.cause.message : JSON.stringify(error.cause);
|
|
1719
|
+
const msg = deepErrorMessage(error);
|
|
1593
1720
|
const failedMigration = results?.find((r) => r.status === "Error");
|
|
1594
|
-
if (
|
|
1595
|
-
|
|
1721
|
+
if (MIGRATION_RACE_PATTERN.test(msg)) {
|
|
1722
|
+
if (await waitForConcurrentMigrator(db)) return { applied };
|
|
1723
|
+
}
|
|
1724
|
+
const failedSuffix = failedMigration ? ` (migration: ${failedMigration.migrationName})` : "";
|
|
1725
|
+
throw new Error(`Migration failed: ${msg || "unknown error"}${failedSuffix}`);
|
|
1596
1726
|
}
|
|
1597
1727
|
return { applied };
|
|
1598
1728
|
}
|
|
@@ -1615,5 +1745,5 @@ async function rollbackMigration(db) {
|
|
|
1615
1745
|
}
|
|
1616
1746
|
|
|
1617
1747
|
//#endregion
|
|
1618
|
-
export { rollbackMigration as n, runMigrations as r, getMigrationStatus as t };
|
|
1619
|
-
//# sourceMappingURL=runner-
|
|
1748
|
+
export { __exportAll as i, rollbackMigration as n, runMigrations as r, getMigrationStatus as t };
|
|
1749
|
+
//# sourceMappingURL=runner-C7ADox5q.mjs.map
|