dineway 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/{apply-CAPvMfoU.mjs → apply-iVSqz2qs.mjs} +132 -39
- package/dist/astro/index.d.mts +18 -9
- package/dist/astro/index.mjs +238 -16
- package/dist/astro/middleware/auth.d.mts +16 -5
- package/dist/astro/middleware/auth.mjs +74 -37
- package/dist/astro/middleware/redirect.mjs +24 -8
- package/dist/astro/middleware/request-context.mjs +18 -5
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.mjs +411 -169
- package/dist/astro/types.d.mts +25 -8
- package/dist/{byline-DeWCMU_i.mjs → byline-OhH2dlRu.mjs} +6 -21
- package/dist/{bylines-DyqBV9EQ.mjs → bylines-BGpD9_hy.mjs} +16 -6
- package/dist/cache-BdSY-gQN.mjs +42 -0
- package/dist/chunks--4F8ddV4.mjs +18 -0
- package/dist/cli/index.mjs +935 -15
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +11 -3
- package/dist/client/index.mjs +4 -3
- package/dist/{connection-C9pxzuag.mjs → connection-BCNICDWN.mjs} +22 -5
- package/dist/{content-zSgdNmnt.mjs → content-DWi4d0rT.mjs} +41 -2
- package/dist/database/instrumentation.d.mts +34 -0
- package/dist/database/instrumentation.mjs +53 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/libsql.mjs +11 -5
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +7 -1
- package/dist/db-errors-CEqD7qH9.mjs +23 -0
- package/dist/{default-WYlzADZL.mjs → default-VjJyuuG9.mjs} +2 -0
- package/dist/{dialect-helpers-B9uSp2GJ.mjs → dialect-helpers-DhTzaUxP.mjs} +3 -0
- package/dist/{error-DrxtnGPg.mjs → error-BmL6QipT.mjs} +7 -3
- package/dist/{index-C-jx21qs.d.mts → index-yvc6E_17.d.mts} +157 -30
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +24 -22
- package/dist/{loader-qKmo0wAY.mjs → loader-sMG4TZ-u.mjs} +9 -3
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +1 -1
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/page/index.d.mts +10 -2
- package/dist/page/index.mjs +22 -1
- package/dist/patterns-CrCYkMBb.mjs +92 -0
- package/dist/{placeholder-bOx1xCTY.d.mts → placeholder--wOi4TbO.d.mts} +1 -1
- package/dist/{placeholder-B3knXwNc.mjs → placeholder-Cp8g5Emj.mjs} +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{query-BiaPl_g2.mjs → query-kDmwCsHh.mjs} +118 -50
- package/dist/{redirect-JPqLAbxa.mjs → redirect-DnEWAkVg.mjs} +43 -99
- package/dist/{registry-DSd1GWB8.mjs → registry-C0zjeB9P.mjs} +191 -123
- package/dist/request-cache-Dk5qPSOx.mjs +66 -0
- package/dist/request-context.d.mts +4 -16
- package/dist/{runner-B5l1JfOj.d.mts → runner-CFI6B6J2.d.mts} +1 -1
- package/dist/{runner-BGUGywgG.mjs → runner-DWZm2KQm.mjs} +589 -137
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +2 -2
- package/dist/{search-BNruJHDL.mjs → search-ByRGV2pq.mjs} +570 -424
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +11 -10
- package/dist/seo/index.d.mts +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +11 -3
- package/dist/storage/s3.mjs +78 -15
- package/dist/taxonomies-1s5PaS_8.mjs +266 -0
- package/dist/transaction-Cn2rjY78.mjs +27 -0
- package/dist/{types-BgQeVaPj.d.mts → types-BuMDPy5C.d.mts} +52 -3
- package/dist/{types-DuNbGKjF.mjs → types-COeOq9nK.mjs} +6 -1
- package/dist/{types-ju-_ORz7.d.mts → types-CWbdtiux.d.mts} +13 -5
- package/dist/{types-D38djUXv.d.mts → types-Cj0KMIZV.d.mts} +16 -3
- package/dist/{types-DkvMXalq.d.mts → types-DOrVigru.d.mts} +159 -0
- package/dist/{validate-CXnRKfJK.mjs → validate-BZ5wnLLp.mjs} +2 -1
- package/dist/{validate-DVKJJ-M_.d.mts → validate-IPf8n4Fj.d.mts} +4 -51
- package/dist/{validate-CqRJb_xU.mjs → validate-VPnKoIzW.mjs} +10 -10
- package/dist/version-BKXPsfmJ.mjs +6 -0
- package/package.json +53 -39
- package/src/astro/routes/PluginRegistry.tsx +21 -0
- package/src/astro/routes/admin.astro +99 -0
- package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
- package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
- package/src/astro/routes/api/admin/api-tokens/[id].ts +44 -0
- package/src/astro/routes/api/admin/api-tokens/index.ts +90 -0
- package/src/astro/routes/api/admin/briefing.ts +76 -0
- package/src/astro/routes/api/admin/bylines/[id]/index.ts +90 -0
- package/src/astro/routes/api/admin/bylines/index.ts +74 -0
- package/src/astro/routes/api/admin/comments/[id]/status.ts +120 -0
- package/src/astro/routes/api/admin/comments/[id].ts +64 -0
- package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
- package/src/astro/routes/api/admin/comments/counts.ts +30 -0
- package/src/astro/routes/api/admin/comments/index.ts +46 -0
- package/src/astro/routes/api/admin/context/[id]/history.ts +35 -0
- package/src/astro/routes/api/admin/context/[id]/index.ts +35 -0
- package/src/astro/routes/api/admin/context/[id]/review.ts +57 -0
- package/src/astro/routes/api/admin/context/[id]/supersede.ts +58 -0
- package/src/astro/routes/api/admin/context/diff.ts +35 -0
- package/src/astro/routes/api/admin/context/index.ts +69 -0
- package/src/astro/routes/api/admin/context/stale.ts +35 -0
- package/src/astro/routes/api/admin/hitl-requests/[id]/index.ts +38 -0
- package/src/astro/routes/api/admin/hitl-requests/[id]/resolve.ts +54 -0
- package/src/astro/routes/api/admin/hitl-requests/index.ts +38 -0
- package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +132 -0
- package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
- package/src/astro/routes/api/admin/oauth-clients/[id].ts +137 -0
- package/src/astro/routes/api/admin/oauth-clients/index.ts +95 -0
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +91 -0
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +91 -0
- package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +98 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +154 -0
- package/src/astro/routes/api/admin/plugins/index.ts +32 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +62 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +135 -0
- package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
- package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
- package/src/astro/routes/api/admin/review-requests/[id]/index.ts +35 -0
- package/src/astro/routes/api/admin/review-requests/[id]/resolve.ts +52 -0
- package/src/astro/routes/api/admin/review-requests/index.ts +35 -0
- package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
- package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +62 -0
- package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
- package/src/astro/routes/api/admin/users/[id]/disable.ts +72 -0
- package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
- package/src/astro/routes/api/admin/users/[id]/index.ts +166 -0
- package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
- package/src/astro/routes/api/admin/users/index.ts +66 -0
- package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
- package/src/astro/routes/api/auth/invite/accept.ts +52 -0
- package/src/astro/routes/api/auth/invite/complete.ts +86 -0
- package/src/astro/routes/api/auth/invite/index.ts +99 -0
- package/src/astro/routes/api/auth/invite/register-options.ts +73 -0
- package/src/astro/routes/api/auth/logout.ts +40 -0
- package/src/astro/routes/api/auth/magic-link/send.ts +90 -0
- package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
- package/src/astro/routes/api/auth/me.ts +60 -0
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +221 -0
- package/src/astro/routes/api/auth/oauth/[provider].ts +120 -0
- package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
- package/src/astro/routes/api/auth/passkey/index.ts +54 -0
- package/src/astro/routes/api/auth/passkey/options.ts +85 -0
- package/src/astro/routes/api/auth/passkey/register/options.ts +88 -0
- package/src/astro/routes/api/auth/passkey/register/verify.ts +119 -0
- package/src/astro/routes/api/auth/passkey/verify.ts +72 -0
- package/src/astro/routes/api/auth/signup/complete.ts +87 -0
- package/src/astro/routes/api/auth/signup/request.ts +89 -0
- package/src/astro/routes/api/auth/signup/verify.ts +53 -0
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +310 -0
- package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +68 -0
- package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +77 -0
- package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +42 -0
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +100 -0
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +64 -0
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +129 -0
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +143 -0
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +50 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +69 -0
- package/src/astro/routes/api/content/[collection]/[id].ts +173 -0
- package/src/astro/routes/api/content/[collection]/index.ts +103 -0
- package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
- package/src/astro/routes/api/dashboard.ts +32 -0
- package/src/astro/routes/api/dev/emails.ts +36 -0
- package/src/astro/routes/api/health.ts +54 -0
- package/src/astro/routes/api/import/probe.ts +47 -0
- package/src/astro/routes/api/import/wordpress/analyze.ts +523 -0
- package/src/astro/routes/api/import/wordpress/execute.ts +330 -0
- package/src/astro/routes/api/import/wordpress/media.ts +338 -0
- package/src/astro/routes/api/import/wordpress/prepare.ts +212 -0
- package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +425 -0
- package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
- package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +399 -0
- package/src/astro/routes/api/manifest.ts +75 -0
- package/src/astro/routes/api/mcp.ts +125 -0
- package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
- package/src/astro/routes/api/media/[id].ts +145 -0
- package/src/astro/routes/api/media/file/[...key].ts +79 -0
- package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +91 -0
- package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
- package/src/astro/routes/api/media/providers/index.ts +30 -0
- package/src/astro/routes/api/media/upload-url.ts +146 -0
- package/src/astro/routes/api/media.ts +204 -0
- package/src/astro/routes/api/menus/[name]/items.ts +206 -0
- package/src/astro/routes/api/menus/[name]/reorder.ts +79 -0
- package/src/astro/routes/api/menus/[name].ts +145 -0
- package/src/astro/routes/api/menus/index.ts +91 -0
- package/src/astro/routes/api/oauth/authorize.ts +430 -0
- package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
- package/src/astro/routes/api/oauth/device/code.ts +56 -0
- package/src/astro/routes/api/oauth/device/token.ts +70 -0
- package/src/astro/routes/api/oauth/register.ts +182 -0
- package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
- package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
- package/src/astro/routes/api/oauth/token.ts +195 -0
- package/src/astro/routes/api/openapi.json.ts +33 -0
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +109 -0
- package/src/astro/routes/api/redirects/404s/index.ts +72 -0
- package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
- package/src/astro/routes/api/redirects/[id].ts +183 -0
- package/src/astro/routes/api/redirects/index.ts +100 -0
- package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
- package/src/astro/routes/api/revisions/[revisionId]/restore.ts +62 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +104 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +67 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +45 -0
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +107 -0
- package/src/astro/routes/api/schema/collections/index.ts +61 -0
- package/src/astro/routes/api/schema/index.ts +109 -0
- package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
- package/src/astro/routes/api/schema/orphans/index.ts +26 -0
- package/src/astro/routes/api/search/enable.ts +64 -0
- package/src/astro/routes/api/search/index.ts +52 -0
- package/src/astro/routes/api/search/rebuild.ts +72 -0
- package/src/astro/routes/api/search/stats.ts +35 -0
- package/src/astro/routes/api/search/suggest.ts +50 -0
- package/src/astro/routes/api/sections/[slug].ts +203 -0
- package/src/astro/routes/api/sections/index.ts +107 -0
- package/src/astro/routes/api/settings/email.ts +150 -0
- package/src/astro/routes/api/settings.ts +116 -0
- package/src/astro/routes/api/setup/admin-verify.ts +122 -0
- package/src/astro/routes/api/setup/admin.ts +104 -0
- package/src/astro/routes/api/setup/dev-bypass.ts +200 -0
- package/src/astro/routes/api/setup/dev-reset.ts +40 -0
- package/src/astro/routes/api/setup/index.ts +128 -0
- package/src/astro/routes/api/setup/status.ts +122 -0
- package/src/astro/routes/api/snapshot.ts +76 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +232 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +131 -0
- package/src/astro/routes/api/taxonomies/index.ts +114 -0
- package/src/astro/routes/api/themes/preview.ts +78 -0
- package/src/astro/routes/api/typegen.ts +114 -0
- package/src/astro/routes/api/well-known/auth.ts +71 -0
- package/src/astro/routes/api/well-known/oauth-authorization-server.ts +48 -0
- package/src/astro/routes/api/well-known/oauth-protected-resource.ts +39 -0
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +114 -0
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +213 -0
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +126 -0
- package/src/astro/routes/api/widget-areas/[name].ts +135 -0
- package/src/astro/routes/api/widget-areas/index.ts +149 -0
- package/src/astro/routes/api/widget-components.ts +22 -0
- package/src/astro/routes/robots.txt.ts +81 -0
- package/src/astro/routes/sitemap-[collection].xml.ts +104 -0
- package/src/astro/routes/sitemap.xml.ts +92 -0
- package/src/components/Break.astro +45 -0
- package/src/components/Button.astro +71 -0
- package/src/components/Buttons.astro +49 -0
- package/src/components/Code.astro +59 -0
- package/src/components/Columns.astro +59 -0
- package/src/components/CommentForm.astro +315 -0
- package/src/components/Comments.astro +232 -0
- package/src/components/Cover.astro +128 -0
- package/src/components/DinewayBodyEnd.astro +32 -0
- package/src/components/DinewayBodyStart.astro +32 -0
- package/src/components/DinewayHead.astro +61 -0
- package/src/components/DinewayImage.astro +178 -0
- package/src/components/DinewayMedia.astro +167 -0
- package/src/components/Embed.astro +128 -0
- package/src/components/File.astro +122 -0
- package/src/components/Gallery.astro +93 -0
- package/src/components/HtmlBlock.astro +33 -0
- package/src/components/Image.astro +178 -0
- package/src/components/InlineEditor.astro +27 -0
- package/src/components/InlinePortableTextEditor.tsx +1937 -0
- package/src/components/LiveSearch.astro +614 -0
- package/src/components/PortableText.astro +51 -0
- package/src/components/Pullquote.astro +51 -0
- package/src/components/Table.astro +135 -0
- package/src/components/WidgetArea.astro +22 -0
- package/src/components/WidgetRenderer.astro +72 -0
- package/src/components/index.ts +106 -0
- package/src/components/marks/Link.astro +31 -0
- package/src/components/marks/StrikeThrough.astro +7 -0
- package/src/components/marks/Subscript.astro +7 -0
- package/src/components/marks/Superscript.astro +7 -0
- package/src/components/marks/Underline.astro +7 -0
- package/src/components/marks.ts +19 -0
- package/src/components/widgets/Archives.astro +65 -0
- package/src/components/widgets/Categories.astro +35 -0
- package/src/components/widgets/RecentPosts.astro +51 -0
- package/src/components/widgets/Search.astro +18 -0
- package/src/components/widgets/Tags.astro +38 -0
- package/src/ui.ts +75 -0
- package/LICENSE +0 -9
- /package/dist/{adapters-BlzWJG82.d.mts → adapters-C2ypTrZZ.d.mts} +0 -0
- /package/dist/{config-Cq8H0SfX.mjs → config-BXwuX8Bx.mjs} +0 -0
- /package/dist/{load-C6FCD1FU.mjs → load-Coc9HpHH.mjs} +0 -0
- /package/dist/{manifest-schema-CTSEyIJ3.mjs → manifest-schema-D1MSVnoI.mjs} +0 -0
- /package/dist/{mode-BlyYtIFO.mjs → mode-47goXBBK.mjs} +0 -0
- /package/dist/{tokens-4vgYuXsZ.mjs → tokens-CJz9ubV6.mjs} +0 -0
- /package/dist/{transport-C5FYnid7.mjs → transport-DB5eDN4x.mjs} +0 -0
- /package/dist/{transport-gIL-e43D.d.mts → transport-Wge_IzKl.d.mts} +0 -0
- /package/dist/{types-CLLdsG3g.d.mts → types-BzcUjoqg.d.mts} +0 -0
- /package/dist/{types-DShnjzb6.mjs → types-griIBQOQ.mjs} +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as __exportAll } from "../chunk-ClPoSABd.mjs";
|
|
3
|
-
import { n as createDatabase } from "../connection-
|
|
4
|
-
import { s as listTablesLike } from "../dialect-helpers-
|
|
5
|
-
import { r as runMigrations, t as getMigrationStatus } from "../runner-
|
|
6
|
-
import { t as ContentRepository } from "../content-
|
|
3
|
+
import { n as createDatabase } from "../connection-BCNICDWN.mjs";
|
|
4
|
+
import { s as listTablesLike } from "../dialect-helpers-DhTzaUxP.mjs";
|
|
5
|
+
import { r as runMigrations, t as getMigrationStatus } from "../runner-DWZm2KQm.mjs";
|
|
6
|
+
import { t as ContentRepository } from "../content-DWi4d0rT.mjs";
|
|
7
7
|
import { i as encodeBase64url } from "../base64-F8-DUraK.mjs";
|
|
8
8
|
import "../types-BawVha09.mjs";
|
|
9
9
|
import { t as MediaRepository } from "../media-DMTr80Gv.mjs";
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import "../
|
|
13
|
-
import "../
|
|
14
|
-
import {
|
|
15
|
-
import "../loader-
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
10
|
+
import { m as TaxonomyRepository, p as OptionsRepository, t as applySeed } from "../apply-iVSqz2qs.mjs";
|
|
11
|
+
import "../redirect-DnEWAkVg.mjs";
|
|
12
|
+
import "../byline-OhH2dlRu.mjs";
|
|
13
|
+
import { r as isI18nEnabled } from "../config-BXwuX8Bx.mjs";
|
|
14
|
+
import { n as SchemaRegistry } from "../registry-C0zjeB9P.mjs";
|
|
15
|
+
import "../loader-sMG4TZ-u.mjs";
|
|
16
|
+
import "../request-cache-Dk5qPSOx.mjs";
|
|
17
|
+
import { i as pluginManifestSchema } from "../manifest-schema-D1MSVnoI.mjs";
|
|
18
|
+
import { t as validateSeed } from "../validate-BZ5wnLLp.mjs";
|
|
18
19
|
import { LocalStorage } from "../storage/local.mjs";
|
|
19
20
|
import { createHeaderAwareFetch, customHeadersInterceptor, isRedirectResponse, resolveCustomHeaders } from "../client/external-auth-headers.mjs";
|
|
20
21
|
import { DinewayClient } from "../client/index.mjs";
|
|
@@ -28,6 +29,7 @@ import { defineCommand, runCommand, runMain } from "citty";
|
|
|
28
29
|
import consola, { consola as consola$1 } from "consola";
|
|
29
30
|
import pc from "picocolors";
|
|
30
31
|
import { homedir } from "node:os";
|
|
32
|
+
import { createInterface } from "node:readline/promises";
|
|
31
33
|
import { spawn } from "node:child_process";
|
|
32
34
|
import { pipeline } from "node:stream/promises";
|
|
33
35
|
import { packTar } from "modern-tar/fs";
|
|
@@ -648,12 +650,16 @@ const publishCommand$1 = defineCommand({
|
|
|
648
650
|
description: "Content item ID or slug",
|
|
649
651
|
required: true
|
|
650
652
|
},
|
|
653
|
+
"review-request-id": {
|
|
654
|
+
type: "string",
|
|
655
|
+
description: "Approved review request ID for token-authenticated publish"
|
|
656
|
+
},
|
|
651
657
|
...connectionArgs
|
|
652
658
|
},
|
|
653
659
|
async run({ args }) {
|
|
654
660
|
configureOutputMode(args);
|
|
655
661
|
try {
|
|
656
|
-
await createClientFromArgs(args).publish(args.collection, args.id);
|
|
662
|
+
await createClientFromArgs(args).publish(args.collection, args.id, { reviewRequestId: args["review-request-id"] });
|
|
657
663
|
consola$1.success(`Published ${args.collection}/${args.id}`);
|
|
658
664
|
} catch (error) {
|
|
659
665
|
consola$1.error(error instanceof Error ? error.message : "Unknown error");
|
|
@@ -800,6 +806,918 @@ const contentCommand = defineCommand({
|
|
|
800
806
|
}
|
|
801
807
|
});
|
|
802
808
|
|
|
809
|
+
//#endregion
|
|
810
|
+
//#region src/cli/commands/deploy/utils/dockerfile.ts
|
|
811
|
+
const NODE_START_COMMAND = "node ./dist/server/entry.mjs";
|
|
812
|
+
const HEALTH_CHECK_PATH = "/_dineway/api/health";
|
|
813
|
+
function generateDockerfile() {
|
|
814
|
+
return `FROM node:22-bookworm-slim AS dependencies
|
|
815
|
+
WORKDIR /app
|
|
816
|
+
RUN corepack enable
|
|
817
|
+
COPY . .
|
|
818
|
+
RUN if [ -f pnpm-lock.yaml ]; then pnpm install --frozen-lockfile; \\
|
|
819
|
+
\telif [ -f yarn.lock ]; then yarn install --frozen-lockfile; \\
|
|
820
|
+
\telif [ -f bun.lock ] || [ -f bun.lockb ]; then npm install --global bun && bun install --frozen-lockfile; \\
|
|
821
|
+
\telif [ -f package-lock.json ]; then npm ci; \\
|
|
822
|
+
\telse npm install; fi
|
|
823
|
+
|
|
824
|
+
FROM dependencies AS builder
|
|
825
|
+
RUN mkdir -p public seed
|
|
826
|
+
RUN if [ -f pnpm-lock.yaml ]; then pnpm build; \\
|
|
827
|
+
\telif [ -f yarn.lock ]; then yarn build; \\
|
|
828
|
+
\telif [ -f bun.lock ] || [ -f bun.lockb ]; then bun run build; \\
|
|
829
|
+
\telse npm run build; fi
|
|
830
|
+
|
|
831
|
+
FROM node:22-bookworm-slim AS runner
|
|
832
|
+
WORKDIR /app
|
|
833
|
+
ENV HOST=0.0.0.0
|
|
834
|
+
ENV PORT=4321
|
|
835
|
+
ENV NODE_ENV=production
|
|
836
|
+
COPY --from=builder /app/package.json ./package.json
|
|
837
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
838
|
+
COPY --from=builder /app/dist ./dist
|
|
839
|
+
COPY --from=builder /app/public ./public
|
|
840
|
+
COPY --from=builder /app/seed ./seed
|
|
841
|
+
EXPOSE 4321
|
|
842
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 CMD ["node", "-e", "fetch('http://127.0.0.1:' + (process.env.PORT || '4321') + '${HEALTH_CHECK_PATH}').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"]
|
|
843
|
+
CMD ["node", "./dist/server/entry.mjs"]
|
|
844
|
+
`;
|
|
845
|
+
}
|
|
846
|
+
function generateDockerignore() {
|
|
847
|
+
return `.astro
|
|
848
|
+
.dineway
|
|
849
|
+
.env
|
|
850
|
+
.env.*
|
|
851
|
+
.git
|
|
852
|
+
.github
|
|
853
|
+
.plan
|
|
854
|
+
dist
|
|
855
|
+
node_modules
|
|
856
|
+
uploads
|
|
857
|
+
data
|
|
858
|
+
*.db
|
|
859
|
+
*.db-*
|
|
860
|
+
npm-debug.log*
|
|
861
|
+
pnpm-debug.log*
|
|
862
|
+
yarn-debug.log*
|
|
863
|
+
yarn-error.log*
|
|
864
|
+
`;
|
|
865
|
+
}
|
|
866
|
+
function generateDockerCompose() {
|
|
867
|
+
return `services:
|
|
868
|
+
dineway:
|
|
869
|
+
build: .
|
|
870
|
+
ports:
|
|
871
|
+
- "4321:4321"
|
|
872
|
+
environment:
|
|
873
|
+
HOST: 0.0.0.0
|
|
874
|
+
PORT: 4321
|
|
875
|
+
DINEWAY_DATABASE_URL: file:./data/dineway.db
|
|
876
|
+
DINEWAY_AUTH_SECRET: \${DINEWAY_AUTH_SECRET}
|
|
877
|
+
DINEWAY_PREVIEW_SECRET: \${DINEWAY_PREVIEW_SECRET}
|
|
878
|
+
volumes:
|
|
879
|
+
- dineway-data:/app/data
|
|
880
|
+
healthcheck:
|
|
881
|
+
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:4321${HEALTH_CHECK_PATH}').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"]
|
|
882
|
+
interval: 30s
|
|
883
|
+
timeout: 5s
|
|
884
|
+
retries: 3
|
|
885
|
+
start_period: 30s
|
|
886
|
+
restart: unless-stopped
|
|
887
|
+
|
|
888
|
+
volumes:
|
|
889
|
+
dineway-data:
|
|
890
|
+
`;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
//#endregion
|
|
894
|
+
//#region src/cli/commands/deploy/targets/docker.ts
|
|
895
|
+
async function fileExists$9(path) {
|
|
896
|
+
try {
|
|
897
|
+
await access(path);
|
|
898
|
+
return true;
|
|
899
|
+
} catch {
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
async function writeGeneratedFile$2(cwd, relativePath, content, dryRun) {
|
|
904
|
+
const path = join(cwd, relativePath);
|
|
905
|
+
if (await fileExists$9(path)) return {
|
|
906
|
+
path: relativePath,
|
|
907
|
+
action: "exists"
|
|
908
|
+
};
|
|
909
|
+
if (dryRun) return {
|
|
910
|
+
path: relativePath,
|
|
911
|
+
action: "skipped"
|
|
912
|
+
};
|
|
913
|
+
await writeFile(path, content, "utf-8");
|
|
914
|
+
return {
|
|
915
|
+
path: relativePath,
|
|
916
|
+
action: "created"
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
const dockerTarget = {
|
|
920
|
+
name: "docker",
|
|
921
|
+
label: "Docker",
|
|
922
|
+
description: "Generate Docker deployment files without running Docker locally.",
|
|
923
|
+
supportLevel: "stable",
|
|
924
|
+
async generateConfig(cwd, options) {
|
|
925
|
+
const files = [await writeGeneratedFile$2(cwd, "Dockerfile", generateDockerfile(), options.dryRun), await writeGeneratedFile$2(cwd, ".dockerignore", generateDockerignore(), options.dryRun)];
|
|
926
|
+
if (options.compose) files.push(await writeGeneratedFile$2(cwd, "docker-compose.yml", generateDockerCompose(), options.dryRun));
|
|
927
|
+
return files;
|
|
928
|
+
},
|
|
929
|
+
async deploy(_cwd, options) {
|
|
930
|
+
if (options.dryRun) return { message: options.compose ? "[dry-run] Would generate Dockerfile, .dockerignore, and docker-compose.yml." : "[dry-run] Would generate Dockerfile and .dockerignore." };
|
|
931
|
+
return { message: options.compose ? "Generated Dockerfile, .dockerignore, and docker-compose.yml." : "Generated Dockerfile and .dockerignore." };
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
|
|
935
|
+
//#endregion
|
|
936
|
+
//#region src/cli/commands/deploy/utils/spawn.ts
|
|
937
|
+
async function runCommand$1(command, args, options) {
|
|
938
|
+
return new Promise((resolve, reject) => {
|
|
939
|
+
const child = spawn(command, args, {
|
|
940
|
+
cwd: options.cwd,
|
|
941
|
+
env: {
|
|
942
|
+
...process.env,
|
|
943
|
+
...options.env
|
|
944
|
+
},
|
|
945
|
+
stdio: options.stdio === "inherit" ? "inherit" : [
|
|
946
|
+
"ignore",
|
|
947
|
+
"pipe",
|
|
948
|
+
"pipe"
|
|
949
|
+
],
|
|
950
|
+
shell: false
|
|
951
|
+
});
|
|
952
|
+
let stdout = "";
|
|
953
|
+
let stderr = "";
|
|
954
|
+
if (options.stdio !== "inherit") {
|
|
955
|
+
child.stdout?.on("data", (chunk) => {
|
|
956
|
+
stdout += chunk.toString();
|
|
957
|
+
});
|
|
958
|
+
child.stderr?.on("data", (chunk) => {
|
|
959
|
+
stderr += chunk.toString();
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
child.on("error", reject);
|
|
963
|
+
child.on("close", (code) => {
|
|
964
|
+
resolve({
|
|
965
|
+
code: code ?? 0,
|
|
966
|
+
stdout,
|
|
967
|
+
stderr
|
|
968
|
+
});
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
async function runCommandOrThrow(command, args, options) {
|
|
973
|
+
const result = await runCommand$1(command, args, options);
|
|
974
|
+
if (result.code !== 0) {
|
|
975
|
+
const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
|
|
976
|
+
throw new Error(`${command} ${args.join(" ")} failed: ${detail}`);
|
|
977
|
+
}
|
|
978
|
+
return result;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
//#endregion
|
|
982
|
+
//#region src/cli/commands/deploy/targets/fly.ts
|
|
983
|
+
const FLY_URL_RE = /https:\/\/[^\s"]+\.fly\.dev[^\s"]*/;
|
|
984
|
+
const FLY_HOST_RE = /\b[a-z0-9][a-z0-9-]*\.fly\.dev\b/;
|
|
985
|
+
const INVALID_FLY_APP_CHARS_RE = /[^a-z0-9-]+/g;
|
|
986
|
+
const REPEATED_HYPHENS_RE$1 = /-+/g;
|
|
987
|
+
const EDGE_HYPHENS_RE$1 = /^-|-$/g;
|
|
988
|
+
const LINE_SPLIT_RE = /\r?\n/;
|
|
989
|
+
const DEFAULT_REGION$1 = "iad";
|
|
990
|
+
const FLY_VOLUME_NAME = "dineway_data";
|
|
991
|
+
async function fileExists$8(path) {
|
|
992
|
+
try {
|
|
993
|
+
await access(path);
|
|
994
|
+
return true;
|
|
995
|
+
} catch {
|
|
996
|
+
return false;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
async function writeGeneratedFile$1(cwd, relativePath, content, dryRun) {
|
|
1000
|
+
const path = join(cwd, relativePath);
|
|
1001
|
+
if (await fileExists$8(path)) return {
|
|
1002
|
+
path: relativePath,
|
|
1003
|
+
action: "exists"
|
|
1004
|
+
};
|
|
1005
|
+
if (dryRun) return {
|
|
1006
|
+
path: relativePath,
|
|
1007
|
+
action: "skipped"
|
|
1008
|
+
};
|
|
1009
|
+
await writeFile(path, content, "utf-8");
|
|
1010
|
+
return {
|
|
1011
|
+
path: relativePath,
|
|
1012
|
+
action: "created"
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
async function readPackageName$1(cwd) {
|
|
1016
|
+
try {
|
|
1017
|
+
return JSON.parse(await readFile(join(cwd, "package.json"), "utf-8")).name;
|
|
1018
|
+
} catch {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
function normalizeFlyAppName(name) {
|
|
1023
|
+
return (name?.split("/").at(-1) ?? "dineway-app").toLowerCase().replace(INVALID_FLY_APP_CHARS_RE, "-").replace(REPEATED_HYPHENS_RE$1, "-").replace(EDGE_HYPHENS_RE$1, "") || "dineway-app";
|
|
1024
|
+
}
|
|
1025
|
+
async function defaultFlyAppName(cwd) {
|
|
1026
|
+
return normalizeFlyAppName(await readPackageName$1(cwd));
|
|
1027
|
+
}
|
|
1028
|
+
function parseFlyTomlValue(toml, key) {
|
|
1029
|
+
return toml.match(new RegExp(`^\\s*${key}\\s*=\\s*"([^"]+)"`, "m"))?.[1];
|
|
1030
|
+
}
|
|
1031
|
+
async function readFlyConfig(cwd) {
|
|
1032
|
+
try {
|
|
1033
|
+
const toml = await readFile(join(cwd, "fly.toml"), "utf-8");
|
|
1034
|
+
return {
|
|
1035
|
+
app: parseFlyTomlValue(toml, "app"),
|
|
1036
|
+
region: parseFlyTomlValue(toml, "primary_region"),
|
|
1037
|
+
hasMount: toml.includes(`source = "${FLY_VOLUME_NAME}"`)
|
|
1038
|
+
};
|
|
1039
|
+
} catch {
|
|
1040
|
+
return { hasMount: false };
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
function generateFlyToml(app, region = DEFAULT_REGION$1) {
|
|
1044
|
+
return `app = "${app}"
|
|
1045
|
+
primary_region = "${region}"
|
|
1046
|
+
|
|
1047
|
+
[build]
|
|
1048
|
+
dockerfile = "Dockerfile"
|
|
1049
|
+
|
|
1050
|
+
[env]
|
|
1051
|
+
HOST = "0.0.0.0"
|
|
1052
|
+
PORT = "4321"
|
|
1053
|
+
DINEWAY_DATABASE_URL = "file:./data/dineway.db"
|
|
1054
|
+
|
|
1055
|
+
[[mounts]]
|
|
1056
|
+
source = "${FLY_VOLUME_NAME}"
|
|
1057
|
+
destination = "/app/data"
|
|
1058
|
+
|
|
1059
|
+
[http_service]
|
|
1060
|
+
internal_port = 4321
|
|
1061
|
+
force_https = true
|
|
1062
|
+
auto_stop_machines = "stop"
|
|
1063
|
+
auto_start_machines = true
|
|
1064
|
+
min_machines_running = 1
|
|
1065
|
+
|
|
1066
|
+
[checks]
|
|
1067
|
+
[checks.dineway_liveness]
|
|
1068
|
+
grace_period = "30s"
|
|
1069
|
+
interval = "30s"
|
|
1070
|
+
method = "get"
|
|
1071
|
+
path = "${HEALTH_CHECK_PATH}"
|
|
1072
|
+
port = 4321
|
|
1073
|
+
timeout = "5s"
|
|
1074
|
+
type = "http"
|
|
1075
|
+
`;
|
|
1076
|
+
}
|
|
1077
|
+
function parseFlyUrl(stdout) {
|
|
1078
|
+
const direct = stdout.match(FLY_URL_RE);
|
|
1079
|
+
if (direct) return direct[0];
|
|
1080
|
+
for (const line of stdout.split(LINE_SPLIT_RE).filter(Boolean)) try {
|
|
1081
|
+
const url = findFlyUrl(JSON.parse(line));
|
|
1082
|
+
if (url) return url;
|
|
1083
|
+
} catch {
|
|
1084
|
+
const host = line.match(FLY_HOST_RE);
|
|
1085
|
+
if (host) return `https://${host[0]}`;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
function findFlyUrl(value) {
|
|
1089
|
+
if (typeof value === "string") {
|
|
1090
|
+
if (value.startsWith("https://") && value.includes(".fly.dev")) return value;
|
|
1091
|
+
if (FLY_HOST_RE.test(value)) return `https://${value.match(FLY_HOST_RE)?.[0]}`;
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
if (!value || typeof value !== "object") return void 0;
|
|
1095
|
+
for (const item of Object.values(value)) {
|
|
1096
|
+
const found = findFlyUrl(item);
|
|
1097
|
+
if (found) return found;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
function volumeExists(stdout, volumeName) {
|
|
1101
|
+
try {
|
|
1102
|
+
return findVolumeName(JSON.parse(stdout), volumeName);
|
|
1103
|
+
} catch {
|
|
1104
|
+
return stdout.includes(volumeName);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function findVolumeName(value, volumeName) {
|
|
1108
|
+
if (typeof value === "string") return value === volumeName;
|
|
1109
|
+
if (!value || typeof value !== "object") return false;
|
|
1110
|
+
return Object.values(value).some((item) => findVolumeName(item, volumeName));
|
|
1111
|
+
}
|
|
1112
|
+
async function ensureVolume(cwd) {
|
|
1113
|
+
const config = await readFlyConfig(cwd);
|
|
1114
|
+
if (!config.hasMount) return;
|
|
1115
|
+
const result = await runCommand$1("fly", [
|
|
1116
|
+
"volumes",
|
|
1117
|
+
"list",
|
|
1118
|
+
"--json"
|
|
1119
|
+
], { cwd });
|
|
1120
|
+
if (result.code === 0 && volumeExists(result.stdout, FLY_VOLUME_NAME)) return;
|
|
1121
|
+
const region = config.region ?? DEFAULT_REGION$1;
|
|
1122
|
+
throw new Error(`Fly volume "${FLY_VOLUME_NAME}" is required for file-backed Dineway data. Create it with: fly volumes create ${FLY_VOLUME_NAME} --region ${region} --size 1`);
|
|
1123
|
+
}
|
|
1124
|
+
const flyTarget = {
|
|
1125
|
+
name: "fly",
|
|
1126
|
+
label: "fly.io",
|
|
1127
|
+
description: "Deploy with flyctl and the Fly remote builder.",
|
|
1128
|
+
supportLevel: "stable",
|
|
1129
|
+
cli: {
|
|
1130
|
+
npmPackage: null,
|
|
1131
|
+
binary: "fly",
|
|
1132
|
+
versionCommand: {
|
|
1133
|
+
command: "fly",
|
|
1134
|
+
args: ["version"]
|
|
1135
|
+
},
|
|
1136
|
+
installHint: "Install flyctl from https://fly.io/docs/flyctl/install/"
|
|
1137
|
+
},
|
|
1138
|
+
async checkAuth(cwd) {
|
|
1139
|
+
return (await runCommand$1("fly", ["auth", "whoami"], { cwd })).code === 0;
|
|
1140
|
+
},
|
|
1141
|
+
async login(cwd) {
|
|
1142
|
+
await runCommandOrThrow("fly", ["auth", "login"], {
|
|
1143
|
+
cwd,
|
|
1144
|
+
stdio: "inherit"
|
|
1145
|
+
});
|
|
1146
|
+
},
|
|
1147
|
+
async isLinked(cwd) {
|
|
1148
|
+
return (await runCommand$1("fly", ["status"], { cwd })).code === 0;
|
|
1149
|
+
},
|
|
1150
|
+
async link(cwd) {
|
|
1151
|
+
await runCommandOrThrow("fly", [
|
|
1152
|
+
"launch",
|
|
1153
|
+
"--no-deploy",
|
|
1154
|
+
"--copy-config",
|
|
1155
|
+
"--dockerfile",
|
|
1156
|
+
"Dockerfile",
|
|
1157
|
+
"--no-github-workflow",
|
|
1158
|
+
"--no-db",
|
|
1159
|
+
"--no-object-storage"
|
|
1160
|
+
], {
|
|
1161
|
+
cwd,
|
|
1162
|
+
stdio: "inherit"
|
|
1163
|
+
});
|
|
1164
|
+
},
|
|
1165
|
+
async generateConfig(cwd, options) {
|
|
1166
|
+
return [
|
|
1167
|
+
await writeGeneratedFile$1(cwd, "Dockerfile", generateDockerfile(), options.dryRun),
|
|
1168
|
+
await writeGeneratedFile$1(cwd, ".dockerignore", generateDockerignore(), options.dryRun),
|
|
1169
|
+
await writeGeneratedFile$1(cwd, "fly.toml", generateFlyToml(await defaultFlyAppName(cwd)), options.dryRun)
|
|
1170
|
+
];
|
|
1171
|
+
},
|
|
1172
|
+
async deploy(cwd, options) {
|
|
1173
|
+
if (options.dryRun) return { message: "[dry-run] Would run fly deploy --remote-only." };
|
|
1174
|
+
await ensureVolume(cwd);
|
|
1175
|
+
await runCommandOrThrow("fly", ["deploy", "--remote-only"], {
|
|
1176
|
+
cwd,
|
|
1177
|
+
env: options.env,
|
|
1178
|
+
stdio: "inherit"
|
|
1179
|
+
});
|
|
1180
|
+
const status = await runCommand$1("fly", ["status", "--json"], { cwd }).catch(() => null);
|
|
1181
|
+
const url = status ? parseFlyUrl(status.stdout) : void 0;
|
|
1182
|
+
return {
|
|
1183
|
+
url,
|
|
1184
|
+
message: url ? `Deploy complete: ${url}` : "Deploy complete. Check Fly dashboard for URL."
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region src/cli/commands/deploy/targets/gcp.ts
|
|
1191
|
+
const CLOUD_RUN_URL_RE = /https:\/\/[^\s"]+\.run\.app[^\s"]*/;
|
|
1192
|
+
const INVALID_SERVICE_CHARS_RE = /[^a-z0-9-]+/g;
|
|
1193
|
+
const REPEATED_HYPHENS_RE = /-+/g;
|
|
1194
|
+
const EDGE_HYPHENS_RE = /^-|-$/g;
|
|
1195
|
+
const DEFAULT_REGION = "us-central1";
|
|
1196
|
+
const GCLOUDIGNORE = `.env
|
|
1197
|
+
.env.*
|
|
1198
|
+
.git
|
|
1199
|
+
.github
|
|
1200
|
+
.plan
|
|
1201
|
+
.astro
|
|
1202
|
+
.dineway
|
|
1203
|
+
node_modules
|
|
1204
|
+
dist
|
|
1205
|
+
uploads
|
|
1206
|
+
data
|
|
1207
|
+
*.db
|
|
1208
|
+
*.db-*
|
|
1209
|
+
npm-debug.log*
|
|
1210
|
+
pnpm-debug.log*
|
|
1211
|
+
yarn-debug.log*
|
|
1212
|
+
yarn-error.log*
|
|
1213
|
+
`;
|
|
1214
|
+
async function fileExists$7(path) {
|
|
1215
|
+
try {
|
|
1216
|
+
await access(path);
|
|
1217
|
+
return true;
|
|
1218
|
+
} catch {
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
async function writeGeneratedFile(cwd, relativePath, content, dryRun) {
|
|
1223
|
+
const path = join(cwd, relativePath);
|
|
1224
|
+
if (await fileExists$7(path)) return {
|
|
1225
|
+
path: relativePath,
|
|
1226
|
+
action: "exists"
|
|
1227
|
+
};
|
|
1228
|
+
if (dryRun) return {
|
|
1229
|
+
path: relativePath,
|
|
1230
|
+
action: "skipped"
|
|
1231
|
+
};
|
|
1232
|
+
await writeFile(path, content, "utf-8");
|
|
1233
|
+
return {
|
|
1234
|
+
path: relativePath,
|
|
1235
|
+
action: "created"
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
async function readPackageName(cwd) {
|
|
1239
|
+
try {
|
|
1240
|
+
return JSON.parse(await readFile(join(cwd, "package.json"), "utf-8")).name;
|
|
1241
|
+
} catch {
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
function normalizeCloudRunServiceName(name) {
|
|
1246
|
+
return (name?.split("/").at(-1) ?? "dineway").toLowerCase().replace(INVALID_SERVICE_CHARS_RE, "-").replace(REPEATED_HYPHENS_RE, "-").replace(EDGE_HYPHENS_RE, "") || "dineway";
|
|
1247
|
+
}
|
|
1248
|
+
function resolveEnvValue(env, key) {
|
|
1249
|
+
return env?.[key] ?? process.env[key];
|
|
1250
|
+
}
|
|
1251
|
+
async function resolveServiceName(cwd, env) {
|
|
1252
|
+
return resolveEnvValue(env, "DINEWAY_GCP_SERVICE") || resolveEnvValue(env, "CLOUD_RUN_SERVICE") || normalizeCloudRunServiceName(await readPackageName(cwd));
|
|
1253
|
+
}
|
|
1254
|
+
function resolveRegion(env) {
|
|
1255
|
+
return resolveEnvValue(env, "DINEWAY_GCP_REGION") || resolveEnvValue(env, "GOOGLE_CLOUD_REGION") || resolveEnvValue(env, "CLOUDSDK_RUN_REGION") || DEFAULT_REGION;
|
|
1256
|
+
}
|
|
1257
|
+
function parseCloudRunUrl(stdout) {
|
|
1258
|
+
return stdout.match(CLOUD_RUN_URL_RE)?.[0];
|
|
1259
|
+
}
|
|
1260
|
+
function assertCloudRunStorageEnv(env) {
|
|
1261
|
+
const databaseUrl = resolveEnvValue(env, "DINEWAY_DATABASE_URL");
|
|
1262
|
+
if (!databaseUrl || databaseUrl.startsWith("file:")) throw new Error("Cloud Run requires a remote DINEWAY_DATABASE_URL such as libSQL HTTP or PostgreSQL. File-backed libSQL is not supported on Cloud Run's ephemeral filesystem.");
|
|
1263
|
+
}
|
|
1264
|
+
function buildDeployArgs(service, region) {
|
|
1265
|
+
return [
|
|
1266
|
+
"run",
|
|
1267
|
+
"deploy",
|
|
1268
|
+
service,
|
|
1269
|
+
"--source",
|
|
1270
|
+
".",
|
|
1271
|
+
"--region",
|
|
1272
|
+
region,
|
|
1273
|
+
"--port",
|
|
1274
|
+
"4321",
|
|
1275
|
+
"--allow-unauthenticated",
|
|
1276
|
+
"--set-build-env-vars",
|
|
1277
|
+
"GOOGLE_NODE_RUN_SCRIPTS=build",
|
|
1278
|
+
"--update-env-vars",
|
|
1279
|
+
"HOST=0.0.0.0",
|
|
1280
|
+
"--liveness-probe",
|
|
1281
|
+
`httpGet.path=${HEALTH_CHECK_PATH},httpGet.port=4321,initialDelaySeconds=30,timeoutSeconds=5,periodSeconds=30,failureThreshold=3`
|
|
1282
|
+
];
|
|
1283
|
+
}
|
|
1284
|
+
async function describeServiceUrl(cwd, service, region, env) {
|
|
1285
|
+
const result = await runCommand$1("gcloud", [
|
|
1286
|
+
"run",
|
|
1287
|
+
"services",
|
|
1288
|
+
"describe",
|
|
1289
|
+
service,
|
|
1290
|
+
"--region",
|
|
1291
|
+
region,
|
|
1292
|
+
"--format",
|
|
1293
|
+
"value(status.url)"
|
|
1294
|
+
], {
|
|
1295
|
+
cwd,
|
|
1296
|
+
env
|
|
1297
|
+
}).catch(() => null);
|
|
1298
|
+
if (!result || result.code !== 0) return void 0;
|
|
1299
|
+
return parseCloudRunUrl(result.stdout) ?? (result.stdout.trim() || void 0);
|
|
1300
|
+
}
|
|
1301
|
+
const gcpTarget = {
|
|
1302
|
+
name: "gcp",
|
|
1303
|
+
label: "GCP Cloud Run",
|
|
1304
|
+
description: "Deploy to Cloud Run from local source with gcloud.",
|
|
1305
|
+
supportLevel: "experimental",
|
|
1306
|
+
cli: {
|
|
1307
|
+
npmPackage: null,
|
|
1308
|
+
binary: "gcloud",
|
|
1309
|
+
versionCommand: {
|
|
1310
|
+
command: "gcloud",
|
|
1311
|
+
args: ["--version"]
|
|
1312
|
+
},
|
|
1313
|
+
installHint: "Install the Google Cloud CLI from https://cloud.google.com/sdk/docs/install"
|
|
1314
|
+
},
|
|
1315
|
+
async checkAuth(cwd) {
|
|
1316
|
+
const result = await runCommand$1("gcloud", [
|
|
1317
|
+
"auth",
|
|
1318
|
+
"list",
|
|
1319
|
+
"--filter=status:ACTIVE",
|
|
1320
|
+
"--format",
|
|
1321
|
+
"value(account)"
|
|
1322
|
+
], { cwd });
|
|
1323
|
+
return result.code === 0 && result.stdout.trim().length > 0;
|
|
1324
|
+
},
|
|
1325
|
+
async login(cwd) {
|
|
1326
|
+
await runCommandOrThrow("gcloud", ["auth", "login"], {
|
|
1327
|
+
cwd,
|
|
1328
|
+
stdio: "inherit"
|
|
1329
|
+
});
|
|
1330
|
+
},
|
|
1331
|
+
async isLinked(cwd) {
|
|
1332
|
+
const result = await runCommand$1("gcloud", [
|
|
1333
|
+
"config",
|
|
1334
|
+
"get-value",
|
|
1335
|
+
"project"
|
|
1336
|
+
], { cwd });
|
|
1337
|
+
const project = result.stdout.trim();
|
|
1338
|
+
return result.code === 0 && project.length > 0 && project !== "(unset)";
|
|
1339
|
+
},
|
|
1340
|
+
async link() {
|
|
1341
|
+
throw new Error("No active Google Cloud project. Run: gcloud config set project PROJECT_ID");
|
|
1342
|
+
},
|
|
1343
|
+
async generateConfig(cwd, options) {
|
|
1344
|
+
return [await writeGeneratedFile(cwd, ".gcloudignore", GCLOUDIGNORE, options.dryRun)];
|
|
1345
|
+
},
|
|
1346
|
+
async deploy(cwd, options) {
|
|
1347
|
+
const service = await resolveServiceName(cwd, options.env);
|
|
1348
|
+
const region = resolveRegion(options.env);
|
|
1349
|
+
if (options.dryRun) return { message: `[dry-run] Would run gcloud run deploy ${service} --source . --region ${region}.` };
|
|
1350
|
+
assertCloudRunStorageEnv(options.env);
|
|
1351
|
+
const deployArgs = buildDeployArgs(service, region);
|
|
1352
|
+
let result = await runCommand$1("gcloud", deployArgs, {
|
|
1353
|
+
cwd,
|
|
1354
|
+
env: options.env,
|
|
1355
|
+
stdio: "inherit"
|
|
1356
|
+
});
|
|
1357
|
+
if (result.code !== 0 && !await fileExists$7(join(cwd, "Dockerfile"))) {
|
|
1358
|
+
await writeFile(join(cwd, "Dockerfile"), generateDockerfile(), "utf-8");
|
|
1359
|
+
result = await runCommand$1("gcloud", deployArgs, {
|
|
1360
|
+
cwd,
|
|
1361
|
+
env: options.env,
|
|
1362
|
+
stdio: "inherit"
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
if (result.code !== 0) throw new Error("gcloud run deploy failed. Check Cloud Build and Cloud Run logs for details.");
|
|
1366
|
+
const url = parseCloudRunUrl(result.stdout) ?? await describeServiceUrl(cwd, service, region, options.env);
|
|
1367
|
+
return {
|
|
1368
|
+
url,
|
|
1369
|
+
message: url ? `Deploy complete: ${url}` : `Deploy complete. Start command is ${NODE_START_COMMAND}; check Cloud Run dashboard for URL.`
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1374
|
+
//#endregion
|
|
1375
|
+
//#region src/cli/commands/deploy/utils/build.ts
|
|
1376
|
+
async function fileExists$6(path) {
|
|
1377
|
+
try {
|
|
1378
|
+
await access(path);
|
|
1379
|
+
return true;
|
|
1380
|
+
} catch {
|
|
1381
|
+
return false;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
async function detectBuildCommand(cwd) {
|
|
1385
|
+
if (await fileExists$6(join(cwd, "pnpm-lock.yaml"))) return {
|
|
1386
|
+
packageManager: "pnpm",
|
|
1387
|
+
command: "pnpm",
|
|
1388
|
+
args: ["build"],
|
|
1389
|
+
display: "pnpm build"
|
|
1390
|
+
};
|
|
1391
|
+
if (await fileExists$6(join(cwd, "yarn.lock"))) return {
|
|
1392
|
+
packageManager: "yarn",
|
|
1393
|
+
command: "yarn",
|
|
1394
|
+
args: ["build"],
|
|
1395
|
+
display: "yarn build"
|
|
1396
|
+
};
|
|
1397
|
+
if (await fileExists$6(join(cwd, "bun.lock")) || await fileExists$6(join(cwd, "bun.lockb"))) return {
|
|
1398
|
+
packageManager: "bun",
|
|
1399
|
+
command: "bun",
|
|
1400
|
+
args: ["run", "build"],
|
|
1401
|
+
display: "bun run build"
|
|
1402
|
+
};
|
|
1403
|
+
return {
|
|
1404
|
+
packageManager: "npm",
|
|
1405
|
+
command: "npm",
|
|
1406
|
+
args: ["run", "build"],
|
|
1407
|
+
display: "npm run build"
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
async function runBuild(cwd, env) {
|
|
1411
|
+
const build = await detectBuildCommand(cwd);
|
|
1412
|
+
await runCommandOrThrow(build.command, build.args, {
|
|
1413
|
+
cwd,
|
|
1414
|
+
env,
|
|
1415
|
+
stdio: "inherit"
|
|
1416
|
+
});
|
|
1417
|
+
return build;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
//#endregion
|
|
1421
|
+
//#region src/cli/commands/deploy/targets/railway.ts
|
|
1422
|
+
const NONEMPTY_LINE_RE = /\r?\n/;
|
|
1423
|
+
const RAILWAY_URL_RE = /https:\/\/[^\s"]+\.up\.railway\.app[^\s"]*/;
|
|
1424
|
+
async function fileExists$5(path) {
|
|
1425
|
+
try {
|
|
1426
|
+
await access(path);
|
|
1427
|
+
return true;
|
|
1428
|
+
} catch {
|
|
1429
|
+
return false;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
function parseRailwayUrl(stdout) {
|
|
1433
|
+
for (const line of stdout.split(NONEMPTY_LINE_RE).filter(Boolean)) try {
|
|
1434
|
+
const url = findUrl(JSON.parse(line));
|
|
1435
|
+
if (url) return url;
|
|
1436
|
+
} catch {
|
|
1437
|
+
const match = line.match(RAILWAY_URL_RE);
|
|
1438
|
+
if (match) return match[0];
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
function findUrl(value) {
|
|
1442
|
+
if (typeof value === "string") return value.startsWith("https://") && value.includes("railway.app") ? value : void 0;
|
|
1443
|
+
if (!value || typeof value !== "object") return void 0;
|
|
1444
|
+
for (const item of Object.values(value)) {
|
|
1445
|
+
const found = findUrl(item);
|
|
1446
|
+
if (found) return found;
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
const railwayTarget = {
|
|
1450
|
+
name: "railway",
|
|
1451
|
+
label: "Railway",
|
|
1452
|
+
description: "Deploy a standard Dineway Node server with Railway CLI.",
|
|
1453
|
+
recommended: true,
|
|
1454
|
+
supportLevel: "stable",
|
|
1455
|
+
cli: {
|
|
1456
|
+
npmPackage: "@railway/cli",
|
|
1457
|
+
binary: "railway",
|
|
1458
|
+
versionCommand: {
|
|
1459
|
+
command: "railway",
|
|
1460
|
+
args: ["--version"]
|
|
1461
|
+
},
|
|
1462
|
+
installHint: "Install the Railway CLI from https://docs.railway.app/reference/cli"
|
|
1463
|
+
},
|
|
1464
|
+
async checkAuth(cwd) {
|
|
1465
|
+
return (await runCommand$1("railway", ["whoami"], { cwd })).code === 0;
|
|
1466
|
+
},
|
|
1467
|
+
async login(cwd) {
|
|
1468
|
+
await runCommandOrThrow("railway", ["login"], {
|
|
1469
|
+
cwd,
|
|
1470
|
+
stdio: "inherit"
|
|
1471
|
+
});
|
|
1472
|
+
},
|
|
1473
|
+
async isLinked(cwd) {
|
|
1474
|
+
return (await runCommand$1("railway", ["status"], { cwd })).code === 0;
|
|
1475
|
+
},
|
|
1476
|
+
async link(cwd) {
|
|
1477
|
+
await runCommandOrThrow("railway", ["link"], {
|
|
1478
|
+
cwd,
|
|
1479
|
+
stdio: "inherit"
|
|
1480
|
+
});
|
|
1481
|
+
},
|
|
1482
|
+
async generateConfig(cwd, options) {
|
|
1483
|
+
const railwayPath = join(cwd, "railway.json");
|
|
1484
|
+
if (await fileExists$5(railwayPath)) return [{
|
|
1485
|
+
path: "railway.json",
|
|
1486
|
+
action: "exists"
|
|
1487
|
+
}];
|
|
1488
|
+
const config = {
|
|
1489
|
+
$schema: "https://railway.app/railway.schema.json",
|
|
1490
|
+
build: {
|
|
1491
|
+
builder: "NIXPACKS",
|
|
1492
|
+
buildCommand: (await detectBuildCommand(cwd)).display
|
|
1493
|
+
},
|
|
1494
|
+
deploy: {
|
|
1495
|
+
startCommand: NODE_START_COMMAND,
|
|
1496
|
+
healthcheckPath: HEALTH_CHECK_PATH,
|
|
1497
|
+
healthcheckTimeout: 100,
|
|
1498
|
+
restartPolicyType: "ON_FAILURE"
|
|
1499
|
+
}
|
|
1500
|
+
};
|
|
1501
|
+
if (options.dryRun) return [{
|
|
1502
|
+
path: "railway.json",
|
|
1503
|
+
action: "skipped"
|
|
1504
|
+
}];
|
|
1505
|
+
await writeFile(railwayPath, JSON.stringify(config, null, " ") + "\n", "utf-8");
|
|
1506
|
+
return [{
|
|
1507
|
+
path: "railway.json",
|
|
1508
|
+
action: "created"
|
|
1509
|
+
}];
|
|
1510
|
+
},
|
|
1511
|
+
async deploy(cwd, options) {
|
|
1512
|
+
if (options.dryRun) return { message: "[dry-run] Would run railway up." };
|
|
1513
|
+
await runCommandOrThrow("railway", ["up"], {
|
|
1514
|
+
cwd,
|
|
1515
|
+
env: options.env,
|
|
1516
|
+
stdio: "inherit"
|
|
1517
|
+
});
|
|
1518
|
+
const domain = await runCommand$1("railway", ["domain", "--json"], { cwd }).catch(() => null);
|
|
1519
|
+
const status = await runCommand$1("railway", ["status", "--json"], { cwd }).catch(() => null);
|
|
1520
|
+
const url = (domain ? parseRailwayUrl(domain.stdout) : void 0) ?? (status ? parseRailwayUrl(status.stdout) : void 0);
|
|
1521
|
+
return {
|
|
1522
|
+
url,
|
|
1523
|
+
message: url ? `Deploy complete: ${url}` : "Deploy started. Check Railway dashboard for URL."
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
//#endregion
|
|
1529
|
+
//#region src/cli/commands/deploy/utils/cli-resolver.ts
|
|
1530
|
+
async function confirm(message) {
|
|
1531
|
+
if (!process.stdin.isTTY) return false;
|
|
1532
|
+
const rl = createInterface({
|
|
1533
|
+
input: process.stdin,
|
|
1534
|
+
output: process.stdout
|
|
1535
|
+
});
|
|
1536
|
+
try {
|
|
1537
|
+
const answer = await rl.question(`${message} [y/N] `);
|
|
1538
|
+
return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
|
|
1539
|
+
} finally {
|
|
1540
|
+
rl.close();
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
async function ensureTargetCli(target, cwd, options = {}) {
|
|
1544
|
+
if (!target.cli) return;
|
|
1545
|
+
if ((await runCommand$1(target.cli.versionCommand.command, target.cli.versionCommand.args, { cwd }).catch(() => ({
|
|
1546
|
+
code: 1,
|
|
1547
|
+
stdout: "",
|
|
1548
|
+
stderr: ""
|
|
1549
|
+
}))).code === 0) return;
|
|
1550
|
+
if (options.dryRun) {
|
|
1551
|
+
consola.info(`[dry-run] Would verify ${target.cli.binary} CLI with ${target.cli.versionCommand.command} ${target.cli.versionCommand.args.join(" ")}`);
|
|
1552
|
+
if (target.cli.npmPackage) consola.info(`[dry-run] Would offer to install ${target.cli.npmPackage}`);
|
|
1553
|
+
else consola.info(`[dry-run] ${target.cli.installHint ?? `Install ${target.cli.binary} before deploying.`}`);
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
if (!target.cli.npmPackage) throw new Error(`${target.label} CLI is required. ${target.cli.installHint ?? `Install ${target.cli.binary} and try again.`}`);
|
|
1557
|
+
if (options.yes) throw new Error(`Install ${target.cli.npmPackage} and run this command again. The --yes flag does not approve global CLI installation.`);
|
|
1558
|
+
if (!await confirm(`${target.label} CLI is not installed. Install ${target.cli.npmPackage} globally now?`)) throw new Error(`Install ${target.cli.npmPackage} and run this command again.`);
|
|
1559
|
+
await runCommandOrThrow("npm", [
|
|
1560
|
+
"install",
|
|
1561
|
+
"--global",
|
|
1562
|
+
target.cli.npmPackage
|
|
1563
|
+
], {
|
|
1564
|
+
cwd,
|
|
1565
|
+
stdio: "inherit"
|
|
1566
|
+
});
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
//#endregion
|
|
1570
|
+
//#region src/cli/commands/deploy/utils/config.ts
|
|
1571
|
+
async function readDeployPackageJson(cwd) {
|
|
1572
|
+
const content = await readFile(join(cwd, "package.json"), "utf-8");
|
|
1573
|
+
return JSON.parse(content);
|
|
1574
|
+
}
|
|
1575
|
+
async function readSavedDeployTarget(cwd) {
|
|
1576
|
+
return (await readDeployPackageJson(cwd)).dineway?.deploy?.target;
|
|
1577
|
+
}
|
|
1578
|
+
async function writeDeployTarget(cwd, target) {
|
|
1579
|
+
const pkgPath = join(cwd, "package.json");
|
|
1580
|
+
const pkg = await readDeployPackageJson(cwd);
|
|
1581
|
+
pkg.dineway = {
|
|
1582
|
+
...pkg.dineway,
|
|
1583
|
+
deploy: {
|
|
1584
|
+
...pkg.dineway?.deploy,
|
|
1585
|
+
target
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, " ") + "\n", "utf-8");
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
//#endregion
|
|
1592
|
+
//#region src/cli/commands/deploy/index.ts
|
|
1593
|
+
const targets = [
|
|
1594
|
+
railwayTarget,
|
|
1595
|
+
dockerTarget,
|
|
1596
|
+
flyTarget,
|
|
1597
|
+
gcpTarget
|
|
1598
|
+
];
|
|
1599
|
+
function getTarget(name) {
|
|
1600
|
+
return targets.find((target) => target.name === name);
|
|
1601
|
+
}
|
|
1602
|
+
function targetList() {
|
|
1603
|
+
return targets.map((target) => target.name).join(", ");
|
|
1604
|
+
}
|
|
1605
|
+
async function promptForTarget() {
|
|
1606
|
+
const recommended = targets.find((target) => target.recommended) ?? targets[0];
|
|
1607
|
+
if (!process.stdin.isTTY || !recommended) throw new Error(`No deploy target configured. Pass one of: ${targetList()}`);
|
|
1608
|
+
const rl = createInterface({
|
|
1609
|
+
input: process.stdin,
|
|
1610
|
+
output: process.stdout
|
|
1611
|
+
});
|
|
1612
|
+
try {
|
|
1613
|
+
consola.info("Available deploy targets:");
|
|
1614
|
+
targets.forEach((target, index) => {
|
|
1615
|
+
const suffix = target.recommended ? " (recommended)" : "";
|
|
1616
|
+
consola.info(` ${index + 1}. ${target.label}${suffix} - ${target.description}`);
|
|
1617
|
+
});
|
|
1618
|
+
const value = (await rl.question(`Choose a target [${recommended.name}]: `)).trim() || recommended.name;
|
|
1619
|
+
const byIndex = Number(value);
|
|
1620
|
+
const target = Number.isInteger(byIndex) ? targets[byIndex - 1] : getTarget(value);
|
|
1621
|
+
if (!target) throw new Error(`Unknown deploy target "${value}". Available targets: ${targetList()}`);
|
|
1622
|
+
return target;
|
|
1623
|
+
} finally {
|
|
1624
|
+
rl.close();
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
async function resolveTarget(cwd, explicitTarget) {
|
|
1628
|
+
if (explicitTarget) {
|
|
1629
|
+
const target = getTarget(explicitTarget);
|
|
1630
|
+
if (!target) throw new Error(`Unknown deploy target "${explicitTarget}". Available targets: ${targetList()}`);
|
|
1631
|
+
return target;
|
|
1632
|
+
}
|
|
1633
|
+
const saved = await readSavedDeployTarget(cwd).catch(() => void 0);
|
|
1634
|
+
if (saved) {
|
|
1635
|
+
const target = getTarget(saved);
|
|
1636
|
+
if (!target) throw new Error(`Saved deploy target "${saved}" is unknown. Available targets: ${targetList()}`);
|
|
1637
|
+
return target;
|
|
1638
|
+
}
|
|
1639
|
+
return promptForTarget();
|
|
1640
|
+
}
|
|
1641
|
+
const deployCommand = defineCommand({
|
|
1642
|
+
meta: {
|
|
1643
|
+
name: "deploy",
|
|
1644
|
+
description: "Deploy a Dineway Node server through a provider CLI"
|
|
1645
|
+
},
|
|
1646
|
+
args: {
|
|
1647
|
+
target: {
|
|
1648
|
+
type: "positional",
|
|
1649
|
+
description: "Deploy target",
|
|
1650
|
+
required: false
|
|
1651
|
+
},
|
|
1652
|
+
cwd: {
|
|
1653
|
+
type: "string",
|
|
1654
|
+
description: "Working directory",
|
|
1655
|
+
default: process.cwd()
|
|
1656
|
+
},
|
|
1657
|
+
"skip-build": {
|
|
1658
|
+
type: "boolean",
|
|
1659
|
+
description: "Skip running the package build command before deploy",
|
|
1660
|
+
default: false
|
|
1661
|
+
},
|
|
1662
|
+
compose: {
|
|
1663
|
+
type: "boolean",
|
|
1664
|
+
description: "Generate docker-compose.yml for Docker target",
|
|
1665
|
+
default: false
|
|
1666
|
+
},
|
|
1667
|
+
yes: {
|
|
1668
|
+
type: "boolean",
|
|
1669
|
+
alias: "y",
|
|
1670
|
+
description: "Accept safe interactive prompts",
|
|
1671
|
+
default: false
|
|
1672
|
+
},
|
|
1673
|
+
"dry-run": {
|
|
1674
|
+
type: "boolean",
|
|
1675
|
+
description: "Print planned actions without writing files or deploying",
|
|
1676
|
+
default: false
|
|
1677
|
+
}
|
|
1678
|
+
},
|
|
1679
|
+
async run({ args }) {
|
|
1680
|
+
const cwd = resolve(args.cwd);
|
|
1681
|
+
const target = await resolveTarget(cwd, args.target);
|
|
1682
|
+
const options = {
|
|
1683
|
+
skipBuild: args["skip-build"],
|
|
1684
|
+
compose: args.compose,
|
|
1685
|
+
yes: args.yes,
|
|
1686
|
+
dryRun: args["dry-run"]
|
|
1687
|
+
};
|
|
1688
|
+
consola.start(`Preparing ${target.label} deploy`);
|
|
1689
|
+
await ensureTargetCli(target, cwd, {
|
|
1690
|
+
yes: options.yes,
|
|
1691
|
+
dryRun: options.dryRun
|
|
1692
|
+
});
|
|
1693
|
+
const generated = await target.generateConfig(cwd, options);
|
|
1694
|
+
for (const file of generated) {
|
|
1695
|
+
if (file.action === "created") consola.success(`Created ${file.path}`);
|
|
1696
|
+
if (file.action === "exists") consola.info(`${file.path} already exists`);
|
|
1697
|
+
if (file.action === "skipped") consola.info(`[dry-run] Would create ${file.path}`);
|
|
1698
|
+
}
|
|
1699
|
+
if (!options.dryRun) {
|
|
1700
|
+
if (target.checkAuth && !await target.checkAuth(cwd)) {
|
|
1701
|
+
if (!target.login) throw new Error(`${target.label} CLI is not authenticated.`);
|
|
1702
|
+
await target.login(cwd);
|
|
1703
|
+
}
|
|
1704
|
+
if (target.isLinked && !await target.isLinked(cwd)) {
|
|
1705
|
+
if (!target.link) throw new Error(`${target.label} project is not linked.`);
|
|
1706
|
+
await target.link(cwd);
|
|
1707
|
+
}
|
|
1708
|
+
} else consola.info("[dry-run] Would verify provider authentication and project link");
|
|
1709
|
+
if (!options.skipBuild && target.name !== "docker") {
|
|
1710
|
+
const build = options.dryRun ? null : await runBuild(cwd, options.env);
|
|
1711
|
+
consola.info(options.dryRun ? "[dry-run] Would run build" : `Built with ${build?.display}`);
|
|
1712
|
+
}
|
|
1713
|
+
if (!options.dryRun) await writeDeployTarget(cwd, target.name);
|
|
1714
|
+
else consola.info(`[dry-run] Would save dineway.deploy.target=${target.name}`);
|
|
1715
|
+
const result = await target.deploy(cwd, options);
|
|
1716
|
+
if (result.url) consola.success(result.url);
|
|
1717
|
+
consola.success(result.message);
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
|
|
803
1721
|
//#endregion
|
|
804
1722
|
//#region src/cli/database-url.ts
|
|
805
1723
|
const REMOTE_DATABASE_URL_PREFIXES = [
|
|
@@ -2276,13 +3194,13 @@ async function findBuildOutput(dir, baseName) {
|
|
|
2276
3194
|
*/
|
|
2277
3195
|
async function resolveSourceEntry(pluginDir, distPath) {
|
|
2278
3196
|
const cleaned = distPath.replace(LEADING_DOT_SLASH_RE, "");
|
|
2279
|
-
const direct = resolve(pluginDir, cleaned);
|
|
2280
|
-
if (await fileExists$1(direct)) return direct;
|
|
2281
3197
|
const srcPath = cleaned.replace(DIST_PREFIX_RE, "src/").replace(MJS_EXT_RE, ".ts");
|
|
2282
3198
|
const srcFull = resolve(pluginDir, srcPath);
|
|
2283
3199
|
if (await fileExists$1(srcFull)) return srcFull;
|
|
2284
3200
|
const tsxFull = resolve(pluginDir, srcPath.replace(TS_TO_TSX_RE, ".tsx"));
|
|
2285
3201
|
if (await fileExists$1(tsxFull)) return tsxFull;
|
|
3202
|
+
const direct = resolve(pluginDir, cleaned);
|
|
3203
|
+
if (await fileExists$1(direct)) return direct;
|
|
2286
3204
|
}
|
|
2287
3205
|
const TS_SOURCE_EXPORT_RE = /\.(?:ts|tsx|mts|cts|jsx)$/;
|
|
2288
3206
|
/**
|
|
@@ -3954,6 +4872,7 @@ const typesCommand = defineCommand({
|
|
|
3954
4872
|
* - search: Full-text search
|
|
3955
4873
|
* - taxonomy: Manage taxonomies and terms
|
|
3956
4874
|
* - menu: Manage navigation menus
|
|
4875
|
+
* - deploy: Deploy a standard Dineway Node server through a provider CLI
|
|
3957
4876
|
* - plugin: Plugin management (init, bundle, validate, publish, login, logout)
|
|
3958
4877
|
*/
|
|
3959
4878
|
runMain(defineCommand({
|
|
@@ -3966,6 +4885,7 @@ runMain(defineCommand({
|
|
|
3966
4885
|
init: initCommand,
|
|
3967
4886
|
types: typesCommand,
|
|
3968
4887
|
dev: devCommand,
|
|
4888
|
+
deploy: deployCommand,
|
|
3969
4889
|
doctor: doctorCommand,
|
|
3970
4890
|
seed: seedCommand,
|
|
3971
4891
|
"export-seed": exportSeedCommand,
|