emdash 0.7.0 → 0.8.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-Di31kZ28.d.mts → adapters-BKSf3T9R.d.mts} +1 -1
- package/dist/{adapters-Di31kZ28.d.mts.map → adapters-BKSf3T9R.d.mts.map} +1 -1
- package/dist/{apply-5uslYdUu.mjs → apply-x0eMK1lX.mjs} +18 -17
- package/dist/apply-x0eMK1lX.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 +86 -15
- 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 +22 -2
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.mjs +2 -2
- package/dist/astro/middleware/request-context.mjs +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +259 -71
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/types.d.mts +16 -8
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{byline-C4OVd8b3.mjs → byline-Chbr2GoP.mjs} +3 -3
- package/dist/byline-Chbr2GoP.mjs.map +1 -0
- package/dist/{bylines-hPTW79hw.mjs → bylines-CRNsVG88.mjs} +4 -4
- package/dist/{bylines-hPTW79hw.mjs.map → bylines-CRNsVG88.mjs.map} +1 -1
- package/dist/cli/index.mjs +16 -12
- 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/{content-D7J5y73J.mjs → content-BcQPYxdV.mjs} +13 -15
- package/dist/content-BcQPYxdV.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- 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 → db-errors-l1Qh2RPR.mjs} +1 -1
- package/dist/{db-errors-D0UT85nC.mjs.map → db-errors-l1Qh2RPR.mjs.map} +1 -1
- package/dist/{default-CME5YdZ3.mjs → default-DCVqE5ib.mjs} +1 -1
- package/dist/{default-CME5YdZ3.mjs.map → default-DCVqE5ib.mjs.map} +1 -1
- package/dist/{error-CiYn9yDu.mjs → error-zG5T1UGA.mjs} +1 -1
- package/dist/error-zG5T1UGA.mjs.map +1 -0
- package/dist/{index-De6_Xv3v.d.mts → index-DIb-CzNx.d.mts} +157 -14
- package/dist/index-DIb-CzNx.d.mts.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +22 -20
- package/dist/{load-CBcmDIot.mjs → load-CyEoextb.mjs} +1 -1
- package/dist/{load-CBcmDIot.mjs.map → load-CyEoextb.mjs.map} +1 -1
- package/dist/{loader-DeiBJEMe.mjs → loader-CndGj8kM.mjs} +8 -6
- package/dist/loader-CndGj8kM.mjs.map +1 -0
- package/dist/{manifest-schema-V30qsMft.mjs → manifest-schema-DH9xhc6t.mjs} +13 -1
- package/dist/manifest-schema-DH9xhc6t.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/media/local-runtime.mjs +2 -2
- package/dist/{media-DqHVh136.mjs → media-D8FbNsl0.mjs} +4 -7
- package/dist/media-D8FbNsl0.mjs.map +1 -0
- package/dist/{mode-CpNnGkPz.mjs → mode-BnAOqItE.mjs} +1 -1
- package/dist/mode-BnAOqItE.mjs.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/placeholder-C-fk5hYI.mjs.map +1 -1
- package/dist/{placeholder-tzpqGWII.d.mts → placeholder-D29tWZ7o.d.mts} +1 -1
- package/dist/{placeholder-tzpqGWII.d.mts.map → placeholder-D29tWZ7o.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-g4Ug-9j9.mjs → query-fqEdLFms.mjs} +9 -9
- package/dist/{query-g4Ug-9j9.mjs.map → query-fqEdLFms.mjs.map} +1 -1
- package/dist/{redirect-CN0Rt9Ob.mjs → redirect-D_pshWdf.mjs} +4 -4
- package/dist/redirect-D_pshWdf.mjs.map +1 -0
- package/dist/{registry-Ci3WxVAr.mjs → registry-C3Mr0ODu.mjs} +33 -9
- package/dist/registry-C3Mr0ODu.mjs.map +1 -0
- package/dist/{request-cache-DiR961CV.mjs → request-cache-Ci7f5pBb.mjs} +1 -1
- package/dist/request-cache-Ci7f5pBb.mjs.map +1 -0
- package/dist/{runner-BR2xKwhn.d.mts → runner-OURCaApa.d.mts} +2 -2
- package/dist/{runner-BR2xKwhn.d.mts.map → runner-OURCaApa.d.mts.map} +1 -1
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +2 -2
- package/dist/{search-B0effn3j.mjs → search-BoZYFuUk.mjs} +227 -84
- package/dist/search-BoZYFuUk.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +12 -12
- 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.d.mts.map +1 -1
- package/dist/storage/s3.mjs +4 -4
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{taxonomies-K2z0Uhnj.mjs → taxonomies-B4IAshV8.mjs} +5 -5
- package/dist/{taxonomies-K2z0Uhnj.mjs.map → taxonomies-B4IAshV8.mjs.map} +1 -1
- package/dist/{tokens-BFPFx3CA.mjs → tokens-D9vnZqYS.mjs} +1 -1
- package/dist/{tokens-BFPFx3CA.mjs.map → tokens-D9vnZqYS.mjs.map} +1 -1
- package/dist/{transport-BykRfpyy.mjs → transport-C9ugt2Nr.mjs} +1 -1
- package/dist/{transport-BykRfpyy.mjs.map → transport-C9ugt2Nr.mjs.map} +1 -1
- package/dist/{transport-H4Iwx7tC.d.mts → transport-CUnEL3Vs.d.mts} +1 -1
- package/dist/{transport-H4Iwx7tC.d.mts.map → transport-CUnEL3Vs.d.mts.map} +1 -1
- package/dist/types-BIgulNsW.mjs +68 -0
- package/dist/types-BIgulNsW.mjs.map +1 -0
- package/dist/{types-DDS4MxsT.mjs → types-Bm1dn-q3.mjs} +1 -1
- package/dist/{types-DDS4MxsT.mjs.map → types-Bm1dn-q3.mjs.map} +1 -1
- package/dist/{types-CnZYHyLW.d.mts → types-BmPPSUEx.d.mts} +1 -1
- package/dist/{types-CnZYHyLW.d.mts.map → types-BmPPSUEx.d.mts.map} +1 -1
- package/dist/{types-6CUZRrZP.d.mts → types-BrA0xf5I.d.mts} +24 -2
- package/dist/{types-6CUZRrZP.d.mts.map → types-BrA0xf5I.d.mts.map} +1 -1
- package/dist/{types-C2v0c34j.d.mts → types-CS8FIX7L.d.mts} +1 -1
- package/dist/{types-C2v0c34j.d.mts.map → types-CS8FIX7L.d.mts.map} +1 -1
- package/dist/{types-BH2L167P.mjs → types-CgqmmMJB.mjs} +1 -1
- package/dist/{types-BH2L167P.mjs.map → types-CgqmmMJB.mjs.map} +1 -1
- package/dist/{types-CFWjXmus.d.mts → types-DIMwPFub.d.mts} +1 -1
- package/dist/{types-CFWjXmus.d.mts.map → types-DIMwPFub.d.mts.map} +1 -1
- package/dist/{types-DgrIP0tF.d.mts → types-i36XcA_X.d.mts} +49 -6
- package/dist/types-i36XcA_X.d.mts.map +1 -0
- package/dist/{validate-CqsNItbt.mjs → validate-CxVsLehf.mjs} +2 -2
- package/dist/{validate-CqsNItbt.mjs.map → validate-CxVsLehf.mjs.map} +1 -1
- package/dist/{validate-kM8Pjuf7.d.mts → validate-DHxmpFJt.d.mts} +4 -4
- package/dist/{validate-kM8Pjuf7.d.mts.map → validate-DHxmpFJt.d.mts.map} +1 -1
- package/dist/validation-C-ZpN2GI.mjs +144 -0
- package/dist/validation-C-ZpN2GI.mjs.map +1 -0
- package/dist/version-Bbq8TCrz.mjs +7 -0
- package/dist/{version-BnTKdfam.mjs.map → version-Bbq8TCrz.mjs.map} +1 -1
- package/dist/zod-generator-CpwccCIv.mjs +132 -0
- package/dist/zod-generator-CpwccCIv.mjs.map +1 -0
- package/package.json +18 -5
- package/src/api/auth-storage.ts +37 -0
- package/src/api/error.ts +6 -0
- package/src/api/errors.ts +8 -0
- package/src/api/handlers/comments.ts +13 -0
- package/src/api/handlers/content.ts +122 -3
- package/src/api/handlers/index.ts +2 -0
- package/src/api/handlers/media.ts +8 -1
- package/src/api/handlers/menus.ts +160 -21
- package/src/api/handlers/redirects.ts +16 -3
- package/src/api/handlers/sections.ts +8 -1
- package/src/api/handlers/taxonomies.ts +128 -16
- package/src/api/handlers/validation.ts +212 -0
- package/src/api/openapi/document.ts +4 -1
- package/src/api/public-url.ts +6 -3
- package/src/api/route-utils.ts +14 -0
- package/src/api/schemas/common.ts +1 -1
- package/src/api/schemas/setup.ts +8 -0
- package/src/api/schemas/widgets.ts +12 -10
- package/src/api/setup-complete.ts +40 -0
- package/src/astro/integration/index.ts +13 -2
- package/src/astro/integration/routes.ts +28 -0
- package/src/astro/integration/runtime.ts +19 -1
- package/src/astro/integration/virtual-modules.ts +41 -0
- package/src/astro/integration/vite-config.ts +43 -12
- package/src/astro/middleware/auth.ts +21 -0
- package/src/astro/middleware.ts +18 -1
- package/src/astro/routes/PluginRegistry.tsx +10 -1
- package/src/astro/routes/api/auth/mode.ts +57 -0
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +23 -3
- package/src/astro/routes/api/auth/oauth/[provider].ts +10 -4
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
- package/src/astro/routes/api/content/[collection]/index.ts +1 -9
- package/src/astro/routes/api/import/wordpress/media.ts +2 -7
- package/src/astro/routes/api/import/wordpress/prepare.ts +10 -0
- package/src/astro/routes/api/settings/email.ts +4 -9
- package/src/astro/routes/api/setup/admin.ts +8 -2
- package/src/astro/routes/api/setup/index.ts +2 -2
- package/src/astro/routes/api/setup/status.ts +3 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +4 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +4 -1
- package/src/astro/routes/api/widget-areas/[name].ts +4 -1
- package/src/astro/routes/api/widget-areas/index.ts +4 -1
- package/src/astro/types.ts +9 -0
- package/src/auth/mode.ts +15 -3
- package/src/auth/providers/github-admin.tsx +29 -0
- package/src/auth/providers/github.ts +31 -0
- package/src/auth/providers/google-admin.tsx +44 -0
- package/src/auth/providers/google.ts +31 -0
- package/src/auth/types.ts +114 -4
- package/src/cli/commands/bundle.ts +3 -1
- package/src/components/EmDashImage.astro +7 -6
- package/src/components/Gallery.astro +5 -3
- package/src/components/Image.astro +8 -3
- package/src/components/InlinePortableTextEditor.tsx +2 -1
- package/src/components/LiveSearch.astro +5 -14
- package/src/database/repositories/audit.ts +6 -8
- package/src/database/repositories/byline.ts +6 -8
- package/src/database/repositories/comment.ts +12 -16
- package/src/database/repositories/content.ts +40 -40
- package/src/database/repositories/index.ts +1 -1
- package/src/database/repositories/media.ts +10 -13
- package/src/database/repositories/plugin-storage.ts +4 -6
- package/src/database/repositories/redirect.ts +12 -16
- package/src/database/repositories/taxonomy.ts +14 -3
- package/src/database/repositories/types.ts +57 -8
- package/src/database/repositories/user.ts +6 -8
- package/src/emdash-runtime.ts +306 -90
- package/src/index.ts +5 -1
- package/src/loader.ts +6 -5
- package/src/mcp/server.ts +678 -105
- package/src/media/normalize.ts +1 -1
- package/src/media/url.ts +78 -0
- package/src/plugins/email-console.ts +10 -3
- package/src/plugins/hooks.ts +11 -0
- package/src/plugins/manifest-schema.ts +12 -0
- package/src/plugins/types.ts +23 -2
- package/src/query.ts +1 -1
- package/src/request-cache.ts +3 -0
- package/src/schema/registry.ts +41 -5
- package/src/search/fts-manager.ts +0 -2
- package/src/search/query.ts +111 -26
- package/src/search/types.ts +8 -1
- package/src/sections/index.ts +7 -9
- package/src/storage/s3.ts +12 -6
- package/src/virtual-modules.d.ts +21 -1
- package/src/widgets/index.ts +1 -1
- package/dist/apply-5uslYdUu.mjs.map +0 -1
- package/dist/byline-C4OVd8b3.mjs.map +0 -1
- package/dist/content-D7J5y73J.mjs.map +0 -1
- package/dist/error-CiYn9yDu.mjs.map +0 -1
- package/dist/index-De6_Xv3v.d.mts.map +0 -1
- package/dist/loader-DeiBJEMe.mjs.map +0 -1
- package/dist/manifest-schema-V30qsMft.mjs.map +0 -1
- package/dist/media-DqHVh136.mjs.map +0 -1
- package/dist/mode-CpNnGkPz.mjs.map +0 -1
- package/dist/redirect-CN0Rt9Ob.mjs.map +0 -1
- package/dist/registry-Ci3WxVAr.mjs.map +0 -1
- package/dist/request-cache-DiR961CV.mjs.map +0 -1
- package/dist/search-B0effn3j.mjs.map +0 -1
- package/dist/types-CMMN0pNg.mjs +0 -31
- package/dist/types-CMMN0pNg.mjs.map +0 -1
- package/dist/types-DgrIP0tF.d.mts.map +0 -1
- package/dist/version-BnTKdfam.mjs +0 -7
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { n as validateJsonFieldName, r as validatePluginIdentifier, t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
|
|
2
2
|
import { o as jsonExtractExpr } from "./dialect-helpers-DhTzaUxP.mjs";
|
|
3
|
-
import { a as slugify, r as RevisionRepository, t as ContentRepository } from "./content-
|
|
3
|
+
import { a as slugify, r as RevisionRepository, t as ContentRepository } from "./content-BcQPYxdV.mjs";
|
|
4
4
|
import { r as encodeBase64, t as decodeBase64 } from "./base64-MBPo9ozB.mjs";
|
|
5
|
-
import { n as
|
|
6
|
-
import { t as MediaRepository } from "./media-
|
|
7
|
-
import { a as ssrfSafeFetch, i as resolveAndValidateExternalUrl, o as stripCredentialHeaders, p as OptionsRepository, r as SsrfError, s as validateExternalUrl } from "./apply-
|
|
5
|
+
import { i as encodeCursor, n as InvalidCursorError, r as decodeCursor, t as EmDashValidationError } from "./types-BIgulNsW.mjs";
|
|
6
|
+
import { t as MediaRepository } from "./media-D8FbNsl0.mjs";
|
|
7
|
+
import { a as ssrfSafeFetch, i as resolveAndValidateExternalUrl, o as stripCredentialHeaders, p as OptionsRepository, r as SsrfError, s as validateExternalUrl } from "./apply-x0eMK1lX.mjs";
|
|
8
8
|
import { t as withTransaction } from "./transaction-Cn2rjY78.mjs";
|
|
9
|
-
import { t as RedirectRepository } from "./redirect-
|
|
9
|
+
import { t as RedirectRepository } from "./redirect-D_pshWdf.mjs";
|
|
10
10
|
import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-HGz06Soa.mjs";
|
|
11
|
-
import { t as BylineRepository } from "./byline-
|
|
11
|
+
import { t as BylineRepository } from "./byline-Chbr2GoP.mjs";
|
|
12
12
|
import { r as isI18nEnabled } from "./config-BXwuX8Bx.mjs";
|
|
13
13
|
import { r as invalidateRedirectCache } from "./cache-BkKBuIvS.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
14
|
+
import { t as isMissingTableError } from "./db-errors-l1Qh2RPR.mjs";
|
|
15
|
+
import { r as hashString } from "./zod-generator-CpwccCIv.mjs";
|
|
16
|
+
import { i as FTSManager, n as SchemaRegistry } from "./registry-C3Mr0ODu.mjs";
|
|
17
|
+
import { n as getDb } from "./loader-CndGj8kM.mjs";
|
|
18
|
+
import { n as requestCached } from "./request-cache-Ci7f5pBb.mjs";
|
|
19
|
+
import { i as pluginManifestSchema } from "./manifest-schema-DH9xhc6t.mjs";
|
|
20
|
+
import { t as generatePreviewToken } from "./tokens-D9vnZqYS.mjs";
|
|
19
21
|
import { sql } from "kysely";
|
|
20
22
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
21
23
|
import { ulid } from "ulidx";
|
|
@@ -78,7 +80,7 @@ var UserRepository = class UserRepository {
|
|
|
78
80
|
if (options.role !== void 0) query = query.where("role", "=", UserRepository.resolveRole(options.role));
|
|
79
81
|
if (options.cursor) {
|
|
80
82
|
const decoded = decodeCursor(options.cursor);
|
|
81
|
-
|
|
83
|
+
query = query.where((eb) => eb.or([eb("created_at", "<", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", "<", decoded.id)])]));
|
|
82
84
|
}
|
|
83
85
|
const rows = await query.execute();
|
|
84
86
|
const items = rows.slice(0, limit).map((row) => this.rowToUser(row));
|
|
@@ -228,7 +230,7 @@ var CommentRepository = class CommentRepository {
|
|
|
228
230
|
if (options.status) query = query.where("status", "=", options.status);
|
|
229
231
|
if (options.cursor) {
|
|
230
232
|
const decoded = decodeCursor(options.cursor);
|
|
231
|
-
|
|
233
|
+
query = query.where((eb) => eb.or([eb("created_at", ">", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", ">", decoded.id)])]));
|
|
232
234
|
}
|
|
233
235
|
query = query.orderBy("created_at", "asc").orderBy("id", "asc").limit(limit + 1);
|
|
234
236
|
const rows = await query.execute();
|
|
@@ -259,7 +261,7 @@ var CommentRepository = class CommentRepository {
|
|
|
259
261
|
}
|
|
260
262
|
if (options.cursor) {
|
|
261
263
|
const decoded = decodeCursor(options.cursor);
|
|
262
|
-
|
|
264
|
+
query = query.where((eb) => eb.or([eb("created_at", "<", decoded.orderValue), eb.and([eb("created_at", "=", decoded.orderValue), eb("id", "<", decoded.id)])]));
|
|
263
265
|
}
|
|
264
266
|
query = query.orderBy("created_at", "desc").orderBy("id", "desc").limit(limit + 1);
|
|
265
267
|
const rows = await query.execute();
|
|
@@ -683,7 +685,7 @@ var PluginStorageRepository = class {
|
|
|
683
685
|
}
|
|
684
686
|
if (cursor) {
|
|
685
687
|
const decoded = decodeCursor(cursor);
|
|
686
|
-
|
|
688
|
+
query = query.where(({ eb }) => eb(sql`(created_at, id)`, ">", sql`(${decoded.orderValue}, ${decoded.id})`));
|
|
687
689
|
}
|
|
688
690
|
if (Object.keys(orderBy).length > 0) for (const [field, direction] of Object.entries(orderBy)) {
|
|
689
691
|
const extract = jsonExtract(this.db, field);
|
|
@@ -976,6 +978,16 @@ function validateRev(rev, item) {
|
|
|
976
978
|
//#endregion
|
|
977
979
|
//#region src/api/handlers/content.ts
|
|
978
980
|
/**
|
|
981
|
+
* Narrow a caught error to one carrying a structured `apiError` discriminant.
|
|
982
|
+
* Used by transaction callbacks that want to surface a specific error code
|
|
983
|
+
* through the standard Error throwing path.
|
|
984
|
+
*/
|
|
985
|
+
function hasApiError(error) {
|
|
986
|
+
if (!(error instanceof Error) || !("apiError" in error)) return false;
|
|
987
|
+
const { apiError } = error;
|
|
988
|
+
return typeof apiError === "object" && apiError !== null && "code" in apiError && typeof apiError.code === "string";
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
979
991
|
* Extract a slug source (title or name) from content data.
|
|
980
992
|
* Returns null if no suitable string field is found.
|
|
981
993
|
*/
|
|
@@ -1125,6 +1137,27 @@ async function handleContentList(db, collection, params) {
|
|
|
1125
1137
|
}
|
|
1126
1138
|
};
|
|
1127
1139
|
} catch (error) {
|
|
1140
|
+
if (error instanceof InvalidCursorError) return {
|
|
1141
|
+
success: false,
|
|
1142
|
+
error: {
|
|
1143
|
+
code: "INVALID_CURSOR",
|
|
1144
|
+
message: error.message
|
|
1145
|
+
}
|
|
1146
|
+
};
|
|
1147
|
+
if (isMissingTableError(error)) return {
|
|
1148
|
+
success: false,
|
|
1149
|
+
error: {
|
|
1150
|
+
code: "COLLECTION_NOT_FOUND",
|
|
1151
|
+
message: `Collection '${collection}' not found`
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
if (error instanceof EmDashValidationError) return {
|
|
1155
|
+
success: false,
|
|
1156
|
+
error: {
|
|
1157
|
+
code: "VALIDATION_ERROR",
|
|
1158
|
+
message: error.message
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1128
1161
|
console.error("Content list error:", error);
|
|
1129
1162
|
return {
|
|
1130
1163
|
success: false,
|
|
@@ -1255,6 +1288,37 @@ async function handleContentCreate(db, collection, body) {
|
|
|
1255
1288
|
}
|
|
1256
1289
|
};
|
|
1257
1290
|
} catch (error) {
|
|
1291
|
+
if (isMissingTableError(error)) return {
|
|
1292
|
+
success: false,
|
|
1293
|
+
error: {
|
|
1294
|
+
code: "COLLECTION_NOT_FOUND",
|
|
1295
|
+
message: `Collection '${collection}' not found`
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
1298
|
+
if (error instanceof EmDashValidationError) return {
|
|
1299
|
+
success: false,
|
|
1300
|
+
error: {
|
|
1301
|
+
code: "VALIDATION_ERROR",
|
|
1302
|
+
message: error.message
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
1306
|
+
if (message.includes("unique constraint failed") || message.includes("duplicate key")) {
|
|
1307
|
+
if (message.includes("slug")) return {
|
|
1308
|
+
success: false,
|
|
1309
|
+
error: {
|
|
1310
|
+
code: "SLUG_CONFLICT",
|
|
1311
|
+
message: `Slug '${body.slug ?? "(auto-generated)"}' already exists in collection '${collection}'`
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
return {
|
|
1315
|
+
success: false,
|
|
1316
|
+
error: {
|
|
1317
|
+
code: "CONFLICT",
|
|
1318
|
+
message: "Unique constraint violation"
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1258
1322
|
console.error("Content create error:", error);
|
|
1259
1323
|
return {
|
|
1260
1324
|
success: false,
|
|
@@ -1324,13 +1388,41 @@ async function handleContentUpdate(db, collection, id, body) {
|
|
|
1324
1388
|
}
|
|
1325
1389
|
};
|
|
1326
1390
|
} catch (error) {
|
|
1327
|
-
if (error
|
|
1328
|
-
|
|
1391
|
+
if (hasApiError(error)) return {
|
|
1392
|
+
success: false,
|
|
1393
|
+
error: {
|
|
1394
|
+
code: error.apiError.code,
|
|
1395
|
+
message: error.message
|
|
1396
|
+
}
|
|
1397
|
+
};
|
|
1398
|
+
if (isMissingTableError(error)) return {
|
|
1399
|
+
success: false,
|
|
1400
|
+
error: {
|
|
1401
|
+
code: "COLLECTION_NOT_FOUND",
|
|
1402
|
+
message: `Collection '${collection}' not found`
|
|
1403
|
+
}
|
|
1404
|
+
};
|
|
1405
|
+
if (error instanceof EmDashValidationError) return {
|
|
1406
|
+
success: false,
|
|
1407
|
+
error: {
|
|
1408
|
+
code: "VALIDATION_ERROR",
|
|
1409
|
+
message: error.message
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
const message = error instanceof Error ? error.message.toLowerCase() : "";
|
|
1413
|
+
if (message.includes("unique constraint failed") || message.includes("duplicate key")) {
|
|
1414
|
+
if (message.includes("slug")) return {
|
|
1415
|
+
success: false,
|
|
1416
|
+
error: {
|
|
1417
|
+
code: "SLUG_CONFLICT",
|
|
1418
|
+
message: `Slug '${body.slug ?? id}' already exists in collection '${collection}'`
|
|
1419
|
+
}
|
|
1420
|
+
};
|
|
1329
1421
|
return {
|
|
1330
1422
|
success: false,
|
|
1331
1423
|
error: {
|
|
1332
|
-
code,
|
|
1333
|
-
message:
|
|
1424
|
+
code: "CONFLICT",
|
|
1425
|
+
message: "Unique constraint violation"
|
|
1334
1426
|
}
|
|
1335
1427
|
};
|
|
1336
1428
|
}
|
|
@@ -1519,6 +1611,13 @@ async function handleContentListTrashed(db, collection, options = {}) {
|
|
|
1519
1611
|
}
|
|
1520
1612
|
};
|
|
1521
1613
|
} catch (error) {
|
|
1614
|
+
if (error instanceof InvalidCursorError) return {
|
|
1615
|
+
success: false,
|
|
1616
|
+
error: {
|
|
1617
|
+
code: "INVALID_CURSOR",
|
|
1618
|
+
message: error.message
|
|
1619
|
+
}
|
|
1620
|
+
};
|
|
1522
1621
|
console.error("Content list trashed error:", error);
|
|
1523
1622
|
return {
|
|
1524
1623
|
success: false,
|
|
@@ -1841,37 +1940,6 @@ async function syncNonTranslatableFields(trx, collectionSlug, updatedItemId, tra
|
|
|
1841
1940
|
`.execute(trx);
|
|
1842
1941
|
}
|
|
1843
1942
|
|
|
1844
|
-
//#endregion
|
|
1845
|
-
//#region src/utils/hash.ts
|
|
1846
|
-
/**
|
|
1847
|
-
* SHA-256 hash of a string, truncated to 16 hex chars (64 bits).
|
|
1848
|
-
* For cache invalidation / ETags — not for security.
|
|
1849
|
-
*/
|
|
1850
|
-
async function hashString(content) {
|
|
1851
|
-
const buf = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content));
|
|
1852
|
-
return Array.from(new Uint8Array(buf).slice(0, 8), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
1853
|
-
}
|
|
1854
|
-
/**
|
|
1855
|
-
* Compute content hash using Web Crypto API
|
|
1856
|
-
*
|
|
1857
|
-
* Uses SHA-1 which is the fastest option in SubtleCrypto.
|
|
1858
|
-
* SHA-1 is cryptographically weak but fine for content deduplication
|
|
1859
|
-
* where we only need to detect identical files, not resist attacks.
|
|
1860
|
-
*
|
|
1861
|
-
* Returns hex string prefixed with "sha1:" for future-proofing
|
|
1862
|
-
*/
|
|
1863
|
-
async function computeContentHash(content) {
|
|
1864
|
-
let buf;
|
|
1865
|
-
if (content instanceof ArrayBuffer) buf = content;
|
|
1866
|
-
else {
|
|
1867
|
-
buf = new ArrayBuffer(content.byteLength);
|
|
1868
|
-
new Uint8Array(buf).set(content);
|
|
1869
|
-
}
|
|
1870
|
-
const hashBuffer = await crypto.subtle.digest("SHA-1", buf);
|
|
1871
|
-
const hashArray = new Uint8Array(hashBuffer);
|
|
1872
|
-
return `sha1:${Array.from(hashArray, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
1943
|
//#endregion
|
|
1876
1944
|
//#region src/api/handlers/manifest.ts
|
|
1877
1945
|
/**
|
|
@@ -2106,7 +2174,14 @@ async function handleMediaList(db, params) {
|
|
|
2106
2174
|
nextCursor: result.nextCursor
|
|
2107
2175
|
}
|
|
2108
2176
|
};
|
|
2109
|
-
} catch {
|
|
2177
|
+
} catch (error) {
|
|
2178
|
+
if (error instanceof InvalidCursorError) return {
|
|
2179
|
+
success: false,
|
|
2180
|
+
error: {
|
|
2181
|
+
code: "INVALID_CURSOR",
|
|
2182
|
+
message: error.message
|
|
2183
|
+
}
|
|
2184
|
+
};
|
|
2110
2185
|
return {
|
|
2111
2186
|
success: false,
|
|
2112
2187
|
error: {
|
|
@@ -2436,7 +2511,7 @@ async function getSectionsWithDb(db, options = {}) {
|
|
|
2436
2511
|
query = query.orderBy("title", "asc").orderBy("id", "asc");
|
|
2437
2512
|
if (options.cursor) {
|
|
2438
2513
|
const decoded = decodeCursor(options.cursor);
|
|
2439
|
-
|
|
2514
|
+
query = query.where((eb) => eb.or([eb("title", ">", decoded.orderValue), eb.and([eb("title", "=", decoded.orderValue), eb("id", ">", decoded.id)])]));
|
|
2440
2515
|
}
|
|
2441
2516
|
query = query.limit(limit + 1);
|
|
2442
2517
|
const rows = await query.$castTo().execute();
|
|
@@ -2542,7 +2617,7 @@ const VALID_ROLE_LEVELS = new Set([
|
|
|
2542
2617
|
const roleLevel = z$1.coerce.number().int().refine((n) => VALID_ROLE_LEVELS.has(n), { message: "Invalid role level. Must be 10, 20, 30, 40, or 50" });
|
|
2543
2618
|
/** Pagination query params — cursor-based */
|
|
2544
2619
|
const cursorPaginationQuery = z$1.object({
|
|
2545
|
-
cursor: z$1.string().optional().meta({ description: "Opaque cursor for pagination" }),
|
|
2620
|
+
cursor: z$1.string().max(2048).optional().meta({ description: "Opaque cursor for pagination" }),
|
|
2546
2621
|
limit: z$1.coerce.number().int().min(1).max(100).optional().default(50).meta({ description: "Maximum number of items to return (1-100, default 50)" })
|
|
2547
2622
|
}).meta({ id: "CursorPaginationQuery" });
|
|
2548
2623
|
/** Pagination query params — offset-based */
|
|
@@ -3498,6 +3573,8 @@ const setupAdminBody = z$1.object({
|
|
|
3498
3573
|
name: z$1.string().optional()
|
|
3499
3574
|
});
|
|
3500
3575
|
const setupAdminVerifyBody = z$1.object({ credential: registrationCredential });
|
|
3576
|
+
const atprotoLoginBody = z$1.object({ handle: z$1.string().trim().min(1) });
|
|
3577
|
+
const setupAtprotoAdminBody = z$1.object({ handle: z$1.string().trim().min(1) });
|
|
3501
3578
|
|
|
3502
3579
|
//#endregion
|
|
3503
3580
|
//#region src/api/schemas/users.ts
|
|
@@ -3601,18 +3678,15 @@ const widgetAreaSchema = z$1.object({
|
|
|
3601
3678
|
}).meta({ id: "WidgetArea" });
|
|
3602
3679
|
const widgetSchema = z$1.object({
|
|
3603
3680
|
id: z$1.string(),
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
component_props: z$1.string().nullable(),
|
|
3611
|
-
sort_order: z$1.number().int(),
|
|
3612
|
-
created_at: z$1.string(),
|
|
3613
|
-
updated_at: z$1.string()
|
|
3681
|
+
type: widgetType,
|
|
3682
|
+
title: z$1.string().optional(),
|
|
3683
|
+
content: z$1.array(z$1.record(z$1.string(), z$1.unknown())).optional(),
|
|
3684
|
+
menuName: z$1.string().optional(),
|
|
3685
|
+
componentId: z$1.string().optional(),
|
|
3686
|
+
componentProps: z$1.record(z$1.string(), z$1.unknown()).optional()
|
|
3614
3687
|
}).meta({ id: "Widget" });
|
|
3615
3688
|
const widgetAreaWithWidgetsSchema = widgetAreaSchema.extend({ widgets: z$1.array(widgetSchema) }).meta({ id: "WidgetAreaWithWidgets" });
|
|
3689
|
+
const widgetAreaWithWidgetsAndCountSchema = widgetAreaWithWidgetsSchema.extend({ widgetCount: z$1.number().int() }).meta({ id: "WidgetAreaWithWidgetsAndCount" });
|
|
3616
3690
|
|
|
3617
3691
|
//#endregion
|
|
3618
3692
|
//#region src/api/schemas/redirects.ts
|
|
@@ -6815,6 +6889,15 @@ var HookPipeline = class HookPipeline {
|
|
|
6815
6889
|
return (this.hooks.get(hookName) ?? []).filter((h) => h.exclusive).map((h) => ({ pluginId: h.pluginId }));
|
|
6816
6890
|
}
|
|
6817
6891
|
/**
|
|
6892
|
+
* Get all plugins that registered a non-exclusive handler for a given
|
|
6893
|
+
* hook (e.g. `email:beforeSend`, `email:afterSend`), preserving priority
|
|
6894
|
+
* order. Partitions with `getExclusiveHookProviders()`, which returns
|
|
6895
|
+
* plugins whose registration is marked `exclusive: true`.
|
|
6896
|
+
*/
|
|
6897
|
+
getHookProviders(hookName) {
|
|
6898
|
+
return (this.hooks.get(hookName) ?? []).filter((h) => !h.exclusive).map((h) => ({ pluginId: h.pluginId }));
|
|
6899
|
+
}
|
|
6900
|
+
/**
|
|
6818
6901
|
* Invoke an exclusive hook — dispatch only to the selected provider.
|
|
6819
6902
|
* Returns null if no provider is selected or if the selected hook
|
|
6820
6903
|
* is not found in the pipeline.
|
|
@@ -7058,8 +7141,15 @@ const MAX_STORED_EMAILS = 100;
|
|
|
7058
7141
|
* instances (the runtime and the route handler may load separate copies
|
|
7059
7142
|
* of this module, but globalThis is always the same object).
|
|
7060
7143
|
*/
|
|
7061
|
-
const GLOBAL_KEY = "
|
|
7062
|
-
const
|
|
7144
|
+
const GLOBAL_KEY = Symbol.for("emdash:dev-emails");
|
|
7145
|
+
const g = globalThis;
|
|
7146
|
+
const storedEmails = (() => {
|
|
7147
|
+
const existing = g[GLOBAL_KEY];
|
|
7148
|
+
if (existing) return existing;
|
|
7149
|
+
const fresh = [];
|
|
7150
|
+
g[GLOBAL_KEY] = fresh;
|
|
7151
|
+
return fresh;
|
|
7152
|
+
})();
|
|
7063
7153
|
/**
|
|
7064
7154
|
* The email:deliver handler for the dev console provider.
|
|
7065
7155
|
* Logs to console and stores in memory.
|
|
@@ -9186,6 +9276,22 @@ const WHITESPACE_SPLIT_PATTERN = /\s+/;
|
|
|
9186
9276
|
const FTS_OPERATORS_PATTERN = /\b(AND|OR|NOT|NEAR)\b/i;
|
|
9187
9277
|
const DOUBLE_QUOTE_PATTERN = /"/g;
|
|
9188
9278
|
/**
|
|
9279
|
+
* Detect FTS5 query syntax errors. Match specifically on the SQLite FTS5
|
|
9280
|
+
* error fingerprints rather than a broad "fts5" / "syntax error" filter
|
|
9281
|
+
* (which would also swallow internal table-corruption errors). The two
|
|
9282
|
+
* fingerprints we care about are:
|
|
9283
|
+
*
|
|
9284
|
+
* - "fts5: syntax error near …" — unbalanced quotes, stray operators,
|
|
9285
|
+
* other malformed user input
|
|
9286
|
+
* - "unknown special query: …" — bare special tokens like `^*` that
|
|
9287
|
+
* parse but don't resolve to a real FTS5 directive
|
|
9288
|
+
*/
|
|
9289
|
+
function isFts5SyntaxError(error) {
|
|
9290
|
+
if (!(error instanceof Error)) return false;
|
|
9291
|
+
const message = error.message.toLowerCase();
|
|
9292
|
+
return message.includes("fts5: syntax error") || message.includes("unknown special query");
|
|
9293
|
+
}
|
|
9294
|
+
/**
|
|
9189
9295
|
* Search across multiple collections
|
|
9190
9296
|
*
|
|
9191
9297
|
* Public API that auto-injects the database.
|
|
@@ -9282,7 +9388,9 @@ async function searchSingleCollection(db, collection, query, options, weights) {
|
|
|
9282
9388
|
bm25Args = weightValues.join(", ");
|
|
9283
9389
|
}
|
|
9284
9390
|
const bm25Expr = bm25Args ? `bm25("${ftsTable}", ${bm25Args})` : `bm25("${ftsTable}")`;
|
|
9285
|
-
|
|
9391
|
+
let results;
|
|
9392
|
+
try {
|
|
9393
|
+
results = await sql`
|
|
9286
9394
|
SELECT
|
|
9287
9395
|
c.id,
|
|
9288
9396
|
c.slug,
|
|
@@ -9298,16 +9406,45 @@ async function searchSingleCollection(db, collection, query, options, weights) {
|
|
|
9298
9406
|
${locale ? sql`AND c.locale = ${locale}` : sql``}
|
|
9299
9407
|
ORDER BY score
|
|
9300
9408
|
LIMIT ${limit}
|
|
9301
|
-
`.execute(db)
|
|
9409
|
+
`.execute(db);
|
|
9410
|
+
} catch (error) {
|
|
9411
|
+
if (isFts5SyntaxError(error)) return [];
|
|
9412
|
+
throw error;
|
|
9413
|
+
}
|
|
9414
|
+
return results.rows.map((row) => ({
|
|
9302
9415
|
collection,
|
|
9303
9416
|
id: row.id,
|
|
9304
9417
|
slug: row.slug,
|
|
9305
9418
|
locale: row.locale,
|
|
9306
9419
|
title: row.title ?? void 0,
|
|
9307
|
-
snippet: row.snippet,
|
|
9420
|
+
snippet: row.snippet === null ? void 0 : sanitizeSnippet(row.snippet),
|
|
9308
9421
|
score: Math.abs(row.score)
|
|
9309
9422
|
}));
|
|
9310
9423
|
}
|
|
9424
|
+
const SNIPPET_AMP_RE = /&/g;
|
|
9425
|
+
const SNIPPET_LT_RE = /</g;
|
|
9426
|
+
const SNIPPET_GT_RE = />/g;
|
|
9427
|
+
const SNIPPET_QUOT_RE = /"/g;
|
|
9428
|
+
const SNIPPET_APOS_RE = /'/g;
|
|
9429
|
+
/**
|
|
9430
|
+
* Make an FTS5 snippet safe to render with `set:html` / `innerHTML`.
|
|
9431
|
+
*
|
|
9432
|
+
* SQLite's `snippet()` function splices literal `<mark>` and `</mark>`
|
|
9433
|
+
* markers around matched terms but does not escape the surrounding
|
|
9434
|
+
* source text. Posts that legitimately contain `<`, `>`, `&`, `"` or
|
|
9435
|
+
* `'` would render as broken markup, and a `<script>` literal in a
|
|
9436
|
+
* title (or any other indexed field) would execute when displayed.
|
|
9437
|
+
*
|
|
9438
|
+
* The fix: HTML-escape the whole string, which turns the markers into
|
|
9439
|
+
* `<mark>` / `</mark>`. Then restore those two patterns to
|
|
9440
|
+
* their original tag form. The result is "the indexed text with all
|
|
9441
|
+
* HTML metacharacters escaped, plus a small set of literal `<mark>`
|
|
9442
|
+
* highlight tags around matched terms" — which matches the API's
|
|
9443
|
+
* documented contract.
|
|
9444
|
+
*/
|
|
9445
|
+
function sanitizeSnippet(snippet) {
|
|
9446
|
+
return snippet.replace(SNIPPET_AMP_RE, "&").replace(SNIPPET_LT_RE, "<").replace(SNIPPET_GT_RE, ">").replace(SNIPPET_QUOT_RE, """).replace(SNIPPET_APOS_RE, "'").replaceAll("<mark>", "<mark>").replaceAll("</mark>", "</mark>");
|
|
9447
|
+
}
|
|
9311
9448
|
/**
|
|
9312
9449
|
* Get search suggestions for autocomplete
|
|
9313
9450
|
*
|
|
@@ -9331,20 +9468,26 @@ async function getSuggestions(db, query, options = {}) {
|
|
|
9331
9468
|
const contentTable = ftsManager.getContentTableName(collection);
|
|
9332
9469
|
const prefixQuery = escapeQuery(query);
|
|
9333
9470
|
if (!prefixQuery) continue;
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9471
|
+
let results;
|
|
9472
|
+
try {
|
|
9473
|
+
results = await sql`
|
|
9474
|
+
SELECT
|
|
9475
|
+
c.id,
|
|
9476
|
+
c.title
|
|
9477
|
+
FROM "${sql.raw(ftsTable)}" f
|
|
9478
|
+
JOIN "${sql.raw(contentTable)}" c ON f.id = c.id
|
|
9479
|
+
WHERE "${sql.raw(ftsTable)}" MATCH ${prefixQuery}
|
|
9480
|
+
AND c.status = 'published'
|
|
9481
|
+
AND c.deleted_at IS NULL
|
|
9482
|
+
AND c.title IS NOT NULL
|
|
9483
|
+
${locale ? sql`AND c.locale = ${locale}` : sql``}
|
|
9484
|
+
ORDER BY bm25("${sql.raw(ftsTable)}")
|
|
9485
|
+
LIMIT ${limit}
|
|
9486
|
+
`.execute(db);
|
|
9487
|
+
} catch (error) {
|
|
9488
|
+
if (isFts5SyntaxError(error)) continue;
|
|
9489
|
+
throw error;
|
|
9490
|
+
}
|
|
9348
9491
|
for (const row of results.rows) suggestions.push({
|
|
9349
9492
|
collection,
|
|
9350
9493
|
id: row.id,
|
|
@@ -9490,5 +9633,5 @@ function extractSearchableFields(entry, fields) {
|
|
|
9490
9633
|
}
|
|
9491
9634
|
|
|
9492
9635
|
//#endregion
|
|
9493
|
-
export { prosemirrorToPortableText as $, isStandardPluginDefinition as A,
|
|
9494
|
-
//# sourceMappingURL=search-
|
|
9636
|
+
export { prosemirrorToPortableText as $, isStandardPluginDefinition as A, handleContentSchedule as At, EmailPipeline as B, getAllSources as C, handleContentGet as Ct, probeUrl as D, handleContentPermanentDelete as Dt, getUrlSources as E, handleContentListTrashed as Et, createPluginManager as F, validateRev as Ft, extractRequestMeta as G, createHookPipeline as H, PluginRouteError as I, portableText as It, definePlugin as J, sanitizeHeadersForSandbox as K, PluginRouteRegistry as L, reference as Lt, SandboxNotAvailableError as M, handleContentUnpublish as Mt, createNoopSandboxRunner as N, handleContentUnschedule as Nt, registerSource as O, handleContentPublish as Ot, PluginManager as P, handleContentUpdate as Pt, portableTextToProsemirror as Q, DEV_CONSOLE_EMAIL_PLUGIN_ID as R, image as Rt, clearSources as S, handleContentDuplicate as St, getSource as T, handleContentList as Tt, resolveExclusiveHooks as U, HookPipeline as V, CronExecutor as W, parseWxrString as X, parseWxr as Y, after as Z, buildPreviewUrl as _, handleContentCountScheduled as _t, search as a, PluginStateRepository as at, parseWxrDate as b, handleContentDelete as bt, getWidgetArea as c, handleMediaDelete as ct, getMenu as d, handleMediaUpdate as dt, isSafeHref as et, getMenus as f, handleRevisionGet as ft, isPreviewRequest as g, handleContentCompare as gt, getPreviewToken as h, generateManifest as ht, getSuggestions as i, getSections as it, NoopSandboxRunner as j, handleContentTranslations as jt, importReusableBlocksAsSections as k, handleContentRestore as kt, getWidgetAreas as l, handleMediaGet as lt, getComments as m, handleRevisionRestore as mt, extractSearchableFields as n, loadBundleFromR2 as nt, searchCollection as o, getCollectionInfo as ot, getCommentCount as p, handleRevisionList as pt, getTrustedProxyHeaders as q, getSearchStats as r, getSection as rt, searchWithDb as s, handleMediaCreate as st, extractPlainText as t, sanitizeHref as tt, getWidgetComponents as u, handleMediaList as ut, getPreviewUrl as v, handleContentCountTrashed as vt, getFileSources as w, handleContentGetIncludingTrashed as wt, wxrSource as x, handleContentDiscardDraft as xt, wordpressRestSource as y, handleContentCreate as yt, devConsoleEmailDeliver as z };
|
|
9637
|
+
//# sourceMappingURL=search-BoZYFuUk.mjs.map
|