deployai 0.1.0-beta.4 → 0.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +48 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ Node 20 or newer. No other setup: the CLI talks to https://deployai.co.il.
|
|
|
49
49
|
| `deployai versions` | Lists versions: number, live or not, status ("replaced by a newer upload" for one that never built), date, size, message, and a dashboard link when its SQL waits for approval. |
|
|
50
50
|
| `deployai rollback v5` | Puts version 5 back live, with no rebuild. |
|
|
51
51
|
| `deployai promote v5` | Puts version 5 live. |
|
|
52
|
-
| `deployai status` | Site state, address, live version and queue. |
|
|
52
|
+
| `deployai status` | Site state, address, live version, the newest version when it is not live yet (with the promote command once it is ready), and queue. |
|
|
53
53
|
| `deployai deploy --guest` | No login needed: puts the site live as a temporary site with a claim link. More below. |
|
|
54
54
|
| `deployai pull` | Downloads the code of the linked site's live version into this empty folder. Needs login. |
|
|
55
55
|
| `deployai claim` | Prints this folder's temporary site keep link again. `--email <address>` mails it, with a reminder before the delete. |
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,9 @@ import { Command } from "commander";
|
|
|
12
12
|
// src/api.ts
|
|
13
13
|
import { arch, platform } from "os";
|
|
14
14
|
|
|
15
|
+
// ../shared/src/plans.ts
|
|
16
|
+
var VAT_RATE = 0.18;
|
|
17
|
+
|
|
15
18
|
// ../shared/src/blockers.ts
|
|
16
19
|
var ISSUES = [
|
|
17
20
|
// Blockers
|
|
@@ -20939,7 +20942,15 @@ var StatusResponse = external_exports.object({
|
|
|
20939
20942
|
project: Project,
|
|
20940
20943
|
queue: external_exports.object({ position: external_exports.number(), running: external_exports.boolean() }),
|
|
20941
20944
|
/** The newest version, with the error and the end of the build log when it failed. */
|
|
20942
|
-
latest: external_exports.object({
|
|
20945
|
+
latest: external_exports.object({
|
|
20946
|
+
number: external_exports.number(),
|
|
20947
|
+
status: VersionStatus,
|
|
20948
|
+
error: external_exports.string().nullable(),
|
|
20949
|
+
logTail: external_exports.string().nullable(),
|
|
20950
|
+
migrationStatus: MigrationStatus.nullable().optional(),
|
|
20951
|
+
/** A ready version that is not live: its preview, for the owner to look at before promote (D-505). */
|
|
20952
|
+
preview: external_exports.string().nullable().optional()
|
|
20953
|
+
}).nullable().optional()
|
|
20943
20954
|
});
|
|
20944
20955
|
var ApiError = external_exports.object({
|
|
20945
20956
|
error: external_exports.string(),
|
|
@@ -21127,17 +21138,17 @@ var ARCH_NODES = [
|
|
|
21127
21138
|
{ id: "board-watcher", kind: "actor", zone: "outside", label: "Board watcher", summary: "\u05E8\u05E5 \u05D0\u05E6\u05DC \u05D4\u05D1\u05E2\u05DC\u05D9\u05DD (pnpm board:watch): \u05DC\u05D5\u05E7\u05D7 \u05DB\u05E8\u05D8\u05D9\u05E1 \u05DE\u05DC\u05D5\u05D7 \u05D4\u05E2\u05D1\u05D5\u05D3\u05D4 (\u05E8\u05E7 \u05DB\u05E9\u05D4\u05DE\u05EA\u05D2 \u05E9\u05DC\u05D5 \u05D1\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05E4\u05D5\u05E2\u05DC), \u05DE\u05E8\u05D9\u05E5 Claude Code \u05DC\u05E7\u05E8\u05D9\u05D0\u05D4 \u05D1\u05DC\u05D1\u05D3 \u05D5\u05DE\u05D7\u05D6\u05D9\u05E8 \u05EA\u05D5\u05DB\u05E0\u05D9\u05EA. \u05DB\u05E8\u05D8\u05D9\u05E1 \u05E2\u05DD \u05D1\u05E0\u05D9\u05D9\u05D4 \u05D0\u05D5\u05D8\u05D5\u05DE\u05D8\u05D9\u05EA \u05E9\u05D0\u05D5\u05E9\u05E8 \u05E0\u05D1\u05E0\u05D4 \u05D1\u05EA\u05D9\u05E7\u05D9\u05D9\u05EA \u05D4\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8, \u05D0\u05D7\u05D3 \u05D1\u05DB\u05DC \u05E4\u05E2\u05DD. \u05D4\u05D5\u05D0 \u05D2\u05DD \u05DB\u05D5\u05EA\u05D1 \u05D2\u05E8\u05E1\u05D0\u05D5\u05EA \u05D7\u05D3\u05E9\u05D5\u05EA \u05DC\u05E1\u05E4\u05E8\u05D9\u05D9\u05EA \u05D4\u05E4\u05E8\u05D5\u05DE\u05E4\u05D8\u05D9\u05DD \u05DC\u05E4\u05D9 \u05D4\u05E2\u05E8\u05D5\u05EA \u05D4\u05D1\u05E2\u05DC\u05D9\u05DD, \u05DC\u05D1\u05D3\u05D9\u05E7\u05D4 \u05D5\u05E4\u05E8\u05E1\u05D5\u05DD.", summaryEn: "Runs on the owner computer (pnpm board:watch): claims a work board ticket (only while its settings switch is on), runs Claude Code read only and posts a plan back. An approved auto build ticket is built in the project folder, one at a time. It also writes new versions of prompt library prompts from the owner notes, for review and publishing.", code: ["scripts/board-watch.ts", "scripts/prompts-sync.ts"], env: ["BOARD_RUNNER_TOKEN", "BOARD_URL"], decisions: ["D-110", "D-127", "D-182", "D-250"] },
|
|
21128
21139
|
{ id: "visitor", kind: "actor", zone: "outside", label: "\u05DE\u05D1\u05E7\u05E8 \u05D1\u05D0\u05EA\u05E8", labelEn: "Site visitor", summary: "\u05DE\u05D1\u05E7\u05E8 \u05D1\u05D0\u05EA\u05E8 \u05E9\u05DC \u05DC\u05E7\u05D5\u05D7 \u05D1\u05DB\u05EA\u05D5\u05D1\u05EA <slug>.<\u05D3\u05D5\u05DE\u05D9\u05D9\u05DF \u05D0\u05EA\u05E8\u05D9\u05DD> (\u05DB\u05DE\u05D5 deploy-net.com \u05D0\u05D5 freesite.click) \u05D0\u05D5 \u05D1\u05D3\u05D5\u05DE\u05D9\u05D9\u05DF \u05DE\u05E9\u05DC\u05D5.", summaryEn: "A visitor on a customer site at <slug>.<a sites domain> (like deploy-net.com or freesite.click) or on their own domain." },
|
|
21129
21140
|
// Platform
|
|
21130
|
-
{ id: "web", kind: "app", zone: "platform", label: "Web app (Next.js)", summary: "\u05D0\u05EA\u05E8 \u05D4\u05E9\u05D9\u05D5\u05D5\u05E7, \u05DC\u05D5\u05D7 \u05D4\u05D1\u05E7\u05E8\u05D4, \u05D4\u05D0\u05D3\u05DE\u05D9\u05DF \u05D5\u05D4\u05BEAPI \u05E9\u05DC \u05D4\u05BECLI. \u05DE\u05DB\u05E0\u05D9\u05E1 \u05E2\u05D1\u05D5\u05D3\u05D5\u05EA \u05DC\u05EA\u05D5\u05E8.", summaryEn: "The marketing site, the dashboard, the admin and the CLI API. Puts jobs in the queue.", code: ["apps/web/src/app", "apps/web/src/server"], env: ["DEPLOYAI_SPACE", "BETTER_AUTH_SECRET", "NEXT_PUBLIC_SUPPORT_WHATSAPP", "DEV_SUPERADMIN_PASSWORD"], portability: "Our app (site, dashboard, API, builds)", docs: ["docs/04-architecture.md"], decisions: ["D-020", "D-057", "D-104", "D-149", "D-238", "D-293"] },
|
|
21141
|
+
{ id: "web", kind: "app", zone: "platform", label: "Web app (Next.js)", summary: "\u05D0\u05EA\u05E8 \u05D4\u05E9\u05D9\u05D5\u05D5\u05E7, \u05DC\u05D5\u05D7 \u05D4\u05D1\u05E7\u05E8\u05D4, \u05D4\u05D0\u05D3\u05DE\u05D9\u05DF \u05D5\u05D4\u05BEAPI \u05E9\u05DC \u05D4\u05BECLI. \u05DE\u05DB\u05E0\u05D9\u05E1 \u05E2\u05D1\u05D5\u05D3\u05D5\u05EA \u05DC\u05EA\u05D5\u05E8.", summaryEn: "The marketing site, the dashboard, the admin and the CLI API. Puts jobs in the queue.", code: ["apps/web/src/app", "apps/web/src/server"], env: ["DEPLOYAI_SPACE", "BETTER_AUTH_SECRET", "NEXT_PUBLIC_SUPPORT_WHATSAPP", "DEV_SUPERADMIN_PASSWORD", "OPENAI_APPS_CHALLENGE"], portability: "Our app (site, dashboard, API, builds)", docs: ["docs/04-architecture.md"], decisions: ["D-020", "D-057", "D-104", "D-149", "D-238", "D-293"] },
|
|
21131
21142
|
{ id: "queue", kind: "db", zone: "platform", label: "pg-boss queue", summary: "\u05DB\u05DC \u05DE\u05D4 \u05E9\u05D0\u05D9\u05D8\u05D9 \u05D0\u05D5 \u05E0\u05D5\u05D2\u05E2 \u05D1\u05BECloudflare \u05E8\u05E5 \u05DB\u05E2\u05D1\u05D5\u05D3\u05D4 \u05D1\u05EA\u05D5\u05E8.", summaryEn: "Everything slow or that touches Cloudflare runs as a job in the queue.", code: ["apps/web/src/server/queue.ts"], portability: "Job queue", decisions: ["D-058"] },
|
|
21132
21143
|
{ id: "worker", kind: "app", zone: "platform", label: "Job worker", summary: "\u05EA\u05D4\u05DC\u05D9\u05DA \u05E0\u05E4\u05E8\u05D3 \u05E9\u05DE\u05E8\u05D9\u05E5 \u05D0\u05EA \u05D4\u05E2\u05D1\u05D5\u05D3\u05D5\u05EA \u05DE\u05D4\u05EA\u05D5\u05E8: \u05D1\u05E0\u05D9\u05D9\u05D4, \u05D4\u05E2\u05DC\u05D0\u05D4, \u05E0\u05D9\u05EA\u05D5\u05D1, \u05D1\u05D9\u05E7\u05D5\u05E8\u05D9\u05DD, \u05E2\u05DC\u05D5\u05D9\u05D5\u05EA \u05D5\u05DE\u05D9\u05D9\u05DC\u05D9\u05DD \u05DC\u05DE\u05E9\u05E4\u05DA (pnpm worker, \u05D0\u05D5 pnpm worker:public \u05DE\u05D0\u05D7\u05D5\u05E8\u05D9 \u05D4\u05BEtunnel).", summaryEn: "A separate process that runs the queued jobs: build, upload, routing, visits, costs and lifecycle emails (pnpm worker, or pnpm worker:public behind the tunnel).", code: ["apps/web/src/server/worker.ts", "apps/web/src/server/jobs.ts", "apps/web/src/server/site-data.ts", "apps/web/src/server/lifecycle", "apps/web/src/server/host-report.ts"], env: ["BUILD_SLOTS", "LIFECYCLE_NOW", "A11Y_RENDER", "DOCKER_HOST", "HOST_REPORT_PATH"], decisions: ["D-058", "D-148", "D-180", "D-340"] },
|
|
21133
21144
|
{ id: "build", kind: "app", zone: "platform", label: "Build service (Docker)", summary: "\u05E7\u05D5\u05E0\u05D8\u05D9\u05D9\u05E0\u05E8 \u05D7\u05D3\u05E9 \u05DC\u05DB\u05DC \u05E9\u05DC\u05D1, \u05D1\u05DC\u05D9 \u05E1\u05D5\u05D3\u05D5\u05EA. \u05D1\u05D5\u05E0\u05D4 \u05D0\u05EA \u05D4\u05E7\u05D5\u05D3 \u05E9\u05DC \u05D4\u05DC\u05E7\u05D5\u05D7 \u05DC\u05E7\u05D5\u05D1\u05E5 Worker.", summaryEn: "A fresh container for every step, with no secrets. Builds the customer's code into a Worker file.", code: ["apps/web/src/server/build.ts"], env: ["BUILD_MODE"] },
|
|
21134
21145
|
{ id: "postgres", kind: "db", zone: "platform", label: "Postgres", summary: "\u05DE\u05E1\u05D3 \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E9\u05DC\u05E0\u05D5: \u05DE\u05E9\u05EA\u05DE\u05E9\u05D9\u05DD, \u05D0\u05EA\u05E8\u05D9\u05DD, \u05D2\u05E8\u05E1\u05D0\u05D5\u05EA, \u05EA\u05E9\u05DC\u05D5\u05DE\u05D9\u05DD, \u05D1\u05D9\u05E7\u05D5\u05E8\u05D9\u05DD \u05D5\u05D9\u05D5\u05DE\u05DF. \u05D1\u05D9\u05D9\u05E6\u05D5\u05E8 \u05D2\u05D9\u05D1\u05D5\u05D9 pg_dump \u05DC\u05D9\u05DC\u05D9 \u05DC\u05D3\u05DC\u05D9 R2 \u05E0\u05E4\u05E8\u05D3 (14 \u05D9\u05D5\u05DE\u05D9\u05D9\u05DD, 4 \u05E9\u05D1\u05D5\u05E2\u05D9\u05D9\u05DD), \u05DE\u05D5\u05E6\u05E4\u05DF \u05D1\u05BEage, \u05D5\u05DE\u05D2\u05D1\u05D9\u05DD \u05D2\u05DD \u05D9\u05D3\u05E0\u05D9\u05EA \u05DE\u05D0\u05D3\u05DE\u05D9\u05DF, \u05E9\u05E8\u05EA, \u05D2\u05D9\u05D1\u05D5\u05D9\u05D9\u05DD.", summaryEn: "Our database: users, sites, versions, payments, visits and the audit log. In production a nightly pg_dump goes to its own R2 bucket (14 daily, 4 weekly), encrypted with age, plus manual copies from Admin, Server, Backups.", code: ["apps/web/src/server/db/schema.ts", "scripts/backup-db.sh", "apps/web/src/server/backups.ts"], env: ["DATABASE_URL", "BACKUP_S3_ACCESS_KEY_ID", "BACKUP_S3_SECRET_ACCESS_KEY", "BACKUP_AGE_RECIPIENT"], portability: "Our database", docs: ["docs/04-architecture.md", "docs/22-go-live.md", "docs/23-server.md"], decisions: ["D-336", "D-340"] },
|
|
21135
|
-
{ id: "files", kind: "storage", zone: "platform", label: "Version files", summary: "\u05D0\u05E8\u05DB\u05D9\u05D5\u05E0\u05D9 \u05DE\u05E7\u05D5\u05E8 \u05D5\u05EA\u05D5\u05E6\u05E8\u05D9 \u05D1\u05E0\u05D9\u05D9\u05D4 \u05E9\u05DC \u05DB\u05DC \u05D2\u05E8\u05E1\u05D4, \u05D3\u05E8\u05DA storage.ts \u05D1\u05DC\u05D1\u05D3. \u05D3\u05DC\u05D9 R2 \u05DC\u05DB\u05DC \u05E1\u05D1\u05D9\u05D1\u05D4, \u05D5\u05E0\u05D9\u05E7\u05D5\u05D9 \u05DC\u05D9\u05DC\u05D9 \u05E9\u05DC \u05E7\u05D1\u05E6\u05D9\u05DD \u05E9\u05D0\u05E3 \u05D2\u05E8\u05E1\u05D4 \u05DC\u05D0 \u05DE\u05E9\u05EA\u05DE\u05E9\u05EA \u05D1\u05D4\u05DD.", summaryEn: "Source archives and build output of every version, through storage.ts only. One R2 bucket per place, and a nightly sweep of files no version uses.", code: ["apps/web/src/server/storage.ts", "apps/web/src/server/storage-sweep.ts"], env: ["STORAGE_DIR", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY"], portability: "Version files (uploads and build output)", docs: ["docs/17-portability.md"], decisions: ["D-095", "D-096", "D-316"] },
|
|
21146
|
+
{ id: "files", kind: "storage", zone: "platform", label: "Version files", summary: "\u05D0\u05E8\u05DB\u05D9\u05D5\u05E0\u05D9 \u05DE\u05E7\u05D5\u05E8 \u05D5\u05EA\u05D5\u05E6\u05E8\u05D9 \u05D1\u05E0\u05D9\u05D9\u05D4 \u05E9\u05DC \u05DB\u05DC \u05D2\u05E8\u05E1\u05D4, \u05D3\u05E8\u05DA storage.ts \u05D1\u05DC\u05D1\u05D3. \u05D3\u05DC\u05D9 R2 \u05DC\u05DB\u05DC \u05E1\u05D1\u05D9\u05D1\u05D4, \u05D5\u05E0\u05D9\u05E7\u05D5\u05D9 \u05DC\u05D9\u05DC\u05D9 \u05E9\u05DC \u05E7\u05D1\u05E6\u05D9\u05DD \u05E9\u05D0\u05E3 \u05D2\u05E8\u05E1\u05D4 \u05DC\u05D0 \u05DE\u05E9\u05EA\u05DE\u05E9\u05EA \u05D1\u05D4\u05DD. \u05D1\u05D9\u05D9\u05E6\u05D5\u05E8 \u05E9\u05D9\u05E7\u05D5\u05E3 \u05DC\u05D9\u05DC\u05D9 \u05DC\u05D3\u05DC\u05D9 \u05D4\u05D2\u05D9\u05D1\u05D5\u05D9\u05D9\u05DD, \u05EA\u05D7\u05EA files/ (D-473).", summaryEn: "Source archives and build output of every version, through storage.ts only. One R2 bucket per place, and a nightly sweep of files no version uses. In prod a nightly mirror into the backups bucket, under files/ (D-473).", code: ["apps/web/src/server/storage.ts", "apps/web/src/server/storage-sweep.ts", "scripts/mirror-files.sh"], env: ["STORAGE_DIR", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY"], portability: "Version files (uploads and build output)", docs: ["docs/17-portability.md"], decisions: ["D-095", "D-096", "D-316", "D-473"] },
|
|
21136
21147
|
// Services
|
|
21137
21148
|
{ id: "email-sending", kind: "external", zone: "services", label: "CF Email Sending", summary: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05D9\u05D9\u05DC\u05D9\u05DD \u05D3\u05E8\u05DA Cloudflare Email Sending. \u05D1\u05DC\u05D9 \u05D8\u05D5\u05E7\u05DF \u05D4\u05DE\u05D9\u05D9\u05DC \u05DE\u05D5\u05D3\u05E4\u05E1 \u05D1\u05DC\u05D5\u05D2.", summaryEn: "Sends email through Cloudflare Email Sending. Without a token, the email is printed to the log.", code: ["apps/web/src/server/email.ts"], portability: "Emails" },
|
|
21138
21149
|
{ id: "oauth", kind: "external", zone: "services", label: "Google / GitHub OAuth", summary: "\u05D4\u05EA\u05D7\u05D1\u05E8\u05D5\u05EA \u05E2\u05DD Google \u05D0\u05D5 GitHub \u05D3\u05E8\u05DA Better Auth.", summaryEn: "Log in with Google or GitHub through Better Auth.", code: ["apps/web/src/server/auth.ts"], env: ["GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET"], decisions: ["D-020"] },
|
|
21139
21150
|
{ id: "payments", kind: "external", zone: "services", label: "Payment provider (Cardcom)", summary: "\u05E7\u05D0\u05E8\u05D3\u05E7\u05D5\u05DD \u05DB\u05D1\u05E8\u05D9\u05E8\u05EA \u05DE\u05D7\u05D3\u05DC, \u05D5\u05E0\u05D1\u05D7\u05E8 \u05D1\u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05D4\u05D0\u05D3\u05DE\u05D9\u05DF (\u05D0\u05D5 \u05DE\u05D3\u05D5\u05DE\u05D4 \u05DC\u05D1\u05D3\u05D9\u05E7\u05D5\u05EA). \u05D4\u05DB\u05E8\u05D8\u05D9\u05E1 \u05DE\u05D5\u05E7\u05DC\u05D3 \u05D1\u05D3\u05E3 \u05D4\u05DE\u05D0\u05D5\u05D1\u05D8\u05D7 \u05E9\u05DC \u05E7\u05D0\u05E8\u05D3\u05E7\u05D5\u05DD \u05D5\u05E0\u05E9\u05DE\u05E8 \u05DB\u05D8\u05D5\u05E7\u05DF \u05DE\u05D5\u05E6\u05E4\u05DF, \u05DB\u05DC \u05D7\u05D9\u05D5\u05D1 \u05E2\u05DD \u05DE\u05E4\u05EA\u05D7 \u05D0\u05D9\u05D3\u05DE\u05E4\u05D5\u05D8\u05E0\u05D8\u05D9\u05D5\u05EA, \u05D5\u05E7\u05D0\u05E8\u05D3\u05E7\u05D5\u05DD \u05DE\u05E4\u05D9\u05E7\u05D4 \u05D7\u05E9\u05D1\u05D5\u05E0\u05D9\u05EA \u05DE\u05E1 \u05DC\u05DB\u05DC \u05D7\u05D9\u05D5\u05D1 \u05D5\u05D7\u05E9\u05D1\u05D5\u05E0\u05D9\u05EA \u05D6\u05D9\u05DB\u05D5\u05D9 \u05DC\u05DB\u05DC \u05D4\u05D7\u05D6\u05E8.", summaryEn: "Cardcom by default, chosen in admin settings (or simulated for tests). The card is typed on the secure Cardcom page and saved as a sealed token, every charge carries an idempotency key, and Cardcom issues a tax invoice per charge and a credit invoice per refund.", code: ["apps/web/src/server/billing/provider.ts", "apps/web/src/server/billing/cardcom.ts", "apps/web/src/server/billing/card-pages.ts", "apps/web/src/app/api/billing/card"], env: ["BILLING_PROVIDER", "BILLING_MOCK_FAIL", "CARDCOM_TERMINAL", "CARDCOM_API_NAME", "CARDCOM_API_PASSWORD", "CARDCOM_INVOICES", "CARDCOM_CSS_URL", "CARDCOM_TOKEN_KEY", "CARDCOM_DEPARTMENT_ID"], portability: "Payments", decisions: ["D-175", "D-292"] },
|
|
21140
|
-
{ id: "registrar", kind: "external", zone: "services", label: "Domain registrars (Cloudflare, LiveDNS)", summary: "\u05E7\u05E0\u05D9\u05D9\u05EA \u05D3\u05D5\u05DE\u05D9\u05D9\u05E0\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8: \u05DB\u05DC \u05E9\u05DD \u05D4\u05D5\u05DC\u05DA \u05DC\u05E8\u05E9\u05DD \u05D4\u05D6\u05D5\u05DC \u05D1\u05D9\u05D5\u05EA\u05E8 \u05E9\u05E4\u05D5\u05E2\u05DC (Cloudflare \u05D1\u05D3\u05D5\u05DC\u05E8\u05D9\u05DD
|
|
21151
|
+
{ id: "registrar", kind: "external", zone: "services", label: "Domain registrars (Cloudflare, LiveDNS)", summary: "\u05E7\u05E0\u05D9\u05D9\u05EA \u05D3\u05D5\u05DE\u05D9\u05D9\u05E0\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8: \u05DB\u05DC \u05E9\u05DD \u05D4\u05D5\u05DC\u05DA \u05DC\u05E8\u05E9\u05DD \u05D4\u05D6\u05D5\u05DC \u05D1\u05D9\u05D5\u05EA\u05E8 \u05E9\u05E4\u05D5\u05E2\u05DC, \u05DB\u05DC \u05E8\u05E9\u05DD \u05D1\u05E2\u05DC\u05D5\u05EA \u05D5\u05D1\u05E2\u05DE\u05DC\u05D4 \u05DE\u05E9\u05DC\u05D5 (Cloudflare \u05D1\u05D3\u05D5\u05DC\u05E8\u05D9\u05DD \u05DC\u05DB\u05DC \u05E9\u05DD, LiveDNS \u05DE\u05E0\u05E7\u05D5\u05D3\u05D5\u05EA \u05E7\u05E8\u05D3\u05D9\u05D8 \u05DC\u05E4\u05D9 \u05D4\u05DE\u05D7\u05D9\u05E8\u05D5\u05DF \u05E9\u05E0\u05E7\u05E8\u05D0 \u05DB\u05DC \u05D9\u05D5\u05DD, \u05D0\u05D5 \u05D9\u05D3\u05E0\u05D9 \u05DE\u05EA\u05D5\u05E8 \u05D4\u05E6\u05D5\u05D5\u05EA), \u05DE\u05D7\u05D9\u05E8 \u05DB\u05DC \u05E1\u05D9\u05D5\u05DE\u05EA \u05E0\u05D1\u05D3\u05E7 \u05DB\u05DC \u05D9\u05D5\u05DD (\u05D5\u05D0\u05E4\u05E9\u05E8 \u05DC\u05DB\u05D1\u05D5\u05EA \u05E1\u05D9\u05D5\u05DE\u05D5\u05EA), \u05E8\u05D9\u05E9\u05D5\u05DD \u05D0\u05D7\u05D3 \u05DC\u05DB\u05DC \u05D4\u05D6\u05DE\u05E0\u05D4, \u05D9\u05D5\u05DE\u05DF \u05E7\u05E8\u05D9\u05D0\u05D5\u05EA \u05DC\u05DB\u05DC \u05D4\u05D6\u05DE\u05E0\u05D4, \u05D5\u05D7\u05D9\u05D3\u05D5\u05E9 \u05E9\u05E0\u05EA\u05D9 \u05D0\u05E6\u05DC \u05D0\u05D5\u05EA\u05D5 \u05E8\u05E9\u05DD. \u05DC\u05D3\u05D5\u05DE\u05D9\u05D9\u05DF \u05E9\u05E0\u05E7\u05E0\u05D4: \u05D3\u05D5\u05D0\u05E8 \u05D3\u05E8\u05DA Cloudflare Email Routing.", summaryEn: "Buying domains for a site: each name goes to the cheapest registrar that is on, each with its own cost and fee (Cloudflare in dollars per name, LiveDNS from credit points priced by its list, read daily, or by hand from the team queue), the price of every extension checked daily (some can be turned off), one registration per order, a call log per order, yearly renewal at the same registrar. For a bought domain: email through Cloudflare Email Routing.", code: ["apps/web/src/server/registrar.ts", "apps/web/src/server/registrar-livedns.ts", "apps/web/src/server/registrar-log.ts", "apps/web/src/server/domain-sales.ts", "apps/web/src/server/domain-extensions.ts", "apps/web/src/server/domain-email.ts", "apps/web/src/server/billing/services.ts"], env: ["CF_REGISTRAR_TOKEN", "LIVEDNS_USER", "LIVEDNS_PASSWORD"], decisions: ["D-299", "D-300", "D-301", "D-458", "D-486", "D-489", "D-491"] },
|
|
21141
21152
|
{ id: "mcp", kind: "external", zone: "services", label: "MCP for AI tools (/api/mcp)", summary: "ChatGPT \u05D5\u05BEClaude \u05DE\u05EA\u05D7\u05D1\u05E8\u05D9\u05DD \u05D1\u05DC\u05D9 \u05D8\u05E8\u05DE\u05D9\u05E0\u05DC: OAuth \u05E2\u05DD \u05D0\u05D9\u05E9\u05D5\u05E8 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF, \u05D5\u05D0\u05D6 \u05DB\u05DC\u05D9\u05DD \u05DC\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D0\u05EA\u05E8\u05D9\u05DD, \u05D1\u05D3\u05D9\u05E7\u05D4, \u05D4\u05E2\u05DC\u05D0\u05EA \u05D2\u05E8\u05E1\u05D4 \u05DC\u05EA\u05E6\u05D5\u05D2\u05D4 \u05DE\u05E7\u05D3\u05D9\u05DE\u05D4, \u05D4\u05E8\u05E6\u05EA \u05EA\u05D5\u05E1\u05E4\u05D9\u05DD \u05E9\u05D4\u05D0\u05EA\u05E8 \u05E7\u05E0\u05D4 (\u05D4\u05E7\u05E0\u05D9\u05D9\u05D4 \u05E8\u05E7 \u05D1\u05D0\u05EA\u05E8), \u05D5\u05D4\u05E2\u05DC\u05D0\u05D4 \u05DC\u05D0\u05D5\u05D5\u05D9\u05E8 \u05E8\u05E7 \u05E2\u05DD \u05D4\u05E8\u05E9\u05D0\u05D4 \u05D5\u05D0\u05D9\u05E9\u05D5\u05E8.", summaryEn: "ChatGPT and Claude connect without a terminal: OAuth with a browser consent, then tools to list sites, check, upload a version to a preview, run add-ons the site owns (buying stays on the site), and go live only with the permission and a yes.", code: ["apps/web/src/app/api/mcp/route.ts", "apps/web/src/server/mcp-tools.ts", "apps/web/src/server/auth.ts"], decisions: ["D-302"] },
|
|
21142
21153
|
{ id: "npm", kind: "external", zone: "services", label: "npm registry", summary: "\u05DE\u05E4\u05D9\u05E5 \u05D0\u05EA \u05D4\u05BECLI, \u05D5\u05DE\u05DE\u05E0\u05D5 \u05D4\u05D1\u05E0\u05D9\u05D9\u05D4 \u05DE\u05EA\u05E7\u05D9\u05E0\u05D4 \u05EA\u05DC\u05D5\u05D9\u05D5\u05EA.", summaryEn: "Distributes the CLI, and the build installs dependencies from it." },
|
|
21143
21154
|
{ id: "pagespeed", kind: "external", zone: "services", label: "Google PageSpeed Insights", summary: "\u05D1\u05D3\u05D9\u05E7\u05D5\u05EA \u05D4\u05DE\u05D4\u05D9\u05E8\u05D5\u05EA, \u05D4\u05E0\u05D2\u05D9\u05E9\u05D5\u05EA \u05D5\u05D4\u05BESEO \u05D4\u05D7\u05D9\u05E0\u05DE\u05D9\u05D5\u05EA: Lighthouse \u05D1\u05DE\u05E2\u05D1\u05D3\u05D4 \u05E9\u05DC \u05D2\u05D5\u05D2\u05DC (\u05DB\u05D5\u05DC\u05DC \u05E1\u05D5\u05DB\u05E0\u05D9 AI) \u05D5\u05E0\u05EA\u05D5\u05E0\u05D9 \u05DE\u05D1\u05E7\u05E8\u05D9\u05DD \u05D0\u05DE\u05D9\u05EA\u05D9\u05D9\u05DD.", summaryEn: "The free speed, accessibility and SEO tests: Lighthouse run at Google (AI agents included) plus real visitor data.", env: ["PAGESPEED_API_KEY"], decisions: ["D-199", "D-222"] },
|
|
@@ -21489,6 +21500,13 @@ function neverUploadedFile(rel) {
|
|
|
21489
21500
|
|
|
21490
21501
|
// ../shared/src/domain-sales.ts
|
|
21491
21502
|
var IL_TLDS = ["co.il", "org.il", "net.il"];
|
|
21503
|
+
var DEFAULT_LIVEDNS_POINTS = { 5: 9100, 10: 8900, 20: 8700, 50: 8500, 100: 8200 };
|
|
21504
|
+
var pointCost = (points, pack) => Math.round(points[pack] / (1 + VAT_RATE));
|
|
21505
|
+
var DEFAULT_DOMAIN_REGISTRARS = {
|
|
21506
|
+
cloudflare: { enabled: true, feeRate: 0.03, maxUsdCentsPerDay: 1e4 },
|
|
21507
|
+
livedns: { enabled: true, feeRate: 0.01, pack: 5, costAgorot: pointCost(DEFAULT_LIVEDNS_POINTS, 5) },
|
|
21508
|
+
manual: { enabled: true, feeRate: 0.01, costAgorot: 7500 }
|
|
21509
|
+
};
|
|
21492
21510
|
var LIVEDNS_TLDS = [...IL_TLDS, "com", "net", "org"];
|
|
21493
21511
|
|
|
21494
21512
|
// ../shared/src/env-scopes.ts
|
|
@@ -21498,6 +21516,7 @@ var ENV_KEYS = {
|
|
|
21498
21516
|
BETTER_AUTH_SECRET: { scope: "own", section: "app", required: ["server"], sample: { local: "change-me-to-a-long-random-string", server: "" }, about: "Signs login sessions and our own links; changing it logs everyone out. 32 characters or more in production: openssl rand -base64 48" },
|
|
21499
21517
|
DEV_SUPERADMIN_PASSWORD: { scope: "local", section: "app", about: "The superadmin password after every local wipe. Without it the one in apps/web/local-logins.md is kept (D-100)." },
|
|
21500
21518
|
NEXT_PUBLIC_SUPPORT_WHATSAPP: { scope: "same", section: "app", about: "The WhatsApp number people reach us on, digits with the country code (972...). Empty shows only the email (D-237)." },
|
|
21519
|
+
OPENAI_APPS_CHALLENGE: { scope: "server", section: "app", about: "The domain check token from the OpenAI platform portal (Plugins, domain verification), served as plain text at /.well-known/openai-apps-challenge (D-474). Unset: that page is a 404." },
|
|
21501
21520
|
TUNNEL_ORIGIN_CERT: { scope: "local", section: "app", about: "The cloudflared login certificate pnpm dev:public checks. Default ~/.cloudflared/cert.pem." },
|
|
21502
21521
|
CF_API_TOKEN: { scope: "own", section: "cloudflare", required: ["server"], about: "Cloudflare token (pnpm cf:token-link): sites, KV, D1, R2, routes, custom hostnames and our emails. Each machine its own. Without it everything Cloudflare is a dry run." },
|
|
21503
21522
|
CF_REGISTRAR_TOKEN: { scope: "server", section: "cloudflare", about: "Buys real domains (D-300): a Cloudflare token with Registrar edit only. Server only." },
|
|
@@ -21824,20 +21843,24 @@ var M = {
|
|
|
21824
21843
|
statusTitle: "DeployAI status",
|
|
21825
21844
|
state: "State",
|
|
21826
21845
|
liveVersion: "Live version",
|
|
21846
|
+
newestVersion: "Newest version",
|
|
21847
|
+
promoteReady: " After the owner approves the preview: npx deployai@latest promote v{n} (to put it live)",
|
|
21848
|
+
askOwner: ' Version {n} is ready and not live. Ask the owner: "Version {n} is ready. Do you want to put it live?"',
|
|
21849
|
+
showPreview: " Send them the preview first: {url}",
|
|
21827
21850
|
notPublished: "not published yet",
|
|
21828
21851
|
none: "none",
|
|
21829
21852
|
buildingNow: "building now",
|
|
21830
21853
|
idle: "idle",
|
|
21831
21854
|
envListTitle: "Variables",
|
|
21832
|
-
envNone: "This site has no variables yet. Add one: npx deployai@latest env set <
|
|
21855
|
+
envNone: "This site has no variables yet. Add one: npx deployai@latest env set <KEY> <value>",
|
|
21833
21856
|
envSecret: "secret",
|
|
21834
21857
|
envPlain: "plain",
|
|
21835
|
-
envNeedValue: 'Give the value after the key, or pipe it in: echo "<value>" | npx deployai@latest env set <
|
|
21858
|
+
envNeedValue: 'Give the value after the key, or pipe it in: echo "<value>" | npx deployai@latest env set <KEY>',
|
|
21836
21859
|
envSavedSecret: "Saved {key} as a secret on the live site. Its value is not stored and is never shown again.",
|
|
21837
21860
|
envSavedPlain: "Saved {key}. The live site gets it in about a minute.",
|
|
21838
21861
|
envRemoved: "Removed {key}. The live site loses it in about a minute.",
|
|
21839
21862
|
guestNoEnv: "A temporary site has no environment variables. Keep it in an account first: npx deployai@latest claim",
|
|
21840
|
-
envInvalidKey: "A variable name is English letters, digits and _,
|
|
21863
|
+
envInvalidKey: "A variable name is capital English letters, digits and _, starts with a letter, up to 64 characters, like STRIPE_KEY.",
|
|
21841
21864
|
envTooLong: "The value is over 5 KB, too long for a variable.",
|
|
21842
21865
|
envSendFailed: "The secret did not reach the site. Try again in a minute.",
|
|
21843
21866
|
envNoKey: "This site has no variable with that name. See them: npx deployai@latest env list",
|
|
@@ -21989,20 +22012,24 @@ var M = {
|
|
|
21989
22012
|
statusTitle: "DeployAI status",
|
|
21990
22013
|
state: "\u05DE\u05E6\u05D1",
|
|
21991
22014
|
liveVersion: "\u05D2\u05E8\u05E1\u05D4 \u05D7\u05D9\u05D4",
|
|
22015
|
+
newestVersion: "\u05D2\u05E8\u05E1\u05D4 \u05D0\u05D7\u05E8\u05D5\u05E0\u05D4",
|
|
22016
|
+
promoteReady: " \u05D0\u05D7\u05E8\u05D9 \u05E9\u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8 \u05D0\u05D9\u05E9\u05E8 \u05D0\u05EA \u05D4\u05EA\u05E6\u05D5\u05D2\u05D4 \u05D4\u05DE\u05E7\u05D3\u05D9\u05DE\u05D4: npx deployai@latest promote v{n} (\u05DB\u05D3\u05D9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05D0\u05D5\u05EA\u05D4 \u05DC\u05D0\u05D5\u05D5\u05D9\u05E8)",
|
|
22017
|
+
askOwner: ' \u05D2\u05E8\u05E1\u05D4 {n} \u05DE\u05D5\u05DB\u05E0\u05D4 \u05D5\u05E2\u05D5\u05D3 \u05DC\u05D0 \u05D1\u05D0\u05D5\u05D5\u05D9\u05E8. \u05E9\u05D0\u05DC\u05D5 \u05D0\u05EA \u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8: "\u05D2\u05E8\u05E1\u05D4 {n} \u05DE\u05D5\u05DB\u05E0\u05D4. \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05D0\u05D5\u05EA\u05D4 \u05DC\u05D0\u05D5\u05D5\u05D9\u05E8?"',
|
|
22018
|
+
showPreview: " \u05E9\u05DC\u05D7\u05D5 \u05E7\u05D5\u05D3\u05DD \u05D0\u05EA \u05D4\u05EA\u05E6\u05D5\u05D2\u05D4 \u05D4\u05DE\u05E7\u05D3\u05D9\u05DE\u05D4: {url}",
|
|
21992
22019
|
notPublished: "\u05E2\u05D3\u05D9\u05D9\u05DF \u05DC\u05D0 \u05D1\u05D0\u05D5\u05D5\u05D9\u05E8",
|
|
21993
22020
|
none: "\u05D0\u05D9\u05DF",
|
|
21994
22021
|
buildingNow: "\u05D1\u05D5\u05E0\u05D9\u05DD \u05E2\u05DB\u05E9\u05D9\u05D5",
|
|
21995
22022
|
idle: "\u05E4\u05E0\u05D5\u05D9",
|
|
21996
22023
|
envListTitle: "\u05DE\u05E9\u05EA\u05E0\u05D9\u05DD",
|
|
21997
|
-
envNone: "\u05DC\u05D0\u05EA\u05E8 \u05D4\u05D6\u05D4 \u05E2\u05D5\u05D3 \u05D0\u05D9\u05DF \u05DE\u05E9\u05EA\u05E0\u05D9\u05DD. \u05D4\u05D5\u05E1\u05D9\u05E4\u05D5 \u05D0\u05D7\u05D3: npx deployai@latest env set <
|
|
22024
|
+
envNone: "\u05DC\u05D0\u05EA\u05E8 \u05D4\u05D6\u05D4 \u05E2\u05D5\u05D3 \u05D0\u05D9\u05DF \u05DE\u05E9\u05EA\u05E0\u05D9\u05DD. \u05D4\u05D5\u05E1\u05D9\u05E4\u05D5 \u05D0\u05D7\u05D3: npx deployai@latest env set <KEY> <value>",
|
|
21998
22025
|
envSecret: "\u05E1\u05D5\u05D3",
|
|
21999
22026
|
envPlain: "\u05D2\u05DC\u05D5\u05D9",
|
|
22000
|
-
envNeedValue: '\u05DB\u05EA\u05D1\u05D5 \u05D0\u05EA \u05D4\u05E2\u05E8\u05DA \u05D0\u05D7\u05E8\u05D9 \u05D4\u05E9\u05DD, \u05D0\u05D5 \u05D4\u05E2\u05D1\u05D9\u05E8\u05D5 \u05D0\u05D5\u05EA\u05D5 \u05D1\u05E6\u05D9\u05E0\u05D5\u05E8: echo "<value>" | npx deployai@latest env set <
|
|
22027
|
+
envNeedValue: '\u05DB\u05EA\u05D1\u05D5 \u05D0\u05EA \u05D4\u05E2\u05E8\u05DA \u05D0\u05D7\u05E8\u05D9 \u05D4\u05E9\u05DD, \u05D0\u05D5 \u05D4\u05E2\u05D1\u05D9\u05E8\u05D5 \u05D0\u05D5\u05EA\u05D5 \u05D1\u05E6\u05D9\u05E0\u05D5\u05E8: echo "<value>" | npx deployai@latest env set <KEY>',
|
|
22001
22028
|
envSavedSecret: "\u05E9\u05DE\u05E8\u05E0\u05D5 \u05D0\u05EA {key} \u05DB\u05E1\u05D5\u05D3 \u05D1\u05D0\u05EA\u05E8 \u05D4\u05D7\u05D9. \u05D4\u05E2\u05E8\u05DA \u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8 \u05D0\u05E6\u05DC\u05E0\u05D5 \u05D5\u05DC\u05D0 \u05D9\u05D5\u05E6\u05D2 \u05E9\u05D5\u05D1.",
|
|
22002
22029
|
envSavedPlain: "\u05E9\u05DE\u05E8\u05E0\u05D5 \u05D0\u05EA {key}. \u05D4\u05D0\u05EA\u05E8 \u05D4\u05D7\u05D9 \u05D9\u05E7\u05D1\u05DC \u05D0\u05D5\u05EA\u05D5 \u05EA\u05D5\u05DA \u05DB\u05D3\u05E7\u05D4.",
|
|
22003
22030
|
envRemoved: "\u05D4\u05E1\u05E8\u05E0\u05D5 \u05D0\u05EA {key}. \u05D4\u05D5\u05D0 \u05D9\u05D9\u05E2\u05DC\u05DD \u05DE\u05D4\u05D0\u05EA\u05E8 \u05D4\u05D7\u05D9 \u05EA\u05D5\u05DA \u05DB\u05D3\u05E7\u05D4.",
|
|
22004
22031
|
guestNoEnv: "\u05DC\u05D0\u05EA\u05E8 \u05D6\u05DE\u05E0\u05D9 \u05D0\u05D9\u05DF \u05DE\u05E9\u05EA\u05E0\u05D9 \u05E1\u05D1\u05D9\u05D1\u05D4. \u05E9\u05DE\u05E8\u05D5 \u05D0\u05D5\u05EA\u05D5 \u05DC\u05D7\u05E9\u05D1\u05D5\u05DF \u05E7\u05D5\u05D3\u05DD: npx deployai@latest claim",
|
|
22005
|
-
envInvalidKey: "\u05E9\u05DD \u05DE\u05E9\u05EA\u05E0\u05D4: \u05D0\u05D5\u05EA\u05D9\u05D5\u05EA \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E1\u05E4\u05E8\u05D5\u05EA \u05D5-_, \
|
|
22032
|
+
envInvalidKey: "\u05E9\u05DD \u05DE\u05E9\u05EA\u05E0\u05D4: \u05D0\u05D5\u05EA\u05D9\u05D5\u05EA \u05D2\u05D3\u05D5\u05DC\u05D5\u05EA \u05D1\u05D0\u05E0\u05D2\u05DC\u05D9\u05EA, \u05E1\u05E4\u05E8\u05D5\u05EA \u05D5-_, \u05DE\u05EA\u05D7\u05D9\u05DC \u05D1\u05D0\u05D5\u05EA, \u05E2\u05D3 64 \u05EA\u05D5\u05D5\u05D9\u05DD, \u05DB\u05DE\u05D5 STRIPE_KEY.",
|
|
22006
22033
|
envTooLong: "\u05D4\u05E2\u05E8\u05DA \u05D2\u05D3\u05D5\u05DC \u05DE\u05BE5KB, \u05D0\u05E8\u05D5\u05DA \u05DE\u05D3\u05D9 \u05DC\u05DE\u05E9\u05EA\u05E0\u05D4.",
|
|
22007
22034
|
envSendFailed: "\u05D4\u05E1\u05D5\u05D3 \u05DC\u05D0 \u05D4\u05D2\u05D9\u05E2 \u05DC\u05D0\u05EA\u05E8. \u05E0\u05E1\u05D5 \u05E9\u05D5\u05D1 \u05D1\u05E2\u05D5\u05D3 \u05D3\u05E7\u05D4.",
|
|
22008
22035
|
envNoKey: "\u05DC\u05D0\u05EA\u05E8 \u05D0\u05D9\u05DF \u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05E9\u05DD \u05D4\u05D6\u05D4. \u05DC\u05E8\u05E9\u05D9\u05DE\u05D4: npx deployai@latest env list",
|
|
@@ -22105,7 +22132,7 @@ function messages(root) {
|
|
|
22105
22132
|
}
|
|
22106
22133
|
|
|
22107
22134
|
// src/version.ts
|
|
22108
|
-
var CLI_VERSION = "0.1.0-beta.
|
|
22135
|
+
var CLI_VERSION = "0.1.0-beta.6";
|
|
22109
22136
|
|
|
22110
22137
|
// src/api.ts
|
|
22111
22138
|
function apiContext(apiFlag) {
|
|
@@ -23925,6 +23952,7 @@ async function statusCommand(root, ctx) {
|
|
|
23925
23952
|
const s = await apiRequest(ctx, `/api/cli/status?projectId=${encodeURIComponent(projectId)}`, StatusResponse);
|
|
23926
23953
|
const p = s.project;
|
|
23927
23954
|
const t = messages(root);
|
|
23955
|
+
const newer = s.latest && s.latest.number !== p.liveVersion ? s.latest : null;
|
|
23928
23956
|
out(t("statusTitle"));
|
|
23929
23957
|
out();
|
|
23930
23958
|
out(
|
|
@@ -23933,9 +23961,18 @@ async function statusCommand(root, ctx) {
|
|
|
23933
23961
|
[t("state"), stateName(p.status, root)],
|
|
23934
23962
|
[t("address"), p.url ?? t("notPublished")],
|
|
23935
23963
|
[t("liveVersion"), p.liveVersion ? `v${p.liveVersion}` : t("none")],
|
|
23964
|
+
// A newer upload than the live one: its state, so "follow the build" after deploy has something to follow.
|
|
23965
|
+
...newer ? [[t("newestVersion"), `v${newer.number} ${stateName(newer.status, root)}`]] : [],
|
|
23936
23966
|
[t("queue"), s.queue.running ? t("buildingNow") : s.queue.position > 0 ? queueText(s.queue.position, root) : t("idle")]
|
|
23937
23967
|
])
|
|
23938
23968
|
);
|
|
23969
|
+
if (newer?.status === "ready") {
|
|
23970
|
+
out();
|
|
23971
|
+
out(t("nextStep"));
|
|
23972
|
+
out(t("askOwner", { n: newer.number }));
|
|
23973
|
+
if (s.latest?.preview) out(t("showPreview", { url: s.latest.preview }));
|
|
23974
|
+
out(t("promoteReady", { n: newer.number }));
|
|
23975
|
+
}
|
|
23939
23976
|
if (s.latest?.migrationStatus === "waiting") {
|
|
23940
23977
|
out();
|
|
23941
23978
|
out(t("sqlWaitingLine", { url: versionsPage(ctx, projectId) }));
|