dineway 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/{apply-CAPvMfoU.mjs → apply-iVSqz2qs.mjs} +132 -39
- package/dist/astro/index.d.mts +18 -9
- package/dist/astro/index.mjs +238 -16
- package/dist/astro/middleware/auth.d.mts +16 -5
- package/dist/astro/middleware/auth.mjs +74 -37
- package/dist/astro/middleware/redirect.mjs +24 -8
- package/dist/astro/middleware/request-context.mjs +18 -5
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.mjs +411 -169
- package/dist/astro/types.d.mts +25 -8
- package/dist/{byline-DeWCMU_i.mjs → byline-OhH2dlRu.mjs} +6 -21
- package/dist/{bylines-DyqBV9EQ.mjs → bylines-BGpD9_hy.mjs} +16 -6
- package/dist/cache-BdSY-gQN.mjs +42 -0
- package/dist/chunks--4F8ddV4.mjs +18 -0
- package/dist/cli/index.mjs +935 -15
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +11 -3
- package/dist/client/index.mjs +4 -3
- package/dist/{connection-C9pxzuag.mjs → connection-BCNICDWN.mjs} +22 -5
- package/dist/{content-zSgdNmnt.mjs → content-DWi4d0rT.mjs} +41 -2
- package/dist/database/instrumentation.d.mts +34 -0
- package/dist/database/instrumentation.mjs +53 -0
- 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.mjs +11 -5
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +7 -1
- package/dist/db-errors-CEqD7qH9.mjs +23 -0
- package/dist/{default-WYlzADZL.mjs → default-VjJyuuG9.mjs} +2 -0
- package/dist/{dialect-helpers-B9uSp2GJ.mjs → dialect-helpers-DhTzaUxP.mjs} +3 -0
- package/dist/{error-DrxtnGPg.mjs → error-BmL6QipT.mjs} +7 -3
- package/dist/{index-C-jx21qs.d.mts → index-yvc6E_17.d.mts} +157 -30
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +24 -22
- package/dist/{loader-qKmo0wAY.mjs → loader-sMG4TZ-u.mjs} +9 -3
- 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/page/index.d.mts +10 -2
- package/dist/page/index.mjs +22 -1
- package/dist/patterns-CrCYkMBb.mjs +92 -0
- package/dist/{placeholder-bOx1xCTY.d.mts → placeholder--wOi4TbO.d.mts} +1 -1
- package/dist/{placeholder-B3knXwNc.mjs → placeholder-Cp8g5Emj.mjs} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{query-BiaPl_g2.mjs → query-kDmwCsHh.mjs} +118 -50
- package/dist/{redirect-JPqLAbxa.mjs → redirect-DnEWAkVg.mjs} +43 -99
- package/dist/{registry-DSd1GWB8.mjs → registry-C0zjeB9P.mjs} +191 -123
- package/dist/request-cache-Dk5qPSOx.mjs +66 -0
- package/dist/request-context.d.mts +4 -16
- package/dist/{runner-B5l1JfOj.d.mts → runner-CFI6B6J2.d.mts} +1 -1
- package/dist/{runner-BGUGywgG.mjs → runner-DWZm2KQm.mjs} +589 -137
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +2 -2
- package/dist/{search-BNruJHDL.mjs → search-BApX1xhM.mjs} +570 -424
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +11 -10
- 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 +11 -3
- package/dist/storage/s3.mjs +78 -15
- package/dist/taxonomies-1s5PaS_8.mjs +266 -0
- package/dist/transaction-Cn2rjY78.mjs +27 -0
- package/dist/{types-BgQeVaPj.d.mts → types-BuMDPy5C.d.mts} +52 -3
- package/dist/{types-DuNbGKjF.mjs → types-COeOq9nK.mjs} +6 -1
- package/dist/{types-ju-_ORz7.d.mts → types-CWbdtiux.d.mts} +13 -5
- package/dist/{types-D38djUXv.d.mts → types-Cj0KMIZV.d.mts} +16 -3
- package/dist/{types-DkvMXalq.d.mts → types-DOrVigru.d.mts} +159 -0
- package/dist/{validate-CXnRKfJK.mjs → validate-BZ5wnLLp.mjs} +2 -1
- package/dist/{validate-DVKJJ-M_.d.mts → validate-IPf8n4Fj.d.mts} +4 -51
- package/dist/{validate-CqRJb_xU.mjs → validate-VPnKoIzW.mjs} +10 -10
- package/dist/version-hmtC3Cmv.mjs +6 -0
- package/package.json +49 -38
- package/src/astro/routes/admin.astro +25 -9
- package/src/astro/routes/api/admin/api-tokens/[id].ts +4 -0
- package/src/astro/routes/api/admin/api-tokens/index.ts +24 -2
- package/src/astro/routes/api/admin/briefing.ts +76 -0
- package/src/astro/routes/api/admin/bylines/[id]/index.ts +3 -0
- package/src/astro/routes/api/admin/bylines/index.ts +2 -0
- package/src/astro/routes/api/admin/context/[id]/history.ts +35 -0
- package/src/astro/routes/api/admin/context/[id]/index.ts +35 -0
- package/src/astro/routes/api/admin/context/[id]/review.ts +57 -0
- package/src/astro/routes/api/admin/context/[id]/supersede.ts +58 -0
- package/src/astro/routes/api/admin/context/diff.ts +35 -0
- package/src/astro/routes/api/admin/context/index.ts +69 -0
- package/src/astro/routes/api/admin/context/stale.ts +35 -0
- package/src/astro/routes/api/admin/hitl-requests/[id]/index.ts +38 -0
- package/src/astro/routes/api/admin/hitl-requests/[id]/resolve.ts +54 -0
- package/src/astro/routes/api/admin/hitl-requests/index.ts +38 -0
- package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +58 -17
- package/src/astro/routes/api/admin/oauth-clients/[id].ts +28 -1
- package/src/astro/routes/api/admin/oauth-clients/index.ts +25 -1
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +54 -2
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +54 -2
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +51 -1
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +98 -3
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +72 -1
- package/src/astro/routes/api/admin/review-requests/[id]/index.ts +35 -0
- package/src/astro/routes/api/admin/review-requests/[id]/resolve.ts +52 -0
- package/src/astro/routes/api/admin/review-requests/index.ts +35 -0
- package/src/astro/routes/api/admin/users/[id]/disable.ts +26 -23
- package/src/astro/routes/api/admin/users/[id]/index.ts +41 -21
- package/src/astro/routes/api/auth/invite/register-options.ts +73 -0
- package/src/astro/routes/api/auth/magic-link/send.ts +2 -1
- package/src/astro/routes/api/auth/passkey/options.ts +2 -1
- package/src/astro/routes/api/auth/passkey/verify.ts +5 -1
- package/src/astro/routes/api/auth/signup/request.ts +20 -8
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +3 -4
- package/src/astro/routes/api/content/[collection]/[id]/compare.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +16 -2
- package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +16 -0
- package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +9 -0
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +45 -1
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +12 -2
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +24 -0
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +3 -0
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +20 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +13 -0
- package/src/astro/routes/api/content/[collection]/[id].ts +36 -0
- package/src/astro/routes/api/content/[collection]/index.ts +48 -4
- package/src/astro/routes/api/content/[collection]/trash.ts +1 -1
- package/src/astro/routes/api/health.ts +54 -0
- package/src/astro/routes/api/import/wordpress/analyze.ts +2 -10
- package/src/astro/routes/api/import/wordpress/execute.ts +40 -6
- package/src/astro/routes/api/import/wordpress/prepare.ts +36 -5
- package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +33 -1
- package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +3 -3
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +57 -15
- package/src/astro/routes/api/manifest.ts +13 -1
- package/src/astro/routes/api/mcp.ts +1 -0
- package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +7 -2
- package/src/astro/routes/api/media/upload-url.ts +11 -2
- package/src/astro/routes/api/media.ts +9 -7
- package/src/astro/routes/api/menus/[name]/items.ts +124 -5
- package/src/astro/routes/api/menus/[name]/reorder.ts +47 -1
- package/src/astro/routes/api/menus/[name].ts +84 -4
- package/src/astro/routes/api/menus/index.ts +46 -2
- package/src/astro/routes/api/oauth/authorize.ts +21 -8
- package/src/astro/routes/api/oauth/device/code.ts +2 -1
- package/src/astro/routes/api/oauth/device/token.ts +2 -1
- package/src/astro/routes/api/oauth/register.ts +182 -0
- package/src/astro/routes/api/oauth/token.ts +18 -7
- package/src/astro/routes/api/openapi.json.ts +3 -2
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +21 -4
- package/src/astro/routes/api/redirects/[id].ts +103 -4
- package/src/astro/routes/api/redirects/index.ts +50 -2
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +28 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +15 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +13 -0
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +27 -0
- package/src/astro/routes/api/schema/collections/index.ts +14 -0
- package/src/astro/routes/api/search/index.ts +1 -0
- package/src/astro/routes/api/search/suggest.ts +1 -0
- package/src/astro/routes/api/sections/[slug].ts +123 -4
- package/src/astro/routes/api/sections/index.ts +57 -2
- package/src/astro/routes/api/settings.ts +51 -2
- package/src/astro/routes/api/setup/admin-verify.ts +25 -5
- package/src/astro/routes/api/setup/admin.ts +16 -8
- package/src/astro/routes/api/setup/index.ts +3 -2
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +141 -4
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +64 -2
- package/src/astro/routes/api/taxonomies/index.ts +57 -2
- package/src/astro/routes/api/well-known/auth.ts +3 -1
- package/src/astro/routes/api/well-known/oauth-authorization-server.ts +8 -5
- package/src/astro/routes/api/well-known/oauth-protected-resource.ts +3 -2
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +58 -16
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +124 -38
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +66 -20
- package/src/astro/routes/api/widget-areas/[name].ts +55 -7
- package/src/astro/routes/api/widget-areas/index.ts +56 -6
- package/src/components/DinewayHead.astro +15 -7
- package/src/components/DinewayMedia.astro +1 -1
- package/src/components/InlinePortableTextEditor.tsx +1 -1
- package/src/components/Table.astro +68 -41
- package/src/components/index.ts +2 -12
- package/src/components/marks.ts +19 -0
- package/LICENSE +0 -9
- /package/dist/{adapters-BlzWJG82.d.mts → adapters-C2ypTrZZ.d.mts} +0 -0
- /package/dist/{config-Cq8H0SfX.mjs → config-BXwuX8Bx.mjs} +0 -0
- /package/dist/{load-C6FCD1FU.mjs → load-Coc9HpHH.mjs} +0 -0
- /package/dist/{manifest-schema-CTSEyIJ3.mjs → manifest-schema-D1MSVnoI.mjs} +0 -0
- /package/dist/{mode-BlyYtIFO.mjs → mode-47goXBBK.mjs} +0 -0
- /package/dist/{tokens-4vgYuXsZ.mjs → tokens-CJz9ubV6.mjs} +0 -0
- /package/dist/{transport-C5FYnid7.mjs → transport-DB5eDN4x.mjs} +0 -0
- /package/dist/{transport-gIL-e43D.d.mts → transport-Wge_IzKl.d.mts} +0 -0
- /package/dist/{types-CLLdsG3g.d.mts → types-BzcUjoqg.d.mts} +0 -0
- /package/dist/{types-DShnjzb6.mjs → types-griIBQOQ.mjs} +0 -0
package/dist/astro/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { n as VERSION, t as COMMIT } from "../version-hmtC3Cmv.mjs";
|
|
2
|
+
import { t as defaultSeed } from "../default-VjJyuuG9.mjs";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
5
|
import { dirname, resolve } from "node:path";
|
|
6
|
+
import { fontProviders } from "astro/config";
|
|
5
7
|
import { fileURLToPath } from "node:url";
|
|
6
8
|
|
|
7
9
|
//#region src/astro/storage/adapters.ts
|
|
@@ -9,19 +11,28 @@ import { fileURLToPath } from "node:url";
|
|
|
9
11
|
* S3-compatible storage adapter
|
|
10
12
|
*
|
|
11
13
|
* Works with AWS S3, MinIO, and other S3-compatible object stores.
|
|
14
|
+
* Any omitted field is resolved from the matching `S3_*` environment
|
|
15
|
+
* variable when the Node process starts. Explicit values take precedence.
|
|
12
16
|
*
|
|
13
17
|
* @example
|
|
14
18
|
* ```ts
|
|
19
|
+
* // All fields from runtime env
|
|
20
|
+
* storage: s3()
|
|
21
|
+
*
|
|
22
|
+
* // Mix explicit CDN config with endpoint/bucket/credentials from env
|
|
23
|
+
* storage: s3({ publicUrl: "https://cdn.example.com" })
|
|
24
|
+
*
|
|
25
|
+
* // All explicit values
|
|
15
26
|
* storage: s3({
|
|
16
27
|
* endpoint: process.env.S3_ENDPOINT!,
|
|
17
28
|
* bucket: "media",
|
|
18
|
-
* accessKeyId: process.env.S3_ACCESS_KEY_ID
|
|
19
|
-
* secretAccessKey: process.env.S3_SECRET_ACCESS_KEY
|
|
29
|
+
* accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
|
30
|
+
* secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
|
20
31
|
* publicUrl: "https://cdn.example.com", // optional CDN
|
|
21
32
|
* })
|
|
22
33
|
* ```
|
|
23
34
|
*/
|
|
24
|
-
function s3(config) {
|
|
35
|
+
function s3(config = {}) {
|
|
25
36
|
return {
|
|
26
37
|
entrypoint: "dineway/storage/s3",
|
|
27
38
|
config
|
|
@@ -48,6 +59,118 @@ function local(config) {
|
|
|
48
59
|
};
|
|
49
60
|
}
|
|
50
61
|
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/astro/integration/font-provider.ts
|
|
64
|
+
/**
|
|
65
|
+
* Dineway Noto Sans font provider.
|
|
66
|
+
*
|
|
67
|
+
* Wraps Google Fonts so the base Noto Sans family and optional
|
|
68
|
+
* script-specific Noto Sans families share one logical font entry.
|
|
69
|
+
* The browser then chooses the right file per character via unicode-range.
|
|
70
|
+
*/
|
|
71
|
+
/**
|
|
72
|
+
* All subset names used by Google Fonts CSS responses.
|
|
73
|
+
* Passed when resolving extra script families so the unifont provider does
|
|
74
|
+
* not filter out faces for those families.
|
|
75
|
+
*/
|
|
76
|
+
const ALL_GOOGLE_SUBSETS = [
|
|
77
|
+
"arabic",
|
|
78
|
+
"armenian",
|
|
79
|
+
"bengali",
|
|
80
|
+
"chinese-simplified",
|
|
81
|
+
"chinese-traditional",
|
|
82
|
+
"chinese-hongkong",
|
|
83
|
+
"cyrillic",
|
|
84
|
+
"cyrillic-ext",
|
|
85
|
+
"devanagari",
|
|
86
|
+
"ethiopic",
|
|
87
|
+
"farsi",
|
|
88
|
+
"georgian",
|
|
89
|
+
"greek",
|
|
90
|
+
"greek-ext",
|
|
91
|
+
"gujarati",
|
|
92
|
+
"gurmukhi",
|
|
93
|
+
"hebrew",
|
|
94
|
+
"japanese",
|
|
95
|
+
"kannada",
|
|
96
|
+
"khmer",
|
|
97
|
+
"korean",
|
|
98
|
+
"lao",
|
|
99
|
+
"latin",
|
|
100
|
+
"latin-ext",
|
|
101
|
+
"malayalam",
|
|
102
|
+
"math",
|
|
103
|
+
"myanmar",
|
|
104
|
+
"oriya",
|
|
105
|
+
"sinhala",
|
|
106
|
+
"symbols",
|
|
107
|
+
"tamil",
|
|
108
|
+
"telugu",
|
|
109
|
+
"thai",
|
|
110
|
+
"tibetan",
|
|
111
|
+
"vietnamese"
|
|
112
|
+
];
|
|
113
|
+
/**
|
|
114
|
+
* Known Noto Sans and compatible script families on Google Fonts.
|
|
115
|
+
*/
|
|
116
|
+
const NOTO_SCRIPT_FAMILIES = {
|
|
117
|
+
arabic: "Noto Sans Arabic",
|
|
118
|
+
armenian: "Noto Sans Armenian",
|
|
119
|
+
bengali: "Noto Sans Bengali",
|
|
120
|
+
"chinese-simplified": "Noto Sans SC",
|
|
121
|
+
"chinese-traditional": "Noto Sans TC",
|
|
122
|
+
"chinese-hongkong": "Noto Sans HK",
|
|
123
|
+
devanagari: "Noto Sans Devanagari",
|
|
124
|
+
ethiopic: "Noto Sans Ethiopic",
|
|
125
|
+
farsi: "Vazirmatn",
|
|
126
|
+
georgian: "Noto Sans Georgian",
|
|
127
|
+
gujarati: "Noto Sans Gujarati",
|
|
128
|
+
gurmukhi: "Noto Sans Gurmukhi",
|
|
129
|
+
hebrew: "Noto Sans Hebrew",
|
|
130
|
+
japanese: "Noto Sans JP",
|
|
131
|
+
kannada: "Noto Sans Kannada",
|
|
132
|
+
khmer: "Noto Sans Khmer",
|
|
133
|
+
korean: "Noto Sans KR",
|
|
134
|
+
lao: "Noto Sans Lao",
|
|
135
|
+
malayalam: "Noto Sans Malayalam",
|
|
136
|
+
myanmar: "Noto Sans Myanmar",
|
|
137
|
+
oriya: "Noto Sans Oriya",
|
|
138
|
+
sinhala: "Noto Sans Sinhala",
|
|
139
|
+
tamil: "Noto Sans Tamil",
|
|
140
|
+
telugu: "Noto Sans Telugu",
|
|
141
|
+
thai: "Noto Sans Thai",
|
|
142
|
+
tibetan: "Noto Sans Tibetan"
|
|
143
|
+
};
|
|
144
|
+
function notoSans(options) {
|
|
145
|
+
const googleProvider = fontProviders.google();
|
|
146
|
+
return {
|
|
147
|
+
name: "dineway-noto",
|
|
148
|
+
async init(context) {
|
|
149
|
+
await googleProvider.init?.(context);
|
|
150
|
+
},
|
|
151
|
+
async resolveFont(resolveFontOptions) {
|
|
152
|
+
const base = await googleProvider.resolveFont(resolveFontOptions);
|
|
153
|
+
const baseFonts = base?.fonts ?? [];
|
|
154
|
+
if (!options?.scripts?.length) return base;
|
|
155
|
+
const baseSubsets = new Set(baseFonts.map((font) => font.meta?.subset).filter(Boolean));
|
|
156
|
+
const extraFaces = (await Promise.all(options.scripts.map(async (script) => {
|
|
157
|
+
const family = NOTO_SCRIPT_FAMILIES[script];
|
|
158
|
+
if (!family) {
|
|
159
|
+
if (ALL_GOOGLE_SUBSETS.includes(script)) return;
|
|
160
|
+
console.warn(`[dineway] Unknown Noto Sans script "${script}". Available: ${Object.keys(NOTO_SCRIPT_FAMILIES).join(", ")}`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
return googleProvider.resolveFont({
|
|
164
|
+
...resolveFontOptions,
|
|
165
|
+
familyName: family,
|
|
166
|
+
subsets: ALL_GOOGLE_SUBSETS
|
|
167
|
+
});
|
|
168
|
+
}))).flatMap((result) => (result?.fonts ?? []).filter((font) => !font.meta?.subset || !baseSubsets.has(font.meta.subset)));
|
|
169
|
+
return { fonts: [...baseFonts, ...extraFaces] };
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
51
174
|
//#endregion
|
|
52
175
|
//#region src/astro/integration/routes.ts
|
|
53
176
|
/**
|
|
@@ -84,6 +207,10 @@ function injectCoreRoutes(injectRoute) {
|
|
|
84
207
|
pattern: "/_dineway/api/dashboard",
|
|
85
208
|
entrypoint: resolveRoute("api/dashboard.ts")
|
|
86
209
|
});
|
|
210
|
+
injectRoute({
|
|
211
|
+
pattern: "/_dineway/api/health",
|
|
212
|
+
entrypoint: resolveRoute("api/health.ts")
|
|
213
|
+
});
|
|
87
214
|
injectRoute({
|
|
88
215
|
pattern: "/_dineway/api/content/[collection]",
|
|
89
216
|
entrypoint: resolveRoute("api/content/[collection]/index.ts")
|
|
@@ -360,6 +487,62 @@ function injectCoreRoutes(injectRoute) {
|
|
|
360
487
|
pattern: "/_dineway/api/admin/bylines/[id]",
|
|
361
488
|
entrypoint: resolveRoute("api/admin/bylines/[id]/index.ts")
|
|
362
489
|
});
|
|
490
|
+
injectRoute({
|
|
491
|
+
pattern: "/_dineway/api/admin/briefing",
|
|
492
|
+
entrypoint: resolveRoute("api/admin/briefing.ts")
|
|
493
|
+
});
|
|
494
|
+
injectRoute({
|
|
495
|
+
pattern: "/_dineway/api/admin/review-requests",
|
|
496
|
+
entrypoint: resolveRoute("api/admin/review-requests/index.ts")
|
|
497
|
+
});
|
|
498
|
+
injectRoute({
|
|
499
|
+
pattern: "/_dineway/api/admin/review-requests/[id]",
|
|
500
|
+
entrypoint: resolveRoute("api/admin/review-requests/[id]/index.ts")
|
|
501
|
+
});
|
|
502
|
+
injectRoute({
|
|
503
|
+
pattern: "/_dineway/api/admin/review-requests/[id]/resolve",
|
|
504
|
+
entrypoint: resolveRoute("api/admin/review-requests/[id]/resolve.ts")
|
|
505
|
+
});
|
|
506
|
+
injectRoute({
|
|
507
|
+
pattern: "/_dineway/api/admin/hitl-requests",
|
|
508
|
+
entrypoint: resolveRoute("api/admin/hitl-requests/index.ts")
|
|
509
|
+
});
|
|
510
|
+
injectRoute({
|
|
511
|
+
pattern: "/_dineway/api/admin/hitl-requests/[id]",
|
|
512
|
+
entrypoint: resolveRoute("api/admin/hitl-requests/[id]/index.ts")
|
|
513
|
+
});
|
|
514
|
+
injectRoute({
|
|
515
|
+
pattern: "/_dineway/api/admin/hitl-requests/[id]/resolve",
|
|
516
|
+
entrypoint: resolveRoute("api/admin/hitl-requests/[id]/resolve.ts")
|
|
517
|
+
});
|
|
518
|
+
injectRoute({
|
|
519
|
+
pattern: "/_dineway/api/admin/context",
|
|
520
|
+
entrypoint: resolveRoute("api/admin/context/index.ts")
|
|
521
|
+
});
|
|
522
|
+
injectRoute({
|
|
523
|
+
pattern: "/_dineway/api/admin/context/stale",
|
|
524
|
+
entrypoint: resolveRoute("api/admin/context/stale.ts")
|
|
525
|
+
});
|
|
526
|
+
injectRoute({
|
|
527
|
+
pattern: "/_dineway/api/admin/context/diff",
|
|
528
|
+
entrypoint: resolveRoute("api/admin/context/diff.ts")
|
|
529
|
+
});
|
|
530
|
+
injectRoute({
|
|
531
|
+
pattern: "/_dineway/api/admin/context/[id]",
|
|
532
|
+
entrypoint: resolveRoute("api/admin/context/[id]/index.ts")
|
|
533
|
+
});
|
|
534
|
+
injectRoute({
|
|
535
|
+
pattern: "/_dineway/api/admin/context/[id]/history",
|
|
536
|
+
entrypoint: resolveRoute("api/admin/context/[id]/history.ts")
|
|
537
|
+
});
|
|
538
|
+
injectRoute({
|
|
539
|
+
pattern: "/_dineway/api/admin/context/[id]/supersede",
|
|
540
|
+
entrypoint: resolveRoute("api/admin/context/[id]/supersede.ts")
|
|
541
|
+
});
|
|
542
|
+
injectRoute({
|
|
543
|
+
pattern: "/_dineway/api/admin/context/[id]/review",
|
|
544
|
+
entrypoint: resolveRoute("api/admin/context/[id]/review.ts")
|
|
545
|
+
});
|
|
363
546
|
injectRoute({
|
|
364
547
|
pattern: "/_dineway/api/admin/users/[id]",
|
|
365
548
|
entrypoint: resolveRoute("api/admin/users/[id]/index.ts")
|
|
@@ -420,6 +603,10 @@ function injectCoreRoutes(injectRoute) {
|
|
|
420
603
|
pattern: "/_dineway/api/oauth/token",
|
|
421
604
|
entrypoint: resolveRoute("api/oauth/token.ts")
|
|
422
605
|
});
|
|
606
|
+
injectRoute({
|
|
607
|
+
pattern: "/_dineway/api/oauth/register",
|
|
608
|
+
entrypoint: resolveRoute("api/oauth/register.ts")
|
|
609
|
+
});
|
|
423
610
|
injectRoute({
|
|
424
611
|
pattern: "/_dineway/oauth/authorize",
|
|
425
612
|
entrypoint: resolveRoute("api/oauth/authorize.ts")
|
|
@@ -429,7 +616,7 @@ function injectCoreRoutes(injectRoute) {
|
|
|
429
616
|
entrypoint: resolveRoute("api/well-known/oauth-protected-resource.ts")
|
|
430
617
|
});
|
|
431
618
|
injectRoute({
|
|
432
|
-
pattern: "
|
|
619
|
+
pattern: "/.well-known/oauth-authorization-server/_dineway",
|
|
433
620
|
entrypoint: resolveRoute("api/well-known/oauth-authorization-server.ts")
|
|
434
621
|
});
|
|
435
622
|
injectRoute({
|
|
@@ -591,7 +778,7 @@ function injectCoreRoutes(injectRoute) {
|
|
|
591
778
|
}
|
|
592
779
|
/**
|
|
593
780
|
* Injects the MCP (Model Context Protocol) server route.
|
|
594
|
-
*
|
|
781
|
+
* Injected by default unless `mcp: false` is set in the Dineway config.
|
|
595
782
|
*/
|
|
596
783
|
function injectMcpRoute(injectRoute) {
|
|
597
784
|
injectRoute({
|
|
@@ -640,6 +827,10 @@ function injectBuiltinAuthRoutes(injectRoute) {
|
|
|
640
827
|
pattern: "/_dineway/api/auth/invite/accept",
|
|
641
828
|
entrypoint: resolveRoute("api/auth/invite/accept.ts")
|
|
642
829
|
});
|
|
830
|
+
injectRoute({
|
|
831
|
+
pattern: "/_dineway/api/auth/invite/register-options",
|
|
832
|
+
entrypoint: resolveRoute("api/auth/invite/register-options.ts")
|
|
833
|
+
});
|
|
643
834
|
injectRoute({
|
|
644
835
|
pattern: "/_dineway/api/auth/invite/complete",
|
|
645
836
|
entrypoint: resolveRoute("api/auth/invite/complete.ts")
|
|
@@ -1106,10 +1297,16 @@ const NODE_NATIVE_EXTERNALS = [
|
|
|
1106
1297
|
*/
|
|
1107
1298
|
function createViteConfig(options, command) {
|
|
1108
1299
|
const adminDistPath = resolveAdminDist();
|
|
1109
|
-
const
|
|
1300
|
+
const isDev = command === "dev";
|
|
1301
|
+
const adminSourcePath = isDev ? resolveAdminSource() : void 0;
|
|
1110
1302
|
const useSource = adminSourcePath !== void 0;
|
|
1111
1303
|
const devPlugins = adminSourcePath ? [linguiMacroPlugin(adminSourcePath, adminDistPath)] : [];
|
|
1112
1304
|
return {
|
|
1305
|
+
define: {
|
|
1306
|
+
__DINEWAY_VERSION__: JSON.stringify(VERSION),
|
|
1307
|
+
__DINEWAY_COMMIT__: JSON.stringify(COMMIT),
|
|
1308
|
+
__DINEWAY_PSEUDO_LOCALE__: JSON.stringify(isDev && process.env["DINEWAY_PSEUDO_LOCALE"] === "1")
|
|
1309
|
+
},
|
|
1113
1310
|
resolve: {
|
|
1114
1311
|
dedupe: [
|
|
1115
1312
|
"@dineway-ai/admin",
|
|
@@ -1219,7 +1416,10 @@ function dineway(config = {}) {
|
|
|
1219
1416
|
storage: resolvedConfig.storage,
|
|
1220
1417
|
auth: resolvedConfig.auth,
|
|
1221
1418
|
marketplace: resolvedConfig.marketplace,
|
|
1222
|
-
|
|
1419
|
+
maxUploadSize: resolvedConfig.maxUploadSize,
|
|
1420
|
+
admin: resolvedConfig.admin,
|
|
1421
|
+
siteUrl: resolvedConfig.siteUrl,
|
|
1422
|
+
trustedProxyHeaders: resolvedConfig.trustedProxyHeaders
|
|
1223
1423
|
};
|
|
1224
1424
|
const useExternalAuth = !!(resolvedConfig.auth && "entrypoint" in resolvedConfig.auth);
|
|
1225
1425
|
return {
|
|
@@ -1236,11 +1436,36 @@ function dineway(config = {}) {
|
|
|
1236
1436
|
prefixDefaultLocale: typeof routing === "object" ? routing.prefixDefaultLocale ?? false : false
|
|
1237
1437
|
};
|
|
1238
1438
|
}
|
|
1439
|
+
const securityConfig = {
|
|
1440
|
+
checkOrigin: false,
|
|
1441
|
+
...resolvedConfig.siteUrl ? { allowedDomains: [{ hostname: new URL(resolvedConfig.siteUrl).hostname }] } : {}
|
|
1442
|
+
};
|
|
1443
|
+
const fontsConfig = resolvedConfig.fonts;
|
|
1444
|
+
const fontScripts = fontsConfig && typeof fontsConfig === "object" ? fontsConfig.scripts : void 0;
|
|
1239
1445
|
updateConfig({
|
|
1240
|
-
security:
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1446
|
+
security: securityConfig,
|
|
1447
|
+
fonts: fontsConfig === false ? [] : [{
|
|
1448
|
+
provider: notoSans({ scripts: fontScripts }),
|
|
1449
|
+
name: "Noto Sans",
|
|
1450
|
+
cssVariable: "--font-dineway",
|
|
1451
|
+
weights: ["100 900"],
|
|
1452
|
+
styles: ["normal", "italic"],
|
|
1453
|
+
subsets: [
|
|
1454
|
+
"latin",
|
|
1455
|
+
"latin-ext",
|
|
1456
|
+
"cyrillic",
|
|
1457
|
+
"cyrillic-ext",
|
|
1458
|
+
"devanagari",
|
|
1459
|
+
"greek",
|
|
1460
|
+
"greek-ext",
|
|
1461
|
+
"vietnamese"
|
|
1462
|
+
],
|
|
1463
|
+
fallbacks: [
|
|
1464
|
+
"ui-sans-serif",
|
|
1465
|
+
"system-ui",
|
|
1466
|
+
"sans-serif"
|
|
1467
|
+
]
|
|
1468
|
+
}],
|
|
1244
1469
|
vite: createViteConfig({
|
|
1245
1470
|
serializableConfig,
|
|
1246
1471
|
resolvedConfig,
|
|
@@ -1250,10 +1475,7 @@ function dineway(config = {}) {
|
|
|
1250
1475
|
});
|
|
1251
1476
|
injectCoreRoutes(injectRoute);
|
|
1252
1477
|
if (!useExternalAuth) injectBuiltinAuthRoutes(injectRoute);
|
|
1253
|
-
if (resolvedConfig.mcp)
|
|
1254
|
-
injectMcpRoute(injectRoute);
|
|
1255
|
-
logger.info("MCP server enabled at /_dineway/api/mcp");
|
|
1256
|
-
}
|
|
1478
|
+
if (resolvedConfig.mcp !== false) injectMcpRoute(injectRoute);
|
|
1257
1479
|
if (resolvedConfig.playground) addMiddleware({
|
|
1258
1480
|
entrypoint: resolvedConfig.playground.middlewareEntrypoint,
|
|
1259
1481
|
order: "pre"
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import "../../types-
|
|
2
|
-
import "../../index-
|
|
3
|
-
import "../../runner-
|
|
4
|
-
import "../../types-
|
|
5
|
-
import "../../validate-
|
|
1
|
+
import "../../types-DOrVigru.mjs";
|
|
2
|
+
import "../../index-yvc6E_17.mjs";
|
|
3
|
+
import "../../runner-CFI6B6J2.mjs";
|
|
4
|
+
import "../../types-Cj0KMIZV.mjs";
|
|
5
|
+
import "../../validate-IPf8n4Fj.mjs";
|
|
6
6
|
import { DinewayHandlers, DinewayManifest } from "../types.mjs";
|
|
7
|
+
import { Kysely } from "kysely";
|
|
7
8
|
import { User } from "@dineway-ai/auth";
|
|
8
9
|
import * as astro from "astro";
|
|
9
10
|
|
|
11
|
+
//#region src/site-context/actor.d.ts
|
|
12
|
+
type SiteAuthTokenType = "api_token" | "oauth_token";
|
|
13
|
+
interface SiteAuthTokenContext {
|
|
14
|
+
type: SiteAuthTokenType;
|
|
15
|
+
/** Non-secret persistent token id. Present for API tokens; absent for OAuth access tokens today. */
|
|
16
|
+
id?: string | null;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
10
19
|
//#region src/astro/middleware/auth.d.ts
|
|
11
20
|
declare global {
|
|
12
21
|
namespace App {
|
|
@@ -14,6 +23,8 @@ declare global {
|
|
|
14
23
|
user?: User;
|
|
15
24
|
/** Token scopes when authenticated via API token or OAuth token. Undefined for session auth. */
|
|
16
25
|
tokenScopes?: string[];
|
|
26
|
+
/** Non-secret bearer token metadata for activity attribution. Undefined for session auth. */
|
|
27
|
+
authToken?: SiteAuthTokenContext;
|
|
17
28
|
dineway?: DinewayHandlers;
|
|
18
29
|
dinewayManifest?: DinewayManifest;
|
|
19
30
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as apiError } from "../../error-
|
|
2
|
-
import { t as getAuthMode } from "../../mode-
|
|
1
|
+
import { t as apiError } from "../../error-BmL6QipT.mjs";
|
|
2
|
+
import { t as getAuthMode } from "../../mode-47goXBBK.mjs";
|
|
3
3
|
import { ulid } from "ulidx";
|
|
4
4
|
import { defineMiddleware } from "astro:middleware";
|
|
5
5
|
import { createKyselyAdapter } from "@dineway-ai/auth/adapters/kysely";
|
|
@@ -58,7 +58,7 @@ function checkPublicCsrf(request, url, publicOrigin) {
|
|
|
58
58
|
* the build. Container deployments set env vars at runtime, so we must read
|
|
59
59
|
* process.env which Vite leaves untouched.
|
|
60
60
|
*
|
|
61
|
-
* On
|
|
61
|
+
* On runtimes without `process.env`, the fallback chain
|
|
62
62
|
* continues to url.origin.
|
|
63
63
|
*
|
|
64
64
|
* Caches after first call.
|
|
@@ -117,7 +117,8 @@ async function resolveApiToken(db, rawToken) {
|
|
|
117
117
|
db.updateTable("_dineway_api_tokens").set({ last_used_at: (/* @__PURE__ */ new Date()).toISOString() }).where("id", "=", row.id).execute().catch(() => {});
|
|
118
118
|
return {
|
|
119
119
|
userId: row.user_id,
|
|
120
|
-
scopes: JSON.parse(row.scopes)
|
|
120
|
+
scopes: JSON.parse(row.scopes),
|
|
121
|
+
tokenId: row.id
|
|
121
122
|
};
|
|
122
123
|
}
|
|
123
124
|
/**
|
|
@@ -174,6 +175,35 @@ function buildDinewayCsp() {
|
|
|
174
175
|
/** Cache headers for middleware error responses (matches API_CACHE_HEADERS in api/error.ts) */
|
|
175
176
|
const MW_CACHE_HEADERS = { "Cache-Control": "private, no-store" };
|
|
176
177
|
const ROLE_ADMIN = 50;
|
|
178
|
+
const MCP_ENDPOINT_PATH = "/_dineway/api/mcp";
|
|
179
|
+
function isUnsafeMethod(method) {
|
|
180
|
+
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS";
|
|
181
|
+
}
|
|
182
|
+
function csrfRejectedResponse() {
|
|
183
|
+
return new Response(JSON.stringify({ error: {
|
|
184
|
+
code: "CSRF_REJECTED",
|
|
185
|
+
message: "Missing required header"
|
|
186
|
+
} }), {
|
|
187
|
+
status: 403,
|
|
188
|
+
headers: {
|
|
189
|
+
"Content-Type": "application/json",
|
|
190
|
+
...MW_CACHE_HEADERS
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function mcpUnauthorizedResponse(url, config) {
|
|
195
|
+
const origin = getPublicOrigin(url, config);
|
|
196
|
+
return Response.json({ error: {
|
|
197
|
+
code: "NOT_AUTHENTICATED",
|
|
198
|
+
message: "Not authenticated"
|
|
199
|
+
} }, {
|
|
200
|
+
status: 401,
|
|
201
|
+
headers: {
|
|
202
|
+
"WWW-Authenticate": `Bearer resource_metadata="${origin}/.well-known/oauth-protected-resource"`,
|
|
203
|
+
...MW_CACHE_HEADERS
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
177
207
|
/**
|
|
178
208
|
* API routes that skip auth — each handles its own access control.
|
|
179
209
|
*
|
|
@@ -187,29 +217,39 @@ const PUBLIC_API_PREFIXES = [
|
|
|
187
217
|
"/_dineway/api/auth/dev-bypass",
|
|
188
218
|
"/_dineway/api/auth/signup/",
|
|
189
219
|
"/_dineway/api/auth/magic-link/",
|
|
190
|
-
"/_dineway/api/auth/invite/
|
|
191
|
-
"/_dineway/api/auth/invite/complete",
|
|
220
|
+
"/_dineway/api/auth/invite/",
|
|
192
221
|
"/_dineway/api/auth/oauth/",
|
|
193
222
|
"/_dineway/api/oauth/device/token",
|
|
194
223
|
"/_dineway/api/oauth/device/code",
|
|
195
224
|
"/_dineway/api/oauth/token",
|
|
225
|
+
"/_dineway/api/oauth/register",
|
|
196
226
|
"/_dineway/api/comments/",
|
|
197
227
|
"/_dineway/api/media/file/",
|
|
198
228
|
"/_dineway/.well-known/"
|
|
199
229
|
];
|
|
200
230
|
const PUBLIC_API_EXACT = new Set([
|
|
231
|
+
"/_dineway/api/health",
|
|
201
232
|
"/_dineway/api/auth/passkey/options",
|
|
202
233
|
"/_dineway/api/auth/passkey/verify",
|
|
203
234
|
"/_dineway/api/oauth/token",
|
|
204
235
|
"/_dineway/api/snapshot",
|
|
205
236
|
"/_dineway/api/search"
|
|
206
237
|
]);
|
|
238
|
+
const CSRF_EXEMPT_PUBLIC_ROUTES = new Set([
|
|
239
|
+
"/_dineway/api/oauth/token",
|
|
240
|
+
"/_dineway/api/oauth/register",
|
|
241
|
+
"/_dineway/api/oauth/device/code",
|
|
242
|
+
"/_dineway/api/oauth/device/token"
|
|
243
|
+
]);
|
|
207
244
|
function isPublicDinewayRoute(pathname) {
|
|
208
245
|
if (PUBLIC_API_EXACT.has(pathname)) return true;
|
|
209
246
|
if (PUBLIC_API_PREFIXES.some((p) => pathname.startsWith(p))) return true;
|
|
210
247
|
if (import.meta.env.DEV && pathname === "/_dineway/api/typegen") return true;
|
|
211
248
|
return false;
|
|
212
249
|
}
|
|
250
|
+
function isCsrfExemptPublicRoute(pathname) {
|
|
251
|
+
return CSRF_EXEMPT_PUBLIC_ROUTES.has(pathname);
|
|
252
|
+
}
|
|
213
253
|
const onRequest = defineMiddleware(async (context, next) => {
|
|
214
254
|
const { url } = context;
|
|
215
255
|
const isAdminRoute = url.pathname.startsWith("/_dineway/admin");
|
|
@@ -218,8 +258,7 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
218
258
|
const isPublicApiRoute = isPublicDinewayRoute(url.pathname);
|
|
219
259
|
const isPublicRoute = !isAdminRoute && !isApiRoute;
|
|
220
260
|
if (isPublicApiRoute) {
|
|
221
|
-
|
|
222
|
-
if (method !== "GET" && method !== "HEAD" && method !== "OPTIONS") {
|
|
261
|
+
if (isUnsafeMethod(context.request.method.toUpperCase()) && !isCsrfExemptPublicRoute(url.pathname)) {
|
|
223
262
|
const publicOrigin = getPublicOrigin(url, context.locals.dineway?.config);
|
|
224
263
|
const csrfError = checkPublicCsrf(context.request, url, publicOrigin);
|
|
225
264
|
if (csrfError) return csrfError;
|
|
@@ -258,7 +297,7 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
258
297
|
"Content-Type": "application/json",
|
|
259
298
|
...MW_CACHE_HEADERS
|
|
260
299
|
};
|
|
261
|
-
if (url.pathname ===
|
|
300
|
+
if (url.pathname === MCP_ENDPOINT_PATH) headers["WWW-Authenticate"] = `Bearer resource_metadata="${getPublicOrigin(url, context.locals.dineway?.config)}/.well-known/oauth-protected-resource"`;
|
|
262
301
|
return new Response(JSON.stringify({ error: {
|
|
263
302
|
code: "INVALID_TOKEN",
|
|
264
303
|
message: "Invalid or expired token"
|
|
@@ -269,18 +308,10 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
269
308
|
}
|
|
270
309
|
const isTokenAuth = bearerResult === "authenticated";
|
|
271
310
|
const method = context.request.method.toUpperCase();
|
|
311
|
+
if (url.pathname === MCP_ENDPOINT_PATH && !isTokenAuth) return mcpUnauthorizedResponse(url, context.locals.dineway?.config);
|
|
272
312
|
const isOAuthConsent = url.pathname.startsWith("/_dineway/oauth/authorize");
|
|
273
|
-
if (isApiRoute && !isTokenAuth && !isOAuthConsent && method
|
|
274
|
-
if (context.request.headers.get("X-Dineway-Request") !== "1") return
|
|
275
|
-
code: "CSRF_REJECTED",
|
|
276
|
-
message: "Missing required header"
|
|
277
|
-
} }), {
|
|
278
|
-
status: 403,
|
|
279
|
-
headers: {
|
|
280
|
-
"Content-Type": "application/json",
|
|
281
|
-
...MW_CACHE_HEADERS
|
|
282
|
-
}
|
|
283
|
-
});
|
|
313
|
+
if (isApiRoute && !isTokenAuth && !isOAuthConsent && isUnsafeMethod(method) && !isPublicApiRoute) {
|
|
314
|
+
if (context.request.headers.get("X-Dineway-Request") !== "1") return csrfRejectedResponse();
|
|
284
315
|
}
|
|
285
316
|
if (isTokenAuth) {
|
|
286
317
|
const scopeError = enforceTokenScope(url.pathname, method, context.locals.tokenScopes);
|
|
@@ -300,18 +331,18 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
300
331
|
async function handleDinewayAuth(context, next) {
|
|
301
332
|
const { url, locals } = context;
|
|
302
333
|
const { dineway } = locals;
|
|
303
|
-
const
|
|
334
|
+
const isPublicAdminRoute = url.pathname.startsWith("/_dineway/admin/login") || url.pathname.startsWith("/_dineway/admin/invite/accept");
|
|
304
335
|
const isApiRoute = url.pathname.startsWith("/_dineway/api");
|
|
305
336
|
if (!dineway?.db) return next();
|
|
306
337
|
const authMode = getAuthMode(dineway.config);
|
|
307
338
|
if (authMode.type === "external") {
|
|
308
339
|
if (import.meta.env.DEV) {
|
|
309
|
-
if (
|
|
340
|
+
if (isPublicAdminRoute) return next();
|
|
310
341
|
return handlePasskeyAuth(context, next, isApiRoute);
|
|
311
342
|
}
|
|
312
343
|
return handleExternalAuth(context, next, authMode, isApiRoute);
|
|
313
344
|
}
|
|
314
|
-
if (
|
|
345
|
+
if (isPublicAdminRoute) return next();
|
|
315
346
|
return handlePasskeyAuth(context, next, isApiRoute);
|
|
316
347
|
}
|
|
317
348
|
/**
|
|
@@ -471,14 +502,24 @@ async function handleBearerAuth(context) {
|
|
|
471
502
|
const { dineway } = locals;
|
|
472
503
|
if (!dineway?.db) return "none";
|
|
473
504
|
let resolved = null;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
505
|
+
let authToken;
|
|
506
|
+
if (token.startsWith("ec_pat_")) {
|
|
507
|
+
const apiToken = await resolveApiToken(dineway.db, token);
|
|
508
|
+
resolved = apiToken;
|
|
509
|
+
if (apiToken) authToken = {
|
|
510
|
+
type: "api_token",
|
|
511
|
+
id: apiToken.tokenId
|
|
512
|
+
};
|
|
513
|
+
} else if (token.startsWith("ec_oat_")) {
|
|
514
|
+
resolved = await resolveOAuthToken(dineway.db, token);
|
|
515
|
+
if (resolved) authToken = { type: "oauth_token" };
|
|
516
|
+
} else return "invalid";
|
|
477
517
|
if (!resolved) return "invalid";
|
|
478
518
|
const user = await createKyselyAdapter(dineway.db).getUserById(resolved.userId);
|
|
479
519
|
if (!user || user.disabled) return "invalid";
|
|
480
520
|
locals.user = user;
|
|
481
521
|
locals.tokenScopes = resolved.scopes;
|
|
522
|
+
locals.authToken = authToken;
|
|
482
523
|
return "authenticated";
|
|
483
524
|
}
|
|
484
525
|
/**
|
|
@@ -490,17 +531,13 @@ async function handlePasskeyAuth(context, next, isApiRoute) {
|
|
|
490
531
|
try {
|
|
491
532
|
const sessionUser = await session?.get("user");
|
|
492
533
|
if (!sessionUser?.id) {
|
|
493
|
-
if (isApiRoute) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
status: 401,
|
|
501
|
-
headers
|
|
502
|
-
});
|
|
503
|
-
}
|
|
534
|
+
if (isApiRoute) return Response.json({ error: {
|
|
535
|
+
code: "NOT_AUTHENTICATED",
|
|
536
|
+
message: "Not authenticated"
|
|
537
|
+
} }, {
|
|
538
|
+
status: 401,
|
|
539
|
+
headers: MW_CACHE_HEADERS
|
|
540
|
+
});
|
|
504
541
|
const loginUrl = new URL("/_dineway/admin/login", getPublicOrigin(url, dineway?.config));
|
|
505
542
|
loginUrl.searchParams.set("redirect", url.pathname);
|
|
506
543
|
return context.redirect(loginUrl.toString());
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import "../../
|
|
1
|
+
import { getRequestContext } from "../../request-context.mjs";
|
|
2
|
+
import "../../dialect-helpers-DhTzaUxP.mjs";
|
|
2
3
|
import "../../base64-F8-DUraK.mjs";
|
|
3
4
|
import "../../types-BawVha09.mjs";
|
|
4
|
-
import { t as RedirectRepository } from "../../redirect-
|
|
5
|
+
import { t as RedirectRepository } from "../../redirect-DnEWAkVg.mjs";
|
|
6
|
+
import { a as matchCachedPatterns, n as compileRedirectRules, o as setCachedPatternRules, r as getCachedPatternRules } from "../../cache-BdSY-gQN.mjs";
|
|
5
7
|
import { defineMiddleware } from "astro:middleware";
|
|
6
8
|
|
|
7
9
|
//#region src/astro/middleware/redirect.ts
|
|
@@ -35,12 +37,26 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
35
37
|
if (!dineway?.db) return next();
|
|
36
38
|
try {
|
|
37
39
|
const repo = new RedirectRepository(dineway.db);
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
if (
|
|
41
|
-
repo.recordHit(
|
|
42
|
-
const code = isRedirectCode(
|
|
43
|
-
return context.redirect(
|
|
40
|
+
const exact = await repo.findExactMatch(pathname);
|
|
41
|
+
if (exact) {
|
|
42
|
+
if (exact.destination.startsWith("//") || exact.destination.startsWith("/\\")) return next();
|
|
43
|
+
repo.recordHit(exact.id).catch(() => {});
|
|
44
|
+
const code = isRedirectCode(exact.type) ? exact.type : 301;
|
|
45
|
+
return context.redirect(exact.destination, code);
|
|
46
|
+
}
|
|
47
|
+
const hasDbOverride = !!getRequestContext()?.db;
|
|
48
|
+
let rules = !hasDbOverride ? getCachedPatternRules() : null;
|
|
49
|
+
if (!rules) {
|
|
50
|
+
const patternRedirects = await repo.findEnabledPatternRules();
|
|
51
|
+
rules = hasDbOverride ? compileRedirectRules(patternRedirects) : setCachedPatternRules(patternRedirects);
|
|
52
|
+
}
|
|
53
|
+
const patternMatch = matchCachedPatterns(rules, pathname);
|
|
54
|
+
if (patternMatch) {
|
|
55
|
+
const { redirect, destination } = patternMatch;
|
|
56
|
+
if (destination.startsWith("//") || destination.startsWith("/\\")) return next();
|
|
57
|
+
repo.recordHit(redirect.id).catch(() => {});
|
|
58
|
+
const code = isRedirectCode(redirect.type) ? redirect.type : 301;
|
|
59
|
+
return context.redirect(destination, code);
|
|
44
60
|
}
|
|
45
61
|
const response = await next();
|
|
46
62
|
if (response.status === 404) {
|