emdash 0.4.0 → 0.6.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-C2BzVy0p.d.mts → adapters-Di31kZ28.d.mts} +16 -1
- package/dist/adapters-Di31kZ28.d.mts.map +1 -0
- package/dist/{apply-Cma_PiF6.mjs → apply-B4MsLM-w.mjs} +27 -12
- package/dist/apply-B4MsLM-w.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 +208 -34
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +5 -5
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +34 -9
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.mjs +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +5 -3
- 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 +460 -180
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/types.d.mts +8 -8
- package/dist/{byline-WuOq9MFJ.mjs → byline-C4OVd8b3.mjs} +3 -19
- package/dist/byline-C4OVd8b3.mjs.map +1 -0
- package/dist/{bylines-C_Wsnz4L.mjs → bylines-hPTW79hw.mjs} +20 -33
- package/dist/bylines-hPTW79hw.mjs.map +1 -0
- package/dist/{cache-E3Dts-yT.mjs → cache-BkKBuIvS.mjs} +1 -1
- package/dist/{cache-E3Dts-yT.mjs.map → cache-BkKBuIvS.mjs.map} +1 -1
- package/dist/chunks-HGz06Soa.mjs +19 -0
- package/dist/chunks-HGz06Soa.mjs.map +1 -0
- package/dist/cli/index.mjs +9 -8
- 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 +1 -1
- package/dist/{config-DkxPrM9l.mjs → config-BXwuX8Bx.mjs} +1 -1
- package/dist/{config-DkxPrM9l.mjs.map → config-BXwuX8Bx.mjs.map} +1 -1
- package/dist/{connection-B4zVnQIa.mjs → connection-2igzM-AT.mjs} +19 -2
- package/dist/connection-2igzM-AT.mjs.map +1 -0
- package/dist/database/instrumentation.d.mts +45 -0
- package/dist/database/instrumentation.d.mts.map +1 -0
- package/dist/database/instrumentation.mjs +61 -0
- package/dist/database/instrumentation.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db-errors-D0UT85nC.mjs +41 -0
- package/dist/db-errors-D0UT85nC.mjs.map +1 -0
- package/dist/{default-PUx9RK6u.mjs → default-CME5YdZ3.mjs} +1 -1
- package/dist/{default-PUx9RK6u.mjs.map → default-CME5YdZ3.mjs.map} +1 -1
- package/dist/{error-HBeQbVhV.mjs → error-CiYn9yDu.mjs} +1 -1
- package/dist/{error-HBeQbVhV.mjs.map → error-CiYn9yDu.mjs.map} +1 -1
- package/dist/{index-CRg3PWfZ.d.mts → index-BYv0mB9g.d.mts} +135 -19
- package/dist/index-BYv0mB9g.d.mts.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +20 -18
- package/dist/{load-BhSSm-TS.mjs → load-CBcmDIot.mjs} +1 -1
- package/dist/{load-BhSSm-TS.mjs.map → load-CBcmDIot.mjs.map} +1 -1
- package/dist/{loader-BYzwzORf.mjs → loader-DeiBJEMe.mjs} +18 -12
- package/dist/loader-DeiBJEMe.mjs.map +1 -0
- package/dist/{manifest-schema-BsXINkQD.mjs → manifest-schema-V30qsMft.mjs} +1 -1
- package/dist/{manifest-schema-BsXINkQD.mjs.map → manifest-schema-V30qsMft.mjs.map} +1 -1
- 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/{mode-CyPLdO3C.mjs → mode-CpNnGkPz.mjs} +1 -1
- package/dist/{mode-CyPLdO3C.mjs.map → mode-CpNnGkPz.mjs.map} +1 -1
- package/dist/page/index.d.mts +11 -2
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs +23 -1
- package/dist/page/index.mjs.map +1 -1
- package/dist/{placeholder-DntBEQo7.mjs → placeholder-C-fk5hYI.mjs} +1 -1
- package/dist/{placeholder-DntBEQo7.mjs.map → placeholder-C-fk5hYI.mjs.map} +1 -1
- package/dist/{placeholder-BBCtpTES.d.mts → placeholder-tzpqGWII.d.mts} +1 -1
- package/dist/{placeholder-BBCtpTES.d.mts.map → placeholder-tzpqGWII.d.mts.map} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{query-B6Vu0d2i.mjs → query-Bk_3vKvU.mjs} +78 -11
- package/dist/query-Bk_3vKvU.mjs.map +1 -0
- package/dist/{registry-BgnP3ysR.mjs → registry-Ci3WxVAr.mjs} +133 -97
- package/dist/registry-Ci3WxVAr.mjs.map +1 -0
- package/dist/request-cache-DiR961CV.mjs +79 -0
- package/dist/request-cache-DiR961CV.mjs.map +1 -0
- package/dist/request-context.d.mts +19 -16
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{runner-DYv3rX8P.d.mts → runner-Fl2NcUUz.d.mts} +2 -2
- package/dist/{runner-DYv3rX8P.d.mts.map → runner-Fl2NcUUz.d.mts.map} +1 -1
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +1 -1
- package/dist/{search-B5p9D36n.mjs → search-DI4bM2w9.mjs} +110 -209
- package/dist/search-DI4bM2w9.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +8 -7
- 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-DbrKzDju.mjs +308 -0
- package/dist/taxonomies-DbrKzDju.mjs.map +1 -0
- package/dist/{tokens-DKHiCYCB.mjs → tokens-BFPFx3CA.mjs} +1 -1
- package/dist/{tokens-DKHiCYCB.mjs.map → tokens-BFPFx3CA.mjs.map} +1 -1
- package/dist/{transport-BtcQ-Z7T.mjs → transport-BykRfpyy.mjs} +1 -1
- package/dist/{transport-BtcQ-Z7T.mjs.map → transport-BykRfpyy.mjs.map} +1 -1
- package/dist/{transport-CKQA_G44.d.mts → transport-H4Iwx7tC.d.mts} +1 -1
- package/dist/{transport-CKQA_G44.d.mts.map → transport-H4Iwx7tC.d.mts.map} +1 -1
- package/dist/{types-BmkQR1En.d.mts → types-6CUZRrZP.d.mts} +1 -1
- package/dist/{types-BmkQR1En.d.mts.map → types-6CUZRrZP.d.mts.map} +1 -1
- package/dist/{types-B6BzlZxx.d.mts → types-8xrvl_68.d.mts} +1 -1
- package/dist/{types-B6BzlZxx.d.mts.map → types-8xrvl_68.d.mts.map} +1 -1
- package/dist/{types-Dz9_WMS6.mjs → types-BH2L167P.mjs} +1 -1
- package/dist/{types-Dz9_WMS6.mjs.map → types-BH2L167P.mjs.map} +1 -1
- package/dist/{types-DNZpaCBk.d.mts → types-CFWjXmus.d.mts} +1 -1
- package/dist/{types-DNZpaCBk.d.mts.map → types-CFWjXmus.d.mts.map} +1 -1
- package/dist/{types-gLYVCXCQ.d.mts → types-CnZYHyLW.d.mts} +55 -5
- package/dist/types-CnZYHyLW.d.mts.map +1 -0
- package/dist/{types-xxCWI3j0.mjs → types-DDS4MxsT.mjs} +11 -3
- package/dist/types-DDS4MxsT.mjs.map +1 -0
- package/dist/{types-BYWYxLcp.d.mts → types-DgrIP0tF.d.mts} +9 -2
- package/dist/types-DgrIP0tF.d.mts.map +1 -0
- package/dist/{validate-CcNRWH6I.d.mts → validate-CaLH1Ia2.d.mts} +5 -52
- package/dist/validate-CaLH1Ia2.d.mts.map +1 -0
- package/dist/{validate-DuZDIxfy.mjs → validate-CqsNItbt.mjs} +2 -2
- package/dist/{validate-DuZDIxfy.mjs.map → validate-CqsNItbt.mjs.map} +1 -1
- package/dist/version-Uaf2ynPX.mjs +7 -0
- package/dist/{version-DlTDRdpv.mjs.map → version-Uaf2ynPX.mjs.map} +1 -1
- package/package.json +10 -5
- package/src/after.ts +62 -0
- package/src/api/handlers/oauth-authorization.ts +2 -32
- package/src/api/handlers/oauth-clients.ts +40 -4
- package/src/api/handlers/taxonomies.ts +13 -0
- package/src/api/oauth/redirect-uri.ts +34 -0
- package/src/api/openapi/document.ts +126 -118
- package/src/api/schemas/auth.ts +7 -0
- package/src/api/schemas/media.ts +26 -15
- package/src/api/schemas/schema.ts +1 -0
- package/src/astro/integration/font-provider.ts +176 -0
- package/src/astro/integration/index.ts +42 -0
- package/src/astro/integration/routes.ts +17 -1
- package/src/astro/integration/runtime.ts +63 -0
- package/src/astro/integration/virtual-modules.ts +41 -39
- package/src/astro/integration/vite-config.ts +16 -5
- package/src/astro/middleware/auth.ts +39 -6
- package/src/astro/middleware/request-context.ts +15 -3
- package/src/astro/middleware.ts +340 -263
- package/src/astro/routes/admin.astro +10 -5
- package/src/astro/routes/api/auth/invite/register-options.ts +78 -0
- package/src/astro/routes/api/auth/passkey/verify.ts +5 -1
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +5 -0
- package/src/astro/routes/api/import/wordpress/execute.ts +1 -1
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +1 -1
- package/src/astro/routes/api/media/upload-url.ts +10 -2
- package/src/astro/routes/api/media.ts +10 -7
- package/src/astro/routes/api/oauth/register.ts +178 -0
- package/src/astro/routes/api/oauth/token.ts +15 -0
- package/src/astro/routes/api/openapi.json.ts +15 -5
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +2 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +1 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +1 -0
- package/src/astro/routes/api/search/index.ts +5 -0
- package/src/astro/routes/api/search/suggest.ts +3 -0
- package/src/astro/routes/api/taxonomies/index.ts +1 -0
- package/src/astro/routes/api/well-known/oauth-authorization-server.ts +6 -4
- package/src/bylines/index.ts +22 -45
- package/src/components/EmDashHead.astro +23 -7
- package/src/components/Table.astro +73 -41
- package/src/components/index.ts +2 -12
- package/src/components/marks.ts +20 -0
- package/src/database/connection.ts +23 -1
- package/src/database/instrumentation.ts +98 -0
- package/src/db/adapters.ts +15 -0
- package/src/emdash-runtime.ts +309 -91
- package/src/index.ts +6 -0
- package/src/loader.ts +19 -24
- package/src/menus/index.ts +6 -3
- package/src/page/index.ts +1 -1
- package/src/page/seo-contributions.ts +36 -0
- package/src/plugins/context.ts +1 -0
- package/src/plugins/email-console.ts +9 -2
- package/src/plugins/types.ts +8 -0
- package/src/query.ts +104 -7
- package/src/request-cache.ts +106 -0
- package/src/request-context.ts +19 -0
- package/src/schema/query.ts +5 -2
- package/src/schema/registry.ts +243 -166
- package/src/schema/types.ts +13 -2
- package/src/schema/zod-generator.ts +4 -0
- package/src/search/fts-manager.ts +19 -5
- package/src/search/query.ts +4 -3
- package/src/seed/apply.ts +15 -1
- package/src/settings/index.ts +24 -5
- package/src/taxonomies/index.ts +324 -124
- package/src/utils/db-errors.ts +46 -0
- package/src/virtual-modules.d.ts +31 -10
- package/src/widgets/index.ts +54 -25
- package/dist/adapters-C2BzVy0p.d.mts.map +0 -1
- package/dist/apply-Cma_PiF6.mjs.map +0 -1
- package/dist/byline-WuOq9MFJ.mjs.map +0 -1
- package/dist/bylines-C_Wsnz4L.mjs.map +0 -1
- package/dist/connection-B4zVnQIa.mjs.map +0 -1
- package/dist/index-CRg3PWfZ.d.mts.map +0 -1
- package/dist/loader-BYzwzORf.mjs.map +0 -1
- package/dist/query-B6Vu0d2i.mjs.map +0 -1
- package/dist/registry-BgnP3ysR.mjs.map +0 -1
- package/dist/search-B5p9D36n.mjs.map +0 -1
- package/dist/types-BYWYxLcp.d.mts.map +0 -1
- package/dist/types-gLYVCXCQ.d.mts.map +0 -1
- package/dist/types-xxCWI3j0.mjs.map +0 -1
- package/dist/validate-CcNRWH6I.d.mts.map +0 -1
- package/dist/version-DlTDRdpv.mjs +0 -7
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
import "../
|
|
1
|
+
import { getRequestContext, runWithContext } from "../request-context.mjs";
|
|
2
|
+
import { createRecorder, flushRecorder, isInstrumentationEnabled, kyselyLogOption } from "../database/instrumentation.mjs";
|
|
3
|
+
import "../connection-2igzM-AT.mjs";
|
|
2
4
|
import { t as validateIdentifier } from "../validate-VPnKoIzW.mjs";
|
|
3
5
|
import { a as isSqlite } from "../dialect-helpers-DhTzaUxP.mjs";
|
|
4
6
|
import { r as runMigrations } from "../runner-Cd-_WyDo.mjs";
|
|
5
|
-
import {
|
|
7
|
+
import { At as handleContentRestore, B as EmailPipeline, Ct as handleContentDuplicate, Dt as handleContentListTrashed, Et as handleContentList, Ft as handleContentUpdate, G as extractRequestMeta, H as createHookPipeline, It as validateRev, K as sanitizeHeadersForSandbox, L as PluginRouteRegistry, Mt as handleContentTranslations, Nt as handleContentUnpublish, Ot as handleContentPermanentDelete, Pt as handleContentUnschedule, R as DEV_CONSOLE_EMAIL_PLUGIN_ID, St as handleContentDiscardDraft, Tt as handleContentGetIncludingTrashed, U as resolveExclusiveHooks, W as CronExecutor, X as after, _t as handleContentCompare, bt as handleContentCreate, ct as handleMediaGet, dt as handleRevisionGet, ft as handleRevisionList, gt as hashString, it as PluginStateRepository, jt as handleContentSchedule, kt as handleContentPublish, lt as handleMediaList, ot as handleMediaCreate, pt as handleRevisionRestore, q as definePlugin, st as handleMediaDelete, tt as loadBundleFromR2, ut as handleMediaUpdate, vt as handleContentCountScheduled, wt as handleContentGet, xt as handleContentDelete, yt as handleContentCountTrashed, z as devConsoleEmailDeliver } from "../search-DI4bM2w9.mjs";
|
|
6
8
|
import { r as RevisionRepository } from "../content-BsBoyj8G.mjs";
|
|
7
9
|
import "../base64-MBPo9ozB.mjs";
|
|
8
10
|
import "../types-CMMN0pNg.mjs";
|
|
9
11
|
import { t as MediaRepository } from "../media-DqHVh136.mjs";
|
|
10
|
-
import { f as OptionsRepository } from "../apply-
|
|
12
|
+
import { f as OptionsRepository } from "../apply-B4MsLM-w.mjs";
|
|
11
13
|
import "../redirect-7lGhLBNZ.mjs";
|
|
12
|
-
import "../byline-
|
|
13
|
-
import { n as normalizeMediaValue } from "../placeholder-
|
|
14
|
-
import { i as setI18nConfig } from "../config-
|
|
15
|
-
import { i as FTSManager, n as SchemaRegistry } from "../registry-
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
import "../
|
|
21
|
-
import "../
|
|
22
|
-
import "../
|
|
14
|
+
import "../byline-C4OVd8b3.mjs";
|
|
15
|
+
import { n as normalizeMediaValue } from "../placeholder-C-fk5hYI.mjs";
|
|
16
|
+
import { i as setI18nConfig } from "../config-BXwuX8Bx.mjs";
|
|
17
|
+
import { i as FTSManager, n as SchemaRegistry } from "../registry-Ci3WxVAr.mjs";
|
|
18
|
+
import { n as getDb } from "../loader-DeiBJEMe.mjs";
|
|
19
|
+
import "../request-cache-DiR961CV.mjs";
|
|
20
|
+
import "../taxonomies-DbrKzDju.mjs";
|
|
21
|
+
import { r as normalizeManifestRoute } from "../manifest-schema-V30qsMft.mjs";
|
|
22
|
+
import { a as invalidateUrlPatternCache } from "../query-Bk_3vKvU.mjs";
|
|
23
|
+
import "../tokens-BFPFx3CA.mjs";
|
|
24
|
+
import "../bylines-hPTW79hw.mjs";
|
|
25
|
+
import "../load-CBcmDIot.mjs";
|
|
23
26
|
import "../index.mjs";
|
|
24
|
-
import { n as VERSION, t as COMMIT } from "../version-
|
|
25
|
-
import { t as getAuthMode } from "../mode-
|
|
27
|
+
import { n as VERSION, t as COMMIT } from "../version-Uaf2ynPX.mjs";
|
|
28
|
+
import { t as getAuthMode } from "../mode-CpNnGkPz.mjs";
|
|
26
29
|
import { Kysely, sql } from "kysely";
|
|
27
30
|
import { defineMiddleware } from "astro:middleware";
|
|
28
31
|
import virtualConfig from "virtual:emdash/config";
|
|
29
|
-
import { createDialect,
|
|
32
|
+
import { createDialect, createRequestScopedDb } from "virtual:emdash/dialect";
|
|
30
33
|
import { mediaProviders } from "virtual:emdash/media-providers";
|
|
31
34
|
import { plugins } from "virtual:emdash/plugins";
|
|
32
35
|
import { createSandboxRunner, sandboxEnabled } from "virtual:emdash/sandbox-runner";
|
|
@@ -316,6 +319,7 @@ function isValidMetadataContribution(c) {
|
|
|
316
319
|
const FIELD_TYPE_TO_KIND = {
|
|
317
320
|
string: "string",
|
|
318
321
|
slug: "string",
|
|
322
|
+
url: "url",
|
|
319
323
|
text: "richText",
|
|
320
324
|
number: "number",
|
|
321
325
|
integer: "number",
|
|
@@ -371,6 +375,16 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
371
375
|
cronScheduler;
|
|
372
376
|
enabledPlugins;
|
|
373
377
|
pluginStates;
|
|
378
|
+
_cachedManifest = null;
|
|
379
|
+
_manifestPromise = null;
|
|
380
|
+
_manifestCacheKey;
|
|
381
|
+
/**
|
|
382
|
+
* Set to true after FTS indexes have been verified for this worker
|
|
383
|
+
* lifetime so we don't re-scan on every admin request. See
|
|
384
|
+
* ensureSearchHealthy().
|
|
385
|
+
*/
|
|
386
|
+
_searchHealthChecked = false;
|
|
387
|
+
_searchHealthPromise = null;
|
|
374
388
|
/** Current hook pipeline. Use the `hooks` getter for external access. */
|
|
375
389
|
get hooks() {
|
|
376
390
|
return this._hooks;
|
|
@@ -396,7 +410,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
396
410
|
if (ctx?.db) return ctx.db;
|
|
397
411
|
return this._db;
|
|
398
412
|
}
|
|
399
|
-
constructor(db, storage, configuredPlugins, sandboxedPlugins, sandboxedPluginEntries, hooks, enabledPlugins, pluginStates, config, mediaProviders, mediaProviderEntries, cronExecutor, cronScheduler, emailPipeline, allPipelinePlugins, pipelineFactoryOptions, runtimeDeps, pipelineRef) {
|
|
413
|
+
constructor(db, storage, configuredPlugins, sandboxedPlugins, sandboxedPluginEntries, hooks, enabledPlugins, pluginStates, config, mediaProviders, mediaProviderEntries, cronExecutor, cronScheduler, emailPipeline, allPipelinePlugins, pipelineFactoryOptions, runtimeDeps, pipelineRef, manifestCacheKey) {
|
|
400
414
|
this._db = db;
|
|
401
415
|
this.storage = storage;
|
|
402
416
|
this.configuredPlugins = configuredPlugins;
|
|
@@ -416,6 +430,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
416
430
|
this.pipelineFactoryOptions = pipelineFactoryOptions;
|
|
417
431
|
this.runtimeDeps = runtimeDeps;
|
|
418
432
|
this.pipelineRef = pipelineRef;
|
|
433
|
+
this._manifestCacheKey = manifestCacheKey;
|
|
419
434
|
}
|
|
420
435
|
/**
|
|
421
436
|
* Get the sandbox runner instance (for marketplace install/update)
|
|
@@ -456,6 +471,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
456
471
|
this.enabledPlugins.delete(pluginId);
|
|
457
472
|
await this.rebuildHookPipeline();
|
|
458
473
|
}
|
|
474
|
+
this.invalidateManifest();
|
|
459
475
|
}
|
|
460
476
|
/**
|
|
461
477
|
* Rebuild the hook pipeline from the current set of enabled plugins.
|
|
@@ -564,35 +580,49 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
564
580
|
/**
|
|
565
581
|
* Create and initialize the runtime
|
|
566
582
|
*/
|
|
567
|
-
static async create(deps) {
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
583
|
+
static async create(deps, timings) {
|
|
584
|
+
const phase = async (name, desc, fn) => {
|
|
585
|
+
if (!timings) return fn();
|
|
586
|
+
const t0 = performance.now();
|
|
587
|
+
try {
|
|
588
|
+
return await fn();
|
|
589
|
+
} finally {
|
|
590
|
+
timings.push({
|
|
591
|
+
name,
|
|
592
|
+
dur: performance.now() - t0,
|
|
593
|
+
desc
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
const db = await phase("rt.db", "DB init + migrations", () => EmDashRuntime.getDatabase(deps));
|
|
573
598
|
const storage = EmDashRuntime.getStorage(deps);
|
|
574
599
|
let pluginStates = /* @__PURE__ */ new Map();
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
600
|
+
await phase("rt.plugins", "Plugin states", async () => {
|
|
601
|
+
try {
|
|
602
|
+
const states = await db.selectFrom("_plugin_state").select(["plugin_id", "status"]).execute();
|
|
603
|
+
pluginStates = new Map(states.map((s) => [s.plugin_id, s.status]));
|
|
604
|
+
} catch {}
|
|
605
|
+
});
|
|
579
606
|
const enabledPlugins = /* @__PURE__ */ new Set();
|
|
580
607
|
for (const plugin of deps.plugins) {
|
|
581
608
|
const status = pluginStates.get(plugin.id);
|
|
582
609
|
if (status === void 0 || status === "active") enabledPlugins.add(plugin.id);
|
|
583
610
|
}
|
|
584
611
|
let siteInfo;
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
612
|
+
await phase("rt.site", "Site info options", async () => {
|
|
613
|
+
try {
|
|
614
|
+
const siteOpts = await new OptionsRepository(db).getMany([
|
|
615
|
+
"emdash:site_title",
|
|
616
|
+
"emdash:site_url",
|
|
617
|
+
"emdash:locale"
|
|
618
|
+
]);
|
|
619
|
+
siteInfo = {
|
|
620
|
+
siteName: siteOpts.get("emdash:site_title") ?? void 0,
|
|
621
|
+
siteUrl: siteOpts.get("emdash:site_url") ?? void 0,
|
|
622
|
+
locale: siteOpts.get("emdash:locale") ?? void 0
|
|
623
|
+
};
|
|
624
|
+
} catch {}
|
|
625
|
+
});
|
|
596
626
|
const allPipelinePlugins = [...deps.plugins];
|
|
597
627
|
if (import.meta.env.DEV) try {
|
|
598
628
|
const devConsolePlugin = definePlugin({
|
|
@@ -631,8 +661,8 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
631
661
|
siteInfo
|
|
632
662
|
};
|
|
633
663
|
const pipeline = createHookPipeline(enabledPluginList, pipelineFactoryOptions);
|
|
634
|
-
const sandboxedPlugins = await EmDashRuntime.loadSandboxedPlugins(deps, db);
|
|
635
|
-
if (deps.config.marketplace && storage) await EmDashRuntime.loadMarketplacePlugins(db, storage, deps, sandboxedPlugins);
|
|
664
|
+
const sandboxedPlugins = await phase("rt.sandbox", "Sandboxed plugins", () => EmDashRuntime.loadSandboxedPlugins(deps, db));
|
|
665
|
+
if (deps.config.marketplace && storage) await phase("rt.market", "Marketplace plugins", () => EmDashRuntime.loadMarketplacePlugins(db, storage, deps, sandboxedPlugins));
|
|
636
666
|
const mediaProviders = /* @__PURE__ */ new Map();
|
|
637
667
|
const mediaProviderEntries = deps.mediaProviderEntries ?? [];
|
|
638
668
|
const providerContext = {
|
|
@@ -645,7 +675,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
645
675
|
} catch (error) {
|
|
646
676
|
console.warn(`Failed to initialize media provider "${entry.id}":`, error);
|
|
647
677
|
}
|
|
648
|
-
await EmDashRuntime.resolveExclusiveHooks(pipeline, db, deps);
|
|
678
|
+
await phase("rt.hooks", "Exclusive hook resolution", () => EmDashRuntime.resolveExclusiveHooks(pipeline, db, deps));
|
|
649
679
|
const emailPipeline = new EmailPipeline(pipeline);
|
|
650
680
|
if (sandboxRunner) sandboxRunner.setEmailSend((message, pluginId) => emailPipeline.send(message, pluginId));
|
|
651
681
|
const pipelineRef = { current: pipeline };
|
|
@@ -659,25 +689,41 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
659
689
|
});
|
|
660
690
|
let cronExecutor = null;
|
|
661
691
|
let cronScheduler = null;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
692
|
+
await phase("rt.cron", "Cron init (recovery deferred post-response)", async () => {
|
|
693
|
+
try {
|
|
694
|
+
cronExecutor = new CronExecutor(db, invokeCronHook);
|
|
695
|
+
const executorForRecovery = cronExecutor;
|
|
696
|
+
after(async () => {
|
|
697
|
+
try {
|
|
698
|
+
const recovered = await executorForRecovery.recoverStaleLocks();
|
|
699
|
+
if (recovered > 0) console.log(`[cron] Recovered ${recovered} stale task lock(s)`);
|
|
700
|
+
} catch (error) {
|
|
701
|
+
console.error("[cron] Failed to recover stale task locks:", error);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
if (typeof globalThis.navigator !== "undefined" && globalThis.navigator.userAgent === "Cloudflare-Workers") cronScheduler = new PiggybackScheduler(cronExecutor);
|
|
705
|
+
else cronScheduler = new NodeCronScheduler(cronExecutor);
|
|
706
|
+
cronScheduler.setSystemCleanup(async () => {
|
|
707
|
+
try {
|
|
708
|
+
await runSystemCleanup(db, storage ?? void 0);
|
|
709
|
+
} catch (error) {
|
|
710
|
+
console.error("[cleanup] System cleanup failed:", error);
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
pipeline.setContextFactory({ cronReschedule: () => cronScheduler?.reschedule() });
|
|
714
|
+
await cronScheduler.start();
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.warn("[cron] Failed to initialize cron system:", error);
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
const manifestCacheKey = await hashString([
|
|
720
|
+
COMMIT,
|
|
721
|
+
...deps.plugins.map((p) => `${p.id}@${p.version ?? ""}`).toSorted(),
|
|
722
|
+
...deps.sandboxedPluginEntries.map((e) => `${e.id}@${e.version}`).toSorted(),
|
|
723
|
+
virtualConfig?.i18n?.defaultLocale ?? "",
|
|
724
|
+
(virtualConfig?.i18n?.locales ?? []).toSorted().join(",")
|
|
725
|
+
].join("|"));
|
|
726
|
+
return new EmDashRuntime(db, storage, deps.plugins, sandboxedPlugins, deps.sandboxedPluginEntries, pipeline, enabledPlugins, pluginStates, deps.config, mediaProviders, mediaProviderEntries, cronExecutor, cronScheduler, emailPipeline, allPipelinePlugins, pipelineFactoryOptions, deps, pipelineRef, manifestCacheKey);
|
|
681
727
|
}
|
|
682
728
|
/**
|
|
683
729
|
* Get a media provider by ID
|
|
@@ -701,7 +747,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
701
747
|
*/
|
|
702
748
|
static async getDatabase(deps) {
|
|
703
749
|
const ctx = getRequestContext();
|
|
704
|
-
if (ctx?.db) return ctx.db;
|
|
750
|
+
if (ctx?.dbIsIsolated && ctx.db) return ctx.db;
|
|
705
751
|
const dbConfig = deps.config.database;
|
|
706
752
|
if (!dbConfig) try {
|
|
707
753
|
return await getDb();
|
|
@@ -713,8 +759,14 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
713
759
|
if (cached) return cached;
|
|
714
760
|
if (dbInitPromise) return dbInitPromise;
|
|
715
761
|
dbInitPromise = (async () => {
|
|
716
|
-
const db = new Kysely({
|
|
717
|
-
|
|
762
|
+
const db = new Kysely({
|
|
763
|
+
dialect: deps.createDialect(dbConfig.config),
|
|
764
|
+
log: kyselyLogOption()
|
|
765
|
+
});
|
|
766
|
+
const { applied } = await runMigrations(db);
|
|
767
|
+
if (applied.length > 0) try {
|
|
768
|
+
await new OptionsRepository(db).delete("emdash:manifest_cache");
|
|
769
|
+
} catch {}
|
|
718
770
|
try {
|
|
719
771
|
const [collectionCount, setupOption] = await Promise.all([db.selectFrom("_emdash_collections").select((eb) => eb.fn.countAll().as("count")).executeTakeFirstOrThrow(), db.selectFrom("options").select("value").where("name", "=", "emdash:setup_complete").executeTakeFirst()]);
|
|
720
772
|
const setupDone = (() => {
|
|
@@ -725,9 +777,9 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
725
777
|
}
|
|
726
778
|
})();
|
|
727
779
|
if (collectionCount.count === 0 && !setupDone) {
|
|
728
|
-
const { applySeed } = await import("../apply-
|
|
729
|
-
const { loadSeed } = await import("../load-
|
|
730
|
-
const { validateSeed } = await import("../validate-
|
|
780
|
+
const { applySeed } = await import("../apply-B4MsLM-w.mjs").then((n) => n.n);
|
|
781
|
+
const { loadSeed } = await import("../load-CBcmDIot.mjs").then((n) => n.r);
|
|
782
|
+
const { validateSeed } = await import("../validate-CqsNItbt.mjs").then((n) => n.n);
|
|
731
783
|
const seed = await loadSeed();
|
|
732
784
|
if (validateSeed(seed).valid) {
|
|
733
785
|
await applySeed(db, seed, { onConflict: "skip" });
|
|
@@ -866,9 +918,52 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
866
918
|
});
|
|
867
919
|
}
|
|
868
920
|
/**
|
|
869
|
-
*
|
|
921
|
+
* Get the manifest, using an in-memory cache with a DB-persisted
|
|
922
|
+
* fallback for cold starts. Avoids N+1 schema registry queries
|
|
923
|
+
* on every request.
|
|
924
|
+
*
|
|
925
|
+
* Cache is invalidated by invalidateManifest(), called from schema
|
|
926
|
+
* API routes, MCP server, plugin toggle, and taxonomy def changes.
|
|
870
927
|
*/
|
|
871
928
|
async getManifest() {
|
|
929
|
+
if (getRequestContext()?.dbIsIsolated) return this._buildManifest();
|
|
930
|
+
if (this._cachedManifest) return this._cachedManifest;
|
|
931
|
+
try {
|
|
932
|
+
const cached = await new OptionsRepository(this.db).get("emdash:manifest_cache");
|
|
933
|
+
if (cached && cached.key === this._manifestCacheKey && cached.manifest) {
|
|
934
|
+
this._cachedManifest = cached.manifest;
|
|
935
|
+
return cached.manifest;
|
|
936
|
+
}
|
|
937
|
+
} catch {}
|
|
938
|
+
if (!this._manifestPromise) {
|
|
939
|
+
let manifestPromise;
|
|
940
|
+
const isCurrentLoad = () => this._manifestPromise === manifestPromise;
|
|
941
|
+
manifestPromise = this._loadManifest(isCurrentLoad);
|
|
942
|
+
this._manifestPromise = manifestPromise;
|
|
943
|
+
}
|
|
944
|
+
return this._manifestPromise;
|
|
945
|
+
}
|
|
946
|
+
async _loadManifest(isCurrentLoad) {
|
|
947
|
+
try {
|
|
948
|
+
const manifest = await this._buildManifest();
|
|
949
|
+
if (isCurrentLoad()) {
|
|
950
|
+
this._cachedManifest = manifest;
|
|
951
|
+
try {
|
|
952
|
+
await new OptionsRepository(this.db).set("emdash:manifest_cache", {
|
|
953
|
+
key: this._manifestCacheKey,
|
|
954
|
+
manifest
|
|
955
|
+
});
|
|
956
|
+
} catch {}
|
|
957
|
+
}
|
|
958
|
+
return manifest;
|
|
959
|
+
} finally {
|
|
960
|
+
if (isCurrentLoad()) this._manifestPromise = null;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Build the manifest from database (N+1 collection queries).
|
|
965
|
+
*/
|
|
966
|
+
async _buildManifest() {
|
|
872
967
|
const manifestCollections = {};
|
|
873
968
|
try {
|
|
874
969
|
const registry = new SchemaRegistry(this.db);
|
|
@@ -987,10 +1082,62 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
987
1082
|
}
|
|
988
1083
|
/**
|
|
989
1084
|
* Invalidate cached data derived from the manifest/schema.
|
|
990
|
-
* Called when collections
|
|
1085
|
+
* Called when collections, fields, plugins, or taxonomy defs change.
|
|
991
1086
|
*/
|
|
992
1087
|
invalidateManifest() {
|
|
1088
|
+
this._cachedManifest = null;
|
|
1089
|
+
this._manifestPromise = null;
|
|
993
1090
|
invalidateUrlPatternCache();
|
|
1091
|
+
try {
|
|
1092
|
+
new OptionsRepository(this.db).delete("emdash:manifest_cache").catch((error) => {
|
|
1093
|
+
console.error("Failed to delete persisted manifest cache", error);
|
|
1094
|
+
});
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
console.error("Failed to initialize manifest cache invalidation", error);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Verify and repair FTS indexes on demand. Runs at most once per worker
|
|
1101
|
+
* lifetime.
|
|
1102
|
+
*
|
|
1103
|
+
* Originally called from `EmDashRuntime.create()`, but on a busy D1 link
|
|
1104
|
+
* (e.g. SIN replica ~80-150ms per query) it added ~1.5s to every cold
|
|
1105
|
+
* start for a modest-sized site — more than every other init phase
|
|
1106
|
+
* combined. Anonymous public reads never touch the search write path,
|
|
1107
|
+
* so the cost isn't paid back for the vast majority of requests.
|
|
1108
|
+
*
|
|
1109
|
+
* Instead, search endpoints call this lazily: the first request that
|
|
1110
|
+
* actually needs the index pays the verify cost (usually fast — no
|
|
1111
|
+
* rebuild needed), everyone else runs cold-free.
|
|
1112
|
+
*
|
|
1113
|
+
* Uses the runtime's singleton database (`this._db`) rather than the
|
|
1114
|
+
* request-scoped DB. Verify reads only, but `rebuildIndex` writes, and
|
|
1115
|
+
* a GET search request on D1 carries a `first-unconstrained` session
|
|
1116
|
+
* that's free to route at a read replica — unsafe for writes. The
|
|
1117
|
+
* singleton always goes through the default binding, which the D1
|
|
1118
|
+
* adapter will promote to `first-primary` for write statements.
|
|
1119
|
+
*
|
|
1120
|
+
* Safe to call concurrently: repeated callers share the same in-flight
|
|
1121
|
+
* promise. Errors are swallowed internally so callers don't need to
|
|
1122
|
+
* defend against FTS not existing yet (pre-setup).
|
|
1123
|
+
*/
|
|
1124
|
+
async ensureSearchHealthy() {
|
|
1125
|
+
if (this._searchHealthChecked) return;
|
|
1126
|
+
if (this._searchHealthPromise) return this._searchHealthPromise;
|
|
1127
|
+
if (!isSqlite(this._db)) {
|
|
1128
|
+
this._searchHealthChecked = true;
|
|
1129
|
+
return;
|
|
1130
|
+
}
|
|
1131
|
+
this._searchHealthPromise = (async () => {
|
|
1132
|
+
try {
|
|
1133
|
+
const repaired = await new FTSManager(this._db).verifyAndRepairAll();
|
|
1134
|
+
if (repaired > 0) console.log(`Repaired ${repaired} corrupted FTS index(es)`);
|
|
1135
|
+
} catch {} finally {
|
|
1136
|
+
this._searchHealthChecked = true;
|
|
1137
|
+
this._searchHealthPromise = null;
|
|
1138
|
+
}
|
|
1139
|
+
})();
|
|
1140
|
+
return this._searchHealthPromise;
|
|
994
1141
|
}
|
|
995
1142
|
async handleContentList(collection, params) {
|
|
996
1143
|
return handleContentList(this.db, collection, params);
|
|
@@ -1539,18 +1686,23 @@ function buildDependencies(config) {
|
|
|
1539
1686
|
};
|
|
1540
1687
|
}
|
|
1541
1688
|
/**
|
|
1542
|
-
* Get or create the runtime instance
|
|
1689
|
+
* Get or create the runtime instance.
|
|
1690
|
+
*
|
|
1691
|
+
* When `initTimings` is provided, any timing samples recorded during a
|
|
1692
|
+
* genuine cold init are appended. Subsequent warm calls (hitting the
|
|
1693
|
+
* cached instance) push nothing — callers should treat an empty array
|
|
1694
|
+
* as "warm, nothing to report".
|
|
1543
1695
|
*/
|
|
1544
|
-
async function getRuntime(config) {
|
|
1696
|
+
async function getRuntime(config, initTimings) {
|
|
1545
1697
|
if (runtimeInstance) return runtimeInstance;
|
|
1546
1698
|
if (runtimeInitializing) {
|
|
1547
1699
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1548
|
-
return getRuntime(config);
|
|
1700
|
+
return getRuntime(config, initTimings);
|
|
1549
1701
|
}
|
|
1550
1702
|
runtimeInitializing = true;
|
|
1551
1703
|
try {
|
|
1552
1704
|
const deps = buildDependencies(config);
|
|
1553
|
-
const runtime = await EmDashRuntime.create(deps);
|
|
1705
|
+
const runtime = await EmDashRuntime.create(deps, initTimings);
|
|
1554
1706
|
runtimeInstance = runtime;
|
|
1555
1707
|
return runtime;
|
|
1556
1708
|
} finally {
|
|
@@ -1558,142 +1710,270 @@ async function getRuntime(config) {
|
|
|
1558
1710
|
}
|
|
1559
1711
|
}
|
|
1560
1712
|
/**
|
|
1713
|
+
* Astro attaches AstroCookies to outgoing responses via a well-known global
|
|
1714
|
+
* symbol. Cloning a Response (`new Response(body, init)`) drops non-header
|
|
1715
|
+
* metadata, so any middleware that wraps the response must explicitly forward
|
|
1716
|
+
* this symbol or `cookies.set()` calls will be silently dropped.
|
|
1717
|
+
*/
|
|
1718
|
+
const ASTRO_COOKIES_SYMBOL = Symbol.for("astro.cookies");
|
|
1719
|
+
/**
|
|
1561
1720
|
* Baseline security headers applied to all responses.
|
|
1562
1721
|
* Admin routes get additional headers (strict CSP) from auth middleware.
|
|
1563
1722
|
*/
|
|
1564
|
-
function
|
|
1723
|
+
function finalizeResponse(response, serverTimings) {
|
|
1565
1724
|
const res = new Response(response.body, response);
|
|
1725
|
+
const astroCookies = Reflect.get(response, ASTRO_COOKIES_SYMBOL);
|
|
1726
|
+
if (astroCookies !== void 0) Reflect.set(res, ASTRO_COOKIES_SYMBOL, astroCookies);
|
|
1566
1727
|
res.headers.set("X-Content-Type-Options", "nosniff");
|
|
1567
1728
|
res.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
1568
1729
|
res.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=()");
|
|
1569
1730
|
if (!res.headers.has("Content-Security-Policy")) res.headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
1731
|
+
if (serverTimings && serverTimings.length > 0) res.headers.set("Server-Timing", serverTimings.map((t) => {
|
|
1732
|
+
const dur = Math.round(t.dur);
|
|
1733
|
+
return t.desc ? `${t.name};dur=${dur};desc="${t.desc}"` : `${t.name};dur=${dur}`;
|
|
1734
|
+
}).join(", "));
|
|
1570
1735
|
return res;
|
|
1571
1736
|
}
|
|
1572
1737
|
/** Public routes that require the runtime (sitemap, robots.txt, etc.) */
|
|
1573
1738
|
const PUBLIC_RUNTIME_ROUTES = new Set(["/sitemap.xml", "/robots.txt"]);
|
|
1574
1739
|
const SITEMAP_COLLECTION_RE = /^\/sitemap-[a-z][a-z0-9_]*\.xml$/;
|
|
1740
|
+
/**
|
|
1741
|
+
* Ask the configured database adapter for a per-request scoped Kysely. The
|
|
1742
|
+
* adapter encapsulates any per-request semantics (D1 sessions, read-replica
|
|
1743
|
+
* routing, bookmark cookies, etc.); core just forwards the cookie jar and
|
|
1744
|
+
* request flags and wraps next() in ALS if a scope was returned.
|
|
1745
|
+
*/
|
|
1746
|
+
function createRequestScopedDb$1(opts) {
|
|
1747
|
+
if (typeof createRequestScopedDb !== "function") return null;
|
|
1748
|
+
return createRequestScopedDb(opts);
|
|
1749
|
+
}
|
|
1575
1750
|
const onRequest = defineMiddleware(async (context, next) => {
|
|
1576
1751
|
const { request, locals, cookies } = context;
|
|
1577
1752
|
const url = context.url;
|
|
1578
|
-
const
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1753
|
+
const queryRecorder = isInstrumentationEnabled() ? createRecorder(url.pathname, request.method, request.headers.get("x-perf-phase") ?? "default") : void 0;
|
|
1754
|
+
const run = async () => {
|
|
1755
|
+
const isEmDashRoute = url.pathname.startsWith("/_emdash");
|
|
1756
|
+
const isPublicRuntimeRoute = PUBLIC_RUNTIME_ROUTES.has(url.pathname) || SITEMAP_COLLECTION_RE.test(url.pathname);
|
|
1757
|
+
const hasEditCookie = cookies.get("emdash-edit-mode")?.value === "true";
|
|
1758
|
+
const hasPreviewToken = url.searchParams.has("_preview");
|
|
1759
|
+
const playgroundDb = locals.__playgroundDb;
|
|
1760
|
+
const sessionUser = context.isPrerendered ? null : await context.session?.get("user");
|
|
1761
|
+
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
|
1762
|
+
if (!sessionUser && !playgroundDb) {
|
|
1763
|
+
const timings = [];
|
|
1764
|
+
const mwStart = performance.now();
|
|
1765
|
+
if (!setupVerified) {
|
|
1766
|
+
const t0 = performance.now();
|
|
1767
|
+
try {
|
|
1768
|
+
const { getDb } = await import("../loader-DeiBJEMe.mjs").then((n) => n.r);
|
|
1769
|
+
await (await getDb()).selectFrom("_emdash_migrations").selectAll().limit(1).execute();
|
|
1770
|
+
setupVerified = true;
|
|
1771
|
+
} catch {
|
|
1772
|
+
return context.redirect("/_emdash/admin/setup");
|
|
1773
|
+
}
|
|
1774
|
+
timings.push({
|
|
1775
|
+
name: "setup",
|
|
1776
|
+
dur: performance.now() - t0,
|
|
1777
|
+
desc: "Setup probe"
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
const config = getConfig();
|
|
1781
|
+
if (config) {
|
|
1782
|
+
const initSubTimings = [];
|
|
1783
|
+
const t0 = performance.now();
|
|
1784
|
+
try {
|
|
1785
|
+
const runtime = await getRuntime(config, initSubTimings);
|
|
1786
|
+
setupVerified = true;
|
|
1787
|
+
locals.emdash = {
|
|
1788
|
+
collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
|
|
1789
|
+
collectPageFragments: runtime.collectPageFragments.bind(runtime)
|
|
1790
|
+
};
|
|
1791
|
+
} catch {}
|
|
1792
|
+
timings.push({
|
|
1793
|
+
name: "rt",
|
|
1794
|
+
dur: performance.now() - t0,
|
|
1795
|
+
desc: "Runtime init"
|
|
1796
|
+
});
|
|
1797
|
+
for (const sub of initSubTimings) timings.push(sub);
|
|
1798
|
+
}
|
|
1799
|
+
const anonScoped = createRequestScopedDb$1({
|
|
1800
|
+
config: config?.database?.config,
|
|
1801
|
+
isAuthenticated: false,
|
|
1802
|
+
isWrite: request.method !== "GET" && request.method !== "HEAD",
|
|
1803
|
+
cookies,
|
|
1804
|
+
url
|
|
1805
|
+
});
|
|
1806
|
+
const runAnon = async () => {
|
|
1807
|
+
const t0 = performance.now();
|
|
1808
|
+
const response = await next();
|
|
1809
|
+
timings.push({
|
|
1810
|
+
name: "render",
|
|
1811
|
+
dur: performance.now() - t0,
|
|
1812
|
+
desc: "Page render"
|
|
1813
|
+
});
|
|
1814
|
+
timings.push({
|
|
1815
|
+
name: "mw",
|
|
1816
|
+
dur: performance.now() - mwStart,
|
|
1817
|
+
desc: "Total middleware"
|
|
1818
|
+
});
|
|
1819
|
+
return finalizeResponse(response, timings);
|
|
1820
|
+
};
|
|
1821
|
+
if (anonScoped) {
|
|
1822
|
+
const parent = getRequestContext();
|
|
1823
|
+
return runWithContext(parent ? {
|
|
1824
|
+
...parent,
|
|
1825
|
+
db: anonScoped.db
|
|
1826
|
+
} : {
|
|
1827
|
+
editMode: false,
|
|
1828
|
+
db: anonScoped.db
|
|
1829
|
+
}, async () => {
|
|
1830
|
+
const response = await runAnon();
|
|
1831
|
+
anonScoped.commit();
|
|
1832
|
+
return response;
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
return runAnon();
|
|
1591
1836
|
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1837
|
+
}
|
|
1838
|
+
const config = getConfig();
|
|
1839
|
+
if (!config) {
|
|
1840
|
+
console.error("EmDash: No configuration found");
|
|
1841
|
+
return finalizeResponse(await next());
|
|
1842
|
+
}
|
|
1843
|
+
const doInit = async () => {
|
|
1844
|
+
const timings = [];
|
|
1845
|
+
const mwStart = performance.now();
|
|
1846
|
+
try {
|
|
1847
|
+
const initSubTimings = [];
|
|
1848
|
+
let t0 = performance.now();
|
|
1849
|
+
const runtime = await getRuntime(config, initSubTimings);
|
|
1850
|
+
timings.push({
|
|
1851
|
+
name: "rt",
|
|
1852
|
+
dur: performance.now() - t0,
|
|
1853
|
+
desc: "Runtime init"
|
|
1854
|
+
});
|
|
1855
|
+
for (const sub of initSubTimings) timings.push(sub);
|
|
1595
1856
|
setupVerified = true;
|
|
1857
|
+
t0 = performance.now();
|
|
1858
|
+
const manifest = await runtime.getManifest();
|
|
1859
|
+
timings.push({
|
|
1860
|
+
name: "manifest",
|
|
1861
|
+
dur: performance.now() - t0,
|
|
1862
|
+
desc: "Manifest"
|
|
1863
|
+
});
|
|
1864
|
+
locals.emdashManifest = manifest;
|
|
1596
1865
|
locals.emdash = {
|
|
1866
|
+
handleContentList: runtime.handleContentList.bind(runtime),
|
|
1867
|
+
handleContentGet: runtime.handleContentGet.bind(runtime),
|
|
1868
|
+
handleContentCreate: runtime.handleContentCreate.bind(runtime),
|
|
1869
|
+
handleContentUpdate: runtime.handleContentUpdate.bind(runtime),
|
|
1870
|
+
handleContentDelete: runtime.handleContentDelete.bind(runtime),
|
|
1871
|
+
handleContentListTrashed: runtime.handleContentListTrashed.bind(runtime),
|
|
1872
|
+
handleContentRestore: runtime.handleContentRestore.bind(runtime),
|
|
1873
|
+
handleContentPermanentDelete: runtime.handleContentPermanentDelete.bind(runtime),
|
|
1874
|
+
handleContentCountTrashed: runtime.handleContentCountTrashed.bind(runtime),
|
|
1875
|
+
handleContentGetIncludingTrashed: runtime.handleContentGetIncludingTrashed.bind(runtime),
|
|
1876
|
+
handleContentDuplicate: runtime.handleContentDuplicate.bind(runtime),
|
|
1877
|
+
handleContentPublish: runtime.handleContentPublish.bind(runtime),
|
|
1878
|
+
handleContentUnpublish: runtime.handleContentUnpublish.bind(runtime),
|
|
1879
|
+
handleContentSchedule: runtime.handleContentSchedule.bind(runtime),
|
|
1880
|
+
handleContentUnschedule: runtime.handleContentUnschedule.bind(runtime),
|
|
1881
|
+
handleContentCountScheduled: runtime.handleContentCountScheduled.bind(runtime),
|
|
1882
|
+
handleContentDiscardDraft: runtime.handleContentDiscardDraft.bind(runtime),
|
|
1883
|
+
handleContentCompare: runtime.handleContentCompare.bind(runtime),
|
|
1884
|
+
handleContentTranslations: runtime.handleContentTranslations.bind(runtime),
|
|
1885
|
+
handleMediaList: runtime.handleMediaList.bind(runtime),
|
|
1886
|
+
handleMediaGet: runtime.handleMediaGet.bind(runtime),
|
|
1887
|
+
handleMediaCreate: runtime.handleMediaCreate.bind(runtime),
|
|
1888
|
+
handleMediaUpdate: runtime.handleMediaUpdate.bind(runtime),
|
|
1889
|
+
handleMediaDelete: runtime.handleMediaDelete.bind(runtime),
|
|
1890
|
+
handleRevisionList: runtime.handleRevisionList.bind(runtime),
|
|
1891
|
+
handleRevisionGet: runtime.handleRevisionGet.bind(runtime),
|
|
1892
|
+
handleRevisionRestore: runtime.handleRevisionRestore.bind(runtime),
|
|
1893
|
+
handlePluginApiRoute: runtime.handlePluginApiRoute.bind(runtime),
|
|
1894
|
+
getPluginRouteMeta: runtime.getPluginRouteMeta.bind(runtime),
|
|
1895
|
+
getMediaProvider: runtime.getMediaProvider.bind(runtime),
|
|
1896
|
+
getMediaProviderList: runtime.getMediaProviderList.bind(runtime),
|
|
1597
1897
|
collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
|
|
1598
|
-
collectPageFragments: runtime.collectPageFragments.bind(runtime)
|
|
1898
|
+
collectPageFragments: runtime.collectPageFragments.bind(runtime),
|
|
1899
|
+
ensureSearchHealthy: runtime.ensureSearchHealthy.bind(runtime),
|
|
1900
|
+
storage: runtime.storage,
|
|
1901
|
+
db: runtime.db,
|
|
1902
|
+
hooks: runtime.hooks,
|
|
1903
|
+
email: runtime.email,
|
|
1904
|
+
configuredPlugins: runtime.configuredPlugins,
|
|
1905
|
+
config,
|
|
1906
|
+
invalidateManifest: runtime.invalidateManifest.bind(runtime),
|
|
1907
|
+
getSandboxRunner: runtime.getSandboxRunner.bind(runtime),
|
|
1908
|
+
syncMarketplacePlugins: runtime.syncMarketplacePlugins.bind(runtime),
|
|
1909
|
+
setPluginStatus: runtime.setPluginStatus.bind(runtime)
|
|
1599
1910
|
};
|
|
1600
|
-
} catch {
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
handleContentGetIncludingTrashed: runtime.handleContentGetIncludingTrashed.bind(runtime),
|
|
1625
|
-
handleContentDuplicate: runtime.handleContentDuplicate.bind(runtime),
|
|
1626
|
-
handleContentPublish: runtime.handleContentPublish.bind(runtime),
|
|
1627
|
-
handleContentUnpublish: runtime.handleContentUnpublish.bind(runtime),
|
|
1628
|
-
handleContentSchedule: runtime.handleContentSchedule.bind(runtime),
|
|
1629
|
-
handleContentUnschedule: runtime.handleContentUnschedule.bind(runtime),
|
|
1630
|
-
handleContentCountScheduled: runtime.handleContentCountScheduled.bind(runtime),
|
|
1631
|
-
handleContentDiscardDraft: runtime.handleContentDiscardDraft.bind(runtime),
|
|
1632
|
-
handleContentCompare: runtime.handleContentCompare.bind(runtime),
|
|
1633
|
-
handleContentTranslations: runtime.handleContentTranslations.bind(runtime),
|
|
1634
|
-
handleMediaList: runtime.handleMediaList.bind(runtime),
|
|
1635
|
-
handleMediaGet: runtime.handleMediaGet.bind(runtime),
|
|
1636
|
-
handleMediaCreate: runtime.handleMediaCreate.bind(runtime),
|
|
1637
|
-
handleMediaUpdate: runtime.handleMediaUpdate.bind(runtime),
|
|
1638
|
-
handleMediaDelete: runtime.handleMediaDelete.bind(runtime),
|
|
1639
|
-
handleRevisionList: runtime.handleRevisionList.bind(runtime),
|
|
1640
|
-
handleRevisionGet: runtime.handleRevisionGet.bind(runtime),
|
|
1641
|
-
handleRevisionRestore: runtime.handleRevisionRestore.bind(runtime),
|
|
1642
|
-
handlePluginApiRoute: runtime.handlePluginApiRoute.bind(runtime),
|
|
1643
|
-
getPluginRouteMeta: runtime.getPluginRouteMeta.bind(runtime),
|
|
1644
|
-
getMediaProvider: runtime.getMediaProvider.bind(runtime),
|
|
1645
|
-
getMediaProviderList: runtime.getMediaProviderList.bind(runtime),
|
|
1646
|
-
collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
|
|
1647
|
-
collectPageFragments: runtime.collectPageFragments.bind(runtime),
|
|
1648
|
-
storage: runtime.storage,
|
|
1649
|
-
db: runtime.db,
|
|
1650
|
-
hooks: runtime.hooks,
|
|
1651
|
-
email: runtime.email,
|
|
1652
|
-
configuredPlugins: runtime.configuredPlugins,
|
|
1653
|
-
config,
|
|
1654
|
-
invalidateManifest: runtime.invalidateManifest.bind(runtime),
|
|
1655
|
-
getSandboxRunner: runtime.getSandboxRunner.bind(runtime),
|
|
1656
|
-
syncMarketplacePlugins: runtime.syncMarketplacePlugins.bind(runtime),
|
|
1657
|
-
setPluginStatus: runtime.setPluginStatus.bind(runtime)
|
|
1911
|
+
} catch (error) {
|
|
1912
|
+
console.error("EmDash middleware error:", error);
|
|
1913
|
+
}
|
|
1914
|
+
const scoped = createRequestScopedDb$1({
|
|
1915
|
+
config: config?.database?.config,
|
|
1916
|
+
isAuthenticated: !!sessionUser,
|
|
1917
|
+
isWrite: request.method !== "GET" && request.method !== "HEAD",
|
|
1918
|
+
cookies: context.cookies,
|
|
1919
|
+
url
|
|
1920
|
+
});
|
|
1921
|
+
const renderAndFinalize = async () => {
|
|
1922
|
+
const t0 = performance.now();
|
|
1923
|
+
const response = await next();
|
|
1924
|
+
timings.push({
|
|
1925
|
+
name: "render",
|
|
1926
|
+
dur: performance.now() - t0,
|
|
1927
|
+
desc: "Page render"
|
|
1928
|
+
});
|
|
1929
|
+
timings.push({
|
|
1930
|
+
name: "mw",
|
|
1931
|
+
dur: performance.now() - mwStart,
|
|
1932
|
+
desc: "Total middleware"
|
|
1933
|
+
});
|
|
1934
|
+
return finalizeResponse(response, timings);
|
|
1658
1935
|
};
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
if (d1Binding && typeof d1Binding === "object" && "withSession" in d1Binding) {
|
|
1666
|
-
const isAuthenticated = context.isPrerendered ? false : !!await context.session?.get("user");
|
|
1667
|
-
const isWrite = request.method !== "GET" && request.method !== "HEAD";
|
|
1668
|
-
const configConstraint = getDefaultConstraint(dbConfig);
|
|
1669
|
-
const cookieName = getBookmarkCookieName(dbConfig);
|
|
1670
|
-
let constraint = configConstraint;
|
|
1671
|
-
if (isAuthenticated && isWrite) constraint = "first-primary";
|
|
1672
|
-
else if (isAuthenticated) {
|
|
1673
|
-
const bookmarkCookie = context.cookies.get(cookieName);
|
|
1674
|
-
if (bookmarkCookie?.value) constraint = bookmarkCookie.value;
|
|
1675
|
-
}
|
|
1676
|
-
const session = d1Binding.withSession.call(d1Binding, constraint);
|
|
1677
|
-
return runWithContext({
|
|
1936
|
+
if (scoped) {
|
|
1937
|
+
const parent = getRequestContext();
|
|
1938
|
+
return runWithContext(parent ? {
|
|
1939
|
+
...parent,
|
|
1940
|
+
db: scoped.db
|
|
1941
|
+
} : {
|
|
1678
1942
|
editMode: false,
|
|
1679
|
-
db:
|
|
1943
|
+
db: scoped.db
|
|
1680
1944
|
}, async () => {
|
|
1681
|
-
const response =
|
|
1682
|
-
|
|
1683
|
-
const newBookmark = session.getBookmark.call(session);
|
|
1684
|
-
if (newBookmark) response.headers.append("Set-Cookie", `${cookieName}=${newBookmark}; Path=/; HttpOnly; SameSite=Lax; Secure`);
|
|
1685
|
-
}
|
|
1945
|
+
const response = await renderAndFinalize();
|
|
1946
|
+
scoped.commit();
|
|
1686
1947
|
return response;
|
|
1687
1948
|
});
|
|
1688
1949
|
}
|
|
1950
|
+
return renderAndFinalize();
|
|
1951
|
+
};
|
|
1952
|
+
if (playgroundDb) {
|
|
1953
|
+
const editMode = context.cookies.get("emdash-edit-mode")?.value === "true";
|
|
1954
|
+
const parent = getRequestContext();
|
|
1955
|
+
return runWithContext(parent ? {
|
|
1956
|
+
...parent,
|
|
1957
|
+
editMode,
|
|
1958
|
+
db: playgroundDb,
|
|
1959
|
+
dbIsIsolated: true
|
|
1960
|
+
} : {
|
|
1961
|
+
editMode,
|
|
1962
|
+
db: playgroundDb,
|
|
1963
|
+
dbIsIsolated: true
|
|
1964
|
+
}, doInit);
|
|
1689
1965
|
}
|
|
1690
|
-
return
|
|
1966
|
+
return doInit();
|
|
1691
1967
|
};
|
|
1692
|
-
if (
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1968
|
+
if (queryRecorder) try {
|
|
1969
|
+
return await runWithContext({
|
|
1970
|
+
editMode: false,
|
|
1971
|
+
queryRecorder
|
|
1972
|
+
}, run);
|
|
1973
|
+
} finally {
|
|
1974
|
+
flushRecorder(queryRecorder);
|
|
1975
|
+
}
|
|
1976
|
+
return run();
|
|
1697
1977
|
});
|
|
1698
1978
|
|
|
1699
1979
|
//#endregion
|