dineway 0.1.47 → 0.1.49
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 +57 -54
- package/dist/{activity-events-CNk3clTT.mjs → activity-events-CwM7yxPW.mjs} +1 -1
- package/dist/{allowed-origins-QirBXiDj.mjs → allowed-origins-CyGnbgBd.mjs} +1 -1
- package/dist/api/route-utils.d.mts +8 -22
- package/dist/api/route-utils.mjs +10 -10
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +4 -4
- package/dist/{api-ePsOhL3q.mjs → api-BMIxRIEN.mjs} +65 -18
- package/dist/{apply-BpRBCqUt.mjs → apply-D_RlTYtC.mjs} +54 -48
- package/dist/astro/index.d.mts +8 -8
- package/dist/astro/index.mjs +67 -25
- package/dist/astro/middleware/auth.d.mts +7 -7
- package/dist/astro/middleware/auth.mjs +1 -1
- package/dist/astro/middleware/redirect.mjs +5 -5
- package/dist/astro/middleware/request-context.mjs +4 -4
- package/dist/astro/middleware/seed.d.mts +1 -1
- package/dist/astro/middleware/seed.mjs +2 -2
- package/dist/astro/middleware.d.mts +2 -1
- package/dist/astro/middleware.mjs +366 -147
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +3 -3
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +3 -3
- package/dist/astro/routes/api/admin/briefing.mjs +16 -16
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +2 -2
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +5 -5
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +11 -11
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +11 -11
- package/dist/astro/routes/api/admin/bylines/index.mjs +11 -11
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/comments/bulk.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/counts.mjs +4 -4
- package/dist/astro/routes/api/admin/comments/index.mjs +7 -7
- package/dist/astro/routes/api/admin/context/_id_/history.mjs +23 -23
- package/dist/astro/routes/api/admin/context/_id_/index.mjs +23 -23
- package/dist/astro/routes/api/admin/context/_id_/review.mjs +26 -26
- package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +26 -26
- package/dist/astro/routes/api/admin/context/diff.mjs +25 -25
- package/dist/astro/routes/api/admin/context/index.mjs +26 -26
- package/dist/astro/routes/api/admin/context/stale.mjs +25 -25
- package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +24 -24
- package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +26 -26
- package/dist/astro/routes/api/admin/hitl-requests/index.mjs +26 -26
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +23 -23
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +43 -43
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +43 -43
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +37 -37
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +43 -43
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +43 -43
- package/dist/astro/routes/api/admin/plugins/index.mjs +37 -37
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +37 -37
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +43 -43
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +37 -37
- package/dist/astro/routes/api/admin/plugins/updates.mjs +37 -37
- package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +4 -4
- package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +25 -25
- package/dist/astro/routes/api/admin/review-requests/index.mjs +7 -7
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +37 -37
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +37 -37
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
- package/dist/astro/routes/api/admin/users/index.mjs +3 -3
- package/dist/astro/routes/api/auth/dev-bypass.mjs +1 -1
- package/dist/astro/routes/api/auth/invite/complete.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/index.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/register-options.mjs +5 -5
- package/dist/astro/routes/api/auth/magic-link/send.mjs +5 -5
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +5 -5
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +5 -5
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/verify.mjs +6 -6
- package/dist/astro/routes/api/auth/setup-token/index.mjs +4 -4
- package/dist/astro/routes/api/auth/signup/complete.mjs +6 -6
- package/dist/astro/routes/api/auth/signup/request.mjs +5 -5
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +7 -6
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +13 -11
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -10
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +7 -6
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/authors.d.mts +7 -0
- package/dist/astro/routes/api/content/_collection_/authors.mjs +16 -0
- package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/trash.mjs +3 -3
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/health.mjs +1 -1
- package/dist/astro/routes/api/import/probe.d.mts +2 -2
- package/dist/astro/routes/api/import/probe.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.mjs +28 -28
- package/dist/astro/routes/api/import/wordpress/media.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +29 -29
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +27 -27
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +8 -8
- package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +29 -29
- package/dist/astro/routes/api/manifest.mjs +1 -1
- package/dist/astro/routes/api/mcp.mjs +49 -49
- package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
- package/dist/astro/routes/api/media/_id_.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.mjs +8 -8
- package/dist/astro/routes/api/media.mjs +9 -9
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +26 -26
- package/dist/astro/routes/api/menus/_name_/items.mjs +26 -26
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +26 -26
- package/dist/astro/routes/api/menus/_name_/translations.mjs +26 -26
- package/dist/astro/routes/api/menus/_name_.mjs +26 -26
- package/dist/astro/routes/api/menus/index.mjs +26 -26
- package/dist/astro/routes/api/oauth/authorize.mjs +2 -2
- package/dist/astro/routes/api/oauth/device/authorize.mjs +1 -1
- package/dist/astro/routes/api/oauth/device/code.mjs +2 -2
- package/dist/astro/routes/api/oauth/device/token.mjs +1 -1
- package/dist/astro/routes/api/oauth/token/refresh.mjs +1 -1
- package/dist/astro/routes/api/oauth/token/revoke.mjs +1 -1
- package/dist/astro/routes/api/oauth/token.mjs +2 -2
- package/dist/astro/routes/api/openapi.json.mjs +16 -2
- package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
- package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
- package/dist/astro/routes/api/redirects/_id_.mjs +27 -27
- package/dist/astro/routes/api/redirects/index.mjs +27 -27
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +38 -38
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +38 -38
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +38 -38
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +38 -38
- package/dist/astro/routes/api/schema/collections/index.mjs +38 -38
- package/dist/astro/routes/api/schema/index.mjs +3 -3
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +37 -37
- package/dist/astro/routes/api/schema/orphans/index.mjs +37 -37
- package/dist/astro/routes/api/search/enable.mjs +8 -8
- package/dist/astro/routes/api/search/index.mjs +8 -8
- package/dist/astro/routes/api/search/rebuild.mjs +8 -8
- package/dist/astro/routes/api/search/stats.mjs +5 -5
- package/dist/astro/routes/api/search/suggest.mjs +8 -8
- package/dist/astro/routes/api/sections/_slug_.mjs +26 -26
- package/dist/astro/routes/api/sections/index.mjs +26 -26
- package/dist/astro/routes/api/settings/email.mjs +1 -1
- package/dist/astro/routes/api/settings.mjs +26 -26
- package/dist/astro/routes/api/setup/admin-verify.mjs +7 -7
- package/dist/astro/routes/api/setup/admin.mjs +5 -5
- package/dist/astro/routes/api/setup/dev-bypass.mjs +19 -19
- package/dist/astro/routes/api/setup/dev-reset.mjs +1 -1
- package/dist/astro/routes/api/setup/index.mjs +22 -22
- package/dist/astro/routes/api/setup/status.mjs +1 -1
- package/dist/astro/routes/api/snapshot.mjs +4 -4
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +28 -28
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +28 -28
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +28 -28
- package/dist/astro/routes/api/taxonomies/index.mjs +28 -28
- package/dist/astro/routes/api/themes/preview.mjs +4 -4
- package/dist/astro/routes/api/typegen.mjs +3 -3
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +25 -25
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +26 -26
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +26 -26
- package/dist/astro/routes/api/widget-areas/_name_.mjs +24 -24
- package/dist/astro/routes/api/widget-areas/index.mjs +26 -26
- package/dist/astro/routes/robots.txt.mjs +47 -24
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +8 -8
- package/dist/astro/routes/sitemap.xml.mjs +8 -8
- package/dist/astro/session-driver.d.mts +1 -1
- package/dist/astro/session-driver.mjs +3 -3
- package/dist/astro/types.d.mts +15 -8
- package/dist/{audit-DuRbTm8L.mjs → audit-BeNsSyfU.mjs} +1 -1
- package/dist/{briefing-BFEWeJtR.mjs → briefing-CkTee1ex.mjs} +7 -7
- package/dist/{briefing-C4fJSVYW.mjs → briefing-DJX6irto.mjs} +1 -1
- package/dist/{byline-CXQcMsBu.mjs → byline-BVC1lV6G.mjs} +5 -5
- package/dist/{byline-fields-Dc7L6Yry.mjs → byline-fields-Cj39WhXC.mjs} +1 -1
- package/dist/{byline-fields-D7TJ_oHF.mjs → byline-fields-cNrLJVRs.mjs} +3 -3
- package/dist/{byline-fields-Cuo-JI3B.d.mts → byline-fields-uJlygdzM.d.mts} +34 -10
- package/dist/{byline-registry-CL8BxPPp.mjs → byline-registry-4v6tXMNX.mjs} +2 -2
- package/dist/{bylines-BgriNlW7.mjs → bylines-DwokOFj6.mjs} +38 -4
- package/dist/{bylines-D2vqm1aZ.mjs → bylines-LN9XISRo.mjs} +2 -2
- package/dist/{cache-GRK71jOU.mjs → cache-Bac05gBd.mjs} +2 -2
- package/dist/{chunks-DgEw12Bc.mjs → chunks-CuUt7K50.mjs} +1 -1
- package/dist/cli/index.mjs +709 -589
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/{comment-ogMaF1gk.mjs → comment-Beue8-15.mjs} +1 -1
- package/dist/{comments-CTSOKrZq.mjs → comments-DcjFIfqX.mjs} +1 -1
- package/dist/{content-BfyjOiMi.mjs → content-CBxYGWfL.mjs} +104 -41
- package/dist/{context-ZMHhwzkG.mjs → context-CQVNZaR8.mjs} +7 -7
- package/dist/{context-CdsYb1m8.mjs → context-Df1xVYyr.mjs} +2 -2
- package/dist/{context-route-helpers-YLWx2N1j.mjs → context-route-helpers-B9wj8Rmh.mjs} +1 -1
- package/dist/{dashboard-D0gWuzNp.mjs → dashboard-B7ZUNuyF.mjs} +4 -4
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +1 -1
- package/dist/{default-BHauvIdG.mjs → default-B6iaLvP7.mjs} +4 -2
- package/dist/{device-flow-B3_FEoMI.mjs → device-flow-BZVGftqi.mjs} +1 -1
- package/dist/{fts-manager-EHY2Kes9.mjs → fts-manager-B5l_qwrA.mjs} +1 -1
- package/dist/{hitl-requests-B1Zqgut6.mjs → hitl-requests-7NlzVeUA.mjs} +1 -1
- package/dist/{hitl-route-helpers-CjpWUMuw.mjs → hitl-route-helpers-k---_H3-.mjs} +2 -2
- package/dist/{import-CvHY6sf5.mjs → import-4YBXbDkI.mjs} +2 -2
- package/dist/{index-DJVaYiUV.d.mts → index-CZiWCQDp.d.mts} +1 -1
- package/dist/index.d.mts +10 -10
- package/dist/index.mjs +59 -59
- package/dist/{jsonld-AcPnCEGD.d.mts → jsonld-DZ67souc.d.mts} +1 -1
- package/dist/{load-BdbvtoDb.mjs → load-D9OiGr2m.mjs} +1 -1
- package/dist/{loader-Y0QvC_QO.mjs → loader--GOYux8M.mjs} +138 -36
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/media/local-runtime.mjs +3 -3
- package/dist/{media-DhBwiCYR.mjs → media-CbKyYukG.mjs} +1 -1
- package/dist/{media-allowlist-BsXkT9RK.mjs → media-allowlist-BYxJIcTO.mjs} +1 -1
- package/dist/{menus-BzGQpw9d.mjs → menus-BZbXf-ej.mjs} +2 -2
- package/dist/{menus-fqqzXyHd.mjs → menus-C7F0sCrC.mjs} +13 -8
- package/dist/{normalize-O-hi3a27.mjs → normalize-ByemhhfW.mjs} +1 -1
- package/dist/{oauth-authorization-DsF81vki.mjs → oauth-authorization-DF-LCsIA.mjs} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/plugin-utils.d.mts +7 -7
- package/dist/plugins/adapt-sandbox-entry.d.mts +7 -7
- package/dist/{plugins-BQ5Joz6v.mjs → plugins-DzfqRREq.mjs} +195 -5
- package/dist/{preview-D5rvDhRt.mjs → preview-C-3YTX2U.mjs} +1 -1
- package/dist/public-url-B4xV4rGa.d.mts +19 -0
- package/dist/{public-url-DLUM5OOv.mjs → public-url-B_m9IwdV.mjs} +24 -18
- package/dist/{query-BJuUydtD.mjs → query-CZ3TH_Uu.mjs} +3 -3
- package/dist/{query-CSx0EdSW.mjs → query-Ds0EnMFX.mjs} +29 -18
- package/dist/{redirect-BqFMj67n.mjs → redirect-CEACczxo.mjs} +2 -2
- package/dist/{redirects-CJwHl_YG.mjs → redirects-DYj1yPxs.mjs} +4 -4
- package/dist/{redirects-q_cToaHv.mjs → redirects-ocRJmQHP.mjs} +23 -3
- package/dist/{registry-Cq3QRBW2.mjs → registry-D7HACema.mjs} +38 -6
- package/dist/{review-requests-tPw8_pAO.mjs → review-requests-BW2NxY-l.mjs} +1 -1
- package/dist/{review-requests-GYqjl2jO.mjs → review-requests-Qum4713s.mjs} +1 -1
- package/dist/{runner-Cnz4dl0f.d.mts → runner-09sTqtv0.d.mts} +1 -1
- package/dist/{runner-DTfG5v0G.mjs → runner-DzIpHGND.mjs} +328 -193
- package/dist/{runtime-Cd-kjPfN.d.mts → runtime-C4-2lSFg.d.mts} +261 -128
- package/dist/runtime.d.mts +8 -8
- package/dist/runtime.mjs +3 -3
- package/dist/schema-Bsi-VpYv.mjs +8 -0
- package/dist/{search-BAiFLz81.mjs → search-Gdrqj582.mjs} +3 -3
- package/dist/{secrets-CPoFLJjm.mjs → secrets-CeGpBFV2.mjs} +2 -2
- package/dist/{sections-DsuIrFDC.mjs → sections-BOjU13Y-.mjs} +2 -2
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +18 -18
- package/dist/seo/index.d.mts +1 -1
- package/dist/{seo-uMFBaR8G.mjs → seo-CLj8lS7Q.mjs} +1 -1
- package/dist/{service-CifrxCru.mjs → service-jGlhrICs.mjs} +1 -1
- package/dist/{settings-DNRQuX3d.mjs → settings-CUXOxzsT.mjs} +4 -4
- package/dist/{settings-BYGdocdj.mjs → settings-DlBsT2VS.mjs} +2 -2
- package/dist/{setup-complete-4EiBS1E5.mjs → setup-complete-BRrdPYjZ.mjs} +1 -1
- package/dist/{site-activity-6x1JccoR.mjs → site-activity-DONFrMBJ.mjs} +1 -1
- package/dist/{site-context-c1ZFa_OF.mjs → site-context-C8Az_P_I.mjs} +13 -13
- package/dist/{site-url-C-cu8Ff2.mjs → site-url-DIMD68go.mjs} +1 -1
- package/dist/{taxonomies-faQVeMgj.mjs → taxonomies-CZ-_DitR.mjs} +9 -7
- package/dist/{taxonomies-CQFmkP5u.mjs → taxonomies-D9Sw4wWM.mjs} +3 -3
- package/dist/{taxonomy-BnH-6VsX.mjs → taxonomy-B169Nm6B.mjs} +2 -2
- package/dist/{tokens-CjSgb0AC.mjs → tokens-SLmgowfd.mjs} +1 -1
- package/dist/{types-Ck7-WoUD.mjs → types-CSgR9nQB.mjs} +10 -3
- package/dist/{types-DYKtk8f1.d.mts → types-CuJOqHfM.d.mts} +128 -0
- package/dist/{types-DEAQG87T.d.mts → types-CwawBUTa.d.mts} +1 -1
- package/dist/{types-B7_vSiPD.d.mts → types-DRIKLmJI.d.mts} +14 -2
- package/dist/{types-UGmU5sWx.d.mts → types-DSPGWjxO.d.mts} +1 -1
- package/dist/ui/server-runtime.d.mts +58 -10
- package/dist/ui/server-runtime.mjs +98 -16
- package/dist/{user-CqZwN21P.mjs → user-DTLoZs16.mjs} +15 -1
- package/dist/{utils-wv-zvC-Y.mjs → utils-B8hBJ9Oz.mjs} +1 -1
- package/dist/{validate-CK4a1sIF.mjs → validate-DWmPO6oj.mjs} +5 -2
- package/dist/{validate-BJuG-ISL.d.mts → validate-DzjCdy6v.d.mts} +10 -2
- package/dist/version-C4gfn0PJ.mjs +6 -0
- package/dist/{widgets-CdDvF4fV.mjs → widgets-BpJ8EpPd.mjs} +1 -1
- package/dist/{wordpress-slugs-B6Gw9q3Q.mjs → wordpress-slugs-DHNR9LpG.mjs} +1 -1
- package/dist/{zod-generator-D1ROBNuC.mjs → zod-generator-K91-g665.mjs} +3 -2
- package/package.json +6 -5
- package/src/components/DinewayImage.astro +23 -5
- package/src/components/Image.astro +19 -3
- package/dist/schema-DmHMWnSA.mjs +0 -8
- package/dist/version-Cb1tZ6s_.mjs +0 -6
- /package/dist/{base64-C1Q9yr0B.mjs → base64-F8-DUraK.mjs} +0 -0
- /package/dist/{context-types-DQh_XKkn.mjs → context-types-r8oFvyOq.mjs} +0 -0
- /package/dist/{entity-aliases-uOrKvlPg.mjs → entity-aliases-4y93Yjuc.mjs} +0 -0
- /package/dist/{mime-8pAB8-77.mjs → mime-CbKsKDCB.mjs} +0 -0
- /package/dist/{options-BF11H_FD.mjs → options-LsPjZlqD.mjs} +0 -0
- /package/dist/{patterns-D9iDO3j8.mjs → patterns-DKAX6oqN.mjs} +0 -0
- /package/dist/{placeholder-BDo81Is5.mjs → placeholder-d54Qr_7n.mjs} +0 -0
- /package/dist/{provider-loader-B5PMjpN7.d.mts → provider-loader-9it4vd6L.d.mts} +0 -0
- /package/dist/{request-cache-w5cj5itT.mjs → request-cache-ho99schz.mjs} +0 -0
- /package/dist/{slugify-BzGxlOFx.mjs → slugify-BqebcqBg.mjs} +0 -0
- /package/dist/{transaction-D0FOsb3X.mjs → transaction-CFLhEOuH.mjs} +0 -0
- /package/dist/{transport-DidKKxvW.d.mts → transport-BnsNxh2l.d.mts} +0 -0
- /package/dist/{types-DbZhHtqS.mjs → types-CJ8DkL0q.mjs} +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as __exportAll, i as runMigrations, n as getMigrationStatus, t as getMigrationFingerprint } from "../runner-
|
|
2
|
+
import { a as __exportAll, i as runMigrations, n as getMigrationStatus, t as getMigrationFingerprint } from "../runner-DzIpHGND.mjs";
|
|
3
3
|
import { t as createDatabase } from "../connection-CiJWiWya.mjs";
|
|
4
4
|
import { t as validateIdentifier } from "../validate-VPnKoIzW.mjs";
|
|
5
5
|
import { l as listTablesLike } from "../dialect-helpers-fk43GbDb.mjs";
|
|
6
|
-
import { r as isI18nEnabled } from "../config-CVssduLe.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
import "../
|
|
11
|
-
import { t as
|
|
12
|
-
import { t as
|
|
13
|
-
import { t as
|
|
14
|
-
import "../
|
|
15
|
-
import "../
|
|
16
|
-
import "../
|
|
17
|
-
import
|
|
18
|
-
import "../
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import "../settings-
|
|
22
|
-
import { n as VERSION } from "../version-
|
|
6
|
+
import { n as getI18nConfig, r as isI18nEnabled } from "../config-CVssduLe.mjs";
|
|
7
|
+
import { i as encodeBase64url } from "../base64-F8-DUraK.mjs";
|
|
8
|
+
import "../types-CSgR9nQB.mjs";
|
|
9
|
+
import { a as isMissingTableError } from "../loader--GOYux8M.mjs";
|
|
10
|
+
import { n as slugify } from "../slugify-BqebcqBg.mjs";
|
|
11
|
+
import { t as ContentRepository } from "../content-CBxYGWfL.mjs";
|
|
12
|
+
import { t as MediaRepository } from "../media-CbKyYukG.mjs";
|
|
13
|
+
import { t as TaxonomyRepository } from "../taxonomy-B169Nm6B.mjs";
|
|
14
|
+
import { t as OptionsRepository } from "../options-LsPjZlqD.mjs";
|
|
15
|
+
import "../redirect-CEACczxo.mjs";
|
|
16
|
+
import "../request-cache-ho99schz.mjs";
|
|
17
|
+
import "../byline-registry-4v6tXMNX.mjs";
|
|
18
|
+
import { t as BylineRepository } from "../byline-BVC1lV6G.mjs";
|
|
19
|
+
import "../fts-manager-B5l_qwrA.mjs";
|
|
20
|
+
import { n as SchemaRegistry } from "../registry-D7HACema.mjs";
|
|
21
|
+
import "../settings-CUXOxzsT.mjs";
|
|
22
|
+
import { n as VERSION } from "../version-C4gfn0PJ.mjs";
|
|
23
23
|
import { i as pluginManifestSchema } from "../manifest-schema-qh2P7RDX.mjs";
|
|
24
24
|
import "../ssrf-DiKqWd3N.mjs";
|
|
25
|
-
import { t as validateSeed } from "../validate-
|
|
26
|
-
import { t as applySeed } from "../apply-
|
|
27
|
-
import { n as fingerprintKey, r as generateEncryptionKey, t as DinewaySecretsError } from "../secrets-
|
|
25
|
+
import { t as validateSeed } from "../validate-DWmPO6oj.mjs";
|
|
26
|
+
import { t as applySeed } from "../apply-D_RlTYtC.mjs";
|
|
27
|
+
import { n as fingerprintKey, r as generateEncryptionKey, t as DinewaySecretsError } from "../secrets-CeGpBFV2.mjs";
|
|
28
28
|
import { createHeaderAwareFetch, customHeadersInterceptor, isRedirectResponse, resolveCustomHeaders } from "../client/external-auth-headers.mjs";
|
|
29
29
|
import { o as convertDataForRead } from "../transport-LSdZVXHF.mjs";
|
|
30
30
|
import { DinewayClient } from "../client/index.mjs";
|
|
31
31
|
import { LocalStorage } from "../storage/local.mjs";
|
|
32
|
-
import { createHash } from "node:crypto";
|
|
32
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
33
33
|
import { sql } from "kysely";
|
|
34
34
|
import { imageSize } from "image-size";
|
|
35
35
|
import { createGzipDecoder, unpackTar } from "modern-tar";
|
|
@@ -37,15 +37,474 @@ import { createReadStream, createWriteStream, existsSync, mkdirSync, readFileSyn
|
|
|
37
37
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
38
38
|
import { pathToFileURL } from "node:url";
|
|
39
39
|
import { defineCommand, runCommand, runMain } from "citty";
|
|
40
|
+
import { createInterface } from "node:readline/promises";
|
|
40
41
|
import consola, { consola as consola$1 } from "consola";
|
|
41
42
|
import pc from "picocolors";
|
|
42
|
-
import {
|
|
43
|
+
import { ForgewayClient } from "@forgeway/sdk";
|
|
43
44
|
import { access, chmod, copyFile, mkdir, readFile, readdir, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
44
|
-
import {
|
|
45
|
+
import { homedir } from "node:os";
|
|
45
46
|
import { spawn } from "node:child_process";
|
|
46
47
|
import { pipeline } from "node:stream/promises";
|
|
47
48
|
import { packTar } from "modern-tar/fs";
|
|
48
49
|
|
|
50
|
+
//#region src/cli/commands/deploy/utils/forgeway-secrets.ts
|
|
51
|
+
const DINEWAY_USER_CONFIG_DIR_NAME = "dineway";
|
|
52
|
+
const TRAILING_SLASH_PATTERN$3 = /\/$/;
|
|
53
|
+
function getDinewayUserConfigDir() {
|
|
54
|
+
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), DINEWAY_USER_CONFIG_DIR_NAME);
|
|
55
|
+
}
|
|
56
|
+
function getForgewayAccountSecretPath() {
|
|
57
|
+
return join(getDinewayUserConfigDir(), "forgeway.json");
|
|
58
|
+
}
|
|
59
|
+
function normalizePlatformApiUrl$1(platformApiUrl) {
|
|
60
|
+
return platformApiUrl.replace(TRAILING_SLASH_PATTERN$3, "");
|
|
61
|
+
}
|
|
62
|
+
function normalizeEmail$2(email) {
|
|
63
|
+
return email.trim().toLowerCase();
|
|
64
|
+
}
|
|
65
|
+
function accountKey(platformApiUrl, email) {
|
|
66
|
+
return `${normalizePlatformApiUrl$1(platformApiUrl)}#${normalizeEmail$2(email)}`;
|
|
67
|
+
}
|
|
68
|
+
function normalizeLookup(lookup) {
|
|
69
|
+
if (typeof lookup === "string") return { cwd: lookup };
|
|
70
|
+
return lookup ?? {};
|
|
71
|
+
}
|
|
72
|
+
async function readAccountStore() {
|
|
73
|
+
try {
|
|
74
|
+
const raw = await readFile(getForgewayAccountSecretPath(), "utf-8");
|
|
75
|
+
return JSON.parse(raw);
|
|
76
|
+
} catch {
|
|
77
|
+
return { version: 1 };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function writeAccountStore(store) {
|
|
81
|
+
await mkdir(getDinewayUserConfigDir(), {
|
|
82
|
+
recursive: true,
|
|
83
|
+
mode: 448
|
|
84
|
+
});
|
|
85
|
+
const file = getForgewayAccountSecretPath();
|
|
86
|
+
await writeFile(file, JSON.stringify({
|
|
87
|
+
...store,
|
|
88
|
+
version: 1
|
|
89
|
+
}, null, " ") + "\n", {
|
|
90
|
+
encoding: "utf-8",
|
|
91
|
+
mode: 384
|
|
92
|
+
});
|
|
93
|
+
await chmod(file, 384);
|
|
94
|
+
}
|
|
95
|
+
function accountMatches(credentials, lookup) {
|
|
96
|
+
if (lookup.platformApiUrl && normalizePlatformApiUrl$1(credentials.platformApiUrl) !== normalizePlatformApiUrl$1(lookup.platformApiUrl)) return false;
|
|
97
|
+
if (lookup.email && normalizeEmail$2(credentials.user?.email ?? "") !== normalizeEmail$2(lookup.email)) return false;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
async function readForgewayCredentials(lookup) {
|
|
101
|
+
const normalizedLookup = normalizeLookup(lookup);
|
|
102
|
+
const store = await readAccountStore();
|
|
103
|
+
const accounts = Object.values(store.accounts ?? {}).filter((credentials) => accountMatches(credentials, normalizedLookup));
|
|
104
|
+
if (normalizedLookup.platformApiUrl && normalizedLookup.email) return store.accounts?.[accountKey(normalizedLookup.platformApiUrl, normalizedLookup.email)] ?? null;
|
|
105
|
+
if (accounts.length === 1) return accounts[0] ?? null;
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
async function writeForgewayCredentials(credentials, lookup) {
|
|
109
|
+
const normalizedLookup = normalizeLookup(lookup);
|
|
110
|
+
const platformApiUrl = normalizePlatformApiUrl$1(normalizedLookup.platformApiUrl ?? credentials.platformApiUrl);
|
|
111
|
+
const email = normalizeEmail$2(normalizedLookup.email ?? credentials.user?.email ?? "");
|
|
112
|
+
if (!email) throw new Error("Forgeway credentials require a user email before they can be stored.");
|
|
113
|
+
const key = accountKey(platformApiUrl, email);
|
|
114
|
+
const store = await readAccountStore();
|
|
115
|
+
store.accounts = {
|
|
116
|
+
...store.accounts,
|
|
117
|
+
[key]: {
|
|
118
|
+
...credentials,
|
|
119
|
+
platformApiUrl
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
store.lastAccountKey = key;
|
|
123
|
+
await writeAccountStore(store);
|
|
124
|
+
}
|
|
125
|
+
async function listForgewayCredentials(platformApiUrl) {
|
|
126
|
+
const lookup = platformApiUrl ? { platformApiUrl } : {};
|
|
127
|
+
const store = await readAccountStore();
|
|
128
|
+
return Object.values(store.accounts ?? {}).filter((credentials) => accountMatches(credentials, lookup));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/cli/forgeway-account.ts
|
|
133
|
+
const TRAILING_SLASH_PATTERN$2 = /\/$/;
|
|
134
|
+
const SHADOW_EMAIL_PATTERN$2 = /^shadow_[a-f0-9]{16}@dineway\.ai$/i;
|
|
135
|
+
const DEFAULT_FORGEWAY_API_BASE_URL = "https://api.dineway.ai";
|
|
136
|
+
const DEFAULT_DINEWAY_WEB_URL = "https://dineway.ai";
|
|
137
|
+
function normalizeForgewayApiUrl(value) {
|
|
138
|
+
return (value || DEFAULT_FORGEWAY_API_BASE_URL).replace(TRAILING_SLASH_PATTERN$2, "");
|
|
139
|
+
}
|
|
140
|
+
function normalizeDinewayWebUrl(value) {
|
|
141
|
+
return (value || DEFAULT_DINEWAY_WEB_URL).replace(TRAILING_SLASH_PATTERN$2, "");
|
|
142
|
+
}
|
|
143
|
+
function normalizeForgewayEmail(value) {
|
|
144
|
+
return value?.trim().toLowerCase() ?? "";
|
|
145
|
+
}
|
|
146
|
+
function isShadowForgewayEmail(email) {
|
|
147
|
+
return Boolean(email && SHADOW_EMAIL_PATTERN$2.test(email));
|
|
148
|
+
}
|
|
149
|
+
function createForgewayAccountClient(platformApiUrl, accessToken) {
|
|
150
|
+
return new ForgewayClient({
|
|
151
|
+
baseUrl: normalizeForgewayApiUrl(platformApiUrl),
|
|
152
|
+
accessToken,
|
|
153
|
+
isServerMode: true,
|
|
154
|
+
auth: { detectOAuthCallback: false }
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function normalizeForgewayUser$2(user) {
|
|
158
|
+
if (!user?.id || !user.email) throw new Error("Forgeway session response did not include a user email.");
|
|
159
|
+
return {
|
|
160
|
+
id: user.id,
|
|
161
|
+
name: user.profile?.name ?? user.name ?? user.email,
|
|
162
|
+
email: user.email,
|
|
163
|
+
avatarUrl: user.profile?.avatar_url ?? user.avatarUrl ?? user.avatar_url ?? null,
|
|
164
|
+
emailVerified: user.emailVerified ?? user.email_verified ?? false
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function assertFormalForgewayUser(user) {
|
|
168
|
+
if (!user || user.emailVerified !== true || isShadowForgewayEmail(user.email)) throw new Error("Dineway account commands require a verified Forgeway account.");
|
|
169
|
+
return user;
|
|
170
|
+
}
|
|
171
|
+
async function readStoredForgewayAccount(lookup = {}) {
|
|
172
|
+
const platformApiUrl = normalizeForgewayApiUrl(lookup.platformApiUrl);
|
|
173
|
+
const email = normalizeForgewayEmail(lookup.email);
|
|
174
|
+
if (email) return readForgewayCredentials({
|
|
175
|
+
platformApiUrl,
|
|
176
|
+
email
|
|
177
|
+
});
|
|
178
|
+
const stored = await readForgewayCredentials({ platformApiUrl });
|
|
179
|
+
if (stored) return stored;
|
|
180
|
+
const accounts = (await listForgewayCredentials(platformApiUrl)).filter((credentials) => {
|
|
181
|
+
try {
|
|
182
|
+
assertFormalForgewayUser(credentials.user);
|
|
183
|
+
return true;
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
return accounts.length === 1 ? accounts[0] ?? null : null;
|
|
189
|
+
}
|
|
190
|
+
async function refreshForgewayAccountCredentials(credentials) {
|
|
191
|
+
const user = assertFormalForgewayUser(credentials.user);
|
|
192
|
+
if (!credentials.refreshToken) throw new Error("Stored Forgeway account is missing a refresh token. Run `dineway account login`.");
|
|
193
|
+
const { data, error } = await createForgewayAccountClient(credentials.platformApiUrl).auth.refreshSession({ refreshToken: credentials.refreshToken });
|
|
194
|
+
if (error || !data?.accessToken) throw new Error(error?.message || "Failed to refresh Forgeway account. Run `dineway account login`.");
|
|
195
|
+
const refreshedUser = normalizeForgewayUser$2(data.user);
|
|
196
|
+
if (normalizeForgewayEmail(refreshedUser.email) !== normalizeForgewayEmail(user.email)) throw new Error("Forgeway refresh returned credentials for a different account.");
|
|
197
|
+
const updated = {
|
|
198
|
+
...credentials,
|
|
199
|
+
platformApiUrl: normalizeForgewayApiUrl(credentials.platformApiUrl),
|
|
200
|
+
accessToken: data.accessToken,
|
|
201
|
+
refreshToken: data.refreshToken ?? credentials.refreshToken,
|
|
202
|
+
user: {
|
|
203
|
+
...refreshedUser,
|
|
204
|
+
emailVerified: true
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
await writeForgewayCredentials(updated, {
|
|
208
|
+
platformApiUrl: updated.platformApiUrl,
|
|
209
|
+
email: updated.user?.email
|
|
210
|
+
});
|
|
211
|
+
return updated;
|
|
212
|
+
}
|
|
213
|
+
async function sendForgewayAccountLoginLink(input) {
|
|
214
|
+
const platformApiUrl = normalizeForgewayApiUrl(input.platformApiUrl);
|
|
215
|
+
const webUrl = normalizeDinewayWebUrl(input.webUrl);
|
|
216
|
+
const redirectTo = new URL("/cli-auth", webUrl).toString();
|
|
217
|
+
const { error } = await createForgewayAccountClient(platformApiUrl).auth.sendPasswordlessSignInEmail({
|
|
218
|
+
email: input.email,
|
|
219
|
+
redirectTo
|
|
220
|
+
});
|
|
221
|
+
if (error) throw new Error(error.message || "Failed to send Forgeway account sign-in link.");
|
|
222
|
+
}
|
|
223
|
+
async function completeForgewayAccountLogin(input) {
|
|
224
|
+
const platformApiUrl = normalizeForgewayApiUrl(input.platformApiUrl);
|
|
225
|
+
const { data, error } = await createForgewayAccountClient(platformApiUrl).auth.signInWithPasswordlessToken({ token: input.token });
|
|
226
|
+
if (error || !data?.accessToken || !data.refreshToken) throw new Error(error?.message || "Forgeway sign-in token is invalid or expired.");
|
|
227
|
+
const user = normalizeForgewayUser$2(data.user);
|
|
228
|
+
if (input.email && normalizeForgewayEmail(user.email) !== normalizeForgewayEmail(input.email)) throw new Error("Forgeway sign-in returned credentials for a different email.");
|
|
229
|
+
const credentials = {
|
|
230
|
+
platformApiUrl,
|
|
231
|
+
accessToken: data.accessToken,
|
|
232
|
+
refreshToken: data.refreshToken,
|
|
233
|
+
user: {
|
|
234
|
+
...user,
|
|
235
|
+
emailVerified: true
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
await writeForgewayCredentials(credentials, {
|
|
239
|
+
platformApiUrl,
|
|
240
|
+
email: credentials.user?.email
|
|
241
|
+
});
|
|
242
|
+
return credentials;
|
|
243
|
+
}
|
|
244
|
+
async function getForgewayDinewayAccount(credentials) {
|
|
245
|
+
const refreshed = await refreshForgewayAccountCredentials(credentials);
|
|
246
|
+
const { data, error } = await createForgewayAccountClient(refreshed.platformApiUrl, refreshed.accessToken).dineway.getAccount();
|
|
247
|
+
if (error || !data) throw new Error(error?.message || "Failed to fetch Dineway account status from Forgeway.");
|
|
248
|
+
return {
|
|
249
|
+
credentials: refreshed,
|
|
250
|
+
account: data
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//#endregion
|
|
255
|
+
//#region src/cli/output.ts
|
|
256
|
+
/**
|
|
257
|
+
* Redirect consola output to stderr so it doesn't pollute JSON on stdout.
|
|
258
|
+
*
|
|
259
|
+
* Call this early in any command that uses `output()` with `--json`.
|
|
260
|
+
* Safe to call multiple times — only applies the redirect once.
|
|
261
|
+
*/
|
|
262
|
+
function configureOutputMode(args) {
|
|
263
|
+
if (args.json || !process.stdout.isTTY) {
|
|
264
|
+
consola$1.options.stdout = process.stderr;
|
|
265
|
+
consola$1.options.stderr = process.stderr;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Output data as JSON or pretty-printed.
|
|
270
|
+
*
|
|
271
|
+
* If stdout is not a TTY or --json is set, outputs JSON.
|
|
272
|
+
* Otherwise, outputs a formatted representation.
|
|
273
|
+
*/
|
|
274
|
+
function output(data, args) {
|
|
275
|
+
if (args.json || !process.stdout.isTTY) process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
276
|
+
else prettyPrint(data);
|
|
277
|
+
}
|
|
278
|
+
function prettyPrint(data, indent = 0) {
|
|
279
|
+
if (data === null || data === void 0) {
|
|
280
|
+
consola$1.log("(empty)");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (Array.isArray(data)) {
|
|
284
|
+
if (data.length === 0) {
|
|
285
|
+
consola$1.log("(no items)");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
for (const item of data) {
|
|
289
|
+
prettyPrint(item, indent);
|
|
290
|
+
if (indent === 0) consola$1.log("---");
|
|
291
|
+
}
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (typeof data === "object") {
|
|
295
|
+
const obj = Object(data);
|
|
296
|
+
if ("items" in obj && Array.isArray(obj.items)) {
|
|
297
|
+
prettyPrint(obj.items, indent);
|
|
298
|
+
if (typeof obj.nextCursor === "string") consola$1.log(`\nNext cursor: ${obj.nextCursor}`);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const prefix = " ".repeat(indent);
|
|
302
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
303
|
+
if (value === null || value === void 0) continue;
|
|
304
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
305
|
+
consola$1.log(`${prefix}${key}:`);
|
|
306
|
+
prettyPrint(value, indent + 1);
|
|
307
|
+
} else if (Array.isArray(value)) consola$1.log(`${prefix}${key}: [${value.length} items]`);
|
|
308
|
+
else {
|
|
309
|
+
const str = typeof value === "string" ? value : JSON.stringify(value);
|
|
310
|
+
const display = str.length > 80 ? str.slice(0, 77) + "..." : str;
|
|
311
|
+
consola$1.log(`${prefix}${key}: ${display}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
consola$1.log(typeof data === "string" ? data : JSON.stringify(data));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/cli/commands/account.ts
|
|
321
|
+
async function promptLine(question) {
|
|
322
|
+
const readline = createInterface({
|
|
323
|
+
input: process.stdin,
|
|
324
|
+
output: process.stdout
|
|
325
|
+
});
|
|
326
|
+
try {
|
|
327
|
+
return (await readline.question(question)).trim();
|
|
328
|
+
} finally {
|
|
329
|
+
readline.close();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
function resolveApiUrl(args) {
|
|
333
|
+
return normalizeForgewayApiUrl(args["api-url"] ?? process.env.DINEWAY_API_BASE_URL ?? process.env.FORGEWAY_API_URL);
|
|
334
|
+
}
|
|
335
|
+
function outputAccountJson(value) {
|
|
336
|
+
console.log(JSON.stringify(value, null, " "));
|
|
337
|
+
}
|
|
338
|
+
const accountLoginCommand = defineCommand({
|
|
339
|
+
meta: {
|
|
340
|
+
name: "login",
|
|
341
|
+
description: "Log in to the Dineway Web / Forgeway account used for paid services"
|
|
342
|
+
},
|
|
343
|
+
args: {
|
|
344
|
+
email: {
|
|
345
|
+
type: "string",
|
|
346
|
+
alias: "e",
|
|
347
|
+
description: "Forgeway account email"
|
|
348
|
+
},
|
|
349
|
+
token: {
|
|
350
|
+
type: "string",
|
|
351
|
+
description: "Passwordless sign-in token from the Dineway CLI auth page"
|
|
352
|
+
},
|
|
353
|
+
"api-url": {
|
|
354
|
+
type: "string",
|
|
355
|
+
description: "Forgeway API URL",
|
|
356
|
+
default: DEFAULT_FORGEWAY_API_BASE_URL
|
|
357
|
+
},
|
|
358
|
+
"web-url": {
|
|
359
|
+
type: "string",
|
|
360
|
+
description: "Dineway Web URL used for the email link",
|
|
361
|
+
default: DEFAULT_DINEWAY_WEB_URL
|
|
362
|
+
},
|
|
363
|
+
"send-link": {
|
|
364
|
+
type: "boolean",
|
|
365
|
+
description: "Send the email link and exit without prompting for the token"
|
|
366
|
+
},
|
|
367
|
+
json: {
|
|
368
|
+
type: "boolean",
|
|
369
|
+
description: "Output as JSON"
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
async run({ args }) {
|
|
373
|
+
configureOutputMode(args);
|
|
374
|
+
const platformApiUrl = resolveApiUrl(args);
|
|
375
|
+
const webUrl = normalizeDinewayWebUrl(args["web-url"]);
|
|
376
|
+
const email = normalizeForgewayEmail(args.email) || normalizeForgewayEmail(await promptLine("Dineway account email: "));
|
|
377
|
+
if (!email) {
|
|
378
|
+
consola$1.error("Email is required.");
|
|
379
|
+
process.exit(2);
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const existing = await readStoredForgewayAccount({
|
|
383
|
+
platformApiUrl,
|
|
384
|
+
email
|
|
385
|
+
});
|
|
386
|
+
if (existing && !args.token && !args["send-link"]) {
|
|
387
|
+
const { account } = await getForgewayDinewayAccount(existing);
|
|
388
|
+
if (args.json) outputAccountJson({
|
|
389
|
+
loggedIn: true,
|
|
390
|
+
platformApiUrl,
|
|
391
|
+
account
|
|
392
|
+
});
|
|
393
|
+
else {
|
|
394
|
+
consola$1.success(`Already logged in as ${pc.bold(account.account.email ?? email)}`);
|
|
395
|
+
consola$1.info(`Plan: ${pc.cyan(account.plan.name)}`);
|
|
396
|
+
}
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (!args.token) {
|
|
400
|
+
await sendForgewayAccountLoginLink({
|
|
401
|
+
email,
|
|
402
|
+
platformApiUrl,
|
|
403
|
+
webUrl
|
|
404
|
+
});
|
|
405
|
+
if (args.json) outputAccountJson({
|
|
406
|
+
sent: true,
|
|
407
|
+
email,
|
|
408
|
+
platformApiUrl,
|
|
409
|
+
cliAuthUrl: new URL("/cli-auth", webUrl).toString()
|
|
410
|
+
});
|
|
411
|
+
else {
|
|
412
|
+
consola$1.success(`Sent Dineway account sign-in link to ${pc.bold(email)}`);
|
|
413
|
+
consola$1.info("Open the email link, copy the CLI token, then paste it here.");
|
|
414
|
+
}
|
|
415
|
+
if (args["send-link"]) return;
|
|
416
|
+
}
|
|
417
|
+
const { account } = await getForgewayDinewayAccount(await completeForgewayAccountLogin({
|
|
418
|
+
token: typeof args.token === "string" && args.token.trim() ? args.token.trim() : await promptLine("CLI token: "),
|
|
419
|
+
platformApiUrl,
|
|
420
|
+
email
|
|
421
|
+
}));
|
|
422
|
+
if (args.json) outputAccountJson({
|
|
423
|
+
loggedIn: true,
|
|
424
|
+
platformApiUrl,
|
|
425
|
+
account
|
|
426
|
+
});
|
|
427
|
+
else {
|
|
428
|
+
consola$1.success(`Logged in as ${pc.bold(account.account.email ?? email)}`);
|
|
429
|
+
consola$1.info(`Plan: ${pc.cyan(account.plan.name)}`);
|
|
430
|
+
consola$1.info(`Credits: ${account.credits.availableCredits.toLocaleString()}`);
|
|
431
|
+
consola$1.info(`Hosted sites: ${account.sites.usedHostedSites.toLocaleString()} / ${account.sites.hostedSiteLimitLabel}`);
|
|
432
|
+
}
|
|
433
|
+
} catch (error) {
|
|
434
|
+
consola$1.error(error instanceof Error ? error.message : "Dineway account login failed");
|
|
435
|
+
process.exit(2);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
const accountStatusCommand = defineCommand({
|
|
440
|
+
meta: {
|
|
441
|
+
name: "status",
|
|
442
|
+
description: "Show Dineway Web / Forgeway account plan, credits, and hosted site slots"
|
|
443
|
+
},
|
|
444
|
+
args: {
|
|
445
|
+
email: {
|
|
446
|
+
type: "string",
|
|
447
|
+
alias: "e",
|
|
448
|
+
description: "Forgeway account email"
|
|
449
|
+
},
|
|
450
|
+
"api-url": {
|
|
451
|
+
type: "string",
|
|
452
|
+
description: "Forgeway API URL",
|
|
453
|
+
default: DEFAULT_FORGEWAY_API_BASE_URL
|
|
454
|
+
},
|
|
455
|
+
json: {
|
|
456
|
+
type: "boolean",
|
|
457
|
+
description: "Output as JSON"
|
|
458
|
+
}
|
|
459
|
+
},
|
|
460
|
+
async run({ args }) {
|
|
461
|
+
configureOutputMode(args);
|
|
462
|
+
const platformApiUrl = resolveApiUrl(args);
|
|
463
|
+
try {
|
|
464
|
+
const credentials = await readStoredForgewayAccount({
|
|
465
|
+
platformApiUrl,
|
|
466
|
+
email: normalizeForgewayEmail(args.email)
|
|
467
|
+
});
|
|
468
|
+
if (!credentials) {
|
|
469
|
+
if (args.json) outputAccountJson({
|
|
470
|
+
loggedIn: false,
|
|
471
|
+
platformApiUrl
|
|
472
|
+
});
|
|
473
|
+
else consola$1.error("Not logged in. Run: dineway account login");
|
|
474
|
+
process.exit(2);
|
|
475
|
+
}
|
|
476
|
+
const { account } = await getForgewayDinewayAccount(credentials);
|
|
477
|
+
if (args.json) {
|
|
478
|
+
outputAccountJson({
|
|
479
|
+
loggedIn: true,
|
|
480
|
+
platformApiUrl,
|
|
481
|
+
account
|
|
482
|
+
});
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
consola$1.info(`Email: ${pc.bold(account.account.email ?? credentials.user?.email ?? "unknown")}`);
|
|
486
|
+
consola$1.info(`Plan: ${pc.cyan(account.plan.name)}`);
|
|
487
|
+
consola$1.info(`Credits available: ${account.credits.availableCredits.toLocaleString()}`);
|
|
488
|
+
consola$1.info(`Hosted sites: ${account.sites.usedHostedSites.toLocaleString()} / ${account.sites.hostedSiteLimitLabel}`);
|
|
489
|
+
if (account.billing.subscription?.status) consola$1.info(`Billing: ${account.billing.subscription.status}`);
|
|
490
|
+
} catch (error) {
|
|
491
|
+
consola$1.error(error instanceof Error ? error.message : "Dineway account status failed");
|
|
492
|
+
process.exit(2);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
const accountCommand = defineCommand({
|
|
497
|
+
meta: {
|
|
498
|
+
name: "account",
|
|
499
|
+
description: "Dineway Web account login, status, and billing helpers"
|
|
500
|
+
},
|
|
501
|
+
subCommands: {
|
|
502
|
+
login: accountLoginCommand,
|
|
503
|
+
status: accountStatusCommand
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
//#endregion
|
|
49
508
|
//#region src/cli/credentials.ts
|
|
50
509
|
/**
|
|
51
510
|
* Credential storage for CLI auth tokens.
|
|
@@ -99,7 +558,7 @@ function findProjectRoot(from) {
|
|
|
99
558
|
}
|
|
100
559
|
return null;
|
|
101
560
|
}
|
|
102
|
-
function readStore
|
|
561
|
+
function readStore() {
|
|
103
562
|
const path = getCredentialPath();
|
|
104
563
|
try {
|
|
105
564
|
if (existsSync(path)) {
|
|
@@ -109,7 +568,7 @@ function readStore$1() {
|
|
|
109
568
|
} catch {}
|
|
110
569
|
return {};
|
|
111
570
|
}
|
|
112
|
-
function writeStore
|
|
571
|
+
function writeStore(store) {
|
|
113
572
|
mkdirSync(getConfigDir(), {
|
|
114
573
|
recursive: true,
|
|
115
574
|
mode: 448
|
|
@@ -124,7 +583,7 @@ function writeStore$1(store) {
|
|
|
124
583
|
*/
|
|
125
584
|
function getCredentials(baseUrl) {
|
|
126
585
|
const key = resolveCredentialKey(baseUrl);
|
|
127
|
-
const cred = readStore
|
|
586
|
+
const cred = readStore()[key];
|
|
128
587
|
if (!cred || !("accessToken" in cred)) return null;
|
|
129
588
|
return cred;
|
|
130
589
|
}
|
|
@@ -133,19 +592,19 @@ function getCredentials(baseUrl) {
|
|
|
133
592
|
*/
|
|
134
593
|
function saveCredentials(baseUrl, cred) {
|
|
135
594
|
const key = resolveCredentialKey(baseUrl);
|
|
136
|
-
const store = readStore
|
|
595
|
+
const store = readStore();
|
|
137
596
|
store[key] = cred;
|
|
138
|
-
writeStore
|
|
597
|
+
writeStore(store);
|
|
139
598
|
}
|
|
140
599
|
/**
|
|
141
600
|
* Remove credentials for a URL.
|
|
142
601
|
*/
|
|
143
602
|
function removeCredentials(baseUrl) {
|
|
144
603
|
const key = resolveCredentialKey(baseUrl);
|
|
145
|
-
const store = readStore
|
|
604
|
+
const store = readStore();
|
|
146
605
|
if (key in store) {
|
|
147
606
|
delete store[key];
|
|
148
|
-
writeStore
|
|
607
|
+
writeStore(store);
|
|
149
608
|
return true;
|
|
150
609
|
}
|
|
151
610
|
return false;
|
|
@@ -162,7 +621,7 @@ function marketplaceKey(registryUrl) {
|
|
|
162
621
|
*/
|
|
163
622
|
function getMarketplaceCredential(registryUrl) {
|
|
164
623
|
const key = marketplaceKey(registryUrl);
|
|
165
|
-
const cred = readStore
|
|
624
|
+
const cred = readStore()[key];
|
|
166
625
|
if (!cred || !("token" in cred)) return null;
|
|
167
626
|
if (new Date(cred.expiresAt) < /* @__PURE__ */ new Date()) return null;
|
|
168
627
|
return cred;
|
|
@@ -172,19 +631,19 @@ function getMarketplaceCredential(registryUrl) {
|
|
|
172
631
|
*/
|
|
173
632
|
function saveMarketplaceCredential(registryUrl, cred) {
|
|
174
633
|
const key = marketplaceKey(registryUrl);
|
|
175
|
-
const store = readStore
|
|
634
|
+
const store = readStore();
|
|
176
635
|
store[key] = cred;
|
|
177
|
-
writeStore
|
|
636
|
+
writeStore(store);
|
|
178
637
|
}
|
|
179
638
|
/**
|
|
180
639
|
* Remove marketplace credential for a registry URL.
|
|
181
640
|
*/
|
|
182
641
|
function removeMarketplaceCredential(registryUrl) {
|
|
183
642
|
const key = marketplaceKey(registryUrl);
|
|
184
|
-
const store = readStore
|
|
643
|
+
const store = readStore();
|
|
185
644
|
if (key in store) {
|
|
186
645
|
delete store[key];
|
|
187
|
-
writeStore
|
|
646
|
+
writeStore(store);
|
|
188
647
|
return true;
|
|
189
648
|
}
|
|
190
649
|
return false;
|
|
@@ -359,71 +818,6 @@ function createClientFromArgs(args) {
|
|
|
359
818
|
});
|
|
360
819
|
}
|
|
361
820
|
|
|
362
|
-
//#endregion
|
|
363
|
-
//#region src/cli/output.ts
|
|
364
|
-
/**
|
|
365
|
-
* Redirect consola output to stderr so it doesn't pollute JSON on stdout.
|
|
366
|
-
*
|
|
367
|
-
* Call this early in any command that uses `output()` with `--json`.
|
|
368
|
-
* Safe to call multiple times — only applies the redirect once.
|
|
369
|
-
*/
|
|
370
|
-
function configureOutputMode(args) {
|
|
371
|
-
if (args.json || !process.stdout.isTTY) {
|
|
372
|
-
consola$1.options.stdout = process.stderr;
|
|
373
|
-
consola$1.options.stderr = process.stderr;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
/**
|
|
377
|
-
* Output data as JSON or pretty-printed.
|
|
378
|
-
*
|
|
379
|
-
* If stdout is not a TTY or --json is set, outputs JSON.
|
|
380
|
-
* Otherwise, outputs a formatted representation.
|
|
381
|
-
*/
|
|
382
|
-
function output(data, args) {
|
|
383
|
-
if (args.json || !process.stdout.isTTY) process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
384
|
-
else prettyPrint(data);
|
|
385
|
-
}
|
|
386
|
-
function prettyPrint(data, indent = 0) {
|
|
387
|
-
if (data === null || data === void 0) {
|
|
388
|
-
consola$1.log("(empty)");
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
if (Array.isArray(data)) {
|
|
392
|
-
if (data.length === 0) {
|
|
393
|
-
consola$1.log("(no items)");
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
for (const item of data) {
|
|
397
|
-
prettyPrint(item, indent);
|
|
398
|
-
if (indent === 0) consola$1.log("---");
|
|
399
|
-
}
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
if (typeof data === "object") {
|
|
403
|
-
const obj = Object(data);
|
|
404
|
-
if ("items" in obj && Array.isArray(obj.items)) {
|
|
405
|
-
prettyPrint(obj.items, indent);
|
|
406
|
-
if (typeof obj.nextCursor === "string") consola$1.log(`\nNext cursor: ${obj.nextCursor}`);
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
const prefix = " ".repeat(indent);
|
|
410
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
411
|
-
if (value === null || value === void 0) continue;
|
|
412
|
-
if (typeof value === "object" && !Array.isArray(value)) {
|
|
413
|
-
consola$1.log(`${prefix}${key}:`);
|
|
414
|
-
prettyPrint(value, indent + 1);
|
|
415
|
-
} else if (Array.isArray(value)) consola$1.log(`${prefix}${key}: [${value.length} items]`);
|
|
416
|
-
else {
|
|
417
|
-
const str = typeof value === "string" ? value : JSON.stringify(value);
|
|
418
|
-
const display = str.length > 80 ? str.slice(0, 77) + "..." : str;
|
|
419
|
-
consola$1.log(`${prefix}${key}: ${display}`);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
consola$1.log(typeof data === "string" ? data : JSON.stringify(data));
|
|
425
|
-
}
|
|
426
|
-
|
|
427
821
|
//#endregion
|
|
428
822
|
//#region src/cli/commands/auth.ts
|
|
429
823
|
/**
|
|
@@ -950,7 +1344,157 @@ const contentCommand = defineCommand({
|
|
|
950
1344
|
restore: restoreCommand,
|
|
951
1345
|
translations: translationsCommand
|
|
952
1346
|
}
|
|
953
|
-
});
|
|
1347
|
+
});
|
|
1348
|
+
|
|
1349
|
+
//#endregion
|
|
1350
|
+
//#region src/cli/paywall.ts
|
|
1351
|
+
const PAYWALL_MESSAGE_PATTERN = /\b(quota|credit|credits|upgrade|plan|billing|subscription|slot)\b/i;
|
|
1352
|
+
function isRecord$1(value) {
|
|
1353
|
+
return typeof value === "object" && value !== null;
|
|
1354
|
+
}
|
|
1355
|
+
function stringField(record, key) {
|
|
1356
|
+
const value = record[key];
|
|
1357
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
1358
|
+
}
|
|
1359
|
+
function getNestedError(value) {
|
|
1360
|
+
if (!isRecord$1(value)) return null;
|
|
1361
|
+
const nested = value.error;
|
|
1362
|
+
return isRecord$1(nested) ? nested : value;
|
|
1363
|
+
}
|
|
1364
|
+
function isHostedSitesResource(resource) {
|
|
1365
|
+
const normalized = resource.toLowerCase();
|
|
1366
|
+
return normalized === "deploy:forgeway" || normalized === "dineway.hosted_sites" || normalized.includes("hosted_site");
|
|
1367
|
+
}
|
|
1368
|
+
function isCreditResource(resource) {
|
|
1369
|
+
const normalized = resource.toLowerCase();
|
|
1370
|
+
return normalized.includes("credit") || normalized.includes("firecrawl") || normalized.includes("dataforseo") || normalized.startsWith("/api/");
|
|
1371
|
+
}
|
|
1372
|
+
function getCliPaywallRefreshStatus(paywall, account) {
|
|
1373
|
+
if (isHostedSitesResource(paywall.resource)) {
|
|
1374
|
+
const remainingHostedSites = account.sites?.remainingHostedSites;
|
|
1375
|
+
if (remainingHostedSites === null || (remainingHostedSites ?? 0) > 0) return {
|
|
1376
|
+
blocked: false,
|
|
1377
|
+
message: "Hosted capacity is now available. Re-run the blocked command."
|
|
1378
|
+
};
|
|
1379
|
+
return {
|
|
1380
|
+
blocked: true,
|
|
1381
|
+
message: "There is still no hosted capacity. Complete checkout in Dineway Web."
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
if (isCreditResource(paywall.resource)) {
|
|
1385
|
+
if ((account.credits?.availableCredits ?? 0) > 0) return {
|
|
1386
|
+
blocked: false,
|
|
1387
|
+
message: "Provider credits are now available. Re-run the blocked command."
|
|
1388
|
+
};
|
|
1389
|
+
return {
|
|
1390
|
+
blocked: true,
|
|
1391
|
+
message: "There are still no provider credits. Complete checkout or top up credits in Dineway Web."
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
return {
|
|
1395
|
+
blocked: false,
|
|
1396
|
+
message: "Account status refreshed. Re-run the blocked command when ready."
|
|
1397
|
+
};
|
|
1398
|
+
}
|
|
1399
|
+
function normalizeCliPaywallError(input) {
|
|
1400
|
+
const error = input.error;
|
|
1401
|
+
const status = error?.status ?? error?.statusCode;
|
|
1402
|
+
const message = error?.message ?? (input.error instanceof Error ? input.error.message : "");
|
|
1403
|
+
const body = error?.body;
|
|
1404
|
+
const candidate = getNestedError(body) ?? getNestedError(input.error) ?? {};
|
|
1405
|
+
if (stringField(candidate, "code") && stringField(candidate, "resource") && stringField(candidate, "reason") && typeof candidate.handoffRequired === "boolean") return {
|
|
1406
|
+
code: stringField(candidate, "code") ?? "PAYWALL_REQUIRED",
|
|
1407
|
+
resource: stringField(candidate, "resource") ?? input.resource,
|
|
1408
|
+
reason: stringField(candidate, "reason") ?? input.reason ?? message,
|
|
1409
|
+
requiredPlan: stringField(candidate, "requiredPlan"),
|
|
1410
|
+
pricingUrl: stringField(candidate, "pricingUrl") ?? new URL("/pricing", normalizeDinewayWebUrl(input.webUrl)).toString(),
|
|
1411
|
+
handoffRequired: candidate.handoffRequired === true
|
|
1412
|
+
};
|
|
1413
|
+
if ((status === 402 || status === 403 || status === 429) && PAYWALL_MESSAGE_PATTERN.test(message)) return {
|
|
1414
|
+
code: status === 429 ? "QUOTA_EXCEEDED" : "PAYWALL_REQUIRED",
|
|
1415
|
+
resource: input.resource,
|
|
1416
|
+
reason: input.reason ?? message,
|
|
1417
|
+
pricingUrl: new URL("/pricing", normalizeDinewayWebUrl(input.webUrl)).toString(),
|
|
1418
|
+
handoffRequired: true
|
|
1419
|
+
};
|
|
1420
|
+
return null;
|
|
1421
|
+
}
|
|
1422
|
+
async function promptEnter(message) {
|
|
1423
|
+
const readline = createInterface({
|
|
1424
|
+
input: process.stdin,
|
|
1425
|
+
output: process.stdout
|
|
1426
|
+
});
|
|
1427
|
+
try {
|
|
1428
|
+
await readline.question(message);
|
|
1429
|
+
} finally {
|
|
1430
|
+
readline.close();
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
async function createHandoff(input) {
|
|
1434
|
+
const credentials = await readStoredForgewayAccount({ platformApiUrl: input.platformApiUrl });
|
|
1435
|
+
if (!credentials) return null;
|
|
1436
|
+
const { credentials: refreshed } = await getForgewayDinewayAccount(credentials);
|
|
1437
|
+
const response = await fetch(new URL("/api/dineway-web/handoffs", input.webUrl), {
|
|
1438
|
+
method: "POST",
|
|
1439
|
+
headers: {
|
|
1440
|
+
Authorization: `Bearer ${refreshed.accessToken}`,
|
|
1441
|
+
"Content-Type": "application/json",
|
|
1442
|
+
"X-Dineway-Request": "1"
|
|
1443
|
+
},
|
|
1444
|
+
body: JSON.stringify({
|
|
1445
|
+
target: "pricing",
|
|
1446
|
+
reason: input.paywall.reason,
|
|
1447
|
+
context: {
|
|
1448
|
+
resource: input.paywall.resource,
|
|
1449
|
+
code: input.paywall.code,
|
|
1450
|
+
requiredPlan: input.paywall.requiredPlan,
|
|
1451
|
+
...input.context
|
|
1452
|
+
}
|
|
1453
|
+
})
|
|
1454
|
+
});
|
|
1455
|
+
const payload = await response.json().catch(() => null);
|
|
1456
|
+
if (!response.ok || !payload?.success || !payload.data?.url) return null;
|
|
1457
|
+
return payload.data.url;
|
|
1458
|
+
}
|
|
1459
|
+
async function handleCliPaywall(input) {
|
|
1460
|
+
const paywall = normalizeCliPaywallError(input);
|
|
1461
|
+
if (!paywall) return false;
|
|
1462
|
+
const platformApiUrl = normalizeForgewayApiUrl(input.platformApiUrl);
|
|
1463
|
+
const webUrl = normalizeDinewayWebUrl(input.webUrl ?? process.env.DINEWAY_WEB_URL);
|
|
1464
|
+
let url = paywall.pricingUrl;
|
|
1465
|
+
let handoffFailed = false;
|
|
1466
|
+
try {
|
|
1467
|
+
const handoffUrl = await createHandoff({
|
|
1468
|
+
paywall,
|
|
1469
|
+
platformApiUrl,
|
|
1470
|
+
webUrl,
|
|
1471
|
+
context: input.context
|
|
1472
|
+
});
|
|
1473
|
+
if (handoffUrl) url = handoffUrl;
|
|
1474
|
+
else handoffFailed = true;
|
|
1475
|
+
} catch {
|
|
1476
|
+
handoffFailed = true;
|
|
1477
|
+
}
|
|
1478
|
+
consola$1.error(paywall.reason);
|
|
1479
|
+
if (handoffFailed) consola$1.info(`Log in first: ${pc.cyan("dineway account login")}`);
|
|
1480
|
+
consola$1.info(`Continue in Dineway Web: ${pc.cyan(url)}`);
|
|
1481
|
+
if (!input.interactive) return true;
|
|
1482
|
+
await promptEnter("Press Enter to continue after upgrading, or Ctrl-C to cancel.");
|
|
1483
|
+
const credentials = await readStoredForgewayAccount({ platformApiUrl });
|
|
1484
|
+
if (!credentials) {
|
|
1485
|
+
consola$1.error("Still not logged in. Run: dineway account login");
|
|
1486
|
+
return true;
|
|
1487
|
+
}
|
|
1488
|
+
try {
|
|
1489
|
+
const { account } = await getForgewayDinewayAccount(credentials);
|
|
1490
|
+
const status = getCliPaywallRefreshStatus(paywall, account);
|
|
1491
|
+
if (status.blocked) consola$1.error(status.message);
|
|
1492
|
+
else consola$1.info(status.message);
|
|
1493
|
+
} catch {
|
|
1494
|
+
consola$1.error("Account is still blocked. Complete checkout or top up credits in Dineway Web.");
|
|
1495
|
+
}
|
|
1496
|
+
return true;
|
|
1497
|
+
}
|
|
954
1498
|
|
|
955
1499
|
//#endregion
|
|
956
1500
|
//#region src/cli/commands/deploy/utils/astro-adapter.ts
|
|
@@ -1637,136 +2181,6 @@ async function writeForgewayDeployMetadata(cwd, metadata) {
|
|
|
1637
2181
|
});
|
|
1638
2182
|
}
|
|
1639
2183
|
|
|
1640
|
-
//#endregion
|
|
1641
|
-
//#region src/cli/commands/deploy/utils/forgeway-secrets.ts
|
|
1642
|
-
const DINEWAY_CONFIG_DIR_NAME = ".dineway";
|
|
1643
|
-
const DINEWAY_USER_CONFIG_DIR_NAME = "dineway";
|
|
1644
|
-
const TRAILING_SLASH_PATTERN$2 = /\/$/;
|
|
1645
|
-
function getDinewayConfigDir(cwd = process.cwd()) {
|
|
1646
|
-
return join(cwd, DINEWAY_CONFIG_DIR_NAME);
|
|
1647
|
-
}
|
|
1648
|
-
function getDinewayUserConfigDir() {
|
|
1649
|
-
return join(process.env.XDG_CONFIG_HOME || join(homedir(), ".config"), DINEWAY_USER_CONFIG_DIR_NAME);
|
|
1650
|
-
}
|
|
1651
|
-
function getForgewaySecretPath(cwd = process.cwd()) {
|
|
1652
|
-
return join(getDinewayConfigDir(cwd), "forgeway.json");
|
|
1653
|
-
}
|
|
1654
|
-
function getForgewayAccountSecretPath() {
|
|
1655
|
-
return join(getDinewayUserConfigDir(), "forgeway.json");
|
|
1656
|
-
}
|
|
1657
|
-
function normalizePlatformApiUrl$1(platformApiUrl) {
|
|
1658
|
-
return platformApiUrl.replace(TRAILING_SLASH_PATTERN$2, "");
|
|
1659
|
-
}
|
|
1660
|
-
function normalizeEmail$2(email) {
|
|
1661
|
-
return email.trim().toLowerCase();
|
|
1662
|
-
}
|
|
1663
|
-
function accountKey(platformApiUrl, email) {
|
|
1664
|
-
return `${normalizePlatformApiUrl$1(platformApiUrl)}#${normalizeEmail$2(email)}`;
|
|
1665
|
-
}
|
|
1666
|
-
function normalizeLookup(lookup) {
|
|
1667
|
-
if (typeof lookup === "string") return { cwd: lookup };
|
|
1668
|
-
return lookup ?? {};
|
|
1669
|
-
}
|
|
1670
|
-
async function readStore(cwd = process.cwd()) {
|
|
1671
|
-
try {
|
|
1672
|
-
const raw = await readFile(getForgewaySecretPath(cwd), "utf-8");
|
|
1673
|
-
return JSON.parse(raw);
|
|
1674
|
-
} catch {
|
|
1675
|
-
return {};
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
async function writeStore(store, cwd = process.cwd()) {
|
|
1679
|
-
await mkdir(getDinewayConfigDir(cwd), {
|
|
1680
|
-
recursive: true,
|
|
1681
|
-
mode: 448
|
|
1682
|
-
});
|
|
1683
|
-
const file = getForgewaySecretPath(cwd);
|
|
1684
|
-
await writeFile(file, JSON.stringify(store, null, " ") + "\n", {
|
|
1685
|
-
encoding: "utf-8",
|
|
1686
|
-
mode: 384
|
|
1687
|
-
});
|
|
1688
|
-
await chmod(file, 384);
|
|
1689
|
-
}
|
|
1690
|
-
async function readAccountStore() {
|
|
1691
|
-
try {
|
|
1692
|
-
const raw = await readFile(getForgewayAccountSecretPath(), "utf-8");
|
|
1693
|
-
return JSON.parse(raw);
|
|
1694
|
-
} catch {
|
|
1695
|
-
return { version: 1 };
|
|
1696
|
-
}
|
|
1697
|
-
}
|
|
1698
|
-
async function writeAccountStore(store) {
|
|
1699
|
-
await mkdir(getDinewayUserConfigDir(), {
|
|
1700
|
-
recursive: true,
|
|
1701
|
-
mode: 448
|
|
1702
|
-
});
|
|
1703
|
-
const file = getForgewayAccountSecretPath();
|
|
1704
|
-
await writeFile(file, JSON.stringify({
|
|
1705
|
-
...store,
|
|
1706
|
-
version: 1
|
|
1707
|
-
}, null, " ") + "\n", {
|
|
1708
|
-
encoding: "utf-8",
|
|
1709
|
-
mode: 384
|
|
1710
|
-
});
|
|
1711
|
-
await chmod(file, 384);
|
|
1712
|
-
}
|
|
1713
|
-
function accountMatches(credentials, lookup) {
|
|
1714
|
-
if (lookup.platformApiUrl && normalizePlatformApiUrl$1(credentials.platformApiUrl) !== normalizePlatformApiUrl$1(lookup.platformApiUrl)) return false;
|
|
1715
|
-
if (lookup.email && normalizeEmail$2(credentials.user?.email ?? "") !== normalizeEmail$2(lookup.email)) return false;
|
|
1716
|
-
return true;
|
|
1717
|
-
}
|
|
1718
|
-
async function readForgewayCredentials(lookup) {
|
|
1719
|
-
const normalizedLookup = normalizeLookup(lookup);
|
|
1720
|
-
const store = await readAccountStore();
|
|
1721
|
-
const accounts = Object.values(store.accounts ?? {}).filter((credentials) => accountMatches(credentials, normalizedLookup));
|
|
1722
|
-
if (normalizedLookup.platformApiUrl && normalizedLookup.email) return store.accounts?.[accountKey(normalizedLookup.platformApiUrl, normalizedLookup.email)] ?? null;
|
|
1723
|
-
if (accounts.length === 1) return accounts[0] ?? null;
|
|
1724
|
-
return null;
|
|
1725
|
-
}
|
|
1726
|
-
async function writeForgewayCredentials(credentials, lookup) {
|
|
1727
|
-
const normalizedLookup = normalizeLookup(lookup);
|
|
1728
|
-
const platformApiUrl = normalizePlatformApiUrl$1(normalizedLookup.platformApiUrl ?? credentials.platformApiUrl);
|
|
1729
|
-
const email = normalizeEmail$2(normalizedLookup.email ?? credentials.user?.email ?? "");
|
|
1730
|
-
if (!email) throw new Error("Forgeway credentials require a user email before they can be stored.");
|
|
1731
|
-
const key = accountKey(platformApiUrl, email);
|
|
1732
|
-
const store = await readAccountStore();
|
|
1733
|
-
store.accounts = {
|
|
1734
|
-
...store.accounts,
|
|
1735
|
-
[key]: {
|
|
1736
|
-
...credentials,
|
|
1737
|
-
platformApiUrl
|
|
1738
|
-
}
|
|
1739
|
-
};
|
|
1740
|
-
store.lastAccountKey = key;
|
|
1741
|
-
await writeAccountStore(store);
|
|
1742
|
-
}
|
|
1743
|
-
async function listForgewayCredentials(platformApiUrl) {
|
|
1744
|
-
const lookup = platformApiUrl ? { platformApiUrl } : {};
|
|
1745
|
-
const store = await readAccountStore();
|
|
1746
|
-
return Object.values(store.accounts ?? {}).filter((credentials) => accountMatches(credentials, lookup));
|
|
1747
|
-
}
|
|
1748
|
-
function shadowGrantKey(platformApiUrl, placeId) {
|
|
1749
|
-
return `${platformApiUrl.replace(TRAILING_SLASH_PATTERN$2, "")}#${placeId ?? "__unbound__"}`;
|
|
1750
|
-
}
|
|
1751
|
-
async function readForgewayShadowGrant(platformApiUrl, placeId, cwd) {
|
|
1752
|
-
const store = await readStore(cwd);
|
|
1753
|
-
if (!store.shadowGrants) return null;
|
|
1754
|
-
if (placeId) return store.shadowGrants[shadowGrantKey(platformApiUrl, placeId)] ?? null;
|
|
1755
|
-
const lastKey = store.lastShadowGrantKey;
|
|
1756
|
-
if (lastKey && store.shadowGrants[lastKey]?.platformApiUrl === platformApiUrl) return store.shadowGrants[lastKey];
|
|
1757
|
-
return Object.values(store.shadowGrants).find((grant) => grant.platformApiUrl === platformApiUrl) ?? null;
|
|
1758
|
-
}
|
|
1759
|
-
async function writeForgewayShadowGrant(grant, cwd) {
|
|
1760
|
-
const store = await readStore(cwd);
|
|
1761
|
-
const key = shadowGrantKey(grant.platformApiUrl, grant.placeId);
|
|
1762
|
-
store.shadowGrants = {
|
|
1763
|
-
...store.shadowGrants,
|
|
1764
|
-
[key]: grant
|
|
1765
|
-
};
|
|
1766
|
-
store.lastShadowGrantKey = key;
|
|
1767
|
-
await writeStore(store, cwd);
|
|
1768
|
-
}
|
|
1769
|
-
|
|
1770
2184
|
//#endregion
|
|
1771
2185
|
//#region src/cli/commands/deploy/targets/forgeway.ts
|
|
1772
2186
|
const DEFAULT_DINEWAY_API_BASE_URL$1 = "https://api.dineway.ai";
|
|
@@ -1790,7 +2204,6 @@ const DINEWAY_PACKAGE_NAME = "dineway";
|
|
|
1790
2204
|
const SEMVER_VERSION_PATTERN = /^\d+\.\d+\.\d+(?:[-+].*)?$/;
|
|
1791
2205
|
const LOCAL_PACKAGE_SPEC_PATTERN = /^(?:workspace|file|link|portal):/;
|
|
1792
2206
|
const SHADOW_EMAIL_PATTERN$1 = /^shadow_[a-f0-9]{16}@dineway\.ai$/i;
|
|
1793
|
-
const OTP_PATTERN = /^\d{6}$/;
|
|
1794
2207
|
const FOOD_TYPES = new Set([
|
|
1795
2208
|
"restaurant",
|
|
1796
2209
|
"cafe",
|
|
@@ -1925,11 +2338,6 @@ async function parseErrorResponse(response) {
|
|
|
1925
2338
|
function normalizeEmail$1(email) {
|
|
1926
2339
|
return email.trim().toLowerCase();
|
|
1927
2340
|
}
|
|
1928
|
-
function normalizeOtp(otp) {
|
|
1929
|
-
const value = otp.trim();
|
|
1930
|
-
if (!OTP_PATTERN.test(value)) throw new Error("Forgeway email verification OTP must be a 6-digit numeric code.");
|
|
1931
|
-
return value;
|
|
1932
|
-
}
|
|
1933
2341
|
function isShadowEmail$1(email) {
|
|
1934
2342
|
return Boolean(email && SHADOW_EMAIL_PATTERN$1.test(email));
|
|
1935
2343
|
}
|
|
@@ -1948,8 +2356,7 @@ async function refreshFormalAccessToken(context, deps) {
|
|
|
1948
2356
|
platformApiUrl: context.platformApiUrl,
|
|
1949
2357
|
accessToken: payload.accessToken,
|
|
1950
2358
|
refreshToken: payload.refreshToken ?? context.refreshToken,
|
|
1951
|
-
...user ? { user } : {}
|
|
1952
|
-
source: "shadow-email-upgrade"
|
|
2359
|
+
...user ? { user } : {}
|
|
1953
2360
|
};
|
|
1954
2361
|
context.accessToken = updated.accessToken;
|
|
1955
2362
|
context.refreshToken = updated.refreshToken;
|
|
@@ -1961,30 +2368,6 @@ async function refreshFormalAccessToken(context, deps) {
|
|
|
1961
2368
|
});
|
|
1962
2369
|
return payload.accessToken;
|
|
1963
2370
|
}
|
|
1964
|
-
async function refreshShadowAccessToken(context, deps) {
|
|
1965
|
-
if (!context.refreshToken) throw new Error("Dineway shadow deploy grant is missing its refresh token.");
|
|
1966
|
-
const response = await forgewayRequest(`${context.platformApiUrl}/api/auth/refresh?client_type=server`, {
|
|
1967
|
-
method: "POST",
|
|
1968
|
-
headers: { "Content-Type": "application/json" },
|
|
1969
|
-
body: JSON.stringify({ refreshToken: context.refreshToken })
|
|
1970
|
-
}, deps);
|
|
1971
|
-
if (!response.ok) throw new Error("Failed to refresh Dineway shadow deploy grant. Run dineway deploy again.");
|
|
1972
|
-
const payload = await response.json();
|
|
1973
|
-
if (!payload.accessToken || !payload.refreshToken) throw new Error("Dineway shadow refresh response was missing tokens.");
|
|
1974
|
-
context.accessToken = payload.accessToken;
|
|
1975
|
-
context.refreshToken = payload.refreshToken;
|
|
1976
|
-
await (deps.writeShadowGrant ?? writeForgewayShadowGrant)({
|
|
1977
|
-
platformApiUrl: context.platformApiUrl,
|
|
1978
|
-
placeId: context.placeId,
|
|
1979
|
-
accessToken: payload.accessToken,
|
|
1980
|
-
refreshToken: payload.refreshToken,
|
|
1981
|
-
restaurantName: context.restaurantName,
|
|
1982
|
-
city: context.city,
|
|
1983
|
-
user: payload.user ? normalizeForgewayUser$1(payload.user) : void 0,
|
|
1984
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1985
|
-
}, context.projectDir);
|
|
1986
|
-
return payload.accessToken;
|
|
1987
|
-
}
|
|
1988
2371
|
async function promptText(question, initialValue, deps) {
|
|
1989
2372
|
if (deps.promptText) return await deps.promptText(question, initialValue);
|
|
1990
2373
|
if (!process.stdin.isTTY) return "";
|
|
@@ -2027,14 +2410,14 @@ function isDinewayDependencySpecCompatible(dependencySpec, cliVersion) {
|
|
|
2027
2410
|
if (LOCAL_PACKAGE_SPEC_PATTERN.test(spec)) return true;
|
|
2028
2411
|
return spec.includes(cliVersion);
|
|
2029
2412
|
}
|
|
2030
|
-
async function
|
|
2413
|
+
async function warnProjectDinewayRuntimeMismatch(cwd, cliVersion = VERSION) {
|
|
2031
2414
|
if (!SEMVER_VERSION_PATTERN.test(cliVersion)) return;
|
|
2032
2415
|
const pkg = await readProjectPackage(cwd);
|
|
2033
2416
|
if (!pkg) return;
|
|
2034
2417
|
const dependencySpec = getDependencySpec(pkg, DINEWAY_PACKAGE_NAME);
|
|
2035
2418
|
if (!dependencySpec) return;
|
|
2036
2419
|
if (isDinewayDependencySpecCompatible(dependencySpec, cliVersion)) return;
|
|
2037
|
-
|
|
2420
|
+
consola.warn(`Forgeway deploy finds that the package.json dineway runtime version does not match the deploy CLI. The CLI initializes the managed database before the site starts, so a mismatch can cause later migration or startup failures. The CLI is ${DINEWAY_PACKAGE_NAME}@${cliVersion}, but package.json declares ${DINEWAY_PACKAGE_NAME}: ${JSON.stringify(dependencySpec)}. If database migration fails, update package.json and reinstall with your package manager, for example: ${DINEWAY_PACKAGE_NAME}@^${cliVersion}. To keep deploying the current manifest, run the matching CLI version instead.`);
|
|
2038
2421
|
}
|
|
2039
2422
|
function explicitPublisherEmail(options) {
|
|
2040
2423
|
return options.email ?? getEnv("DINEWAY_EMAIL") ?? getEnv("FORGEWAY_EMAIL");
|
|
@@ -2047,12 +2430,6 @@ function validatePublisherEmail(rawEmail) {
|
|
|
2047
2430
|
if (!email || isShadowEmail$1(email)) throw new Error("Dineway account email must be a real owner email, not a shadow user email.");
|
|
2048
2431
|
return email;
|
|
2049
2432
|
}
|
|
2050
|
-
async function resolveForgewayAccountEmail(options, saved, deps, preferredEmail) {
|
|
2051
|
-
const suppliedEmail = options.email ?? getEnv("DINEWAY_EMAIL") ?? getEnv("FORGEWAY_EMAIL");
|
|
2052
|
-
const savedEmail = savedPublisherEmail(saved);
|
|
2053
|
-
if ((options.sendOtp || options.otp) && !suppliedEmail && !preferredEmail && !savedEmail) throw new Error("Forgeway OTP deploy requires --email or DINEWAY_EMAIL.");
|
|
2054
|
-
return validatePublisherEmail(suppliedEmail ?? preferredEmail ?? savedEmail ?? await promptRequired("Dineway account email: ", void 0, deps, "Dineway account email is required. Pass --email or set DINEWAY_EMAIL."));
|
|
2055
|
-
}
|
|
2056
2433
|
function isStoredFormalCredentialForEmail(stored, email) {
|
|
2057
2434
|
if (!stored?.accessToken || !stored.user) return false;
|
|
2058
2435
|
if (email && normalizeEmail$1(stored.user.email) !== email) return false;
|
|
@@ -2065,95 +2442,6 @@ function assertVerifiedFormalAccountUser(user, expectedEmail) {
|
|
|
2065
2442
|
if (expectedEmail && normalizeEmail$1(user.email) !== normalizeEmail$1(expectedEmail)) throw new Error("Forgeway refresh returned credentials for a different email.");
|
|
2066
2443
|
return user;
|
|
2067
2444
|
}
|
|
2068
|
-
async function shadowUpgradeFetch(context, path, deps, options) {
|
|
2069
|
-
const request = async (accessToken) => await forgewayRequest(`${context.platformApiUrl}${path}`, {
|
|
2070
|
-
...options,
|
|
2071
|
-
headers: {
|
|
2072
|
-
"Content-Type": "application/json",
|
|
2073
|
-
Authorization: `Bearer ${accessToken}`,
|
|
2074
|
-
...options.headers
|
|
2075
|
-
}
|
|
2076
|
-
}, deps);
|
|
2077
|
-
if (!context.accessToken) throw new Error("Dineway shadow deploy grant is missing its access token.");
|
|
2078
|
-
let response = await request(context.accessToken);
|
|
2079
|
-
if (response.status === 401) response = await request(await refreshShadowAccessToken(context, deps));
|
|
2080
|
-
if (!response.ok) throw new ForgewayApiError(await parseErrorResponse(response), response.status);
|
|
2081
|
-
return await response.json();
|
|
2082
|
-
}
|
|
2083
|
-
async function startShadowEmailUpgrade(context, email, deps) {
|
|
2084
|
-
const payload = await shadowUpgradeFetch(context, "/api/auth/users/shadow/upgrade/email/start", deps, {
|
|
2085
|
-
method: "POST",
|
|
2086
|
-
body: JSON.stringify({ email })
|
|
2087
|
-
});
|
|
2088
|
-
if (payload.email && normalizeEmail$1(payload.email) !== email) throw new Error("Forgeway email verification response returned a different email.");
|
|
2089
|
-
return payload;
|
|
2090
|
-
}
|
|
2091
|
-
async function verifyShadowEmailUpgrade(context, email, otp, deps) {
|
|
2092
|
-
const payload = await shadowUpgradeFetch(context, "/api/auth/users/shadow/upgrade/email/verify", deps, {
|
|
2093
|
-
method: "POST",
|
|
2094
|
-
body: JSON.stringify({
|
|
2095
|
-
email,
|
|
2096
|
-
otp
|
|
2097
|
-
})
|
|
2098
|
-
});
|
|
2099
|
-
if (!payload.accessToken || !payload.refreshToken || !payload.user) throw new Error("Forgeway email upgrade response was missing credentials.");
|
|
2100
|
-
const user = normalizeForgewayUser$1(payload.user);
|
|
2101
|
-
if (normalizeEmail$1(user.email) !== email) throw new Error("Forgeway email upgrade returned credentials for a different email.");
|
|
2102
|
-
if (user.emailVerified !== true || isShadowEmail$1(user.email)) throw new Error("Forgeway email upgrade did not return a verified formal account.");
|
|
2103
|
-
return {
|
|
2104
|
-
platformApiUrl: context.platformApiUrl,
|
|
2105
|
-
accessToken: payload.accessToken,
|
|
2106
|
-
refreshToken: payload.refreshToken,
|
|
2107
|
-
user,
|
|
2108
|
-
source: "shadow-email-upgrade"
|
|
2109
|
-
};
|
|
2110
|
-
}
|
|
2111
|
-
async function resolveFormalAccountCredentials(context, email, options, deps) {
|
|
2112
|
-
const stored = await (deps.readCredentials ?? readForgewayCredentials)({
|
|
2113
|
-
cwd: context.projectDir,
|
|
2114
|
-
platformApiUrl: context.platformApiUrl,
|
|
2115
|
-
email
|
|
2116
|
-
});
|
|
2117
|
-
if (!options.sendOtp && !options.otp && isStoredFormalCredentialForEmail(stored, email)) return {
|
|
2118
|
-
status: "verified",
|
|
2119
|
-
credentials: {
|
|
2120
|
-
...stored,
|
|
2121
|
-
platformApiUrl: context.platformApiUrl
|
|
2122
|
-
}
|
|
2123
|
-
};
|
|
2124
|
-
if (options.sendOtp) {
|
|
2125
|
-
const response = await startShadowEmailUpgrade(context, email, deps);
|
|
2126
|
-
return {
|
|
2127
|
-
status: "otp-sent",
|
|
2128
|
-
email: response.email ? normalizeEmail$1(response.email) : email,
|
|
2129
|
-
expiresAt: response.expiresAt
|
|
2130
|
-
};
|
|
2131
|
-
}
|
|
2132
|
-
if (options.otp) {
|
|
2133
|
-
const credentials = await verifyShadowEmailUpgrade(context, email, normalizeOtp(options.otp), deps);
|
|
2134
|
-
await (deps.writeCredentials ?? writeForgewayCredentials)(credentials, {
|
|
2135
|
-
cwd: context.projectDir,
|
|
2136
|
-
platformApiUrl: context.platformApiUrl,
|
|
2137
|
-
email
|
|
2138
|
-
});
|
|
2139
|
-
return {
|
|
2140
|
-
status: "verified",
|
|
2141
|
-
credentials
|
|
2142
|
-
};
|
|
2143
|
-
}
|
|
2144
|
-
await startShadowEmailUpgrade(context, email, deps);
|
|
2145
|
-
consola.info(`Sent Forgeway email verification code to ${email}`);
|
|
2146
|
-
const credentials = await verifyShadowEmailUpgrade(context, email, await promptRequired("Email verification code: ", void 0, deps, "Email verification code is required."), deps);
|
|
2147
|
-
await (deps.writeCredentials ?? writeForgewayCredentials)(credentials, {
|
|
2148
|
-
cwd: context.projectDir,
|
|
2149
|
-
platformApiUrl: context.platformApiUrl,
|
|
2150
|
-
email
|
|
2151
|
-
});
|
|
2152
|
-
return {
|
|
2153
|
-
status: "verified",
|
|
2154
|
-
credentials
|
|
2155
|
-
};
|
|
2156
|
-
}
|
|
2157
2445
|
async function readCachedPublisherCredentials(cwd, platformApiUrl, email, deps) {
|
|
2158
2446
|
const credentials = await (deps.readCredentials ?? readForgewayCredentials)({
|
|
2159
2447
|
cwd,
|
|
@@ -2218,7 +2506,6 @@ async function resolveFormalProjectContext(cwd, options, deps) {
|
|
|
2218
2506
|
const context = {
|
|
2219
2507
|
projectDir: cwd,
|
|
2220
2508
|
platformApiUrl,
|
|
2221
|
-
authKind: "formal-account",
|
|
2222
2509
|
accessToken: account.credentials.accessToken,
|
|
2223
2510
|
refreshToken: account.credentials.refreshToken,
|
|
2224
2511
|
user,
|
|
@@ -2232,7 +2519,7 @@ async function resolveFormalProjectContext(cwd, options, deps) {
|
|
|
2232
2519
|
city: options.city
|
|
2233
2520
|
};
|
|
2234
2521
|
if (!context.placeId) {
|
|
2235
|
-
const resolvedRestaurant = await
|
|
2522
|
+
const resolvedRestaurant = await resolveRequiredRestaurantInfo(options, deps);
|
|
2236
2523
|
restaurant = resolvedRestaurant;
|
|
2237
2524
|
context.placeId = await resolvePlaceIdWithFormalSearch({
|
|
2238
2525
|
context,
|
|
@@ -2248,100 +2535,11 @@ async function resolveFormalProjectContext(cwd, options, deps) {
|
|
|
2248
2535
|
restaurant
|
|
2249
2536
|
};
|
|
2250
2537
|
}
|
|
2251
|
-
async function resolveShadowProjectContext(cwd, options, deps, preferredEmail) {
|
|
2252
|
-
const saved = await readSavedForgewayMetadata(cwd);
|
|
2253
|
-
const platformApiUrl = resolvePlatformApiUrl(saved.platformApiUrl);
|
|
2254
|
-
const savedPlaceId = options.placeId ?? getEnv("DINEWAY_PLACE_ID") ?? (typeof saved.placeId === "string" ? saved.placeId : void 0);
|
|
2255
|
-
let grant = await (deps.readShadowGrant ?? readForgewayShadowGrant)(platformApiUrl, savedPlaceId, cwd);
|
|
2256
|
-
let restaurant;
|
|
2257
|
-
if (!grant) {
|
|
2258
|
-
const shadowRestaurant = await resolveShadowRestaurantInfo(options, deps);
|
|
2259
|
-
restaurant = shadowRestaurant;
|
|
2260
|
-
if (options.dryRun) throw new Error("Forgeway deploy needs a Dineway shadow deploy grant. Run without --dry-run to create it.");
|
|
2261
|
-
grant = await createShadowGrant({
|
|
2262
|
-
platformApiUrl,
|
|
2263
|
-
placeId: savedPlaceId,
|
|
2264
|
-
restaurantName: shadowRestaurant.name,
|
|
2265
|
-
city: shadowRestaurant.city,
|
|
2266
|
-
cwd,
|
|
2267
|
-
deps
|
|
2268
|
-
});
|
|
2269
|
-
} else restaurant = {
|
|
2270
|
-
name: options.restaurantName ?? grant.restaurantName,
|
|
2271
|
-
city: options.city ?? grant.city
|
|
2272
|
-
};
|
|
2273
|
-
if (!grant.placeId) {
|
|
2274
|
-
const shadowRestaurant = restaurant?.name && restaurant.city ? {
|
|
2275
|
-
name: restaurant.name,
|
|
2276
|
-
city: restaurant.city
|
|
2277
|
-
} : await resolveShadowRestaurantInfo(options, deps);
|
|
2278
|
-
restaurant = shadowRestaurant;
|
|
2279
|
-
grant = savedPlaceId ? await bindShadowGrantPlace({
|
|
2280
|
-
platformApiUrl,
|
|
2281
|
-
grant,
|
|
2282
|
-
placeId: savedPlaceId,
|
|
2283
|
-
restaurant: shadowRestaurant,
|
|
2284
|
-
cwd,
|
|
2285
|
-
deps
|
|
2286
|
-
}) : await resolvePlaceIdWithShadowSearch({
|
|
2287
|
-
platformApiUrl,
|
|
2288
|
-
grant,
|
|
2289
|
-
restaurant: shadowRestaurant,
|
|
2290
|
-
cwd,
|
|
2291
|
-
deps
|
|
2292
|
-
});
|
|
2293
|
-
}
|
|
2294
|
-
if (!grant.placeId) throw new Error("Could not resolve a Dineway place id for Forgeway deploy.");
|
|
2295
|
-
const shadowContext = {
|
|
2296
|
-
projectDir: cwd,
|
|
2297
|
-
platformApiUrl,
|
|
2298
|
-
authKind: "shadow-grant",
|
|
2299
|
-
accessToken: grant.accessToken,
|
|
2300
|
-
refreshToken: grant.refreshToken,
|
|
2301
|
-
user: grant.user,
|
|
2302
|
-
ossHost: platformApiUrl,
|
|
2303
|
-
placeId: grant.placeId,
|
|
2304
|
-
restaurantName: restaurant.name,
|
|
2305
|
-
city: restaurant.city
|
|
2306
|
-
};
|
|
2307
|
-
const credentialsResult = await resolveFormalAccountCredentials(shadowContext, await resolveForgewayAccountEmail(options, saved, deps, preferredEmail), options, deps);
|
|
2308
|
-
if (credentialsResult.status === "otp-sent") return credentialsResult;
|
|
2309
|
-
const { credentials } = credentialsResult;
|
|
2310
|
-
return {
|
|
2311
|
-
status: "ready",
|
|
2312
|
-
context: {
|
|
2313
|
-
...shadowContext,
|
|
2314
|
-
authKind: "formal-account",
|
|
2315
|
-
accessToken: credentials.accessToken,
|
|
2316
|
-
refreshToken: credentials.refreshToken,
|
|
2317
|
-
user: credentials.user,
|
|
2318
|
-
ossHost: platformApiUrl
|
|
2319
|
-
},
|
|
2320
|
-
restaurant
|
|
2321
|
-
};
|
|
2322
|
-
}
|
|
2323
2538
|
async function resolveProjectContext(cwd, options, deps) {
|
|
2324
|
-
|
|
2325
|
-
if (
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
preferredEmail = formal.email;
|
|
2329
|
-
}
|
|
2330
|
-
return await resolveShadowProjectContext(cwd, options, deps, preferredEmail);
|
|
2331
|
-
}
|
|
2332
|
-
async function createShadowUser(platformApiUrl, placeId, deps) {
|
|
2333
|
-
const response = await forgewayRequest(`${platformApiUrl}/api/auth/users/shadow`, {
|
|
2334
|
-
method: "POST",
|
|
2335
|
-
headers: { "Content-Type": "application/json" },
|
|
2336
|
-
body: JSON.stringify({
|
|
2337
|
-
...placeId ? { placeId } : {},
|
|
2338
|
-
language: "en"
|
|
2339
|
-
})
|
|
2340
|
-
}, deps);
|
|
2341
|
-
if (!response.ok) throw new Error(await parseErrorResponse(response));
|
|
2342
|
-
const payload = await response.json();
|
|
2343
|
-
if (!payload.accessToken || !payload.refreshToken) throw new Error("Dineway shadow user response was missing tokens.");
|
|
2344
|
-
return payload;
|
|
2539
|
+
const formal = await resolveFormalProjectContext(cwd, options, deps);
|
|
2540
|
+
if (formal.status !== "missing") return formal;
|
|
2541
|
+
if (formal.email) throw new Error(`No verified Dineway account credentials were found for ${formal.email}. Run: dineway account login --email ${formal.email}`);
|
|
2542
|
+
throw new Error("No verified Dineway account credentials were found. Run: dineway account login");
|
|
2345
2543
|
}
|
|
2346
2544
|
function isRecord(value) {
|
|
2347
2545
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -2522,80 +2720,6 @@ function extractPlaceCandidates(payload) {
|
|
|
2522
2720
|
if (!Array.isArray(places)) throw new Error("Dineway place search response did not include places/results.");
|
|
2523
2721
|
return places.filter(isRecord);
|
|
2524
2722
|
}
|
|
2525
|
-
function shadowContextFromGrant(cwd, platformApiUrl, grant, restaurant) {
|
|
2526
|
-
return {
|
|
2527
|
-
projectDir: cwd,
|
|
2528
|
-
platformApiUrl,
|
|
2529
|
-
authKind: "shadow-grant",
|
|
2530
|
-
accessToken: grant.accessToken,
|
|
2531
|
-
refreshToken: grant.refreshToken,
|
|
2532
|
-
user: grant.user,
|
|
2533
|
-
ossHost: platformApiUrl,
|
|
2534
|
-
placeId: grant.placeId,
|
|
2535
|
-
restaurantName: restaurant?.name ?? grant.restaurantName,
|
|
2536
|
-
city: restaurant?.city ?? grant.city
|
|
2537
|
-
};
|
|
2538
|
-
}
|
|
2539
|
-
function grantFromShadowContext(context, grant, overrides = {}) {
|
|
2540
|
-
return {
|
|
2541
|
-
...grant,
|
|
2542
|
-
platformApiUrl: context.platformApiUrl,
|
|
2543
|
-
accessToken: context.accessToken ?? grant.accessToken,
|
|
2544
|
-
refreshToken: context.refreshToken ?? grant.refreshToken,
|
|
2545
|
-
placeId: context.placeId ?? grant.placeId,
|
|
2546
|
-
restaurantName: context.restaurantName ?? grant.restaurantName,
|
|
2547
|
-
city: context.city ?? grant.city,
|
|
2548
|
-
user: context.user ?? grant.user,
|
|
2549
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2550
|
-
...overrides
|
|
2551
|
-
};
|
|
2552
|
-
}
|
|
2553
|
-
async function searchPlacesWithShadowGrant(options) {
|
|
2554
|
-
const context = shadowContextFromGrant(options.cwd, options.platformApiUrl, options.grant, options.restaurant);
|
|
2555
|
-
const payload = await shadowUpgradeFetch(context, "/api/places/search", options.deps, {
|
|
2556
|
-
method: "POST",
|
|
2557
|
-
body: JSON.stringify({ textQuery: `${options.restaurant.name} in ${options.restaurant.city}` })
|
|
2558
|
-
});
|
|
2559
|
-
return {
|
|
2560
|
-
grant: grantFromShadowContext(context, options.grant),
|
|
2561
|
-
candidates: extractPlaceCandidates(payload)
|
|
2562
|
-
};
|
|
2563
|
-
}
|
|
2564
|
-
async function bindShadowGrantPlace(options) {
|
|
2565
|
-
const context = shadowContextFromGrant(options.cwd, options.platformApiUrl, options.grant, options.restaurant);
|
|
2566
|
-
const payload = await shadowUpgradeFetch(context, "/api/auth/users/shadow/place", options.deps, {
|
|
2567
|
-
method: "POST",
|
|
2568
|
-
body: JSON.stringify({
|
|
2569
|
-
placeId: options.placeId,
|
|
2570
|
-
language: "en"
|
|
2571
|
-
})
|
|
2572
|
-
});
|
|
2573
|
-
const grant = grantFromShadowContext(context, options.grant, {
|
|
2574
|
-
placeId: options.placeId,
|
|
2575
|
-
accessToken: payload.accessToken ?? context.accessToken ?? options.grant.accessToken,
|
|
2576
|
-
refreshToken: payload.refreshToken ?? context.refreshToken ?? options.grant.refreshToken,
|
|
2577
|
-
restaurantName: options.restaurant.name,
|
|
2578
|
-
city: options.restaurant.city,
|
|
2579
|
-
user: payload.user ? normalizeForgewayUser$1(payload.user) : context.user ?? options.grant.user
|
|
2580
|
-
});
|
|
2581
|
-
await (options.deps.writeShadowGrant ?? writeForgewayShadowGrant)(grant, options.cwd);
|
|
2582
|
-
return grant;
|
|
2583
|
-
}
|
|
2584
|
-
async function resolvePlaceIdWithShadowSearch(options) {
|
|
2585
|
-
const { grant, candidates } = await searchPlacesWithShadowGrant(options);
|
|
2586
|
-
if (candidates.length === 0) throw new Error(`Dineway place search returned no candidates for "${options.restaurant.name} in ${options.restaurant.city}".`);
|
|
2587
|
-
const selected = selectPlaceCandidate(candidates, {
|
|
2588
|
-
name: options.restaurant.name,
|
|
2589
|
-
city: options.restaurant.city
|
|
2590
|
-
});
|
|
2591
|
-
const finalPlaceId = selected ? candidatePlaceId(selected.candidate) : "";
|
|
2592
|
-
if (!PLACE_ID_PATTERN.test(finalPlaceId)) throw new Error("Could not resolve a valid Dineway place id for Forgeway deploy.");
|
|
2593
|
-
return await bindShadowGrantPlace({
|
|
2594
|
-
...options,
|
|
2595
|
-
grant,
|
|
2596
|
-
placeId: finalPlaceId
|
|
2597
|
-
});
|
|
2598
|
-
}
|
|
2599
2723
|
async function resolvePlaceIdWithFormalSearch(options) {
|
|
2600
2724
|
const candidates = extractPlaceCandidates(await ossFetch(options.context, "/api/places/search", options.deps, {
|
|
2601
2725
|
method: "POST",
|
|
@@ -2610,22 +2734,6 @@ async function resolvePlaceIdWithFormalSearch(options) {
|
|
|
2610
2734
|
if (!PLACE_ID_PATTERN.test(finalPlaceId)) throw new Error("Could not resolve a valid Dineway place id for Forgeway deploy.");
|
|
2611
2735
|
return finalPlaceId;
|
|
2612
2736
|
}
|
|
2613
|
-
async function createShadowGrant(options) {
|
|
2614
|
-
if (options.placeId && !PLACE_ID_PATTERN.test(options.placeId)) throw new Error("Could not resolve a valid Dineway place id for Forgeway deploy.");
|
|
2615
|
-
const auth = await createShadowUser(options.platformApiUrl, options.placeId, options.deps);
|
|
2616
|
-
const grant = {
|
|
2617
|
-
platformApiUrl: options.platformApiUrl,
|
|
2618
|
-
...options.placeId ? { placeId: options.placeId } : {},
|
|
2619
|
-
accessToken: auth.accessToken,
|
|
2620
|
-
refreshToken: auth.refreshToken,
|
|
2621
|
-
restaurantName: options.restaurantName,
|
|
2622
|
-
city: options.city,
|
|
2623
|
-
user: auth.user ? normalizeForgewayUser$1(auth.user) : void 0,
|
|
2624
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2625
|
-
};
|
|
2626
|
-
await (options.deps.writeShadowGrant ?? writeForgewayShadowGrant)(grant, options.cwd);
|
|
2627
|
-
return grant;
|
|
2628
|
-
}
|
|
2629
2737
|
async function ossFetch(context, path, deps, options = {}) {
|
|
2630
2738
|
const request = async (token) => await forgewayRequest(`${context.ossHost.replace(TRAILING_SLASH_PATTERN$1, "")}${path}`, {
|
|
2631
2739
|
...options,
|
|
@@ -2638,7 +2746,7 @@ async function ossFetch(context, path, deps, options = {}) {
|
|
|
2638
2746
|
const token = context.accessToken;
|
|
2639
2747
|
if (!token) throw new Error("Forgeway deploy context is missing an authorization token.");
|
|
2640
2748
|
let response = await request(token);
|
|
2641
|
-
if (response.status === 401) response = await request(
|
|
2749
|
+
if (response.status === 401) response = await request(await refreshFormalAccessToken(context, deps));
|
|
2642
2750
|
if (!response.ok) throw new ForgewayApiError(await parseErrorResponse(response), response.status);
|
|
2643
2751
|
return await response.json();
|
|
2644
2752
|
}
|
|
@@ -2689,7 +2797,7 @@ async function resolveRestaurantInfo(options, seedPath, deps, requireForSlug, us
|
|
|
2689
2797
|
city
|
|
2690
2798
|
};
|
|
2691
2799
|
}
|
|
2692
|
-
async function
|
|
2800
|
+
async function resolveRequiredRestaurantInfo(options, deps) {
|
|
2693
2801
|
return {
|
|
2694
2802
|
name: options.restaurantName ?? await promptRequired("Restaurant name: ", void 0, deps, "Restaurant name is required. Pass --restaurant-name."),
|
|
2695
2803
|
city: options.city ?? await promptRequired("City: ", void 0, deps, "City is required. Pass --city.")
|
|
@@ -2821,6 +2929,7 @@ async function runDinewayInitialization(options) {
|
|
|
2821
2929
|
seedResult = await applySeed(db, seed, {
|
|
2822
2930
|
includeContent: true,
|
|
2823
2931
|
onConflict: "skip",
|
|
2932
|
+
repairSchema: true,
|
|
2824
2933
|
storage: new LocalStorage({
|
|
2825
2934
|
directory: uploadsDir,
|
|
2826
2935
|
baseUrl: "/_dineway/api/media/file"
|
|
@@ -3093,27 +3202,16 @@ function formatDinewayAdminBootstrapMessage(bootstrap) {
|
|
|
3093
3202
|
"CLI example: npx dineway whoami"
|
|
3094
3203
|
].join("\n");
|
|
3095
3204
|
}
|
|
3096
|
-
function formatForgewayOtpSentMessage(email, expiresAt) {
|
|
3097
|
-
const lines = [
|
|
3098
|
-
`Sent Forgeway email verification code to ${email}.`,
|
|
3099
|
-
"Run the Forgeway deploy command again with the same restaurant/site options and --otp <code>.",
|
|
3100
|
-
`Example: npx dineway deploy forgeway --email ${email} --otp 123456`
|
|
3101
|
-
];
|
|
3102
|
-
if (expiresAt) lines.splice(1, 0, `Code expires at ${expiresAt}.`);
|
|
3103
|
-
return lines.join("\n");
|
|
3104
|
-
}
|
|
3105
3205
|
async function deployForgeway(cwd, options, deps = {}) {
|
|
3106
3206
|
if (options.dryRun) return { message: "[dry-run] Would resolve Forgeway project, create/reuse site, bind database, initialize Dineway, upload files, and start deployment." };
|
|
3107
3207
|
const sourceDir = resolve(cwd);
|
|
3108
3208
|
if (!(await stat(sourceDir).catch(() => null))?.isDirectory()) throw new Error(`"${sourceDir}" is not a valid directory.`);
|
|
3109
3209
|
if (EXCLUDE_PATTERNS.includes(basename(sourceDir))) throw new Error(`"${basename(sourceDir)}" is an excluded directory and cannot be deployed.`);
|
|
3110
3210
|
const database = parseDatabaseMode(options.database);
|
|
3111
|
-
if (database !== "none") await
|
|
3211
|
+
if (database !== "none") await warnProjectDinewayRuntimeMismatch(cwd, deps.dinewayVersion ?? VERSION);
|
|
3112
3212
|
await ensureProjectGitignoreDinewayLocalState(cwd);
|
|
3113
3213
|
const verbose = isVerboseDeploy(options);
|
|
3114
|
-
const
|
|
3115
|
-
if (project.status === "otp-sent") return { message: formatForgewayOtpSentMessage(project.email, project.expiresAt) };
|
|
3116
|
-
const { context, restaurant } = project;
|
|
3214
|
+
const { context, restaurant } = await resolveProjectContext(cwd, options, deps);
|
|
3117
3215
|
const seedPath = options.skipSeed ? null : await resolveSeedPath$1(cwd, options.seed);
|
|
3118
3216
|
if (options.skipSeed) consola.info("Skipping seed initialization by request");
|
|
3119
3217
|
await ensureRestaurantClaim(context, restaurant, deps);
|
|
@@ -3173,7 +3271,6 @@ const forgewayTarget = {
|
|
|
3173
3271
|
remoteBuild: true,
|
|
3174
3272
|
supportLevel: "stable",
|
|
3175
3273
|
async generateConfig(cwd, options) {
|
|
3176
|
-
if (options.sendOtp) return [];
|
|
3177
3274
|
return await configureAstroDeployAdapter(cwd, "vercel", options.dryRun);
|
|
3178
3275
|
},
|
|
3179
3276
|
async deploy(cwd, options) {
|
|
@@ -3705,16 +3802,6 @@ const deployCommand = defineCommand({
|
|
|
3705
3802
|
description: "Dineway account email for deploy authorization",
|
|
3706
3803
|
required: false
|
|
3707
3804
|
},
|
|
3708
|
-
"send-otp": {
|
|
3709
|
-
type: "boolean",
|
|
3710
|
-
description: "Send a Forgeway email verification code and exit without prompting or deploying",
|
|
3711
|
-
default: false
|
|
3712
|
-
},
|
|
3713
|
-
otp: {
|
|
3714
|
-
type: "string",
|
|
3715
|
-
description: "Forgeway email verification code for non-interactive deploy authorization",
|
|
3716
|
-
required: false
|
|
3717
|
-
},
|
|
3718
3805
|
"restaurant-name": {
|
|
3719
3806
|
type: "string",
|
|
3720
3807
|
description: "Restaurant name for first Forgeway site creation",
|
|
@@ -3762,8 +3849,6 @@ const deployCommand = defineCommand({
|
|
|
3762
3849
|
site: args.site,
|
|
3763
3850
|
placeId: args["place-id"],
|
|
3764
3851
|
email: args.email,
|
|
3765
|
-
sendOtp: args["send-otp"],
|
|
3766
|
-
otp: args.otp,
|
|
3767
3852
|
restaurantName: args["restaurant-name"],
|
|
3768
3853
|
city: args.city,
|
|
3769
3854
|
database: args.database,
|
|
@@ -3772,8 +3857,6 @@ const deployCommand = defineCommand({
|
|
|
3772
3857
|
forceDbInit: args["force-db-init"],
|
|
3773
3858
|
verbose: args.verbose
|
|
3774
3859
|
};
|
|
3775
|
-
if ((options.sendOtp || options.otp) && target.name !== "forgeway") throw new Error("--send-otp and --otp are only supported for Forgeway deploys.");
|
|
3776
|
-
if (options.sendOtp && options.otp) throw new Error("Use either --send-otp or --otp, not both.");
|
|
3777
3860
|
consola.start(`Preparing ${target.label} deploy`);
|
|
3778
3861
|
await ensureTargetCli(target, cwd, {
|
|
3779
3862
|
yes: options.yes,
|
|
@@ -3807,7 +3890,21 @@ const deployCommand = defineCommand({
|
|
|
3807
3890
|
consola.info("[dry-run] Would ensure Dineway local state entries in .gitignore");
|
|
3808
3891
|
consola.info(`[dry-run] Would save .dineway/deploy.json target=${target.name}`);
|
|
3809
3892
|
}
|
|
3810
|
-
const result = await target.deploy(cwd, options)
|
|
3893
|
+
const result = await target.deploy(cwd, options).catch(async (error) => {
|
|
3894
|
+
if (await handleCliPaywall({
|
|
3895
|
+
error,
|
|
3896
|
+
resource: `deploy:${target.name}`,
|
|
3897
|
+
platformApiUrl: process.env.DINEWAY_FORGEWAY_API_URL,
|
|
3898
|
+
webUrl: process.env.DINEWAY_WEB_URL,
|
|
3899
|
+
interactive: process.stdin.isTTY && !options.yes,
|
|
3900
|
+
context: {
|
|
3901
|
+
target: target.name,
|
|
3902
|
+
site: options.site,
|
|
3903
|
+
placeId: options.placeId
|
|
3904
|
+
}
|
|
3905
|
+
})) process.exit(2);
|
|
3906
|
+
throw error;
|
|
3907
|
+
});
|
|
3811
3908
|
if (result.url) consola.success(result.url);
|
|
3812
3909
|
consola.success(result.message);
|
|
3813
3910
|
}
|
|
@@ -4209,7 +4306,8 @@ async function exportSeed(db, withContent) {
|
|
|
4209
4306
|
};
|
|
4210
4307
|
seed.settings = await exportSettings(db);
|
|
4211
4308
|
seed.collections = await exportCollections(db);
|
|
4212
|
-
const i18nEnabled = await
|
|
4309
|
+
const { i18nEnabled, defaultLocale } = await detectLocaleInfo(db, seed.collections);
|
|
4310
|
+
if (defaultLocale) seed.defaultLocale = defaultLocale;
|
|
4213
4311
|
seed.taxonomies = await exportTaxonomies(db, i18nEnabled);
|
|
4214
4312
|
seed.menus = await exportMenus(db, i18nEnabled);
|
|
4215
4313
|
seed.widgetAreas = await exportWidgetAreas(db);
|
|
@@ -4251,34 +4349,43 @@ async function exportBylines(db) {
|
|
|
4251
4349
|
};
|
|
4252
4350
|
}
|
|
4253
4351
|
/**
|
|
4254
|
-
* Determine
|
|
4352
|
+
* Determine locale-awareness and the data's default locale for the export.
|
|
4255
4353
|
*
|
|
4256
4354
|
* Runtime i18n config is initialized by middleware, but `dineway export-seed`
|
|
4257
4355
|
* runs in a CLI process. When the runtime flag is unset, derive multi-locale
|
|
4258
4356
|
* status from stored rows instead: a project is multi-locale when any
|
|
4259
4357
|
* i18n-aware table contains more than one distinct locale.
|
|
4358
|
+
*
|
|
4359
|
+
* `defaultLocale` self-describes single-locale data so a non-`en` project
|
|
4360
|
+
* survives an export-seed -> seed round-trip outside the Astro runtime.
|
|
4260
4361
|
*/
|
|
4261
|
-
async function
|
|
4262
|
-
|
|
4362
|
+
async function detectLocaleInfo(db, collections) {
|
|
4363
|
+
const config = getI18nConfig();
|
|
4364
|
+
if (isI18nEnabled() && config) return {
|
|
4365
|
+
i18nEnabled: true,
|
|
4366
|
+
defaultLocale: config.defaultLocale
|
|
4367
|
+
};
|
|
4263
4368
|
const locales = /* @__PURE__ */ new Set();
|
|
4264
4369
|
const collectDistinctLocales = async (tableRef) => {
|
|
4265
4370
|
const result = await sql`
|
|
4266
4371
|
SELECT DISTINCT locale FROM ${tableRef}
|
|
4267
4372
|
`.execute(db);
|
|
4268
4373
|
for (const row of result.rows) if (row.locale) locales.add(row.locale);
|
|
4269
|
-
return locales.size > 1;
|
|
4270
4374
|
};
|
|
4271
|
-
|
|
4272
|
-
|
|
4375
|
+
await collectDistinctLocales(sql.ref("_dineway_taxonomy_defs"));
|
|
4376
|
+
await collectDistinctLocales(sql.ref("_dineway_menus"));
|
|
4273
4377
|
for (const collection of collections) {
|
|
4274
4378
|
validateIdentifier(collection.slug, "collection slug");
|
|
4275
4379
|
try {
|
|
4276
|
-
|
|
4380
|
+
await collectDistinctLocales(sql.ref(`ec_${collection.slug}`));
|
|
4277
4381
|
} catch (error) {
|
|
4278
4382
|
if (!isMissingTableError(error)) throw error;
|
|
4279
4383
|
}
|
|
4280
4384
|
}
|
|
4281
|
-
return
|
|
4385
|
+
return {
|
|
4386
|
+
i18nEnabled: locales.size > 1,
|
|
4387
|
+
defaultLocale: locales.size === 1 ? [...locales][0] : void 0
|
|
4388
|
+
};
|
|
4282
4389
|
}
|
|
4283
4390
|
/**
|
|
4284
4391
|
* Export site settings
|
|
@@ -7293,13 +7400,15 @@ var ForgewaySeoGatewayClient = class {
|
|
|
7293
7400
|
}
|
|
7294
7401
|
async request(path, body, init) {
|
|
7295
7402
|
const credentials = await this.refreshAccessToken(await this.loadCredentials());
|
|
7403
|
+
const method = init?.method ?? "POST";
|
|
7296
7404
|
const response = await this.fetchImpl(`${credentials.platformApiUrl}${path}`, {
|
|
7297
|
-
method
|
|
7405
|
+
method,
|
|
7298
7406
|
headers: {
|
|
7299
7407
|
Authorization: `Bearer ${credentials.accessToken}`,
|
|
7300
|
-
"Content-Type": "application/json"
|
|
7408
|
+
"Content-Type": "application/json",
|
|
7409
|
+
"Idempotency-Key": init?.idempotencyKey ?? randomUUID()
|
|
7301
7410
|
},
|
|
7302
|
-
body:
|
|
7411
|
+
body: method === "GET" ? void 0 : JSON.stringify(body ?? {})
|
|
7303
7412
|
});
|
|
7304
7413
|
const payload = await parseJsonResponse(response);
|
|
7305
7414
|
if (!response.ok) throw new ForgewaySeoApiError(errorMessage(payload, `Forgeway SEO request failed with status ${response.status}.`), response.status, payload);
|
|
@@ -7364,6 +7473,11 @@ async function runSeoRequest(args, path, body) {
|
|
|
7364
7473
|
try {
|
|
7365
7474
|
output(await new ForgewaySeoGatewayClient().request(path, body), args);
|
|
7366
7475
|
} catch (error) {
|
|
7476
|
+
if (await handleCliPaywall({
|
|
7477
|
+
error,
|
|
7478
|
+
resource: path,
|
|
7479
|
+
context: { providerPath: path }
|
|
7480
|
+
})) process.exit(2);
|
|
7367
7481
|
consola$1.error(error instanceof Error ? error.message : "Unknown error");
|
|
7368
7482
|
process.exit(1);
|
|
7369
7483
|
}
|
|
@@ -7506,6 +7620,11 @@ const firecrawlCommand = defineCommand({
|
|
|
7506
7620
|
try {
|
|
7507
7621
|
output(await new ForgewaySeoGatewayClient().request(`/api/firecrawl/crawl/${encodeURIComponent(crawlId)}`, void 0, { method: "GET" }), args);
|
|
7508
7622
|
} catch (error) {
|
|
7623
|
+
if (await handleCliPaywall({
|
|
7624
|
+
error,
|
|
7625
|
+
resource: `/api/firecrawl/crawl/${crawlId}`,
|
|
7626
|
+
context: { providerPath: `/api/firecrawl/crawl/${crawlId}` }
|
|
7627
|
+
})) process.exit(2);
|
|
7509
7628
|
consola$1.error(error instanceof Error ? error.message : "Unknown error");
|
|
7510
7629
|
process.exit(1);
|
|
7511
7630
|
}
|
|
@@ -7961,6 +8080,7 @@ runMain(defineCommand({
|
|
|
7961
8080
|
},
|
|
7962
8081
|
subCommands: {
|
|
7963
8082
|
init: initCommand,
|
|
8083
|
+
account: accountCommand,
|
|
7964
8084
|
types: typesCommand,
|
|
7965
8085
|
dev: devCommand,
|
|
7966
8086
|
deploy: deployCommand,
|