deployai 0.1.0-beta.6 → 0.1.0-beta.7
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 +102 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ Node 20 or newer. No other setup: the CLI talks to https://deployai.co.il.
|
|
|
38
38
|
|
|
39
39
|
| Command | What it does |
|
|
40
40
|
|---------|--------------|
|
|
41
|
-
| `deployai init` | Creates `DEPLOYAI.md` (rules for the AI agent) and `.deployai/project.json`. Never edits your code and does not link a project (use `link`). `--force` overwrites `DEPLOYAI.md
|
|
41
|
+
| `deployai init` | Creates `DEPLOYAI.md` (rules for the AI agent: the stack to build with, what to avoid, how to keep existing data), adds one line pointing to it in `AGENTS.md` and `CLAUDE.md`, and `.deployai/project.json`. Run it first in a new project, even an empty folder. Never edits your code and does not link a project (use `link`). `--force` overwrites `DEPLOYAI.md`, `--no-agent-files` leaves `AGENTS.md` and `CLAUDE.md` alone. |
|
|
42
42
|
| `deployai inspect` | Shows framework, package manager, language, database, storage and the number of env files (values are never read). `--json` for machine output. |
|
|
43
43
|
| `deployai check` | Lists blockers and warnings with file and line. It answers only whether the project can run on DeployAI. More below. |
|
|
44
44
|
| `deployai login` | Logs in through the browser (device code). The token lasts 30 days and is stored in `~/.deployai/config.json` with the API address that issued it; it is never sent to another address. |
|
package/dist/index.js
CHANGED
|
@@ -21365,7 +21365,7 @@ var CLI_MAP_NODES = [
|
|
|
21365
21365
|
n("cmd-start", "cli", "start <id>", "\u05DE\u05DB\u05D9\u05DF \u05D0\u05EA \u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05DC\u05E4\u05D9 \u05DB\u05DC \u05D4\u05D1\u05D7\u05D9\u05E8\u05D5\u05EA: \u05EA\u05D9\u05E7\u05D9\u05D9\u05D4, \u05D3\u05D5\u05D2\u05DE\u05D4 \u05D5\u05D4\u05EA\u05E7\u05E0\u05D4, \u05E7\u05D5\u05D1\u05E5 \u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05D5\u05D7\u05D9\u05D1\u05D5\u05E8 \u05DC\u05D0\u05EA\u05E8. \u05DE\u05D3\u05E4\u05D9\u05E1 \u05DC\u05E1\u05D5\u05DB\u05DF \u05D0\u05EA \u05D4\u05D8\u05E7\u05E1\u05D8 \u05D5\u05D0\u05EA \u05D4\u05E4\u05E7\u05D5\u05D3\u05D5\u05EA.", "Prepares the folder with every choice: folder, sample and install, the details file and the site link. Prints the text and the commands for the agent."),
|
|
21366
21366
|
n("cmd-samples", "cli", "samples [key]", "\u05E8\u05E9\u05D9\u05DE\u05EA \u05D4\u05D3\u05D5\u05D2\u05DE\u05D0\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E8\u05D3\u05D4 \u05E9\u05DC \u05D0\u05D7\u05EA.", "Lists the samples, or downloads one."),
|
|
21367
21367
|
n("cmd-check", "cli", "check", "\u05D4\u05D0\u05DD \u05D4\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E8\u05D5\u05E5 \u05D0\u05E6\u05DC\u05E0\u05D5: \u05D7\u05D5\u05E1\u05DE\u05D9\u05DD \u05D5\u05D0\u05D6\u05D4\u05E8\u05D5\u05EA, \u05E2\u05DD \u05E4\u05E8\u05D5\u05DE\u05E4\u05D8 \u05EA\u05D9\u05E7\u05D5\u05DF.", "Can the project run on our hosting: blockers and warnings, with a fix prompt."),
|
|
21368
|
-
n("cmd-init", "cli", "init", "\u05D9\u05D5\u05E6\u05E8 DEPLOYAI.md \u05D5 .deployai/project.json.", "Creates DEPLOYAI.md and .deployai/project.json."),
|
|
21368
|
+
n("cmd-init", "cli", "init", "\u05D9\u05D5\u05E6\u05E8 DEPLOYAI.md \u05E2\u05DD \u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05DC\u05E1\u05D5\u05DB\u05DF, \u05E9\u05D5\u05E8\u05D4 \u05D0\u05DC\u05D9\u05D5 \u05D1 AGENTS.md \u05D5 CLAUDE.md, \u05D5 .deployai/project.json. \u05E8\u05D0\u05E9\u05D5\u05DF \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8 \u05D7\u05D3\u05E9.", "Creates DEPLOYAI.md with the agent rules, a line to it in AGENTS.md and CLAUDE.md, and .deployai/project.json. First in a new project."),
|
|
21369
21369
|
n("cmd-inspect", "cli", "inspect", "\u05DE\u05D4 \u05D6\u05D5\u05D4\u05D4 \u05D1\u05E4\u05E8\u05D5\u05D9\u05E7\u05D8: \u05DE\u05E1\u05D2\u05E8\u05EA, \u05E9\u05E4\u05D4, \u05DE\u05E1\u05D3 \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD.", "What the project is: framework, language, database."),
|
|
21370
21370
|
n("cmd-login", "cli", "login", "\u05DB\u05E0\u05D9\u05E1\u05D4 \u05D1\u05D3\u05E4\u05D3\u05E4\u05DF, \u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8 \u05DE\u05D0\u05E9\u05E8.", "Login in the browser, the owner approves."),
|
|
21371
21371
|
n("cmd-logout", "cli", "logout", "\u05DE\u05D1\u05D8\u05DC \u05D0\u05EA \u05D4\u05D8\u05D5\u05E7\u05DF \u05D5\u05D9\u05D5\u05E6\u05D0 \u05DE\u05D4\u05D7\u05E9\u05D1\u05D5\u05DF \u05D1\u05DE\u05D7\u05E9\u05D1 \u05D4\u05D6\u05D4.", "Cancels the token and logs out on this computer."),
|
|
@@ -21643,6 +21643,26 @@ var SPACES = {
|
|
|
21643
21643
|
test: build("test", { ...CLOUDFLARE_SPACES.prod, kvNamespaceId: "", sitesZoneId: null, backupBucket: null, toolsWorkerUrl: "" }, { ...SPACE_ADDRESSES.prod, appUrl: "http://localhost:3000", siteUrl: "http://localhost:3000", trustedOrigins: [], storage: "local" })
|
|
21644
21644
|
};
|
|
21645
21645
|
|
|
21646
|
+
// ../shared/src/agent-rules.ts
|
|
21647
|
+
var BUILD_WITH = [
|
|
21648
|
+
`Frameworks: ${SUPPORTED_FRAMEWORKS.map((f) => f.name).join(", ")}. In beta: ${BETA_FRAMEWORKS.map((f) => f.name).join(", ")} (Next.js through the OpenNext Cloudflare adapter).`,
|
|
21649
|
+
"Database: Cloudflare D1 (SQLite), through Drizzle with drizzle-orm/d1 or Prisma with the D1 adapter.",
|
|
21650
|
+
"Uploaded files and images: Cloudflare R2 (object storage), never the local disk.",
|
|
21651
|
+
"Settings and secrets: environment variables, set with: npx deployai@latest env set <key>",
|
|
21652
|
+
"Images: resize at build time or serve them as they are; no native image modules at runtime.",
|
|
21653
|
+
"Passwords: bcryptjs or Web Crypto, never native bcrypt.",
|
|
21654
|
+
"Server code runs per request: no long-running processes, background servers or child processes."
|
|
21655
|
+
];
|
|
21656
|
+
var KEEP_DATA_RULES = [
|
|
21657
|
+
"Moving to DeployAI changes where data lives. It never moves the data by itself. Before you switch any of these, save a copy inside the project and tell the user, in simple words, what was saved and where:",
|
|
21658
|
+
"- Database (Postgres, MySQL, MongoDB, a SQLite file): export it to a file (pg_dump, mysqldump, mongoexport, sqlite3 .dump), so it can be imported into D1 later.",
|
|
21659
|
+
"- Uploaded files and images on the local disk or another storage service: keep them in a folder (download them first if they are on another service), so they can be uploaded to R2 later.",
|
|
21660
|
+
"- User accounts and passwords: keep existing password hashes working (bcryptjs reads bcrypt hashes), so no one has to reset.",
|
|
21661
|
+
"- Sessions and cache (Redis, memory): these can be lost, and users may have to log in again. Say so.",
|
|
21662
|
+
"Never delete the old database, files or storage service."
|
|
21663
|
+
];
|
|
21664
|
+
var AGENT_POINTER = "Read DEPLOYAI.md before you write code, change the plan or add a dependency: this project is published with DeployAI.";
|
|
21665
|
+
|
|
21646
21666
|
// src/config.ts
|
|
21647
21667
|
import { randomUUID } from "crypto";
|
|
21648
21668
|
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -21790,6 +21810,7 @@ var M = {
|
|
|
21790
21810
|
startInstalled: "Installed its packages (npm install).",
|
|
21791
21811
|
startBrief: "Wrote the owner's details to {file} (kept out of git and never uploaded).",
|
|
21792
21812
|
startLinked: 'Linked this folder to the site "{name}".',
|
|
21813
|
+
startRules: "Wrote the rules for your agent to DEPLOYAI.md (never uploaded).",
|
|
21793
21814
|
startRelinked: 'Linked this folder to the site "{name}" instead of the site it was linked to.',
|
|
21794
21815
|
statusLine: "Status: {s}",
|
|
21795
21816
|
ready: "ready",
|
|
@@ -21803,6 +21824,7 @@ var M = {
|
|
|
21803
21824
|
pasteFix: " Paste the prompt below into your AI editor, then run: npx deployai@latest check",
|
|
21804
21825
|
copied: " (copied to clipboard)",
|
|
21805
21826
|
runDeploy: ' Run: npx deployai@latest deploy -m "<message>"',
|
|
21827
|
+
initHint: " So your agent follows the DeployAI rules, run: npx deployai@latest init",
|
|
21806
21828
|
deployTitle: "DeployAI deploy",
|
|
21807
21829
|
guestTitle: "DeployAI deploy (no account)",
|
|
21808
21830
|
uploading: "Uploading...",
|
|
@@ -21959,6 +21981,7 @@ var M = {
|
|
|
21959
21981
|
startInstalled: "\u05D4\u05D7\u05D1\u05D9\u05DC\u05D5\u05EA \u05E9\u05DC\u05D4 \u05D4\u05D5\u05EA\u05E7\u05E0\u05D5 (npm install).",
|
|
21960
21982
|
startBrief: "\u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05E9\u05DC \u05D1\u05E2\u05DC \u05D4\u05D0\u05EA\u05E8 \u05E0\u05DB\u05EA\u05D1\u05D5 \u05DC {file} (\u05DC\u05D0 \u05E0\u05DB\u05E0\u05E1\u05D9\u05DD \u05DC\u05BEgit \u05D5\u05DC\u05D0 \u05E2\u05D5\u05DC\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8).",
|
|
21961
21983
|
startLinked: '\u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05D7\u05D5\u05D1\u05E8\u05D4 \u05DC\u05D0\u05EA\u05E8 "{name}".',
|
|
21984
|
+
startRules: "\u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05DC\u05E1\u05D5\u05DB\u05DF \u05E0\u05DB\u05EA\u05D1\u05D5 \u05DC DEPLOYAI.md (\u05DC\u05D0 \u05E2\u05D5\u05DC\u05D9\u05DD \u05DC\u05D0\u05EA\u05E8).",
|
|
21962
21985
|
startRelinked: '\u05D4\u05EA\u05D9\u05E7\u05D9\u05D9\u05D4 \u05D7\u05D5\u05D1\u05E8\u05D4 \u05DC\u05D0\u05EA\u05E8 "{name}" \u05D1\u05DE\u05E7\u05D5\u05DD \u05D4\u05D0\u05EA\u05E8 \u05E9\u05D4\u05D9\u05D9\u05EA\u05D4 \u05DE\u05D7\u05D5\u05D1\u05E8\u05EA \u05D0\u05DC\u05D9\u05D5.',
|
|
21963
21986
|
statusLine: "\u05DE\u05E6\u05D1: {s}",
|
|
21964
21987
|
ready: "\u05DE\u05D5\u05DB\u05DF \u05DC\u05E2\u05DC\u05D5\u05EA",
|
|
@@ -21972,6 +21995,7 @@ var M = {
|
|
|
21972
21995
|
pasteFix: " \u05D4\u05D3\u05D1\u05D9\u05E7\u05D5 \u05D0\u05EA \u05D4\u05E4\u05E8\u05D5\u05DE\u05E4\u05D8 \u05E9\u05DC\u05DE\u05D8\u05D4 \u05DC\u05E1\u05D5\u05DB\u05DF, \u05D5\u05D0\u05D6 \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest check",
|
|
21973
21996
|
copied: " (\u05D4\u05D5\u05E2\u05EA\u05E7)",
|
|
21974
21997
|
runDeploy: ' \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest deploy -m "<message>"',
|
|
21998
|
+
initHint: " \u05DB\u05D3\u05D9 \u05E9\u05D4\u05E1\u05D5\u05DB\u05DF \u05D9\u05E2\u05D1\u05D5\u05D3 \u05DC\u05E4\u05D9 \u05D4\u05DB\u05DC\u05DC\u05D9\u05DD \u05E9\u05DC DeployAI, \u05D4\u05E8\u05D9\u05E6\u05D5: npx deployai@latest init",
|
|
21975
21999
|
deployTitle: "DeployAI deploy",
|
|
21976
22000
|
guestTitle: "DeployAI deploy (\u05D1\u05DC\u05D9 \u05D7\u05E9\u05D1\u05D5\u05DF)",
|
|
21977
22001
|
uploading: "\u05DE\u05E2\u05DC\u05D9\u05DD...",
|
|
@@ -22132,7 +22156,7 @@ function messages(root) {
|
|
|
22132
22156
|
}
|
|
22133
22157
|
|
|
22134
22158
|
// src/version.ts
|
|
22135
|
-
var CLI_VERSION = "0.1.0-beta.
|
|
22159
|
+
var CLI_VERSION = "0.1.0-beta.7";
|
|
22136
22160
|
|
|
22137
22161
|
// src/api.ts
|
|
22138
22162
|
function apiContext(apiFlag) {
|
|
@@ -22361,7 +22385,7 @@ async function sendTelemetryEvent(ctx, event) {
|
|
|
22361
22385
|
}
|
|
22362
22386
|
|
|
22363
22387
|
// src/commands/init.ts
|
|
22364
|
-
import { existsSync as existsSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
22388
|
+
import { appendFileSync, existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
22365
22389
|
import { join as join5 } from "path";
|
|
22366
22390
|
|
|
22367
22391
|
// src/analyze.ts
|
|
@@ -22529,6 +22553,7 @@ function planUpload(root) {
|
|
|
22529
22553
|
}
|
|
22530
22554
|
|
|
22531
22555
|
// src/analyze.ts
|
|
22556
|
+
var INIT_FILES = /* @__PURE__ */ new Set(["DEPLOYAI.md", "AGENTS.md", "CLAUDE.md"]);
|
|
22532
22557
|
var CODE_EXT = /\.(js|jsx|ts|tsx|mjs|cjs|mts|cts|vue|svelte|astro)$/;
|
|
22533
22558
|
var SECRET_SCAN_EXT = /\.(js|jsx|ts|tsx|mjs|cjs|mts|cts|vue|svelte|astro|json|ya?ml|toml|html|prisma)$/;
|
|
22534
22559
|
var LOCKFILES = /* @__PURE__ */ new Set(["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lock", "bun.lockb"]);
|
|
@@ -22886,7 +22911,7 @@ function analyzeProject(root) {
|
|
|
22886
22911
|
}
|
|
22887
22912
|
const otherStack = detectOtherStack(files.map((f) => f.rel));
|
|
22888
22913
|
if (otherStack) add({ code: "other_stack", severity: "blocker", detail: ` ${otherStack.name}` });
|
|
22889
|
-
const empty = !files.some((f) => !f.rel.startsWith(".deployai/") && f.rel
|
|
22914
|
+
const empty = !files.some((f) => !f.rel.startsWith(".deployai/") && !INIT_FILES.has(f.rel) && !isEnvFile(f.rel.split("/").pop() ?? ""));
|
|
22890
22915
|
if (empty) add({ code: "no_files", severity: "blocker" });
|
|
22891
22916
|
if (framework.id === "unknown" && !otherStack && !empty) {
|
|
22892
22917
|
add({ code: "unknown_framework", severity: "warning", detail: framework.flavor ? ` (looks like ${framework.flavor})` : "" });
|
|
@@ -22984,13 +23009,28 @@ This project is published with DeployAI.
|
|
|
22984
23009
|
|
|
22985
23010
|
Always explain to the user in simple words, in the language they write to you in. The user may not read English.
|
|
22986
23011
|
|
|
22987
|
-
|
|
23012
|
+
Before you write code or change the plan, compare it with these rules. If something in it does not fit, say what and propose the change.
|
|
23013
|
+
|
|
23014
|
+
## Build with
|
|
23015
|
+
|
|
23016
|
+
${BUILD_WITH.map((l) => `- ${l}`).join("\n")}
|
|
23017
|
+
|
|
23018
|
+
To start from working code, see the samples: npx deployai@latest samples
|
|
23019
|
+
|
|
23020
|
+
## Do not add
|
|
23021
|
+
|
|
22988
23022
|
- local file system writes
|
|
22989
23023
|
- database drivers DeployAI does not support (see: npx deployai@latest inspect)
|
|
22990
23024
|
- long-running processes or background servers
|
|
22991
23025
|
- native binary modules
|
|
22992
23026
|
- DeployAI or any cloud credentials in source code
|
|
22993
23027
|
|
|
23028
|
+
## Keep existing data
|
|
23029
|
+
|
|
23030
|
+
${KEEP_DATA_RULES.join("\n")}
|
|
23031
|
+
|
|
23032
|
+
## Check
|
|
23033
|
+
|
|
22994
23034
|
Before adding a dependency or a new server feature, run: npx deployai@latest check
|
|
22995
23035
|
Ask the developer before removing any existing functionality.
|
|
22996
23036
|
|
|
@@ -22998,9 +23038,11 @@ Files:
|
|
|
22998
23038
|
- .deployai/project.json: project id and settings (safe to commit)
|
|
22999
23039
|
- .deployai/last-check.json: latest check result (not committed)
|
|
23000
23040
|
`;
|
|
23041
|
+
var AGENT_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
23001
23042
|
function runInit(root, opts = {}) {
|
|
23002
23043
|
const created = [];
|
|
23003
23044
|
const kept = [];
|
|
23045
|
+
const updated = [];
|
|
23004
23046
|
const md = join5(root, "DEPLOYAI.md");
|
|
23005
23047
|
if (existsSync5(md) && !opts.force) {
|
|
23006
23048
|
kept.push("DEPLOYAI.md");
|
|
@@ -23008,20 +23050,35 @@ function runInit(root, opts = {}) {
|
|
|
23008
23050
|
writeFileSync3(md, DEPLOYAI_MD);
|
|
23009
23051
|
created.push("DEPLOYAI.md");
|
|
23010
23052
|
}
|
|
23053
|
+
if (opts.agentFiles !== false) {
|
|
23054
|
+
for (const name of AGENT_FILES) {
|
|
23055
|
+
const file2 = join5(root, name);
|
|
23056
|
+
const text = existsSync5(file2) ? readFileSync5(file2, "utf8") : null;
|
|
23057
|
+
if (text === null) {
|
|
23058
|
+
writeFileSync3(file2, `${AGENT_POINTER}
|
|
23059
|
+
`);
|
|
23060
|
+
created.push(name);
|
|
23061
|
+
} else if (text.includes("DEPLOYAI.md")) {
|
|
23062
|
+
kept.push(name);
|
|
23063
|
+
} else {
|
|
23064
|
+
const eol = text.includes("\r\n") ? "\r\n" : "\n";
|
|
23065
|
+
const gap = !text.trim() ? "" : text.endsWith("\n") ? eol : eol + eol;
|
|
23066
|
+
appendFileSync(file2, `${gap}${AGENT_POINTER}${eol}`);
|
|
23067
|
+
updated.push(name);
|
|
23068
|
+
}
|
|
23069
|
+
}
|
|
23070
|
+
}
|
|
23011
23071
|
ensureDeployaiDir(root);
|
|
23012
23072
|
const existing = readProject(root);
|
|
23073
|
+
const framework = existing?.framework ?? analyzeProject(root).inspect.framework.id;
|
|
23013
23074
|
if (existing) {
|
|
23014
23075
|
kept.push(".deployai/project.json");
|
|
23015
23076
|
} else {
|
|
23016
|
-
|
|
23017
|
-
writeProject(root, {
|
|
23018
|
-
projectId: null,
|
|
23019
|
-
framework: analysis.inspect.framework.id,
|
|
23020
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
23021
|
-
});
|
|
23077
|
+
writeProject(root, { projectId: null, framework, createdAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
23022
23078
|
created.push(".deployai/project.json");
|
|
23023
23079
|
}
|
|
23024
|
-
|
|
23080
|
+
const hasCode = existsSync5(join5(root, "package.json")) || framework !== "unknown";
|
|
23081
|
+
return { created, kept, updated, hasCode };
|
|
23025
23082
|
}
|
|
23026
23083
|
function initCommand(root, opts) {
|
|
23027
23084
|
const res = runInit(root, opts);
|
|
@@ -23031,6 +23088,7 @@ function initCommand(root, opts) {
|
|
|
23031
23088
|
out(
|
|
23032
23089
|
rows([
|
|
23033
23090
|
...res.created.map((f) => ["Created", f]),
|
|
23091
|
+
...res.updated.map((f) => ["Added a line", `${f} (read DEPLOYAI.md)`]),
|
|
23034
23092
|
...res.kept.map((f) => ["Kept", f]),
|
|
23035
23093
|
["Guard", ".deployai/last-check.json (git ignored)"],
|
|
23036
23094
|
["Linked project", project?.projectId ?? "none yet"]
|
|
@@ -23038,12 +23096,18 @@ function initCommand(root, opts) {
|
|
|
23038
23096
|
);
|
|
23039
23097
|
out();
|
|
23040
23098
|
out("Next step");
|
|
23041
|
-
|
|
23099
|
+
if (res.hasCode) {
|
|
23100
|
+
out(" Run: npx deployai@latest check");
|
|
23101
|
+
} else {
|
|
23102
|
+
out(" Start from a sample: npx deployai@latest samples");
|
|
23103
|
+
out(" Or tell your agent what to build, or to review your plan. It follows DEPLOYAI.md.");
|
|
23104
|
+
}
|
|
23042
23105
|
if (!project?.projectId) out(" Then: npx deployai@latest login, npx deployai@latest link");
|
|
23043
23106
|
}
|
|
23044
23107
|
|
|
23045
23108
|
// src/commands/check.ts
|
|
23046
|
-
import { writeFileSync as writeFileSync4 } from "fs";
|
|
23109
|
+
import { existsSync as existsSync6, writeFileSync as writeFileSync4 } from "fs";
|
|
23110
|
+
import { join as join6 } from "path";
|
|
23047
23111
|
|
|
23048
23112
|
// src/prompt.ts
|
|
23049
23113
|
var PROMPT_RULES = [
|
|
@@ -23053,8 +23117,10 @@ var PROMPT_RULES = [
|
|
|
23053
23117
|
"Keep the project runnable outside DeployAI.",
|
|
23054
23118
|
"Never add credentials to source code.",
|
|
23055
23119
|
"Explain every step to the user in simple words, in the language they write to you in.",
|
|
23056
|
-
"For the database, use D1 as shown in the DeployAI CRUD sample."
|
|
23120
|
+
"For the database, use D1 as shown in the DeployAI CRUD sample.",
|
|
23121
|
+
"Follow DEPLOYAI.md for every future change. If it is missing, run: npx deployai@latest init"
|
|
23057
23122
|
];
|
|
23123
|
+
var DATA_CODES = /* @__PURE__ */ new Set(["fs_write", "unsupported_db_postgres", "unsupported_db_mysql", "unsupported_db_mongodb", "unsupported_db_sqlite_file", "native_module_bcrypt"]);
|
|
23058
23124
|
var MAX_LOCATIONS = 3;
|
|
23059
23125
|
function locList(items) {
|
|
23060
23126
|
const locs = [...new Set(items.map(locationOf).filter(Boolean))];
|
|
@@ -23093,6 +23159,11 @@ function buildPrompt(analysis) {
|
|
|
23093
23159
|
if (def) lines.push(`- ${def.fixForAgent}`);
|
|
23094
23160
|
}
|
|
23095
23161
|
lines.push("");
|
|
23162
|
+
if (blockerGroups.some((g) => DATA_CODES.has(g.code))) {
|
|
23163
|
+
lines.push("Keep existing data:");
|
|
23164
|
+
lines.push(...KEEP_DATA_RULES);
|
|
23165
|
+
lines.push("");
|
|
23166
|
+
}
|
|
23096
23167
|
lines.push("Rules:");
|
|
23097
23168
|
for (const r of PROMPT_RULES) lines.push(`- ${r}`);
|
|
23098
23169
|
lines.push("");
|
|
@@ -23242,6 +23313,7 @@ async function runCheck(root, ctx, opts = {}) {
|
|
|
23242
23313
|
} else {
|
|
23243
23314
|
out(t("runDeploy"));
|
|
23244
23315
|
}
|
|
23316
|
+
if (!existsSync6(join6(root, "DEPLOYAI.md"))) out(t("initHint"));
|
|
23245
23317
|
}
|
|
23246
23318
|
await telemetry;
|
|
23247
23319
|
return a;
|
|
@@ -23455,7 +23527,7 @@ async function linkCommand(root, ctx, target, opts) {
|
|
|
23455
23527
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
23456
23528
|
|
|
23457
23529
|
// src/tar.ts
|
|
23458
|
-
import { readFileSync as
|
|
23530
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
23459
23531
|
import { gzipSync } from "zlib";
|
|
23460
23532
|
var BLOCK = 512;
|
|
23461
23533
|
function writeString(buf, offset, length, value) {
|
|
@@ -23539,7 +23611,7 @@ function packFiles(files) {
|
|
|
23539
23611
|
return createTarGz(
|
|
23540
23612
|
files.map((f) => ({
|
|
23541
23613
|
name: f.rel,
|
|
23542
|
-
data:
|
|
23614
|
+
data: readFileSync6(f.abs),
|
|
23543
23615
|
mtimeMs: f.mtimeMs,
|
|
23544
23616
|
mode: f.mode & 64 ? 493 : 420
|
|
23545
23617
|
}))
|
|
@@ -23742,8 +23814,8 @@ async function claimCommand(root, ctx, opts) {
|
|
|
23742
23814
|
|
|
23743
23815
|
// src/commands/samples.ts
|
|
23744
23816
|
import { createInterface as createInterface3 } from "readline/promises";
|
|
23745
|
-
import { existsSync as
|
|
23746
|
-
import { dirname, join as
|
|
23817
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, readdirSync as readdirSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
23818
|
+
import { dirname, join as join7, relative, resolve, sep } from "path";
|
|
23747
23819
|
import { gunzipSync } from "zlib";
|
|
23748
23820
|
var SAMPLES = [
|
|
23749
23821
|
{ key: "landing", title: "Landing page: a full one-page site with WhatsApp sign-up", stack: "static HTML and CSS" },
|
|
@@ -23754,7 +23826,7 @@ var SAMPLES = [
|
|
|
23754
23826
|
{ key: "admin", title: "Back office with login: dashboard, orders, stock, customers", stack: "Astro on Workers, D1" }
|
|
23755
23827
|
];
|
|
23756
23828
|
var MAX_BYTES = 20 * 1024 * 1024;
|
|
23757
|
-
var IGNORED = /* @__PURE__ */ new Set([".git", ".DS_Store", "Thumbs.db", ".deployai"]);
|
|
23829
|
+
var IGNORED = /* @__PURE__ */ new Set([".git", ".DS_Store", "Thumbs.db", ".deployai", "DEPLOYAI.md", "AGENTS.md", "CLAUDE.md"]);
|
|
23758
23830
|
function listSamples(apiUrl) {
|
|
23759
23831
|
out("DeployAI samples");
|
|
23760
23832
|
out("");
|
|
@@ -23764,7 +23836,7 @@ function listSamples(apiUrl) {
|
|
|
23764
23836
|
out(`See them live: ${apiUrl}/samples`);
|
|
23765
23837
|
}
|
|
23766
23838
|
function filesIn(dir) {
|
|
23767
|
-
return
|
|
23839
|
+
return existsSync7(dir) ? readdirSync3(dir).filter((f) => !IGNORED.has(f)) : [];
|
|
23768
23840
|
}
|
|
23769
23841
|
function freeFolder(cwd, key) {
|
|
23770
23842
|
for (let n2 = 1; ; n2++) {
|
|
@@ -23847,7 +23919,7 @@ async function samplesCommand(cwd, ctx, key, opts = {}) {
|
|
|
23847
23919
|
}
|
|
23848
23920
|
const written = await downloadSample(ctx, sample.key, root);
|
|
23849
23921
|
const base = resolve(root);
|
|
23850
|
-
const hasPackage =
|
|
23922
|
+
const hasPackage = existsSync7(join7(base, "package.json"));
|
|
23851
23923
|
out(base === resolve(cwd) ? `Downloaded the ${sample.key} sample: ${written} files.` : `Downloaded the ${sample.key} sample into the new folder ${relative(cwd, base)}: ${written} files. Work in that folder from now on.`);
|
|
23852
23924
|
out("");
|
|
23853
23925
|
const t = messages(base);
|
|
@@ -23992,8 +24064,8 @@ async function statusCommand(root, ctx) {
|
|
|
23992
24064
|
|
|
23993
24065
|
// src/commands/start.ts
|
|
23994
24066
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
23995
|
-
import { existsSync as
|
|
23996
|
-
import { join as
|
|
24067
|
+
import { existsSync as existsSync8, writeFileSync as writeFileSync6 } from "fs";
|
|
24068
|
+
import { join as join8, relative as relative2, resolve as resolve2 } from "path";
|
|
23997
24069
|
var REASONS = { start_not_found: "startNotFound", start_expired: "startExpired", start_used_up: "startUsedUp" };
|
|
23998
24070
|
var reason = (code) => messages(process.cwd())(REASONS[code] ?? "startNotFound");
|
|
23999
24071
|
async function fetchStart(ctx, id) {
|
|
@@ -24031,19 +24103,20 @@ async function startCommand(cwd, ctx, id, opts = {}) {
|
|
|
24031
24103
|
if (sample && !sameSite) {
|
|
24032
24104
|
const written = await downloadSample(ctx, sample.key, root);
|
|
24033
24105
|
done.push(t("startDownloaded", { key: sample.key, n: written }));
|
|
24034
|
-
if (
|
|
24106
|
+
if (existsSync8(join8(root, "package.json"))) {
|
|
24035
24107
|
if (opts.install !== false && install(root)) done.push(t("startInstalled"));
|
|
24036
24108
|
else steps.unshift({ cmd: "npm install", say: "Installs the sample's packages." });
|
|
24037
24109
|
}
|
|
24038
24110
|
}
|
|
24039
24111
|
if (choices.brief) {
|
|
24040
24112
|
ensureDeployaiDir(root);
|
|
24041
|
-
writeFileSync6(
|
|
24113
|
+
writeFileSync6(join8(root, BRIEF_FILE), `# The owner's details
|
|
24042
24114
|
|
|
24043
24115
|
${choices.brief}
|
|
24044
24116
|
`);
|
|
24045
24117
|
done.push(t("startBrief", { file: BRIEF_FILE }));
|
|
24046
24118
|
}
|
|
24119
|
+
if (runInit(root).created.includes("DEPLOYAI.md")) done.push(t("startRules"));
|
|
24047
24120
|
if (choices.projectId) {
|
|
24048
24121
|
const before = readProject(root);
|
|
24049
24122
|
writeProject(root, { ...before ?? {}, projectId: choices.projectId, name: choices.name ?? void 0, slug: choices.slug ?? void 0, createdAt: before?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -24069,7 +24142,7 @@ ${choices.brief}
|
|
|
24069
24142
|
}
|
|
24070
24143
|
|
|
24071
24144
|
// src/commands/addon.ts
|
|
24072
|
-
import { readFileSync as
|
|
24145
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
24073
24146
|
import { resolve as resolve3 } from "path";
|
|
24074
24147
|
function linkedProjectId2(root) {
|
|
24075
24148
|
const id = readProject(root)?.projectId;
|
|
@@ -24150,7 +24223,7 @@ async function addonDoneCommand(root, ctx, runId, opts) {
|
|
|
24150
24223
|
let report;
|
|
24151
24224
|
if (opts.report) {
|
|
24152
24225
|
try {
|
|
24153
|
-
report = JSON.parse(
|
|
24226
|
+
report = JSON.parse(readFileSync7(resolve3(root, opts.report), "utf8"));
|
|
24154
24227
|
} catch {
|
|
24155
24228
|
throw new CliError(`Cannot read the report file ${opts.report} as JSON.`, 1, "usage");
|
|
24156
24229
|
}
|
|
@@ -24246,7 +24319,7 @@ function buildProgram() {
|
|
|
24246
24319
|
const g = (cmd) => cmd.optsWithGlobals();
|
|
24247
24320
|
const root = (cmd) => resolve4(g(cmd).dir ?? process.cwd());
|
|
24248
24321
|
const ctx = (cmd) => apiContext(g(cmd).api);
|
|
24249
|
-
program.command("init").description("create DEPLOYAI.md and .deployai/ guard files").option("--force", "overwrite DEPLOYAI.md").action((opts, cmd) => initCommand(root(cmd), opts));
|
|
24322
|
+
program.command("init").description("create DEPLOYAI.md and .deployai/ guard files").option("--force", "overwrite DEPLOYAI.md").option("--no-agent-files", "do not add the DEPLOYAI.md line to AGENTS.md and CLAUDE.md").action((opts, cmd) => initCommand(root(cmd), opts));
|
|
24250
24323
|
program.command("inspect").description("show framework, package manager, language, database, storage").option("--json", "machine readable output").action((opts, cmd) => inspectCommand(root(cmd), opts));
|
|
24251
24324
|
program.command("check").description("can this project run on DeployAI: blockers and warnings, with the AI prompt").option("--json", "machine readable output").option("--no-clipboard", "do not copy the prompt to the clipboard").action(async (opts, cmd) => {
|
|
24252
24325
|
const a = await runCheck(root(cmd), ctx(cmd), opts);
|