@appfleet-cli/cli 0.1.0
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 +14 -0
- package/dist/appfleet.d.ts +4 -0
- package/dist/appfleet.js +12253 -0
- package/dist/audit.d.ts +10 -0
- package/dist/audit.js +85 -0
- package/dist/billing-cost.d.ts +8 -0
- package/dist/billing-cost.js +186 -0
- package/dist/cloud-session.d.ts +124 -0
- package/dist/cloud-session.js +1819 -0
- package/dist/command-registry.d.ts +18 -0
- package/dist/command-registry.js +1067 -0
- package/dist/demo-fixture.d.ts +11 -0
- package/dist/demo-fixture.js +39 -0
- package/dist/generate-cli-docs.d.ts +1 -0
- package/dist/generate-cli-docs.js +94 -0
- package/dist/health.d.ts +8 -0
- package/dist/health.js +60 -0
- package/dist/local-vault.d.ts +75 -0
- package/dist/local-vault.js +1169 -0
- package/dist/operations.d.ts +8 -0
- package/dist/operations.js +220 -0
- package/dist/project-memory.d.ts +138 -0
- package/dist/project-memory.js +1529 -0
- package/dist/prototype-inject.d.ts +21 -0
- package/dist/prototype-inject.js +170 -0
- package/dist/provider-integrations.d.ts +8 -0
- package/dist/provider-integrations.js +197 -0
- package/package.json +45 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PrototypeSecretFixture } from "./demo-fixture.ts";
|
|
2
|
+
type ParsedInjectCommand = {
|
|
3
|
+
project: string;
|
|
4
|
+
environment: string;
|
|
5
|
+
command: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
};
|
|
8
|
+
export type PrototypeInjectResult = {
|
|
9
|
+
exitCode: number;
|
|
10
|
+
stdout: string;
|
|
11
|
+
stderr: string;
|
|
12
|
+
childStarted: boolean;
|
|
13
|
+
auditId?: string;
|
|
14
|
+
};
|
|
15
|
+
export type PrototypeInjectOptions = {
|
|
16
|
+
fixture?: PrototypeSecretFixture;
|
|
17
|
+
auditPath?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function parseInjectCommand(argv: string[]): ParsedInjectCommand;
|
|
20
|
+
export declare function runPrototypeInject(argv: string[], options?: PrototypeInjectOptions): Promise<PrototypeInjectResult>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { mkdir, appendFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { AppFleetCryptoAuthError, decryptCredentialValue, unwrapWorkspaceVaultKeyWithMasterPassword, } from "@appfleet/crypto";
|
|
6
|
+
import { demoSecretFixture } from "./demo-fixture.js";
|
|
7
|
+
class PrototypeCliError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.name = "PrototypeCliError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const defaultAuditPath = resolve(".appfleet", "prototype-audit.jsonl");
|
|
16
|
+
export function parseInjectCommand(argv) {
|
|
17
|
+
if (argv[0] !== "secrets" || argv[1] !== "inject") {
|
|
18
|
+
throw new PrototypeCliError("UnsupportedCommand", "usage: secrets inject <project> --env <env> -- <command> [args...]");
|
|
19
|
+
}
|
|
20
|
+
const project = argv[2];
|
|
21
|
+
const envFlagIndex = argv.indexOf("--env");
|
|
22
|
+
const separatorIndex = argv.indexOf("--");
|
|
23
|
+
if (!project || envFlagIndex === -1 || separatorIndex === -1) {
|
|
24
|
+
throw new PrototypeCliError("InvalidArguments", "usage: secrets inject <project> --env <env> -- <command> [args...]");
|
|
25
|
+
}
|
|
26
|
+
if (envFlagIndex + 1 >= separatorIndex) {
|
|
27
|
+
throw new PrototypeCliError("MissingEnvironment", "--env requires a value");
|
|
28
|
+
}
|
|
29
|
+
const environment = argv[envFlagIndex + 1];
|
|
30
|
+
const command = argv[separatorIndex + 1];
|
|
31
|
+
const args = argv.slice(separatorIndex + 2);
|
|
32
|
+
if (!environment || !command) {
|
|
33
|
+
throw new PrototypeCliError("MissingChildCommand", "-- must be followed by a child command");
|
|
34
|
+
}
|
|
35
|
+
return { project, environment, command, args };
|
|
36
|
+
}
|
|
37
|
+
export async function runPrototypeInject(argv, options = {}) {
|
|
38
|
+
const fixture = options.fixture ?? demoSecretFixture;
|
|
39
|
+
const auditPath = options.auditPath ?? defaultAuditPath;
|
|
40
|
+
let parsed;
|
|
41
|
+
try {
|
|
42
|
+
parsed = parseInjectCommand(argv);
|
|
43
|
+
assertFixtureMatchesRequest(parsed, fixture);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return commandError(error);
|
|
47
|
+
}
|
|
48
|
+
let secret;
|
|
49
|
+
try {
|
|
50
|
+
const workspaceVaultKey = await unwrapWorkspaceVaultKeyWithMasterPassword({
|
|
51
|
+
envelope: fixture.keyWrapperEnvelope,
|
|
52
|
+
masterPassword: fixture.masterPassword,
|
|
53
|
+
});
|
|
54
|
+
secret = await decryptCredentialValue({
|
|
55
|
+
envelope: fixture.credentialEnvelope,
|
|
56
|
+
workspaceVaultKey,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
return commandError(error, "DecryptFailed");
|
|
61
|
+
}
|
|
62
|
+
const auditEvent = createAuditEvent(parsed, fixture.alias);
|
|
63
|
+
try {
|
|
64
|
+
await writeAuditEvent(auditPath, auditEvent);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return {
|
|
68
|
+
exitCode: 1,
|
|
69
|
+
stdout: "",
|
|
70
|
+
stderr: "AppFleet prototype inject failed: AuditWriteFailed\n",
|
|
71
|
+
childStarted: false,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
let child;
|
|
75
|
+
try {
|
|
76
|
+
child = await runChildProcess(parsed.command, parsed.args, {
|
|
77
|
+
...process.env,
|
|
78
|
+
[fixture.alias]: secret,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return {
|
|
83
|
+
exitCode: 1,
|
|
84
|
+
stdout: redactSecret(`AppFleet prototype inject: project=${parsed.project} env=${parsed.environment} alias=${fixture.alias} auditId=${auditEvent.id}\nAppFleet prototype inject failed: ChildSpawnFailed\n`, secret),
|
|
85
|
+
stderr: "",
|
|
86
|
+
childStarted: false,
|
|
87
|
+
auditId: auditEvent.id,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const stdout = redactSecret([
|
|
91
|
+
`AppFleet prototype inject: project=${parsed.project} env=${parsed.environment} alias=${fixture.alias} auditId=${auditEvent.id}`,
|
|
92
|
+
child.stdout.trimEnd(),
|
|
93
|
+
`AppFleet prototype inject: childExitCode=${child.exitCode}`,
|
|
94
|
+
]
|
|
95
|
+
.filter(Boolean)
|
|
96
|
+
.join("\n") + "\n", secret);
|
|
97
|
+
const stderr = redactSecret(child.stderr, secret);
|
|
98
|
+
return {
|
|
99
|
+
exitCode: child.exitCode,
|
|
100
|
+
stdout,
|
|
101
|
+
stderr,
|
|
102
|
+
childStarted: true,
|
|
103
|
+
auditId: auditEvent.id,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function runChildProcess(command, args, env) {
|
|
107
|
+
return await new Promise((resolvePromise, reject) => {
|
|
108
|
+
const child = spawn(command, args, {
|
|
109
|
+
env,
|
|
110
|
+
shell: false,
|
|
111
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
+
});
|
|
113
|
+
const stdoutChunks = [];
|
|
114
|
+
const stderrChunks = [];
|
|
115
|
+
child.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
116
|
+
child.stderr.on("data", (chunk) => stderrChunks.push(chunk));
|
|
117
|
+
child.on("error", reject);
|
|
118
|
+
child.on("close", (code) => {
|
|
119
|
+
resolvePromise({
|
|
120
|
+
exitCode: code ?? 1,
|
|
121
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
122
|
+
stderr: Buffer.concat(stderrChunks).toString("utf8"),
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function createAuditEvent(parsed, alias) {
|
|
128
|
+
return {
|
|
129
|
+
id: randomUUID(),
|
|
130
|
+
action: "secret_injection_attempted",
|
|
131
|
+
project: parsed.project,
|
|
132
|
+
environment: parsed.environment,
|
|
133
|
+
alias,
|
|
134
|
+
createdAt: new Date().toISOString(),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async function writeAuditEvent(path, event) {
|
|
138
|
+
await mkdir(dirname(path), { recursive: true });
|
|
139
|
+
await appendFile(path, `${JSON.stringify(event)}\n`, { mode: 0o600 });
|
|
140
|
+
}
|
|
141
|
+
function assertFixtureMatchesRequest(parsed, fixture) {
|
|
142
|
+
if (parsed.project !== fixture.project || parsed.environment !== fixture.environment) {
|
|
143
|
+
throw new PrototypeCliError("FixtureNotFound", "no prototype fixture for requested project/environment");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function redactSecret(value, secret) {
|
|
147
|
+
return secret ? value.split(secret).join("[REDACTED_SECRET]") : value;
|
|
148
|
+
}
|
|
149
|
+
function commandError(error, fallbackCode) {
|
|
150
|
+
const code = fallbackCode ??
|
|
151
|
+
(error instanceof PrototypeCliError
|
|
152
|
+
? error.code
|
|
153
|
+
: error instanceof AppFleetCryptoAuthError
|
|
154
|
+
? "DecryptFailed"
|
|
155
|
+
: "PrototypeInjectFailed");
|
|
156
|
+
return {
|
|
157
|
+
exitCode: 1,
|
|
158
|
+
stdout: "",
|
|
159
|
+
stderr: `AppFleet prototype inject failed: ${code}\n`,
|
|
160
|
+
childStarted: false,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
164
|
+
const result = await runPrototypeInject(process.argv.slice(2), {
|
|
165
|
+
auditPath: process.env.APPFLEET_AUDIT_PATH,
|
|
166
|
+
});
|
|
167
|
+
process.stdout.write(result.stdout);
|
|
168
|
+
process.stderr.write(result.stderr);
|
|
169
|
+
process.exitCode = result.exitCode;
|
|
170
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { createGitHubAppInventoryImportContract, createProviderCatalog, createProviderConnectionStatus, createProviderConnectorBoundaries, createProviderDiscoveryContract, createProviderSyncRun, } from "@appfleet/domain";
|
|
2
|
+
export function runProviderIntegrationCommand(argv, options = {}) {
|
|
3
|
+
const now = options.now ?? (() => new Date());
|
|
4
|
+
let parsed;
|
|
5
|
+
try {
|
|
6
|
+
parsed = parseProviderCommand(argv);
|
|
7
|
+
}
|
|
8
|
+
catch (error) {
|
|
9
|
+
return {
|
|
10
|
+
exitCode: 1,
|
|
11
|
+
stdout: "",
|
|
12
|
+
stderr: `AppFleet provider integrations failed: ${errorMessage(error)}\n`,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const checkedAt = now().toISOString();
|
|
17
|
+
if (parsed.action === "catalog") {
|
|
18
|
+
const catalog = createProviderCatalog();
|
|
19
|
+
const result = {
|
|
20
|
+
type: "provider_catalog_report",
|
|
21
|
+
version: 1,
|
|
22
|
+
workspaceId: parsed.workspaceId,
|
|
23
|
+
providers: catalog,
|
|
24
|
+
boundaries: createProviderConnectorBoundaries(catalog),
|
|
25
|
+
providerApiCallsMade: false,
|
|
26
|
+
acceptsPlaintextSecrets: false,
|
|
27
|
+
includesCredentialValues: false,
|
|
28
|
+
includesProviderPayload: false,
|
|
29
|
+
};
|
|
30
|
+
return ok(parsed.outputFormat, result, formatProviderCatalog(result));
|
|
31
|
+
}
|
|
32
|
+
if (parsed.action === "status") {
|
|
33
|
+
const result = createProviderConnectionStatus({
|
|
34
|
+
workspaceId: parsed.workspaceId,
|
|
35
|
+
providerId: parsed.providerId,
|
|
36
|
+
checkedAt,
|
|
37
|
+
});
|
|
38
|
+
return ok(parsed.outputFormat, result, formatProviderStatus(result));
|
|
39
|
+
}
|
|
40
|
+
if (parsed.action === "sync") {
|
|
41
|
+
const result = createProviderSyncRun({
|
|
42
|
+
id: `provider_sync_${parsed.providerId}_${checkedAt.replace(/[^0-9]/g, "")}`,
|
|
43
|
+
workspaceId: parsed.workspaceId,
|
|
44
|
+
providerId: parsed.providerId,
|
|
45
|
+
startedAt: checkedAt,
|
|
46
|
+
completedAt: checkedAt,
|
|
47
|
+
});
|
|
48
|
+
return ok(parsed.outputFormat, result, formatProviderSync(result));
|
|
49
|
+
}
|
|
50
|
+
if (parsed.action === "discover") {
|
|
51
|
+
const result = createProviderDiscoveryContract({
|
|
52
|
+
workspaceId: parsed.workspaceId,
|
|
53
|
+
providerId: parsed.providerId,
|
|
54
|
+
surface: parsed.surface,
|
|
55
|
+
});
|
|
56
|
+
return ok(parsed.outputFormat, result, formatProviderDiscovery(result));
|
|
57
|
+
}
|
|
58
|
+
const result = createGitHubAppInventoryImportContract({
|
|
59
|
+
workspaceId: parsed.workspaceId,
|
|
60
|
+
repositories: parsed.repositories,
|
|
61
|
+
});
|
|
62
|
+
return ok(parsed.outputFormat, result, formatGitHubInventoryImport(result));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return {
|
|
66
|
+
exitCode: 1,
|
|
67
|
+
stdout: "",
|
|
68
|
+
stderr: `AppFleet provider integrations failed: ${errorMessage(error)}\n`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function parseProviderCommand(argv) {
|
|
73
|
+
const normalizedArgv = argv[0] === "--" ? argv.slice(1) : argv;
|
|
74
|
+
if (normalizedArgv[0] !== "providers") {
|
|
75
|
+
throw new Error("usage: providers <catalog|status|sync|discover|github inventory-import> [arguments]");
|
|
76
|
+
}
|
|
77
|
+
const outputFormat = hasFlag(normalizedArgv, "--json") ? "json" : "human";
|
|
78
|
+
const workspaceId = readFlag(normalizedArgv, "--workspace") ?? "workspace_local";
|
|
79
|
+
const action = normalizedArgv[1];
|
|
80
|
+
if (action === "catalog") {
|
|
81
|
+
return { action, workspaceId, outputFormat };
|
|
82
|
+
}
|
|
83
|
+
if (action === "status" || action === "sync") {
|
|
84
|
+
const providerId = parseProviderId(normalizedArgv[2]);
|
|
85
|
+
return { action, workspaceId, providerId, outputFormat };
|
|
86
|
+
}
|
|
87
|
+
if (action === "discover") {
|
|
88
|
+
const providerId = parseProviderId(normalizedArgv[2]);
|
|
89
|
+
const surface = parseDiscoverySurface(readFlag(normalizedArgv, "--surface") ?? "projects");
|
|
90
|
+
return { action, workspaceId, providerId, surface, outputFormat };
|
|
91
|
+
}
|
|
92
|
+
if (action === "github" && normalizedArgv[2] === "inventory-import") {
|
|
93
|
+
return {
|
|
94
|
+
action: "github-inventory-import",
|
|
95
|
+
workspaceId,
|
|
96
|
+
repositories: readRepeatedFlag(normalizedArgv, "--repo").map(parseGitHubRepository),
|
|
97
|
+
outputFormat,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
throw new Error("usage: providers <catalog|status|sync|discover|github inventory-import> [arguments]");
|
|
101
|
+
}
|
|
102
|
+
function parseProviderId(value) {
|
|
103
|
+
const providerIds = createProviderCatalog().map((provider) => provider.providerId);
|
|
104
|
+
if (providerIds.includes(value)) {
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
throw new Error(`unknown provider "${value ?? ""}"`);
|
|
108
|
+
}
|
|
109
|
+
function parseDiscoverySurface(value) {
|
|
110
|
+
if (value === "projects" ||
|
|
111
|
+
value === "environments" ||
|
|
112
|
+
value === "credential_locations") {
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`unsupported provider discovery surface "${value}"`);
|
|
116
|
+
}
|
|
117
|
+
function parseGitHubRepository(input) {
|
|
118
|
+
const [owner, name] = input.split("/", 2);
|
|
119
|
+
if (!owner || !name) {
|
|
120
|
+
throw new Error("--repo must use owner/name metadata");
|
|
121
|
+
}
|
|
122
|
+
return { owner, name, installationKnown: true };
|
|
123
|
+
}
|
|
124
|
+
function ok(outputFormat, value, human) {
|
|
125
|
+
return {
|
|
126
|
+
exitCode: 0,
|
|
127
|
+
stdout: outputFormat === "json" ? `${JSON.stringify(value, null, 2)}\n` : human,
|
|
128
|
+
stderr: "",
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function formatProviderCatalog(result) {
|
|
132
|
+
return ([
|
|
133
|
+
"AppFleet provider integration catalog.",
|
|
134
|
+
`providers=${result.providers.map((provider) => provider.providerId).join(", ")}`,
|
|
135
|
+
"providerApiCallsMade=false",
|
|
136
|
+
"credentialValuesStored=false",
|
|
137
|
+
"sync=blocked_missing_credentials",
|
|
138
|
+
].join("\n") + "\n");
|
|
139
|
+
}
|
|
140
|
+
function formatProviderStatus(result) {
|
|
141
|
+
return ([
|
|
142
|
+
`AppFleet provider status: ${result.providerId}`,
|
|
143
|
+
`workspace=${result.workspaceId}`,
|
|
144
|
+
`status=${result.status}`,
|
|
145
|
+
`canSync=${result.canSync}`,
|
|
146
|
+
"providerApiCallsMade=false",
|
|
147
|
+
].join("\n") + "\n");
|
|
148
|
+
}
|
|
149
|
+
function formatProviderSync(result) {
|
|
150
|
+
return ([
|
|
151
|
+
`AppFleet provider sync: ${result.providerId}`,
|
|
152
|
+
`status=${result.status}`,
|
|
153
|
+
`recordsImported=${result.recordsImported}`,
|
|
154
|
+
"providerApiCallsMade=false",
|
|
155
|
+
].join("\n") + "\n");
|
|
156
|
+
}
|
|
157
|
+
function formatProviderDiscovery(result) {
|
|
158
|
+
return ([
|
|
159
|
+
`AppFleet provider discovery: ${result.providerId}`,
|
|
160
|
+
`surface=${result.surface}`,
|
|
161
|
+
`status=${result.status}`,
|
|
162
|
+
`discoveredCount=${result.discoveredCount}`,
|
|
163
|
+
"providerApiCallsMade=false",
|
|
164
|
+
].join("\n") + "\n");
|
|
165
|
+
}
|
|
166
|
+
function formatGitHubInventoryImport(result) {
|
|
167
|
+
return ([
|
|
168
|
+
"AppFleet GitHub app inventory import contract.",
|
|
169
|
+
`repositories=${result.repositories.map((repo) => repo.fullName).join(", ") || "none"}`,
|
|
170
|
+
`importedProjectIds=${result.importedProjectIds.join(", ") || "none"}`,
|
|
171
|
+
"providerApiCallsMade=false",
|
|
172
|
+
"persisted=false",
|
|
173
|
+
].join("\n") + "\n");
|
|
174
|
+
}
|
|
175
|
+
function readFlag(argv, flag) {
|
|
176
|
+
const index = argv.indexOf(flag);
|
|
177
|
+
if (index === -1) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
return argv[index + 1];
|
|
181
|
+
}
|
|
182
|
+
function readRepeatedFlag(argv, flag) {
|
|
183
|
+
const values = [];
|
|
184
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
185
|
+
if (argv[index] === flag && argv[index + 1]) {
|
|
186
|
+
values.push(argv[index + 1]);
|
|
187
|
+
index += 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return values;
|
|
191
|
+
}
|
|
192
|
+
function hasFlag(argv, flag) {
|
|
193
|
+
return argv.includes(flag);
|
|
194
|
+
}
|
|
195
|
+
function errorMessage(error) {
|
|
196
|
+
return error instanceof Error ? error.message : String(error);
|
|
197
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@appfleet-cli/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"appfleet": "dist/appfleet.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./dist/appfleet.js",
|
|
11
|
+
"./package": "./dist/appfleet.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md",
|
|
16
|
+
"package.json"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"appfleet": "node src/appfleet.ts",
|
|
23
|
+
"auth": "node src/appfleet.ts auth",
|
|
24
|
+
"cloud": "node src/appfleet.ts cloud",
|
|
25
|
+
"projects": "node src/appfleet.ts",
|
|
26
|
+
"vault": "node src/appfleet.ts",
|
|
27
|
+
"secrets": "node src/appfleet.ts",
|
|
28
|
+
"docs:generate": "node src/generate-cli-docs.ts",
|
|
29
|
+
"docs:check": "node src/generate-cli-docs.ts --check",
|
|
30
|
+
"prototype:inject": "node src/prototype-inject.ts secrets inject demo-project --env dev -- node -e \"console.log(process.env.APPFLEET_DEMO_SECRET ? 'secret_present=true' : 'secret_present=false')\"",
|
|
31
|
+
"build": "tsc -p tsconfig.build.json && esbuild src/appfleet.ts --bundle --platform=node --format=esm --outfile=dist/appfleet.js",
|
|
32
|
+
"pack:dry-run": "pnpm build && pnpm pack --dry-run",
|
|
33
|
+
"test": "node --test test/*.test.ts",
|
|
34
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"libsodium-wrappers-sumo": "^0.7.15"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@appfleet/crypto": "workspace:*",
|
|
41
|
+
"@appfleet/domain": "workspace:*",
|
|
42
|
+
"commander": "^15.0.0",
|
|
43
|
+
"esbuild": "^0.28.1"
|
|
44
|
+
}
|
|
45
|
+
}
|