@backifydev/cli 0.2.1 → 0.2.2
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 +4 -2
- package/dist/index.js +67 -23
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ npx @backifydev/cli login
|
|
|
13
13
|
|
|
14
14
|
`init` installs `@backifydev/sdk`, writes `backify.json`, and maintains the Backify blocks in `AGENTS.md`, `CLAUDE.md`, and `.github/copilot-instructions.md`. It preserves other instructions in those files.
|
|
15
15
|
|
|
16
|
+
The app configuration stores `instructionVersion`, matching the version declared in each managed block and its immutable guide at `https://agent.backify.dev/v<number>`. The agent root always serves the latest guide as plain text. `doctor` detects version/content drift and malformed markers. Use `npx @backifydev/cli@latest sync` to explicitly upgrade all blocks and the configuration together; unrelated configuration and unmanaged instructions remain unchanged.
|
|
17
|
+
|
|
16
18
|
You can start from an empty folder without a Git repository. `init` creates a minimal private `package.json` before installing the SDK, without choosing a framework. Add the application's framework and development/build scripts afterward. Existing manifests are preserved; in a non-empty application or monorepo, run `init` from the appropriate JavaScript/TypeScript package directory.
|
|
17
|
-
|
|
18
|
-
See the [agent setup guide](https://
|
|
19
|
+
|
|
20
|
+
See the [agent setup guide](https://agent.backify.dev/).
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
14
14
|
import { spawnSync } from "node:child_process";
|
|
15
15
|
|
|
16
16
|
// ../platform/dist/index.js
|
|
17
|
-
var INSTRUCTION_VERSION =
|
|
17
|
+
var INSTRUCTION_VERSION = 2;
|
|
18
18
|
var SDK_PACKAGE = "@backifydev/sdk";
|
|
19
19
|
var DOCS_URL = "https://docs.backify.dev";
|
|
20
20
|
var capability = (name, imp, description, stateful = false, provisioner = name) => ({ name, import: imp, version: 1, stateful, provisioner, docs: `${DOCS_URL}/capabilities/${name}`, description, destructiveRemovalRequiresApproval: stateful });
|
|
@@ -41,25 +41,62 @@ function managedInstructions() {
|
|
|
41
41
|
|
|
42
42
|
# Backify Platform Instructions
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
Instruction version: ${INSTRUCTION_VERSION}
|
|
45
|
+
Versioned guide: https://agent.backify.dev/v${INSTRUCTION_VERSION}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
## Scope and platform policy
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
This application runs on Backify. These rules govern application code targeting Backify, not the implementation of the Backify platform itself.
|
|
50
|
+
Use \`@backifydev/sdk\` for platform capabilities. Do not directly integrate or provision cloud infrastructure, hosted authentication, databases, storage, queues, or schedulers when an equivalent Backify capability exists. If a capability is missing, explain the gap and ask before adding an external platform dependency.
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
## SDK capability map
|
|
53
|
+
|
|
54
|
+
- Authentication and authorization: \`auth\`.
|
|
55
|
+
- Persistent data and files: \`db\` and \`storage\`.
|
|
56
|
+
- Server functions: \`defineFunction\`; background work and schedules: \`jobs\` and \`jobs.schedule\`.
|
|
57
|
+
- Events, outbound HTTP, and AI: \`events\`, \`http.fetch\`, and \`ai\`.
|
|
58
|
+
- Server-side secrets, configuration, audit, and logs: \`secrets\`, \`config\`, \`audit\`, and \`logs\`.
|
|
59
|
+
|
|
60
|
+
Verify API signatures against the installed SDK types and the relevant guide at ${DOCS_URL}/capabilities/. Never invent SDK methods. Use \`@backifydev/sdk/local\` for tests and local development; \`@backifydev/sdk/runtime\` is for runtime hosts, not application code.
|
|
61
|
+
|
|
62
|
+
## Security and data safety
|
|
63
|
+
|
|
64
|
+
Keep secrets server-side. Never commit or log credentials, expose secrets to browser code, or place cloud-management credentials in applications. Enforce authorization in trusted server code and scope data access to the authenticated user or organization as required.
|
|
65
|
+
Scope cookies to the exact application hostname by omitting the \`Domain\` attribute. Never use a parent-domain cookie unless explicitly required.
|
|
66
|
+
Require explicit confirmation before destructive data operations or removing stateful resources. Removing a capability declaration does not authorize deleting its data.
|
|
67
|
+
|
|
68
|
+
## Implementation workflow
|
|
69
|
+
|
|
70
|
+
Inspect the framework, lockfile, scripts, configuration, and applicable repository instructions before editing. Preserve the existing framework and unrelated work. Implement the requested application rather than stopping at SDK setup; ask what to build if requirements are missing.
|
|
71
|
+
Run relevant tests, typechecking, lint, and builds using the repository's scripts when available. Report changes, checks, and remaining blockers accurately; do not claim unverified success.
|
|
72
|
+
|
|
73
|
+
## Instruction maintenance
|
|
74
|
+
|
|
75
|
+
The authoritative documentation is ${DOCS_URL}/. The root at https://agent.backify.dev/ always shows the latest guide; use the versioned guide above for this repository's installed instructions.
|
|
76
|
+
Keep \`backify.json\` \`instructionVersion\` aligned with this block. Run \`npx @backifydev/cli@latest doctor\` to check consistency and \`npx @backifydev/cli@latest sync\` to adopt a newer instruction version. Never silently upgrade instructions during an unrelated feature change.
|
|
77
|
+
Preserve all content outside this managed block and all more-specific repository instructions.
|
|
51
78
|
|
|
52
79
|
${MANAGED_END}`;
|
|
53
80
|
}
|
|
81
|
+
function managedInstructionIssues(content) {
|
|
82
|
+
const normalized = content.replace(/\r\n/g, "\n"), starts = normalized.split(MANAGED_START).length - 1, ends = normalized.split(MANAGED_END).length - 1;
|
|
83
|
+
if (starts === 0 && ends === 0)
|
|
84
|
+
return ["does not contain Backify managed instructions"];
|
|
85
|
+
if (starts !== 1 || ends !== 1)
|
|
86
|
+
return ["contains duplicate or incomplete Backify managed markers"];
|
|
87
|
+
const start = normalized.indexOf(MANAGED_START), end = normalized.indexOf(MANAGED_END);
|
|
88
|
+
if (end < start)
|
|
89
|
+
return ["contains reversed Backify managed markers"];
|
|
90
|
+
return normalized.slice(start, end + MANAGED_END.length) === managedInstructions() ? [] : ["contains stale or inconsistent Backify managed instructions; run backify sync"];
|
|
91
|
+
}
|
|
54
92
|
function updateManagedInstructions(content) {
|
|
93
|
+
const issues = managedInstructionIssues(content);
|
|
94
|
+
if (issues.some((issue) => issue.includes("markers")))
|
|
95
|
+
throw new Error(issues.join("; "));
|
|
55
96
|
const block = managedInstructions(), start = content.indexOf(MANAGED_START), end = content.indexOf(MANAGED_END);
|
|
56
|
-
if (start >= 0
|
|
97
|
+
if (start >= 0)
|
|
57
98
|
return content.slice(0, start) + block + content.slice(end + MANAGED_END.length);
|
|
58
|
-
return content.trim() ?
|
|
59
|
-
|
|
60
|
-
${block}
|
|
61
|
-
` : `${block}
|
|
62
|
-
`;
|
|
99
|
+
return content.trim() ? content.trimEnd() + "\n\n" + block + "\n" : block + "\n";
|
|
63
100
|
}
|
|
64
101
|
function createConfig(appId) {
|
|
65
102
|
return { $schema: `${DOCS_URL}/schema/backify.json`, platform: "backify", sdk: SDK_PACKAGE, appId, instructionVersion: INSTRUCTION_VERSION, docs: DOCS_URL, instructions: { preferBackifyCapabilities: true, allowDirectCloudInfrastructure: false } };
|
|
@@ -92,12 +129,25 @@ function detectPackageManager(root = process.cwd()) {
|
|
|
92
129
|
return "npm";
|
|
93
130
|
}
|
|
94
131
|
function updateInstructions(root = process.cwd()) {
|
|
95
|
-
|
|
132
|
+
const updates = instructionFiles.map((relative) => {
|
|
96
133
|
const path = join(root, relative);
|
|
134
|
+
return { path, content: updateManagedInstructions(existsSync(path) ? readFileSync(path, "utf8") : "") };
|
|
135
|
+
});
|
|
136
|
+
for (const { path, content } of updates) {
|
|
97
137
|
mkdirSync(dirname(path), { recursive: true });
|
|
98
|
-
writeFileSync(path,
|
|
138
|
+
writeFileSync(path, content);
|
|
99
139
|
}
|
|
100
140
|
}
|
|
141
|
+
function synchronize(root = process.cwd()) {
|
|
142
|
+
const path = join(root, "backify.json");
|
|
143
|
+
if (!existsSync(path)) throw new Error("backify.json is missing; run backify init --app app_xxxxx");
|
|
144
|
+
const value = JSON.parse(readFileSync(path, "utf8")), issues = validateConfig(value);
|
|
145
|
+
if (issues.length) throw new Error(issues.join("; "));
|
|
146
|
+
if (value.instructionVersion > INSTRUCTION_VERSION) throw new Error("This app uses newer instructions. Install a matching or newer CLI before syncing.");
|
|
147
|
+
updateInstructions(root);
|
|
148
|
+
value.instructionVersion = INSTRUCTION_VERSION;
|
|
149
|
+
writeFileSync(path, JSON.stringify(value, null, 2) + "\n");
|
|
150
|
+
}
|
|
101
151
|
function writeConfig(appId, root = process.cwd()) {
|
|
102
152
|
writeFileSync(join(root, "backify.json"), JSON.stringify(createConfig(appId), null, 2) + "\n");
|
|
103
153
|
}
|
|
@@ -118,7 +168,7 @@ function ensurePackageManifest(root) {
|
|
|
118
168
|
const path = join(root, "package.json");
|
|
119
169
|
if (existsSync(path)) return;
|
|
120
170
|
const setupFiles = /* @__PURE__ */ new Set([".git", ".gitignore", ".github", "AGENTS.md", "CLAUDE.md", "README.md", "LICENSE", "backify.json"]);
|
|
121
|
-
if (readdirSync(root).some((file) => !setupFiles.has(file))) throw new Error("package.json is missing. Run backify init from the existing application's JavaScript/TypeScript package directory, or start in an empty folder. See https://
|
|
171
|
+
if (readdirSync(root).some((file) => !setupFiles.has(file))) throw new Error("package.json is missing. Run backify init from the existing application's JavaScript/TypeScript package directory, or start in an empty folder. See https://agent.backify.dev/");
|
|
122
172
|
const name = basename(resolve(root)).toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "backify-app";
|
|
123
173
|
writeFileSync(path, JSON.stringify({ name, version: "0.0.0", private: true, type: "module" }, null, 2) + "\n", { flag: "wx" });
|
|
124
174
|
}
|
|
@@ -139,15 +189,14 @@ function doctor(root = process.cwd()) {
|
|
|
139
189
|
} catch {
|
|
140
190
|
issues.push("backify.json is missing or invalid JSON");
|
|
141
191
|
}
|
|
142
|
-
if (config
|
|
192
|
+
if (config && config.instructionVersion !== INSTRUCTION_VERSION) issues.push(`Repository instruction version ${config.instructionVersion}; CLI version ${INSTRUCTION_VERSION}. Use the matching CLI or run backify sync to upgrade.`);
|
|
143
193
|
for (const relative of instructionFiles) {
|
|
144
194
|
const path = join(root, relative);
|
|
145
195
|
if (!existsSync(path)) {
|
|
146
196
|
issues.push(`${relative} is missing`);
|
|
147
197
|
continue;
|
|
148
198
|
}
|
|
149
|
-
|
|
150
|
-
if (!text.includes(MANAGED_START) || !text.includes(MANAGED_END)) issues.push(`${relative} does not contain Backify managed instructions`);
|
|
199
|
+
issues.push(...managedInstructionIssues(readFileSync(path, "utf8")).map((issue) => `${relative} ${issue}`));
|
|
151
200
|
}
|
|
152
201
|
let version = "unknown";
|
|
153
202
|
try {
|
|
@@ -239,12 +288,7 @@ async function main() {
|
|
|
239
288
|
console.log("Backify initialized. SDK, configuration, and agent instructions are ready.");
|
|
240
289
|
break;
|
|
241
290
|
case "sync": {
|
|
242
|
-
|
|
243
|
-
if (!existsSync2(path)) throw new Error("backify.json is missing; run backify init --app app_xxxxx");
|
|
244
|
-
const value = JSON.parse(readFileSync2(path, "utf8"));
|
|
245
|
-
value.instructionVersion = INSTRUCTION_VERSION;
|
|
246
|
-
writeFileSync2(path, JSON.stringify(value, null, 2) + "\n");
|
|
247
|
-
updateInstructions();
|
|
291
|
+
synchronize();
|
|
248
292
|
console.log(`Backify instructions synchronized to version ${INSTRUCTION_VERSION}.`);
|
|
249
293
|
break;
|
|
250
294
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backifydev/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Command-line setup and diagnostics for Backify applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": { "backify": "dist/index.js" },
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"test": "vitest run"
|
|
16
16
|
},
|
|
17
17
|
"publishConfig": { "access": "public" },
|
|
18
|
-
"repository": { "type": "git", "url": "git+https://github.com/frejnorling/backify.git", "directory": "packages/cli" },
|
|
19
|
-
"homepage": "https://
|
|
18
|
+
"repository": { "type": "git", "url": "git+https://github.com/frejnorling/backify.git", "directory": "packages/cli" },
|
|
19
|
+
"homepage": "https://agent.backify.dev/",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"engines": { "node": ">=20" },
|
|
22
22
|
"devDependencies": {
|