dineway 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{allowed-origins-46RONHY3.mjs → allowed-origins-CIP5fh83.mjs} +1 -1
- package/dist/api/route-utils.d.mts +10 -10
- package/dist/api/route-utils.mjs +2 -2
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/{api-KH2L2uKb.mjs → api-CetVENIv.mjs} +1 -1
- package/dist/{api-tokens-CMmUPFae.mjs → api-tokens-DAMwe5Kj.mjs} +1 -1
- package/dist/{apply-Wyg77UOb.mjs → apply-D7vu4aFn.mjs} +5 -5
- package/dist/astro/index.d.mts +11 -11
- package/dist/astro/index.mjs +3 -3
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +4 -4
- package/dist/astro/middleware/request-context.mjs +2 -2
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.mjs +23 -22
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +4 -4
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +2 -2
- package/dist/astro/routes/api/admin/bylines/index.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +4 -4
- package/dist/astro/routes/api/admin/comments/_id_.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/bulk.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/counts.mjs +2 -2
- package/dist/astro/routes/api/admin/comments/index.mjs +2 -2
- package/dist/astro/routes/api/admin/context/_id_/history.mjs +6 -6
- package/dist/astro/routes/api/admin/context/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/context/_id_/review.mjs +7 -7
- package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +7 -7
- package/dist/astro/routes/api/admin/context/diff.mjs +6 -6
- package/dist/astro/routes/api/admin/context/index.mjs +7 -7
- package/dist/astro/routes/api/admin/context/stale.mjs +6 -6
- package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +6 -6
- package/dist/astro/routes/api/admin/hitl-requests/index.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +9 -9
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/updates.mjs +4 -4
- package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +1 -1
- package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +5 -5
- package/dist/astro/routes/api/admin/review-requests/index.mjs +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +4 -4
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +4 -4
- package/dist/astro/routes/api/auth/invite/index.mjs +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
- package/dist/astro/routes/api/auth/logout.mjs +1 -1
- package/dist/astro/routes/api/auth/magic-link/send.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/signup/complete.mjs +4 -4
- package/dist/astro/routes/api/auth/signup/request.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/trash.mjs +1 -1
- package/dist/astro/routes/api/dashboard.mjs +1 -1
- package/dist/astro/routes/api/health.mjs +1 -1
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +4 -3
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +6 -3
- package/dist/astro/routes/api/import/wordpress/execute.mjs +11 -9
- package/dist/astro/routes/api/import/wordpress/media.mjs +5 -2
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +8 -7
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +7 -4
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +10 -10
- package/dist/astro/routes/api/manifest.mjs +3 -3
- package/dist/astro/routes/api/mcp.mjs +13 -13
- package/dist/astro/routes/api/media/_id_/confirm.mjs +4 -2
- package/dist/astro/routes/api/media/_id_.mjs +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +1 -1
- package/dist/astro/routes/api/media/providers/index.mjs +1 -1
- package/dist/astro/routes/api/media/upload-url.mjs +5 -3
- package/dist/astro/routes/api/media.mjs +2 -2
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_/items.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_/translations.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_.mjs +6 -6
- package/dist/astro/routes/api/menus/index.mjs +6 -6
- package/dist/astro/routes/api/oauth/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/authorize.mjs +4 -4
- package/dist/astro/routes/api/oauth/device/code.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/token.mjs +5 -5
- package/dist/astro/routes/api/oauth/register.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/refresh.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/revoke.mjs +4 -4
- package/dist/astro/routes/api/oauth/token.mjs +5 -5
- package/dist/astro/routes/api/openapi.json.mjs +3 -3
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +2 -2
- package/dist/astro/routes/api/redirects/404s/index.mjs +2 -2
- package/dist/astro/routes/api/redirects/404s/summary.mjs +2 -2
- package/dist/astro/routes/api/redirects/_id_.mjs +7 -7
- package/dist/astro/routes/api/redirects/index.mjs +7 -7
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/index.mjs +5 -5
- package/dist/astro/routes/api/schema/index.mjs +4 -4
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +4 -4
- package/dist/astro/routes/api/schema/orphans/index.mjs +4 -4
- package/dist/astro/routes/api/search/enable.mjs +2 -2
- package/dist/astro/routes/api/search/index.mjs +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +2 -2
- package/dist/astro/routes/api/search/stats.mjs +2 -2
- package/dist/astro/routes/api/search/suggest.mjs +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +6 -6
- package/dist/astro/routes/api/sections/index.mjs +6 -6
- package/dist/astro/routes/api/settings/email.mjs +1 -1
- package/dist/astro/routes/api/settings.mjs +6 -6
- package/dist/astro/routes/api/setup/admin-verify.mjs +6 -6
- package/dist/astro/routes/api/setup/admin.mjs +4 -4
- package/dist/astro/routes/api/setup/dev-bypass.mjs +8 -8
- package/dist/astro/routes/api/setup/index.mjs +5 -5
- package/dist/astro/routes/api/setup/status.mjs +2 -2
- package/dist/astro/routes/api/snapshot.mjs +3 -3
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/index.mjs +8 -8
- package/dist/astro/routes/api/themes/preview.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 +3 -3
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +3 -3
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/index.mjs +7 -7
- package/dist/astro/routes/api/widget-components.mjs +1 -1
- package/dist/astro/routes/robots.txt.mjs +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +1 -1
- package/dist/astro/types.d.mts +13 -13
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{bylines-BK9FyU4A.d.mts → bylines-BSzNLT0N.d.mts} +18 -18
- package/dist/cli/index.mjs +801 -48
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +1 -1
- package/dist/{context-93X6MFTb.mjs → context-CUJ2Qwb4.mjs} +1 -1
- package/dist/{context-route-helpers-CcvSXJtQ.mjs → context-route-helpers-CdFWd8GK.mjs} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{device-flow-urJvDoBx.mjs → device-flow-Pab2PQTA.mjs} +4 -4
- package/dist/{hitl-requests-DBcruTcs.mjs → hitl-requests-D5CLRMGC.mjs} +2 -2
- package/dist/{hitl-route-helpers-Dwo_LjhN.mjs → hitl-route-helpers-SRAfZqf9.mjs} +3 -3
- package/dist/{import-B8lnqfnN.mjs → import-CzZYGhnG.mjs} +3 -642
- package/dist/{index-JzJUzE4o.d.mts → index-CxVXYBXq.d.mts} +3 -3
- package/dist/{index-DpMWSamU.d.mts → index-DUurmpun.d.mts} +2 -2
- package/dist/index.d.mts +16 -16
- package/dist/index.mjs +16 -15
- package/dist/{jsonld-CvXmIBls.d.mts → jsonld-C3uKF39u.d.mts} +2 -2
- package/dist/media/index.d.mts +2 -2
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/{menus-BTOa-tsI.mjs → menus-DtoRO2gt.mjs} +1 -1
- package/dist/{oauth-authorization-BZSOekHq.mjs → oauth-authorization-CFcMq7NJ.mjs} +4 -4
- package/dist/{oauth-clients-CqAi-6Y4.mjs → oauth-clients-CS1nQbC3.mjs} +2 -2
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.mjs +1 -1
- package/dist/parser-wEX7xttr.mjs +642 -0
- package/dist/{placeholder-DKMMLt42.d.mts → placeholder-2N6m2_O6.d.mts} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/{preview-CIDYFBzd.mjs → preview-B-MTC5mp.mjs} +1 -1
- package/dist/{provider-loader-BPhii_3H.d.mts → provider-loader-DJ5sLxNP.d.mts} +1 -1
- package/dist/{query-TQqoOaxy.mjs → query-D5CIGQv4.mjs} +2 -2
- package/dist/{runner-CHR_W79l.d.mts → runner-BJm_NJr2.d.mts} +1 -1
- package/dist/{runtime-DY_XmE9Y.d.mts → runtime-CbnJMIeq.d.mts} +10 -10
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +4 -4
- package/dist/seo/index.d.mts +1 -1
- package/dist/{service-DgiH1Yud.mjs → service-Dada1k5R.mjs} +1 -1
- package/dist/{site-context-Rwm9auhW.mjs → site-context-CDnyARws.mjs} +4 -4
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/{taxonomies-CagluJHp.mjs → taxonomies-CZJazF0N.mjs} +1 -1
- package/dist/{taxonomies-DPNIwTGk.mjs → taxonomies-DVXCWoUF.mjs} +1 -1
- package/dist/{types-DS5PYew4.d.mts → types-DzBAohLy.d.mts} +1 -1
- package/dist/ui/server-runtime.d.mts +11 -8
- package/dist/ui/server-runtime.mjs +48 -7
- package/dist/{validate-BQ24E8rK.d.mts → validate-BikB29gc.d.mts} +3 -3
- package/dist/version-BSPT181S.mjs +6 -0
- package/dist/{widgets-D7UK-2hW.mjs → widgets-BFh1UZN5.mjs} +1 -1
- package/package.json +8 -5
- package/src/components/DinewayHead.astro +1 -1
- package/dist/version-qhU-AiPQ.mjs +0 -6
- /package/dist/{activity-events-DbqJBNaY.mjs → activity-events-CjOgr0Uv.mjs} +0 -0
- /package/dist/{adapters-BPzUiHHm.d.mts → adapters-C0EARyCK.d.mts} +0 -0
- /package/dist/{api-tokens-B7fvbHM2.mjs → api-tokens-BZ9aAeCo.mjs} +0 -0
- /package/dist/{auth-control-guard--r6LlNkX.mjs → auth-control-guard-_5V1x8U8.mjs} +0 -0
- /package/dist/{authorize-wQDmXQJ1.mjs → authorize-BgIG3yfN.mjs} +0 -0
- /package/dist/{bylines-B6QpwVAr.mjs → bylines-CaPwztlL.mjs} +0 -0
- /package/dist/{challenge-store-B9odzfeh.mjs → challenge-store-cJam-E5R.mjs} +0 -0
- /package/dist/{comments-BW1qFiTa.mjs → comments-85tbgZQN.mjs} +0 -0
- /package/dist/{components-BQiBW_Ji.mjs → components-DAy-UvX7.mjs} +0 -0
- /package/dist/{default-2JDm1rj_.mjs → default-CiZ8bvSC.mjs} +0 -0
- /package/dist/{escape-Bn168-uP.mjs → escape-DA8zlB7z.mjs} +0 -0
- /package/dist/{experimental-workflows-C7o_9V7S.mjs → experimental-workflows-BbZbIEZp.mjs} +0 -0
- /package/dist/{load-BvyvS_76.mjs → load-5R4qZ4zn.mjs} +0 -0
- /package/dist/{media-allowlist-vdlqBR-8.mjs → media-allowlist-D85gK3We.mjs} +0 -0
- /package/dist/{mode-BI1kRvlT.mjs → mode-Bd55iLcP.mjs} +0 -0
- /package/dist/{oauth-state-store-DhifLitQ.mjs → oauth-state-store-DZs1UZwT.mjs} +0 -0
- /package/dist/{oauth-user-lookup-nyXQ2_6Q.mjs → oauth-user-lookup-B7-6YI3R.mjs} +0 -0
- /package/dist/{passkey-config-DZOjt0Hd.mjs → passkey-config-CDew7KVU.mjs} +0 -0
- /package/dist/{provider-loader-Decn0Ktc.mjs → provider-loader-CCPAVrIg.mjs} +0 -0
- /package/dist/{public-url-5fFLJhjh.mjs → public-url-DuRGs0uF.mjs} +0 -0
- /package/dist/{rate-limit-GN64_Jaw.mjs → rate-limit-5ZeKz7oo.mjs} +0 -0
- /package/dist/{redirect-C077gVTf.mjs → redirect-CbEyClKc.mjs} +0 -0
- /package/dist/{redirects-CvIzUvek.mjs → redirects-Dk7N_YeP.mjs} +0 -0
- /package/dist/{search-vzCYAk0F.mjs → search-DjaP_Dw-.mjs} +0 -0
- /package/dist/{secrets-BIrqds5c.mjs → secrets-DfeNNoLa.mjs} +0 -0
- /package/dist/{seo-contributions-BG4TtU7H.mjs → seo-contributions-D_CLIsxJ.mjs} +0 -0
- /package/dist/{setup-complete-DzOSuHUM.mjs → setup-complete-DgsQYTC2.mjs} +0 -0
- /package/dist/{setup-nonce-DN6BHIlP.mjs → setup-nonce-ChVabyO2.mjs} +0 -0
- /package/dist/{site-url-oyqzZtoL.mjs → site-url-BketXXft.mjs} +0 -0
- /package/dist/{tokens-DB4dASZl.mjs → tokens-BMTKHT6X.mjs} +0 -0
- /package/dist/{transport-DA3H3xB4.d.mts → transport-BZCHo8n0.d.mts} +0 -0
- /package/dist/{transport-B3jxvfio.mjs → transport-Dt7A12-i.mjs} +0 -0
- /package/dist/{types-BDm7Ipoq.d.mts → types-B7Uld4FZ.d.mts} +0 -0
- /package/dist/{types-B45uSz1j.d.mts → types-BSP1HbdT.d.mts} +0 -0
- /package/dist/{types-6N-00csp.d.mts → types-Brp7Hv9S.d.mts} +0 -0
- /package/dist/{types-CsnHvu4J.d.mts → types-CsX_6h1v.d.mts} +0 -0
- /package/dist/{types-D_wGrwiY.d.mts → types-D0UvtzG1.d.mts} +0 -0
- /package/dist/{types-BeYn-Yf0.d.mts → types-DbtpYtHx.d.mts} +0 -0
- /package/dist/{types-CYBaBvtm.d.mts → types-DwIXYH8s.d.mts} +0 -0
- /package/dist/{utils-BJF19gfk.mjs → utils-BftjFpR0.mjs} +0 -0
- /package/dist/{validate-CaKEnLed.mjs → validate-BGpmNtMe.mjs} +0 -0
- /package/dist/{wordpress-slugs-Bnf3-sf8.mjs → wordpress-slugs-BzMv9U-N.mjs} +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -20,22 +20,22 @@ import "../loader-dt5DoyI1.mjs";
|
|
|
20
20
|
import "../settings-D2k1JraC.mjs";
|
|
21
21
|
import { i as pluginManifestSchema } from "../manifest-schema-CU0XL_ZK.mjs";
|
|
22
22
|
import "../ssrf-z3oH8wjK.mjs";
|
|
23
|
-
import { t as validateSeed } from "../validate-
|
|
24
|
-
import { t as applySeed } from "../apply-
|
|
25
|
-
import { n as fingerprintKey, r as generateEncryptionKey, t as DinewaySecretsError } from "../secrets-
|
|
23
|
+
import { t as validateSeed } from "../validate-BGpmNtMe.mjs";
|
|
24
|
+
import { t as applySeed } from "../apply-D7vu4aFn.mjs";
|
|
25
|
+
import { n as fingerprintKey, r as generateEncryptionKey, t as DinewaySecretsError } from "../secrets-DfeNNoLa.mjs";
|
|
26
|
+
import { o as convertDataForRead } from "../transport-Dt7A12-i.mjs";
|
|
26
27
|
import { createHeaderAwareFetch, customHeadersInterceptor, isRedirectResponse, resolveCustomHeaders } from "../client/external-auth-headers.mjs";
|
|
27
|
-
import { o as convertDataForRead } from "../transport-B3jxvfio.mjs";
|
|
28
28
|
import { DinewayClient } from "../client/index.mjs";
|
|
29
29
|
import { LocalStorage } from "../storage/local.mjs";
|
|
30
30
|
import { imageSize } from "image-size";
|
|
31
31
|
import { createGzipDecoder, unpackTar } from "modern-tar";
|
|
32
32
|
import { createHash } from "node:crypto";
|
|
33
|
-
import { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
34
|
-
import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
|
|
33
|
+
import { createReadStream, createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
34
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
35
35
|
import { defineCommand, runCommand, runMain } from "citty";
|
|
36
36
|
import consola, { consola as consola$1 } from "consola";
|
|
37
37
|
import pc from "picocolors";
|
|
38
|
-
import { access, copyFile, mkdir, readFile, readdir, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
38
|
+
import { access, chmod, copyFile, mkdir, readFile, readdir, rm, stat, symlink, writeFile } from "node:fs/promises";
|
|
39
39
|
import { homedir } from "node:os";
|
|
40
40
|
import { createInterface } from "node:readline/promises";
|
|
41
41
|
import { spawn } from "node:child_process";
|
|
@@ -132,7 +132,7 @@ function findProjectRoot(from) {
|
|
|
132
132
|
}
|
|
133
133
|
return null;
|
|
134
134
|
}
|
|
135
|
-
function readStore() {
|
|
135
|
+
function readStore$1() {
|
|
136
136
|
const path = getCredentialPath();
|
|
137
137
|
try {
|
|
138
138
|
if (existsSync(path)) {
|
|
@@ -142,7 +142,7 @@ function readStore() {
|
|
|
142
142
|
} catch {}
|
|
143
143
|
return {};
|
|
144
144
|
}
|
|
145
|
-
function writeStore(store) {
|
|
145
|
+
function writeStore$1(store) {
|
|
146
146
|
mkdirSync(getConfigDir(), {
|
|
147
147
|
recursive: true,
|
|
148
148
|
mode: 448
|
|
@@ -157,7 +157,7 @@ function writeStore(store) {
|
|
|
157
157
|
*/
|
|
158
158
|
function getCredentials(baseUrl) {
|
|
159
159
|
const key = resolveCredentialKey(baseUrl);
|
|
160
|
-
const cred = readStore()[key];
|
|
160
|
+
const cred = readStore$1()[key];
|
|
161
161
|
if (!cred || !("accessToken" in cred)) return null;
|
|
162
162
|
return cred;
|
|
163
163
|
}
|
|
@@ -166,19 +166,19 @@ function getCredentials(baseUrl) {
|
|
|
166
166
|
*/
|
|
167
167
|
function saveCredentials(baseUrl, cred) {
|
|
168
168
|
const key = resolveCredentialKey(baseUrl);
|
|
169
|
-
const store = readStore();
|
|
169
|
+
const store = readStore$1();
|
|
170
170
|
store[key] = cred;
|
|
171
|
-
writeStore(store);
|
|
171
|
+
writeStore$1(store);
|
|
172
172
|
}
|
|
173
173
|
/**
|
|
174
174
|
* Remove credentials for a URL.
|
|
175
175
|
*/
|
|
176
176
|
function removeCredentials(baseUrl) {
|
|
177
177
|
const key = resolveCredentialKey(baseUrl);
|
|
178
|
-
const store = readStore();
|
|
178
|
+
const store = readStore$1();
|
|
179
179
|
if (key in store) {
|
|
180
180
|
delete store[key];
|
|
181
|
-
writeStore(store);
|
|
181
|
+
writeStore$1(store);
|
|
182
182
|
return true;
|
|
183
183
|
}
|
|
184
184
|
return false;
|
|
@@ -195,7 +195,7 @@ function marketplaceKey(registryUrl) {
|
|
|
195
195
|
*/
|
|
196
196
|
function getMarketplaceCredential(registryUrl) {
|
|
197
197
|
const key = marketplaceKey(registryUrl);
|
|
198
|
-
const cred = readStore()[key];
|
|
198
|
+
const cred = readStore$1()[key];
|
|
199
199
|
if (!cred || !("token" in cred)) return null;
|
|
200
200
|
if (new Date(cred.expiresAt) < /* @__PURE__ */ new Date()) return null;
|
|
201
201
|
return cred;
|
|
@@ -205,19 +205,19 @@ function getMarketplaceCredential(registryUrl) {
|
|
|
205
205
|
*/
|
|
206
206
|
function saveMarketplaceCredential(registryUrl, cred) {
|
|
207
207
|
const key = marketplaceKey(registryUrl);
|
|
208
|
-
const store = readStore();
|
|
208
|
+
const store = readStore$1();
|
|
209
209
|
store[key] = cred;
|
|
210
|
-
writeStore(store);
|
|
210
|
+
writeStore$1(store);
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Remove marketplace credential for a registry URL.
|
|
214
214
|
*/
|
|
215
215
|
function removeMarketplaceCredential(registryUrl) {
|
|
216
216
|
const key = marketplaceKey(registryUrl);
|
|
217
|
-
const store = readStore();
|
|
217
|
+
const store = readStore$1();
|
|
218
218
|
if (key in store) {
|
|
219
219
|
delete store[key];
|
|
220
|
-
writeStore(store);
|
|
220
|
+
writeStore$1(store);
|
|
221
221
|
return true;
|
|
222
222
|
}
|
|
223
223
|
return false;
|
|
@@ -917,7 +917,7 @@ volumes:
|
|
|
917
917
|
|
|
918
918
|
//#endregion
|
|
919
919
|
//#region src/cli/commands/deploy/targets/docker.ts
|
|
920
|
-
async function fileExists$
|
|
920
|
+
async function fileExists$10(path) {
|
|
921
921
|
try {
|
|
922
922
|
await access(path);
|
|
923
923
|
return true;
|
|
@@ -927,7 +927,7 @@ async function fileExists$9(path) {
|
|
|
927
927
|
}
|
|
928
928
|
async function writeGeneratedFile$2(cwd, relativePath, content, dryRun) {
|
|
929
929
|
const path = join(cwd, relativePath);
|
|
930
|
-
if (await fileExists$
|
|
930
|
+
if (await fileExists$10(path)) return {
|
|
931
931
|
path: relativePath,
|
|
932
932
|
action: "exists"
|
|
933
933
|
};
|
|
@@ -1013,7 +1013,7 @@ const EDGE_HYPHENS_RE$2 = /^-|-$/g;
|
|
|
1013
1013
|
const LINE_SPLIT_RE = /\r?\n/;
|
|
1014
1014
|
const DEFAULT_REGION$1 = "iad";
|
|
1015
1015
|
const FLY_VOLUME_NAME = "dineway_data";
|
|
1016
|
-
async function fileExists$
|
|
1016
|
+
async function fileExists$9(path) {
|
|
1017
1017
|
try {
|
|
1018
1018
|
await access(path);
|
|
1019
1019
|
return true;
|
|
@@ -1023,7 +1023,7 @@ async function fileExists$8(path) {
|
|
|
1023
1023
|
}
|
|
1024
1024
|
async function writeGeneratedFile$1(cwd, relativePath, content, dryRun) {
|
|
1025
1025
|
const path = join(cwd, relativePath);
|
|
1026
|
-
if (await fileExists$
|
|
1026
|
+
if (await fileExists$9(path)) return {
|
|
1027
1027
|
path: relativePath,
|
|
1028
1028
|
action: "exists"
|
|
1029
1029
|
};
|
|
@@ -1211,6 +1211,747 @@ const flyTarget = {
|
|
|
1211
1211
|
}
|
|
1212
1212
|
};
|
|
1213
1213
|
|
|
1214
|
+
//#endregion
|
|
1215
|
+
//#region src/cli/commands/deploy/utils/config.ts
|
|
1216
|
+
async function readDeployPackageJson(cwd) {
|
|
1217
|
+
const content = await readFile(join(cwd, "package.json"), "utf-8");
|
|
1218
|
+
return JSON.parse(content);
|
|
1219
|
+
}
|
|
1220
|
+
async function readSavedDeployTarget(cwd) {
|
|
1221
|
+
return (await readDeployPackageJson(cwd)).dineway?.deploy?.target;
|
|
1222
|
+
}
|
|
1223
|
+
async function writeDeployTarget(cwd, target) {
|
|
1224
|
+
const pkgPath = join(cwd, "package.json");
|
|
1225
|
+
const pkg = await readDeployPackageJson(cwd);
|
|
1226
|
+
pkg.dineway = {
|
|
1227
|
+
...pkg.dineway,
|
|
1228
|
+
deploy: {
|
|
1229
|
+
...pkg.dineway?.deploy,
|
|
1230
|
+
target
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, " ") + "\n", "utf-8");
|
|
1234
|
+
}
|
|
1235
|
+
async function writeForgewayDeployMetadata(cwd, metadata, restaurant) {
|
|
1236
|
+
const pkgPath = join(cwd, "package.json");
|
|
1237
|
+
const pkg = await readDeployPackageJson(cwd);
|
|
1238
|
+
pkg.dineway = {
|
|
1239
|
+
...pkg.dineway,
|
|
1240
|
+
...restaurant ? { restaurant: {
|
|
1241
|
+
...pkg.dineway?.restaurant,
|
|
1242
|
+
...restaurant
|
|
1243
|
+
} } : {},
|
|
1244
|
+
deploy: {
|
|
1245
|
+
...pkg.dineway?.deploy,
|
|
1246
|
+
forgeway: {
|
|
1247
|
+
...pkg.dineway?.deploy?.forgeway,
|
|
1248
|
+
...metadata
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1252
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, " ") + "\n", "utf-8");
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
//#endregion
|
|
1256
|
+
//#region src/cli/commands/deploy/utils/forgeway-secrets.ts
|
|
1257
|
+
function getDinewayConfigDir() {
|
|
1258
|
+
const xdg = process.env["XDG_CONFIG_HOME"];
|
|
1259
|
+
return join(xdg || join(homedir(), ".config"), "dineway");
|
|
1260
|
+
}
|
|
1261
|
+
function getForgewaySecretPath() {
|
|
1262
|
+
return join(getDinewayConfigDir(), "forgeway.json");
|
|
1263
|
+
}
|
|
1264
|
+
async function readStore() {
|
|
1265
|
+
try {
|
|
1266
|
+
const raw = await readFile(getForgewaySecretPath(), "utf-8");
|
|
1267
|
+
return JSON.parse(raw);
|
|
1268
|
+
} catch {
|
|
1269
|
+
return {};
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
async function writeStore(store) {
|
|
1273
|
+
await mkdir(getDinewayConfigDir(), {
|
|
1274
|
+
recursive: true,
|
|
1275
|
+
mode: 448
|
|
1276
|
+
});
|
|
1277
|
+
const file = getForgewaySecretPath();
|
|
1278
|
+
await writeFile(file, JSON.stringify(store, null, " ") + "\n", {
|
|
1279
|
+
encoding: "utf-8",
|
|
1280
|
+
mode: 384
|
|
1281
|
+
});
|
|
1282
|
+
await chmod(file, 384);
|
|
1283
|
+
}
|
|
1284
|
+
async function readForgewayCredentials() {
|
|
1285
|
+
return (await readStore()).credentials ?? null;
|
|
1286
|
+
}
|
|
1287
|
+
async function writeForgewayCredentials(credentials) {
|
|
1288
|
+
const store = await readStore();
|
|
1289
|
+
store.credentials = credentials;
|
|
1290
|
+
await writeStore(store);
|
|
1291
|
+
}
|
|
1292
|
+
async function readForgewayProjectSecret(projectId) {
|
|
1293
|
+
return (await readStore()).projects?.[projectId] ?? null;
|
|
1294
|
+
}
|
|
1295
|
+
async function writeForgewayProjectSecret(projectId, secret) {
|
|
1296
|
+
const store = await readStore();
|
|
1297
|
+
store.projects = {
|
|
1298
|
+
...store.projects,
|
|
1299
|
+
[projectId]: secret
|
|
1300
|
+
};
|
|
1301
|
+
await writeStore(store);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
//#endregion
|
|
1305
|
+
//#region src/cli/commands/deploy/targets/forgeway.ts
|
|
1306
|
+
const DEFAULT_PLATFORM_API_URL = "https://api.dineway.ai";
|
|
1307
|
+
const DEFAULT_SITE_BASE_DOMAIN = "dineway.site";
|
|
1308
|
+
const DATABASE_ENV_VAR_NAMES = ["DINEWAY_DATABASE_URL", "DINEWAY_DATABASE_AUTH_TOKEN"];
|
|
1309
|
+
const POLL_INTERVAL_MS$1 = 5e3;
|
|
1310
|
+
const POLL_TIMEOUT_MS$1 = 3e5;
|
|
1311
|
+
const DIRECT_UPLOAD_CONCURRENCY = 8;
|
|
1312
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
1313
|
+
const SLUG_SEPARATOR_PATTERN = /[^a-z0-9]+/g;
|
|
1314
|
+
const LEADING_TRAILING_HYPHEN_PATTERN = /^-+|-+$/g;
|
|
1315
|
+
const JWT_PATTERN = /[A-Za-z0-9_-]{32,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}/g;
|
|
1316
|
+
const TOKEN_ASSIGNMENT_PATTERN = /(DINEWAY_DATABASE_AUTH_TOKEN|DATABASE_AUTH_TOKEN|AUTH_TOKEN)=\S+/gi;
|
|
1317
|
+
const TRAILING_SLASH_PATTERN = /\/$/;
|
|
1318
|
+
const BACKSLASH_PATTERN = /\\/g;
|
|
1319
|
+
const EXCLUDE_PATTERNS = [
|
|
1320
|
+
"node_modules",
|
|
1321
|
+
".git",
|
|
1322
|
+
".next",
|
|
1323
|
+
".env",
|
|
1324
|
+
".env.local",
|
|
1325
|
+
"dist",
|
|
1326
|
+
"build",
|
|
1327
|
+
".DS_Store",
|
|
1328
|
+
".forgeway",
|
|
1329
|
+
".claude",
|
|
1330
|
+
".agents",
|
|
1331
|
+
".augment",
|
|
1332
|
+
".kilocode",
|
|
1333
|
+
".kiro",
|
|
1334
|
+
".qoder",
|
|
1335
|
+
".qwen",
|
|
1336
|
+
".roo",
|
|
1337
|
+
".trae",
|
|
1338
|
+
".windsurf",
|
|
1339
|
+
".vercel",
|
|
1340
|
+
".turbo",
|
|
1341
|
+
".cache",
|
|
1342
|
+
"skills",
|
|
1343
|
+
"coverage"
|
|
1344
|
+
];
|
|
1345
|
+
var ForgewayApiError = class extends Error {
|
|
1346
|
+
constructor(message, status) {
|
|
1347
|
+
super(message);
|
|
1348
|
+
this.status = status;
|
|
1349
|
+
this.name = "ForgewayApiError";
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
function normalizeForgewayUser(user) {
|
|
1353
|
+
return {
|
|
1354
|
+
id: user.id,
|
|
1355
|
+
name: user.profile?.name ?? user.name ?? user.email,
|
|
1356
|
+
email: user.email,
|
|
1357
|
+
avatarUrl: user.profile?.avatar_url ?? user.avatarUrl ?? user.avatar_url ?? null,
|
|
1358
|
+
emailVerified: user.emailVerified ?? user.email_verified ?? true
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function getFetch(deps) {
|
|
1362
|
+
return deps.fetch ?? fetch;
|
|
1363
|
+
}
|
|
1364
|
+
async function fileExists$8(path) {
|
|
1365
|
+
try {
|
|
1366
|
+
await access(path);
|
|
1367
|
+
return true;
|
|
1368
|
+
} catch {
|
|
1369
|
+
return false;
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
function normalizePlatformApiUrl(value) {
|
|
1373
|
+
return (value || DEFAULT_PLATFORM_API_URL).replace(TRAILING_SLASH_PATTERN, "");
|
|
1374
|
+
}
|
|
1375
|
+
function getEnv(name) {
|
|
1376
|
+
const value = process.env[name];
|
|
1377
|
+
return value && value.trim() ? value.trim() : void 0;
|
|
1378
|
+
}
|
|
1379
|
+
async function readJsonResponse(response) {
|
|
1380
|
+
return await response.json().catch(() => null);
|
|
1381
|
+
}
|
|
1382
|
+
async function forgewayRequest(url, options, deps) {
|
|
1383
|
+
try {
|
|
1384
|
+
return await getFetch(deps)(url, options);
|
|
1385
|
+
} catch (error) {
|
|
1386
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1387
|
+
throw new Error(`Network request to ${url} failed: ${message}`, { cause: error });
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
async function parseErrorResponse(response) {
|
|
1391
|
+
const payload = await readJsonResponse(response);
|
|
1392
|
+
if (payload && typeof payload === "object") {
|
|
1393
|
+
const error = payload;
|
|
1394
|
+
let message = error.message ?? error.error ?? `Forgeway request failed: ${response.status}`;
|
|
1395
|
+
if (error.nextActions) message += `\n${error.nextActions}`;
|
|
1396
|
+
return message;
|
|
1397
|
+
}
|
|
1398
|
+
return `Forgeway request failed: ${response.status}`;
|
|
1399
|
+
}
|
|
1400
|
+
async function loginWithEmail(platformApiUrl, deps) {
|
|
1401
|
+
const email = getEnv("FORGEWAY_EMAIL") ?? await promptRequired("Forgeway email: ", void 0, deps, "Forgeway email is required.");
|
|
1402
|
+
const password = getEnv("FORGEWAY_PASSWORD") ?? await promptRequired("Forgeway password: ", void 0, deps, "Forgeway password is required.");
|
|
1403
|
+
const response = await forgewayRequest(`${platformApiUrl}/api/auth/admin/sessions`, {
|
|
1404
|
+
method: "POST",
|
|
1405
|
+
headers: { "Content-Type": "application/json" },
|
|
1406
|
+
body: JSON.stringify({
|
|
1407
|
+
email,
|
|
1408
|
+
password
|
|
1409
|
+
})
|
|
1410
|
+
}, deps);
|
|
1411
|
+
if (!response.ok) throw new Error(await parseErrorResponse(response));
|
|
1412
|
+
const payload = await response.json();
|
|
1413
|
+
if (!payload.accessToken || !payload.user) throw new Error("Forgeway login response was missing accessToken or user.");
|
|
1414
|
+
return {
|
|
1415
|
+
platformApiUrl,
|
|
1416
|
+
accessToken: payload.accessToken,
|
|
1417
|
+
refreshToken: payload.refreshToken,
|
|
1418
|
+
user: normalizeForgewayUser(payload.user)
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
async function resolveCredentials(platformApiUrl, deps, dryRun) {
|
|
1422
|
+
const envToken = getEnv("FORGEWAY_ACCESS_TOKEN");
|
|
1423
|
+
if (envToken) return {
|
|
1424
|
+
platformApiUrl,
|
|
1425
|
+
accessToken: envToken
|
|
1426
|
+
};
|
|
1427
|
+
const stored = await (deps.readCredentials ?? readForgewayCredentials)();
|
|
1428
|
+
if (stored?.accessToken) return {
|
|
1429
|
+
...stored,
|
|
1430
|
+
platformApiUrl
|
|
1431
|
+
};
|
|
1432
|
+
if (dryRun) throw new Error("Forgeway authentication is required. Set FORGEWAY_ACCESS_TOKEN or deploy without --dry-run after logging in.");
|
|
1433
|
+
const credentials = await loginWithEmail(platformApiUrl, deps);
|
|
1434
|
+
await (deps.writeCredentials ?? writeForgewayCredentials)(credentials);
|
|
1435
|
+
return credentials;
|
|
1436
|
+
}
|
|
1437
|
+
async function platformFetch(path, context, deps, options = {}) {
|
|
1438
|
+
const request = async (accessToken) => await forgewayRequest(`${context.platformApiUrl}${path}`, {
|
|
1439
|
+
...options,
|
|
1440
|
+
headers: {
|
|
1441
|
+
"Content-Type": "application/json",
|
|
1442
|
+
Authorization: `Bearer ${accessToken}`,
|
|
1443
|
+
...options.headers
|
|
1444
|
+
}
|
|
1445
|
+
}, deps);
|
|
1446
|
+
let response = await request(context.credentials.accessToken);
|
|
1447
|
+
if (response.status === 401 && context.credentials.refreshToken) {
|
|
1448
|
+
const refreshed = await refreshAccessToken(context.platformApiUrl, context.credentials, deps);
|
|
1449
|
+
context.credentials.accessToken = refreshed;
|
|
1450
|
+
response = await request(refreshed);
|
|
1451
|
+
}
|
|
1452
|
+
if (!response.ok) throw new ForgewayApiError(await parseErrorResponse(response), response.status);
|
|
1453
|
+
return await response.json();
|
|
1454
|
+
}
|
|
1455
|
+
async function refreshAccessToken(platformApiUrl, credentials, deps) {
|
|
1456
|
+
if (!credentials.refreshToken) throw new Error("Forgeway refresh token is missing. Log in again.");
|
|
1457
|
+
const response = await forgewayRequest(`${platformApiUrl}/api/auth/refresh?client_type=server`, {
|
|
1458
|
+
method: "POST",
|
|
1459
|
+
headers: { "Content-Type": "application/json" },
|
|
1460
|
+
body: JSON.stringify({ refreshToken: credentials.refreshToken })
|
|
1461
|
+
}, deps);
|
|
1462
|
+
if (!response.ok) throw new Error("Failed to refresh Forgeway access token. Log in again.");
|
|
1463
|
+
const payload = await response.json();
|
|
1464
|
+
if (!payload.accessToken) throw new Error("Forgeway refresh response was missing accessToken.");
|
|
1465
|
+
const updated = {
|
|
1466
|
+
...credentials,
|
|
1467
|
+
platformApiUrl,
|
|
1468
|
+
accessToken: payload.accessToken,
|
|
1469
|
+
refreshToken: payload.refreshToken ?? credentials.refreshToken
|
|
1470
|
+
};
|
|
1471
|
+
await (deps.writeCredentials ?? writeForgewayCredentials)(updated);
|
|
1472
|
+
return payload.accessToken;
|
|
1473
|
+
}
|
|
1474
|
+
async function promptText(question, initialValue, deps) {
|
|
1475
|
+
if (deps.promptText) return await deps.promptText(question, initialValue);
|
|
1476
|
+
if (!process.stdin.isTTY) return "";
|
|
1477
|
+
const suffix = initialValue ? ` [${initialValue}]` : "";
|
|
1478
|
+
const rl = createInterface({
|
|
1479
|
+
input: process.stdin,
|
|
1480
|
+
output: process.stdout
|
|
1481
|
+
});
|
|
1482
|
+
try {
|
|
1483
|
+
return (await rl.question(`${question}${suffix}`)).trim() || initialValue || "";
|
|
1484
|
+
} finally {
|
|
1485
|
+
rl.close();
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
async function promptRequired(question, initialValue, deps, errorMessage) {
|
|
1489
|
+
const answer = await promptText(question, initialValue, deps);
|
|
1490
|
+
if (!answer) throw new Error(errorMessage);
|
|
1491
|
+
return answer;
|
|
1492
|
+
}
|
|
1493
|
+
async function chooseSingleOrPrompt(label, items, deps) {
|
|
1494
|
+
if (items.length === 0) throw new Error(`No Forgeway ${label}s found.`);
|
|
1495
|
+
if (items.length === 1) return items[0];
|
|
1496
|
+
if (!process.stdin.isTTY && !deps.promptText) throw new Error(`Multiple Forgeway ${label}s found. Set FORGEWAY_${label.toUpperCase()}_ID.`);
|
|
1497
|
+
consola.info(`Available Forgeway ${label}s:`);
|
|
1498
|
+
items.forEach((item, index) => consola.info(` ${index + 1}. ${item.name} (${item.id})`));
|
|
1499
|
+
const answer = await promptRequired(`Choose ${label}: `, "1", deps, `${label} is required.`);
|
|
1500
|
+
const index = Number(answer);
|
|
1501
|
+
if (!Number.isInteger(index) || index < 1 || index > items.length) throw new Error(`Invalid Forgeway ${label} selection: ${answer}`);
|
|
1502
|
+
return items[index - 1];
|
|
1503
|
+
}
|
|
1504
|
+
function getSavedForgewayMetadata(pkg) {
|
|
1505
|
+
return pkg.dineway?.deploy?.forgeway ?? {};
|
|
1506
|
+
}
|
|
1507
|
+
async function resolveProjectContext(cwd, options, deps) {
|
|
1508
|
+
const saved = getSavedForgewayMetadata(await readDeployPackageJson(cwd));
|
|
1509
|
+
const platformApiUrl = normalizePlatformApiUrl(getEnv("FORGEWAY_API_URL") ?? (typeof saved.platformApiUrl === "string" ? saved.platformApiUrl : void 0));
|
|
1510
|
+
const platformContext = {
|
|
1511
|
+
platformApiUrl,
|
|
1512
|
+
credentials: await resolveCredentials(platformApiUrl, deps, Boolean(options.dryRun))
|
|
1513
|
+
};
|
|
1514
|
+
let projectId = getEnv("FORGEWAY_PROJECT_ID") ?? (typeof saved.projectId === "string" ? saved.projectId : void 0);
|
|
1515
|
+
let project = null;
|
|
1516
|
+
if (!projectId) {
|
|
1517
|
+
const orgId = getEnv("FORGEWAY_ORG_ID");
|
|
1518
|
+
project = await chooseSingleOrPrompt("project", await listProjects((orgId !== void 0 ? {
|
|
1519
|
+
id: orgId,
|
|
1520
|
+
name: orgId
|
|
1521
|
+
} : await chooseSingleOrPrompt("org", await listOrganizations(platformContext, deps), deps)).id, platformContext, deps), deps);
|
|
1522
|
+
projectId = project.id;
|
|
1523
|
+
}
|
|
1524
|
+
if (!project) {
|
|
1525
|
+
if (!projectId) throw new Error("Forgeway project id is required");
|
|
1526
|
+
project = unwrapProjectPayload(await platformFetch(`/projects/v1/${encodeURIComponent(projectId)}`, platformContext, deps));
|
|
1527
|
+
}
|
|
1528
|
+
const savedSecret = await (deps.readProjectSecret ?? readForgewayProjectSecret)(projectId) ?? void 0;
|
|
1529
|
+
const apiKey = getEnv("FORGEWAY_PROJECT_API_KEY") ?? savedSecret?.apiKey ?? await fetchProjectApiKey(projectId, platformContext, deps);
|
|
1530
|
+
const orgId = project.organization_id ?? project.organizationId ?? (typeof saved.orgId === "string" ? saved.orgId : "unknown");
|
|
1531
|
+
const ossHost = getEnv("FORGEWAY_OSS_HOST") ?? savedSecret?.ossHost ?? (typeof saved.ossHost === "string" ? saved.ossHost : void 0) ?? `https://${project.appkey}.${project.region}.${DEFAULT_SITE_BASE_DOMAIN}`;
|
|
1532
|
+
if (!options.dryRun) {
|
|
1533
|
+
await (deps.writeProjectSecret ?? writeForgewayProjectSecret)(projectId, {
|
|
1534
|
+
apiKey,
|
|
1535
|
+
ossHost
|
|
1536
|
+
});
|
|
1537
|
+
await writeForgewayDeployMetadata(cwd, {
|
|
1538
|
+
platformApiUrl,
|
|
1539
|
+
projectId,
|
|
1540
|
+
projectName: project.name,
|
|
1541
|
+
orgId,
|
|
1542
|
+
appkey: project.appkey,
|
|
1543
|
+
region: project.region,
|
|
1544
|
+
ossHost
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
return {
|
|
1548
|
+
platformApiUrl,
|
|
1549
|
+
projectId,
|
|
1550
|
+
projectName: project.name,
|
|
1551
|
+
orgId,
|
|
1552
|
+
appkey: project.appkey,
|
|
1553
|
+
region: project.region,
|
|
1554
|
+
apiKey,
|
|
1555
|
+
ossHost
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1558
|
+
function unwrapProjectPayload(payload) {
|
|
1559
|
+
if (isRecord(payload) && "project" in payload) {
|
|
1560
|
+
if (isForgewayProject(payload.project)) return payload.project;
|
|
1561
|
+
throw new Error("Forgeway project response did not include a project");
|
|
1562
|
+
}
|
|
1563
|
+
if (isForgewayProject(payload)) return payload;
|
|
1564
|
+
throw new Error("Forgeway project response did not include a project");
|
|
1565
|
+
}
|
|
1566
|
+
function isForgewayProject(value) {
|
|
1567
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.name === "string" && typeof value.appkey === "string" && typeof value.region === "string";
|
|
1568
|
+
}
|
|
1569
|
+
function isRecord(value) {
|
|
1570
|
+
return typeof value === "object" && value !== null;
|
|
1571
|
+
}
|
|
1572
|
+
async function listOrganizations(context, deps) {
|
|
1573
|
+
const payload = await platformFetch("/organizations/v1", context, deps);
|
|
1574
|
+
return Array.isArray(payload) ? payload : payload.organizations ?? [];
|
|
1575
|
+
}
|
|
1576
|
+
async function listProjects(orgId, context, deps) {
|
|
1577
|
+
const payload = await platformFetch(`/organizations/v1/${encodeURIComponent(orgId)}/projects`, context, deps);
|
|
1578
|
+
return Array.isArray(payload) ? payload : payload.projects ?? [];
|
|
1579
|
+
}
|
|
1580
|
+
async function fetchProjectApiKey(projectId, context, deps) {
|
|
1581
|
+
const payload = await platformFetch(`/projects/v1/${encodeURIComponent(projectId)}/access-api-key`, context, deps);
|
|
1582
|
+
const apiKey = payload.access_api_key ?? payload.apiKey;
|
|
1583
|
+
if (!apiKey) throw new Error("Forgeway project API key response was empty.");
|
|
1584
|
+
return apiKey;
|
|
1585
|
+
}
|
|
1586
|
+
async function ossFetch(context, path, deps, options = {}) {
|
|
1587
|
+
const response = await forgewayRequest(`${context.ossHost.replace(TRAILING_SLASH_PATTERN, "")}${path}`, {
|
|
1588
|
+
...options,
|
|
1589
|
+
headers: {
|
|
1590
|
+
"Content-Type": "application/json",
|
|
1591
|
+
Authorization: `Bearer ${context.apiKey}`,
|
|
1592
|
+
...options.headers
|
|
1593
|
+
}
|
|
1594
|
+
}, deps);
|
|
1595
|
+
if (!response.ok) throw new ForgewayApiError(await parseErrorResponse(response), response.status);
|
|
1596
|
+
return await response.json();
|
|
1597
|
+
}
|
|
1598
|
+
function parseDatabaseMode(value) {
|
|
1599
|
+
const mode = value ?? "turso";
|
|
1600
|
+
if (mode === "none" || mode === "turso" || UUID_PATTERN.test(mode)) return mode;
|
|
1601
|
+
throw new Error("--database must be \"none\", \"turso\", or a managed database UUID.");
|
|
1602
|
+
}
|
|
1603
|
+
function deriveForgewaySiteSlug(restaurantName, city) {
|
|
1604
|
+
return `${restaurantName} ${city}`.toLowerCase().normalize("NFKD").replace(SLUG_SEPARATOR_PATTERN, "-").replace(LEADING_TRAILING_HYPHEN_PATTERN, "").slice(0, 63).replace(LEADING_TRAILING_HYPHEN_PATTERN, "") || "site";
|
|
1605
|
+
}
|
|
1606
|
+
async function resolveSeedPath$1(cwd, explicitSeedPath) {
|
|
1607
|
+
if (explicitSeedPath) {
|
|
1608
|
+
const resolved = resolve(cwd, explicitSeedPath);
|
|
1609
|
+
if (!await fileExists$8(resolved)) throw new Error(`Seed file not found: ${explicitSeedPath}`);
|
|
1610
|
+
return resolved;
|
|
1611
|
+
}
|
|
1612
|
+
const convention = resolve(cwd, ".dineway", "seed.json");
|
|
1613
|
+
if (await fileExists$8(convention)) return convention;
|
|
1614
|
+
const pkg = await readDeployPackageJson(cwd).catch(() => null);
|
|
1615
|
+
if (typeof pkg?.dineway?.seed === "string") {
|
|
1616
|
+
const configured = resolve(cwd, pkg.dineway.seed);
|
|
1617
|
+
if (await fileExists$8(configured)) return configured;
|
|
1618
|
+
}
|
|
1619
|
+
const legacyConvention = resolve(cwd, "seed", "seed.json");
|
|
1620
|
+
if (await fileExists$8(legacyConvention)) return legacyConvention;
|
|
1621
|
+
return null;
|
|
1622
|
+
}
|
|
1623
|
+
async function readSeedTitle(seedPath) {
|
|
1624
|
+
if (!seedPath) return void 0;
|
|
1625
|
+
try {
|
|
1626
|
+
const title = JSON.parse(await readFile(seedPath, "utf-8")).settings?.title;
|
|
1627
|
+
return typeof title === "string" && title.trim() ? title.trim() : void 0;
|
|
1628
|
+
} catch {
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
async function resolveRestaurantInfo(cwd, options, seedPath, deps, requireForSlug) {
|
|
1633
|
+
const savedRestaurant = (await readDeployPackageJson(cwd).catch(() => null))?.dineway?.restaurant;
|
|
1634
|
+
const seedTitle = await readSeedTitle(seedPath);
|
|
1635
|
+
let name = options.restaurantName ?? savedRestaurant?.name ?? seedTitle;
|
|
1636
|
+
let city = options.city ?? savedRestaurant?.city;
|
|
1637
|
+
if (requireForSlug) {
|
|
1638
|
+
if (!name) name = await promptRequired("Restaurant name: ", void 0, deps, "Restaurant name is required. Pass --restaurant-name or set dineway.restaurant.name.");
|
|
1639
|
+
if (!city) city = await promptRequired("City: ", void 0, deps, "City is required. Pass --city or set dineway.restaurant.city.");
|
|
1640
|
+
}
|
|
1641
|
+
return {
|
|
1642
|
+
name,
|
|
1643
|
+
city
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1646
|
+
function normalizeSiteDetail(payload) {
|
|
1647
|
+
if (payload.site) return payload.site;
|
|
1648
|
+
if (!payload.id || !payload.slug || !payload.domain || !payload.framework) throw new Error("Forgeway site response was missing required fields.");
|
|
1649
|
+
return {
|
|
1650
|
+
id: payload.id,
|
|
1651
|
+
slug: payload.slug,
|
|
1652
|
+
domain: payload.domain,
|
|
1653
|
+
framework: payload.framework
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
async function getDeploymentSite(context, site, deps) {
|
|
1657
|
+
try {
|
|
1658
|
+
return normalizeSiteDetail(await ossFetch(context, `/api/deployments/sites/${encodeURIComponent(site)}`, deps));
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
if (error instanceof ForgewayApiError && error.status === 404) return null;
|
|
1661
|
+
throw error;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
async function createDeploymentSite(context, input, deps) {
|
|
1665
|
+
return await ossFetch(context, "/api/deployments/sites", deps, {
|
|
1666
|
+
method: "POST",
|
|
1667
|
+
body: JSON.stringify({
|
|
1668
|
+
slug: input.slug,
|
|
1669
|
+
framework: "astro",
|
|
1670
|
+
...input.restaurant?.name ? { placeName: input.restaurant.name } : {},
|
|
1671
|
+
...input.restaurant?.city ? { city: input.restaurant.city } : {}
|
|
1672
|
+
})
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
async function resolveDeploymentSite(cwd, context, options, seedPath, deps) {
|
|
1676
|
+
const pkg = await readDeployPackageJson(cwd).catch(() => null);
|
|
1677
|
+
const saved = pkg ? getSavedForgewayMetadata(pkg) : {};
|
|
1678
|
+
const explicitSite = options.site;
|
|
1679
|
+
const savedSite = typeof saved.siteId === "string" ? saved.siteId : saved.siteSlug;
|
|
1680
|
+
const siteRef = explicitSite ?? savedSite;
|
|
1681
|
+
const restaurant = await resolveRestaurantInfo(cwd, options, seedPath, deps, !siteRef);
|
|
1682
|
+
const targetSlug = siteRef ?? deriveForgewaySiteSlug(restaurant.name || "", restaurant.city || "");
|
|
1683
|
+
let site = await getDeploymentSite(context, targetSlug, deps);
|
|
1684
|
+
if (!site) site = await createDeploymentSite(context, {
|
|
1685
|
+
slug: targetSlug,
|
|
1686
|
+
restaurant
|
|
1687
|
+
}, deps);
|
|
1688
|
+
if (!options.dryRun) await writeForgewayDeployMetadata(cwd, {
|
|
1689
|
+
siteId: site.id,
|
|
1690
|
+
siteSlug: site.slug,
|
|
1691
|
+
siteDomain: site.domain
|
|
1692
|
+
}, restaurant);
|
|
1693
|
+
return {
|
|
1694
|
+
site,
|
|
1695
|
+
restaurant
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function redactDatabaseOutput(value, secrets) {
|
|
1699
|
+
let redacted = value;
|
|
1700
|
+
for (const secret of secrets) if (secret.length > 0) redacted = redacted.split(secret).join("[redacted]");
|
|
1701
|
+
return redacted.replace(JWT_PATTERN, "[redacted-token]").replace(TOKEN_ASSIGNMENT_PATTERN, "$1=[redacted]");
|
|
1702
|
+
}
|
|
1703
|
+
async function runDinewayInitialization(options) {
|
|
1704
|
+
const db = createDatabase({
|
|
1705
|
+
url: options.credentials.databaseUrl,
|
|
1706
|
+
authToken: options.credentials.authToken
|
|
1707
|
+
});
|
|
1708
|
+
try {
|
|
1709
|
+
await runMigrations(db);
|
|
1710
|
+
if (options.seedPath) {
|
|
1711
|
+
const seed = JSON.parse(await readFile(options.seedPath, "utf-8"));
|
|
1712
|
+
const validation = validateSeed(seed);
|
|
1713
|
+
if (!validation.valid) throw new Error(`Seed validation failed: ${validation.errors.join("; ")}`);
|
|
1714
|
+
const uploadsDir = resolve(options.cwd, "uploads");
|
|
1715
|
+
await mkdir(uploadsDir, { recursive: true });
|
|
1716
|
+
await applySeed(db, seed, {
|
|
1717
|
+
includeContent: true,
|
|
1718
|
+
onConflict: "skip",
|
|
1719
|
+
storage: new LocalStorage({
|
|
1720
|
+
directory: uploadsDir,
|
|
1721
|
+
baseUrl: "/_dineway/api/media/file"
|
|
1722
|
+
})
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
} catch (error) {
|
|
1726
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1727
|
+
throw new Error(redactDatabaseOutput(message, [options.credentials.authToken, options.credentials.databaseUrl]), { cause: error });
|
|
1728
|
+
} finally {
|
|
1729
|
+
await db.destroy();
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
async function bindSiteDatabase(context, siteId, database, deps) {
|
|
1733
|
+
return await ossFetch(context, `/api/deployments/sites/${encodeURIComponent(siteId)}/database`, deps, {
|
|
1734
|
+
method: "POST",
|
|
1735
|
+
body: JSON.stringify({
|
|
1736
|
+
database,
|
|
1737
|
+
envVarNames: [...DATABASE_ENV_VAR_NAMES]
|
|
1738
|
+
})
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
async function revealDatabaseRuntimeCredentials(context, databaseId, deps) {
|
|
1742
|
+
return await ossFetch(context, `/api/databases/${encodeURIComponent(databaseId)}/tokens/reveal`, deps, { method: "POST" });
|
|
1743
|
+
}
|
|
1744
|
+
async function recordSiteDatabaseInitialization(context, siteId, databaseId, status, error, deps) {
|
|
1745
|
+
await ossFetch(context, `/api/deployments/sites/${encodeURIComponent(siteId)}/database/initialization`, deps, {
|
|
1746
|
+
method: "POST",
|
|
1747
|
+
body: JSON.stringify({
|
|
1748
|
+
databaseId,
|
|
1749
|
+
status,
|
|
1750
|
+
...error ? { error } : {}
|
|
1751
|
+
})
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
async function initializeSiteDatabaseBeforeDeploy(options) {
|
|
1755
|
+
const databaseId = (await bindSiteDatabase(options.context, options.siteId, options.database, options.deps)).binding.database.id;
|
|
1756
|
+
const credentials = await revealDatabaseRuntimeCredentials(options.context, databaseId, options.deps);
|
|
1757
|
+
try {
|
|
1758
|
+
await (options.deps.runDinewayInitialization ?? runDinewayInitialization)({
|
|
1759
|
+
cwd: options.cwd,
|
|
1760
|
+
credentials,
|
|
1761
|
+
seedPath: options.seedPath
|
|
1762
|
+
});
|
|
1763
|
+
await recordSiteDatabaseInitialization(options.context, options.siteId, credentials.databaseId || databaseId, "succeeded", void 0, options.deps);
|
|
1764
|
+
} catch (error) {
|
|
1765
|
+
const message = redactDatabaseOutput(error instanceof Error ? error.message : String(error), [credentials.authToken, credentials.databaseUrl]);
|
|
1766
|
+
await recordSiteDatabaseInitialization(options.context, options.siteId, credentials.databaseId || databaseId, "failed", message, options.deps).catch(() => void 0);
|
|
1767
|
+
throw new Error(message, { cause: error });
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
function shouldExclude(name) {
|
|
1771
|
+
const normalized = name.replace(BACKSLASH_PATTERN, "/");
|
|
1772
|
+
for (const pattern of EXCLUDE_PATTERNS) if (normalized === pattern || normalized.startsWith(`${pattern}/`) || normalized.endsWith(`/${pattern}`) || normalized.includes(`/${pattern}/`)) return true;
|
|
1773
|
+
return normalized.endsWith(".log");
|
|
1774
|
+
}
|
|
1775
|
+
function normalizeRelativePath(sourceDir, absolutePath) {
|
|
1776
|
+
return relative(sourceDir, absolutePath).replace(BACKSLASH_PATTERN, "/");
|
|
1777
|
+
}
|
|
1778
|
+
async function hashFile(filePath) {
|
|
1779
|
+
const hash = createHash("sha1");
|
|
1780
|
+
let size = 0;
|
|
1781
|
+
for await (const chunk of createReadStream(filePath)) {
|
|
1782
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
1783
|
+
size += buffer.length;
|
|
1784
|
+
hash.update(buffer);
|
|
1785
|
+
}
|
|
1786
|
+
return {
|
|
1787
|
+
sha: hash.digest("hex"),
|
|
1788
|
+
size
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
async function collectDeploymentFiles(sourceDir) {
|
|
1792
|
+
const files = [];
|
|
1793
|
+
async function walk(currentDir) {
|
|
1794
|
+
const entries = await readdir(currentDir, { withFileTypes: true });
|
|
1795
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
1796
|
+
for (const entry of entries) {
|
|
1797
|
+
const absolutePath = join(currentDir, entry.name);
|
|
1798
|
+
const normalizedPath = normalizeRelativePath(sourceDir, absolutePath);
|
|
1799
|
+
if (!normalizedPath || shouldExclude(normalizedPath)) continue;
|
|
1800
|
+
if (entry.isDirectory()) {
|
|
1801
|
+
await walk(absolutePath);
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
if (!entry.isFile()) continue;
|
|
1805
|
+
const { sha, size } = await hashFile(absolutePath);
|
|
1806
|
+
files.push({
|
|
1807
|
+
absolutePath,
|
|
1808
|
+
path: normalizedPath,
|
|
1809
|
+
sha,
|
|
1810
|
+
size
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
await walk(sourceDir);
|
|
1815
|
+
return files;
|
|
1816
|
+
}
|
|
1817
|
+
async function runWithConcurrency(items, concurrency, worker) {
|
|
1818
|
+
let nextIndex = 0;
|
|
1819
|
+
async function runWorker() {
|
|
1820
|
+
while (nextIndex < items.length) {
|
|
1821
|
+
const index = nextIndex;
|
|
1822
|
+
nextIndex += 1;
|
|
1823
|
+
await worker(items[index]);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
1827
|
+
const workers = [];
|
|
1828
|
+
for (let index = 0; index < workerCount; index++) workers.push(runWorker());
|
|
1829
|
+
await Promise.all(workers);
|
|
1830
|
+
}
|
|
1831
|
+
async function uploadDirectDeploymentFile(context, deploymentId, manifestFile, localFile, deps) {
|
|
1832
|
+
await ossFetch(context, `/api/deployments/${encodeURIComponent(deploymentId)}/files/${encodeURIComponent(manifestFile.fileId)}/content`, deps, {
|
|
1833
|
+
method: "PUT",
|
|
1834
|
+
headers: {
|
|
1835
|
+
"Content-Type": "application/octet-stream",
|
|
1836
|
+
"Content-Length": String(localFile.size)
|
|
1837
|
+
},
|
|
1838
|
+
body: createReadStream(localFile.absolutePath),
|
|
1839
|
+
duplex: "half"
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
async function startDirectDeployment(context, deploymentId, startBody, deps) {
|
|
1843
|
+
await ossFetch(context, `/api/deployments/${encodeURIComponent(deploymentId)}/start`, deps, {
|
|
1844
|
+
method: "POST",
|
|
1845
|
+
body: JSON.stringify(startBody)
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
function getDeploymentError(metadata) {
|
|
1849
|
+
if (!metadata || typeof metadata.error !== "object" || metadata.error === null) return null;
|
|
1850
|
+
return metadata.error.errorMessage ?? null;
|
|
1851
|
+
}
|
|
1852
|
+
async function pollDeployment(context, deploymentId, deps) {
|
|
1853
|
+
const pollIntervalMs = deps.pollIntervalMs ?? POLL_INTERVAL_MS$1;
|
|
1854
|
+
const pollTimeoutMs = deps.pollTimeoutMs ?? POLL_TIMEOUT_MS$1;
|
|
1855
|
+
const startTime = Date.now();
|
|
1856
|
+
let deployment = null;
|
|
1857
|
+
while (Date.now() - startTime < pollTimeoutMs) {
|
|
1858
|
+
if (pollIntervalMs > 0) await new Promise((done) => setTimeout(done, pollIntervalMs));
|
|
1859
|
+
await ossFetch(context, `/api/deployments/${encodeURIComponent(deploymentId)}/sync`, deps, { method: "POST" }).catch(() => void 0);
|
|
1860
|
+
deployment = await ossFetch(context, `/api/deployments/${encodeURIComponent(deploymentId)}`, deps);
|
|
1861
|
+
const status = deployment.status.toUpperCase();
|
|
1862
|
+
if (status === "READY") break;
|
|
1863
|
+
if (status === "ERROR" || status === "CANCELED") throw new Error(getDeploymentError(deployment.metadata) ?? `Deployment failed with status: ${deployment.status}`);
|
|
1864
|
+
if (pollIntervalMs === 0) break;
|
|
1865
|
+
}
|
|
1866
|
+
const isReady = deployment?.status.toUpperCase() === "READY";
|
|
1867
|
+
return {
|
|
1868
|
+
deployment,
|
|
1869
|
+
isReady,
|
|
1870
|
+
liveUrl: isReady ? deployment?.url ?? null : null
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
async function deploySiteProject(options) {
|
|
1874
|
+
options.deps.onEvent?.("scan");
|
|
1875
|
+
const localFiles = await (options.deps.collectDeploymentFiles ?? collectDeploymentFiles)(options.sourceDir);
|
|
1876
|
+
if (localFiles.length === 0) throw new Error("No deployable files found in the source directory.");
|
|
1877
|
+
const createResult = await ossFetch(options.context, `/api/deployments/sites/${encodeURIComponent(options.siteId)}/deploy`, options.deps, {
|
|
1878
|
+
method: "POST",
|
|
1879
|
+
body: JSON.stringify({ files: localFiles.map(({ path: relativePath, sha, size }) => ({
|
|
1880
|
+
path: relativePath,
|
|
1881
|
+
sha,
|
|
1882
|
+
size
|
|
1883
|
+
})) })
|
|
1884
|
+
});
|
|
1885
|
+
const localFileByPath = new Map(localFiles.map((file) => [file.path, file]));
|
|
1886
|
+
await runWithConcurrency(createResult.files.filter((file) => !file.uploadedAt), DIRECT_UPLOAD_CONCURRENCY, async (manifestFile) => {
|
|
1887
|
+
const localFile = localFileByPath.get(manifestFile.path);
|
|
1888
|
+
if (!localFile) throw new Error(`Forgeway returned an unknown file path: ${manifestFile.path}`);
|
|
1889
|
+
if (localFile.sha !== manifestFile.sha || localFile.size !== manifestFile.size) throw new Error(`Forgeway file metadata mismatch for: ${manifestFile.path}`);
|
|
1890
|
+
await uploadDirectDeploymentFile(options.context, createResult.id, manifestFile, localFile, options.deps);
|
|
1891
|
+
});
|
|
1892
|
+
await startDirectDeployment(options.context, createResult.id, options.startBody, options.deps);
|
|
1893
|
+
const result = await pollDeployment(options.context, createResult.id, options.deps);
|
|
1894
|
+
return {
|
|
1895
|
+
deploymentId: createResult.id,
|
|
1896
|
+
...result,
|
|
1897
|
+
site: createResult.site
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
async function deployForgeway(cwd, options, deps = {}) {
|
|
1901
|
+
if (options.dryRun) return { message: "[dry-run] Would resolve Forgeway project, create/reuse site, bind database, initialize Dineway, upload files, and start deployment." };
|
|
1902
|
+
const sourceDir = resolve(cwd);
|
|
1903
|
+
if (!(await stat(sourceDir).catch(() => null))?.isDirectory()) throw new Error(`"${sourceDir}" is not a valid directory.`);
|
|
1904
|
+
if (EXCLUDE_PATTERNS.includes(basename(sourceDir))) throw new Error(`"${basename(sourceDir)}" is an excluded directory and cannot be deployed.`);
|
|
1905
|
+
const context = await resolveProjectContext(cwd, options, deps);
|
|
1906
|
+
const seedPath = await resolveSeedPath$1(cwd, options.seed);
|
|
1907
|
+
const { site } = await resolveDeploymentSite(cwd, context, options, seedPath, deps);
|
|
1908
|
+
const database = parseDatabaseMode(options.database);
|
|
1909
|
+
if (database !== "none") {
|
|
1910
|
+
consola.start("Initializing Forgeway managed database");
|
|
1911
|
+
try {
|
|
1912
|
+
deps.onEvent?.("initialize");
|
|
1913
|
+
await initializeSiteDatabaseBeforeDeploy({
|
|
1914
|
+
context,
|
|
1915
|
+
siteId: site.id,
|
|
1916
|
+
database,
|
|
1917
|
+
cwd,
|
|
1918
|
+
seedPath,
|
|
1919
|
+
deps
|
|
1920
|
+
});
|
|
1921
|
+
consola.success("Database initialized");
|
|
1922
|
+
} catch (error) {
|
|
1923
|
+
consola.error("Database initialization failed");
|
|
1924
|
+
throw error;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
const deployment = await deploySiteProject({
|
|
1928
|
+
context,
|
|
1929
|
+
siteId: site.id,
|
|
1930
|
+
sourceDir,
|
|
1931
|
+
startBody: {},
|
|
1932
|
+
deps
|
|
1933
|
+
});
|
|
1934
|
+
const url = deployment.liveUrl ?? `https://${site.domain}`;
|
|
1935
|
+
return {
|
|
1936
|
+
url,
|
|
1937
|
+
message: deployment.isReady ? `Deploy complete: ${url}` : `Deploy started for ${site.domain}. Check Forgeway for build status.`
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
const forgewayTarget = {
|
|
1941
|
+
name: "forgeway",
|
|
1942
|
+
label: "Forgeway",
|
|
1943
|
+
description: "Deploy through Dineway's first-party Forgeway platform.",
|
|
1944
|
+
recommended: true,
|
|
1945
|
+
remoteBuild: true,
|
|
1946
|
+
supportLevel: "stable",
|
|
1947
|
+
async generateConfig(_cwd, _options) {
|
|
1948
|
+
return [];
|
|
1949
|
+
},
|
|
1950
|
+
async deploy(cwd, options) {
|
|
1951
|
+
return await deployForgeway(cwd, options);
|
|
1952
|
+
}
|
|
1953
|
+
};
|
|
1954
|
+
|
|
1214
1955
|
//#endregion
|
|
1215
1956
|
//#region src/cli/commands/deploy/targets/gcp.ts
|
|
1216
1957
|
const CLOUD_RUN_URL_RE = /https:\/\/[^\s"]+\.run\.app[^\s"]*/;
|
|
@@ -1629,36 +2370,16 @@ async function ensureTargetCli(target, cwd, options = {}) {
|
|
|
1629
2370
|
});
|
|
1630
2371
|
}
|
|
1631
2372
|
|
|
1632
|
-
//#endregion
|
|
1633
|
-
//#region src/cli/commands/deploy/utils/config.ts
|
|
1634
|
-
async function readDeployPackageJson(cwd) {
|
|
1635
|
-
const content = await readFile(join(cwd, "package.json"), "utf-8");
|
|
1636
|
-
return JSON.parse(content);
|
|
1637
|
-
}
|
|
1638
|
-
async function readSavedDeployTarget(cwd) {
|
|
1639
|
-
return (await readDeployPackageJson(cwd)).dineway?.deploy?.target;
|
|
1640
|
-
}
|
|
1641
|
-
async function writeDeployTarget(cwd, target) {
|
|
1642
|
-
const pkgPath = join(cwd, "package.json");
|
|
1643
|
-
const pkg = await readDeployPackageJson(cwd);
|
|
1644
|
-
pkg.dineway = {
|
|
1645
|
-
...pkg.dineway,
|
|
1646
|
-
deploy: {
|
|
1647
|
-
...pkg.dineway?.deploy,
|
|
1648
|
-
target
|
|
1649
|
-
}
|
|
1650
|
-
};
|
|
1651
|
-
await writeFile(pkgPath, JSON.stringify(pkg, null, " ") + "\n", "utf-8");
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
2373
|
//#endregion
|
|
1655
2374
|
//#region src/cli/commands/deploy/index.ts
|
|
1656
2375
|
const targets = [
|
|
2376
|
+
forgewayTarget,
|
|
1657
2377
|
railwayTarget,
|
|
1658
2378
|
dockerTarget,
|
|
1659
2379
|
flyTarget,
|
|
1660
2380
|
gcpTarget
|
|
1661
2381
|
];
|
|
2382
|
+
const DEFAULT_TARGET = "forgeway";
|
|
1662
2383
|
function getTarget(name) {
|
|
1663
2384
|
return targets.find((target) => target.name === name);
|
|
1664
2385
|
}
|
|
@@ -1699,7 +2420,9 @@ async function resolveTarget(cwd, explicitTarget) {
|
|
|
1699
2420
|
if (!target) throw new Error(`Saved deploy target "${saved}" is unknown. Available targets: ${targetList()}`);
|
|
1700
2421
|
return target;
|
|
1701
2422
|
}
|
|
1702
|
-
|
|
2423
|
+
const target = getTarget(DEFAULT_TARGET);
|
|
2424
|
+
if (!target) return promptForTarget();
|
|
2425
|
+
return target;
|
|
1703
2426
|
}
|
|
1704
2427
|
const deployCommand = defineCommand({
|
|
1705
2428
|
meta: {
|
|
@@ -1737,6 +2460,31 @@ const deployCommand = defineCommand({
|
|
|
1737
2460
|
type: "boolean",
|
|
1738
2461
|
description: "Print planned actions without writing files or deploying",
|
|
1739
2462
|
default: false
|
|
2463
|
+
},
|
|
2464
|
+
site: {
|
|
2465
|
+
type: "string",
|
|
2466
|
+
description: "Forgeway deployment site ID or slug",
|
|
2467
|
+
required: false
|
|
2468
|
+
},
|
|
2469
|
+
"restaurant-name": {
|
|
2470
|
+
type: "string",
|
|
2471
|
+
description: "Restaurant name for first Forgeway site creation",
|
|
2472
|
+
required: false
|
|
2473
|
+
},
|
|
2474
|
+
city: {
|
|
2475
|
+
type: "string",
|
|
2476
|
+
description: "Restaurant city for first Forgeway site creation",
|
|
2477
|
+
required: false
|
|
2478
|
+
},
|
|
2479
|
+
database: {
|
|
2480
|
+
type: "string",
|
|
2481
|
+
description: "Forgeway database mode: \"turso\", \"none\", or a managed database UUID",
|
|
2482
|
+
default: "turso"
|
|
2483
|
+
},
|
|
2484
|
+
seed: {
|
|
2485
|
+
type: "string",
|
|
2486
|
+
description: "Seed file path for Forgeway Dineway initialization",
|
|
2487
|
+
required: false
|
|
1740
2488
|
}
|
|
1741
2489
|
},
|
|
1742
2490
|
async run({ args }) {
|
|
@@ -1746,7 +2494,12 @@ const deployCommand = defineCommand({
|
|
|
1746
2494
|
skipBuild: args["skip-build"],
|
|
1747
2495
|
compose: args.compose,
|
|
1748
2496
|
yes: args.yes,
|
|
1749
|
-
dryRun: args["dry-run"]
|
|
2497
|
+
dryRun: args["dry-run"],
|
|
2498
|
+
site: args.site,
|
|
2499
|
+
restaurantName: args["restaurant-name"],
|
|
2500
|
+
city: args.city,
|
|
2501
|
+
database: args.database,
|
|
2502
|
+
seed: args.seed
|
|
1750
2503
|
};
|
|
1751
2504
|
consola.start(`Preparing ${target.label} deploy`);
|
|
1752
2505
|
await ensureTargetCli(target, cwd, {
|
|
@@ -1769,7 +2522,7 @@ const deployCommand = defineCommand({
|
|
|
1769
2522
|
await target.link(cwd);
|
|
1770
2523
|
}
|
|
1771
2524
|
} else consola.info("[dry-run] Would verify provider authentication and project link");
|
|
1772
|
-
if (!options.skipBuild && target.name !== "docker") {
|
|
2525
|
+
if (!options.skipBuild && target.name !== "docker" && !target.remoteBuild) {
|
|
1773
2526
|
const build = options.dryRun ? null : await runBuild(cwd, options.env);
|
|
1774
2527
|
consola.info(options.dryRun ? "[dry-run] Would run build" : `Built with ${build?.display}`);
|
|
1775
2528
|
}
|