@getjack/jack 0.1.2 → 0.1.3
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/package.json +54 -47
- package/src/commands/agents.ts +145 -10
- package/src/commands/down.ts +110 -102
- package/src/commands/feedback.ts +189 -0
- package/src/commands/init.ts +8 -12
- package/src/commands/login.ts +88 -0
- package/src/commands/logout.ts +14 -0
- package/src/commands/logs.ts +21 -0
- package/src/commands/mcp.ts +134 -7
- package/src/commands/new.ts +43 -17
- package/src/commands/open.ts +13 -6
- package/src/commands/projects.ts +269 -143
- package/src/commands/secrets.ts +413 -0
- package/src/commands/services.ts +96 -123
- package/src/commands/ship.ts +5 -1
- package/src/commands/whoami.ts +31 -0
- package/src/index.ts +218 -144
- package/src/lib/agent-files.ts +34 -0
- package/src/lib/agents.ts +390 -22
- package/src/lib/asset-hash.ts +50 -0
- package/src/lib/auth/client.ts +115 -0
- package/src/lib/auth/constants.ts +5 -0
- package/src/lib/auth/guard.ts +57 -0
- package/src/lib/auth/index.ts +18 -0
- package/src/lib/auth/store.ts +54 -0
- package/src/lib/binding-validator.ts +136 -0
- package/src/lib/build-helper.ts +211 -0
- package/src/lib/cloudflare-api.ts +24 -0
- package/src/lib/config.ts +5 -6
- package/src/lib/control-plane.ts +295 -0
- package/src/lib/debug.ts +3 -1
- package/src/lib/deploy-mode.ts +93 -0
- package/src/lib/deploy-upload.ts +92 -0
- package/src/lib/errors.ts +2 -0
- package/src/lib/github.ts +31 -1
- package/src/lib/hooks.ts +4 -12
- package/src/lib/intent.ts +88 -0
- package/src/lib/jsonc.ts +125 -0
- package/src/lib/local-paths.test.ts +902 -0
- package/src/lib/local-paths.ts +258 -0
- package/src/lib/managed-deploy.ts +175 -0
- package/src/lib/managed-down.ts +159 -0
- package/src/lib/mcp-config.ts +55 -34
- package/src/lib/names.ts +9 -29
- package/src/lib/project-operations.ts +676 -249
- package/src/lib/project-resolver.ts +476 -0
- package/src/lib/registry.ts +76 -37
- package/src/lib/resources.ts +196 -0
- package/src/lib/schema.ts +30 -1
- package/src/lib/storage/file-filter.ts +1 -0
- package/src/lib/storage/index.ts +5 -1
- package/src/lib/telemetry.ts +14 -0
- package/src/lib/tty.ts +15 -0
- package/src/lib/zip-packager.ts +255 -0
- package/src/mcp/resources/index.ts +8 -2
- package/src/mcp/server.ts +32 -4
- package/src/mcp/tools/index.ts +35 -13
- package/src/mcp/types.ts +6 -0
- package/src/mcp/utils.ts +1 -1
- package/src/templates/index.ts +42 -4
- package/src/templates/types.ts +13 -0
- package/templates/CLAUDE.md +166 -0
- package/templates/api/.jack.json +4 -0
- package/templates/api/bun.lock +1 -0
- package/templates/api/wrangler.jsonc +5 -0
- package/templates/hello/.jack.json +28 -0
- package/templates/hello/package.json +10 -0
- package/templates/hello/src/index.ts +11 -0
- package/templates/hello/tsconfig.json +11 -0
- package/templates/hello/wrangler.jsonc +5 -0
- package/templates/miniapp/.jack.json +15 -4
- package/templates/miniapp/bun.lock +135 -40
- package/templates/miniapp/index.html +1 -0
- package/templates/miniapp/package.json +3 -1
- package/templates/miniapp/public/.well-known/farcaster.json +7 -5
- package/templates/miniapp/public/icon.png +0 -0
- package/templates/miniapp/public/og.png +0 -0
- package/templates/miniapp/schema.sql +8 -0
- package/templates/miniapp/src/App.tsx +254 -3
- package/templates/miniapp/src/components/ShareSheet.tsx +147 -0
- package/templates/miniapp/src/hooks/useAI.ts +35 -0
- package/templates/miniapp/src/hooks/useGuestbook.ts +11 -1
- package/templates/miniapp/src/hooks/useShare.ts +76 -0
- package/templates/miniapp/src/index.css +15 -0
- package/templates/miniapp/src/lib/api.ts +2 -1
- package/templates/miniapp/src/worker.ts +515 -1
- package/templates/miniapp/wrangler.jsonc +15 -3
- package/LICENSE +0 -190
- package/README.md +0 -55
- package/src/commands/cloud.ts +0 -230
- package/templates/api/wrangler.toml +0 -3
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { getAuthApiUrl } from "./constants.ts";
|
|
2
|
+
export {
|
|
3
|
+
getValidAccessToken,
|
|
4
|
+
authFetch,
|
|
5
|
+
pollDeviceToken,
|
|
6
|
+
refreshToken,
|
|
7
|
+
startDeviceAuth,
|
|
8
|
+
} from "./client.ts";
|
|
9
|
+
export { requireAuth, requireAuthOrLogin, getCurrentUser } from "./guard.ts";
|
|
10
|
+
export {
|
|
11
|
+
deleteCredentials,
|
|
12
|
+
getCredentials,
|
|
13
|
+
isLoggedIn,
|
|
14
|
+
isTokenExpired,
|
|
15
|
+
saveCredentials,
|
|
16
|
+
type AuthCredentials,
|
|
17
|
+
type AuthUser,
|
|
18
|
+
} from "./store.ts";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { chmod } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { CONFIG_DIR } from "../config.ts";
|
|
5
|
+
|
|
6
|
+
export interface AuthUser {
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
first_name: string | null;
|
|
10
|
+
last_name: string | null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AuthCredentials {
|
|
14
|
+
access_token: string;
|
|
15
|
+
refresh_token: string;
|
|
16
|
+
expires_at: number; // Unix timestamp (seconds)
|
|
17
|
+
user: AuthUser;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const AUTH_PATH = join(CONFIG_DIR, "auth.json");
|
|
21
|
+
|
|
22
|
+
export async function getCredentials(): Promise<AuthCredentials | null> {
|
|
23
|
+
if (!existsSync(AUTH_PATH)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return await Bun.file(AUTH_PATH).json();
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function saveCredentials(creds: AuthCredentials): Promise<void> {
|
|
34
|
+
await Bun.write(AUTH_PATH, JSON.stringify(creds, null, 2));
|
|
35
|
+
await chmod(AUTH_PATH, 0o600);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function deleteCredentials(): Promise<void> {
|
|
39
|
+
if (existsSync(AUTH_PATH)) {
|
|
40
|
+
const { unlink } = await import("node:fs/promises");
|
|
41
|
+
await unlink(AUTH_PATH);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function isLoggedIn(): Promise<boolean> {
|
|
46
|
+
const creds = await getCredentials();
|
|
47
|
+
return creds !== null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isTokenExpired(creds: AuthCredentials): boolean {
|
|
51
|
+
const now = Math.floor(Date.now() / 1000);
|
|
52
|
+
const buffer = 5 * 60; // 5 minutes
|
|
53
|
+
return creds.expires_at < now + buffer;
|
|
54
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binding validator for jack cloud managed deployments.
|
|
3
|
+
*
|
|
4
|
+
* Validates that project bindings are supported by jack cloud and
|
|
5
|
+
* that required resources (like assets directories) exist.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import type { WranglerConfig } from "./build-helper.ts";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Bindings supported by jack cloud managed deployments.
|
|
14
|
+
*/
|
|
15
|
+
export const SUPPORTED_BINDINGS = ["d1_databases", "ai", "assets", "vars"] as const;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Bindings not yet supported by jack cloud.
|
|
19
|
+
* These will cause validation errors if present in wrangler config.
|
|
20
|
+
*/
|
|
21
|
+
export const UNSUPPORTED_BINDINGS = [
|
|
22
|
+
"kv_namespaces",
|
|
23
|
+
"durable_objects",
|
|
24
|
+
"queues",
|
|
25
|
+
"services",
|
|
26
|
+
"r2_buckets",
|
|
27
|
+
"hyperdrive",
|
|
28
|
+
"vectorize",
|
|
29
|
+
"browser",
|
|
30
|
+
"mtls_certificates",
|
|
31
|
+
] as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Human-readable names for unsupported bindings.
|
|
35
|
+
*/
|
|
36
|
+
const BINDING_DISPLAY_NAMES: Record<string, string> = {
|
|
37
|
+
kv_namespaces: "KV Namespaces",
|
|
38
|
+
durable_objects: "Durable Objects",
|
|
39
|
+
queues: "Queues",
|
|
40
|
+
services: "Service Bindings",
|
|
41
|
+
r2_buckets: "R2 Buckets",
|
|
42
|
+
hyperdrive: "Hyperdrive",
|
|
43
|
+
vectorize: "Vectorize",
|
|
44
|
+
browser: "Browser Rendering",
|
|
45
|
+
mtls_certificates: "mTLS Certificates",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface BindingValidationResult {
|
|
49
|
+
valid: boolean;
|
|
50
|
+
errors: string[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates that a wrangler config only uses supported bindings.
|
|
55
|
+
*
|
|
56
|
+
* @param config - Parsed wrangler configuration
|
|
57
|
+
* @param projectPath - Absolute path to project directory (for assets validation)
|
|
58
|
+
* @returns Validation result with errors if invalid
|
|
59
|
+
*/
|
|
60
|
+
export function validateBindings(
|
|
61
|
+
config: WranglerConfig,
|
|
62
|
+
projectPath: string,
|
|
63
|
+
): BindingValidationResult {
|
|
64
|
+
const errors: string[] = [];
|
|
65
|
+
|
|
66
|
+
// Check for unsupported bindings
|
|
67
|
+
for (const binding of UNSUPPORTED_BINDINGS) {
|
|
68
|
+
const value = config[binding as keyof WranglerConfig];
|
|
69
|
+
if (value !== undefined && value !== null) {
|
|
70
|
+
const displayName = BINDING_DISPLAY_NAMES[binding] || binding;
|
|
71
|
+
// Special message for R2 - suggest using Workers Assets instead
|
|
72
|
+
if (binding === "r2_buckets") {
|
|
73
|
+
errors.push(
|
|
74
|
+
`✗ R2 buckets not supported in managed deploy.\n For static files, use Workers Assets instead (assets.directory in wrangler.jsonc).\n Fix: Replace r2_buckets with assets config, or use 'wrangler deploy' for full control.`,
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
errors.push(
|
|
78
|
+
`✗ ${displayName} not supported in managed deploy.\n Managed deploy supports: D1, AI, Assets, vars.\n Fix: Remove ${binding} from wrangler.jsonc, or use 'wrangler deploy' for full control.`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Validate assets directory if configured
|
|
85
|
+
const assetsValidation = validateAssetsDirectory(config, projectPath);
|
|
86
|
+
if (!assetsValidation.valid) {
|
|
87
|
+
errors.push(...assetsValidation.errors);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
valid: errors.length === 0,
|
|
92
|
+
errors,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Validates that the assets directory exists and is not empty.
|
|
98
|
+
*
|
|
99
|
+
* @param config - Parsed wrangler configuration
|
|
100
|
+
* @param projectPath - Absolute path to project directory
|
|
101
|
+
* @returns Validation result with errors if invalid
|
|
102
|
+
*/
|
|
103
|
+
export function validateAssetsDirectory(
|
|
104
|
+
config: WranglerConfig,
|
|
105
|
+
projectPath: string,
|
|
106
|
+
): BindingValidationResult {
|
|
107
|
+
const errors: string[] = [];
|
|
108
|
+
|
|
109
|
+
if (config.assets?.directory) {
|
|
110
|
+
const assetsDir = config.assets.directory;
|
|
111
|
+
const assetsPath = join(projectPath, assetsDir);
|
|
112
|
+
|
|
113
|
+
if (!existsSync(assetsPath)) {
|
|
114
|
+
errors.push(
|
|
115
|
+
`✗ Assets directory not found: ${assetsDir}\n The assets.directory specified in wrangler.jsonc does not exist.\n Fix: Run your build command first, or update assets.directory in wrangler.jsonc.`,
|
|
116
|
+
);
|
|
117
|
+
} else {
|
|
118
|
+
// Check if directory is empty
|
|
119
|
+
try {
|
|
120
|
+
const files = readdirSync(assetsPath);
|
|
121
|
+
if (files.length === 0) {
|
|
122
|
+
errors.push(
|
|
123
|
+
`✗ Assets directory is empty: ${assetsDir}\n No files found in the assets directory.\n Fix: Run your build command to generate assets.`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
// If we can't read the directory, the deploy will fail anyway
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
valid: errors.length === 0,
|
|
134
|
+
errors,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, readdir } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { basename, join } from "node:path";
|
|
5
|
+
import { $ } from "bun";
|
|
6
|
+
import { JackError, JackErrorCode } from "./errors.ts";
|
|
7
|
+
import { parseJsonc } from "./jsonc.ts";
|
|
8
|
+
import type { OperationReporter } from "./project-operations.ts";
|
|
9
|
+
|
|
10
|
+
export interface BuildOutput {
|
|
11
|
+
outDir: string;
|
|
12
|
+
entrypoint: string;
|
|
13
|
+
assetsDir: string | null;
|
|
14
|
+
compatibilityDate: string;
|
|
15
|
+
compatibilityFlags: string[];
|
|
16
|
+
moduleFormat: "esm";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface BuildOptions {
|
|
20
|
+
projectPath: string;
|
|
21
|
+
reporter?: OperationReporter;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface WranglerConfig {
|
|
25
|
+
main?: string;
|
|
26
|
+
compatibility_date?: string;
|
|
27
|
+
compatibility_flags?: string[];
|
|
28
|
+
// Supported bindings
|
|
29
|
+
d1_databases?: Array<{ binding: string; database_name?: string; database_id?: string }>;
|
|
30
|
+
ai?: { binding?: string };
|
|
31
|
+
assets?: {
|
|
32
|
+
directory?: string;
|
|
33
|
+
binding?: string;
|
|
34
|
+
not_found_handling?: "single-page-application" | "404-page" | "none";
|
|
35
|
+
html_handling?: "auto-trailing-slash" | "force-trailing-slash" | "drop-trailing-slash" | "none";
|
|
36
|
+
run_worker_first?: boolean;
|
|
37
|
+
};
|
|
38
|
+
vars?: Record<string, string>;
|
|
39
|
+
// Unsupported bindings (for validation)
|
|
40
|
+
kv_namespaces?: unknown;
|
|
41
|
+
durable_objects?: unknown;
|
|
42
|
+
queues?: unknown;
|
|
43
|
+
services?: unknown;
|
|
44
|
+
r2_buckets?: unknown;
|
|
45
|
+
hyperdrive?: unknown;
|
|
46
|
+
vectorize?: unknown;
|
|
47
|
+
browser?: unknown;
|
|
48
|
+
mtls_certificates?: unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Parses wrangler.jsonc configuration from project directory
|
|
53
|
+
* @param projectPath - Absolute path to project directory
|
|
54
|
+
* @returns Parsed wrangler configuration
|
|
55
|
+
*/
|
|
56
|
+
export async function parseWranglerConfig(projectPath: string): Promise<WranglerConfig> {
|
|
57
|
+
const wranglerPath = join(projectPath, "wrangler.jsonc");
|
|
58
|
+
|
|
59
|
+
if (!existsSync(wranglerPath)) {
|
|
60
|
+
throw new JackError(
|
|
61
|
+
JackErrorCode.VALIDATION_ERROR,
|
|
62
|
+
"wrangler.jsonc not found",
|
|
63
|
+
"Ensure your project has a wrangler.jsonc configuration file",
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const content = await readFile(wranglerPath, "utf-8");
|
|
68
|
+
return parseJsonc<WranglerConfig>(content);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Checks if project requires Vite build by detecting vite config files
|
|
73
|
+
* @param projectPath - Absolute path to project directory
|
|
74
|
+
* @returns true if vite.config.ts or vite.config.js exists
|
|
75
|
+
*/
|
|
76
|
+
export async function needsViteBuild(projectPath: string): Promise<boolean> {
|
|
77
|
+
return (
|
|
78
|
+
existsSync(join(projectPath, "vite.config.ts")) ||
|
|
79
|
+
existsSync(join(projectPath, "vite.config.js")) ||
|
|
80
|
+
existsSync(join(projectPath, "vite.config.mjs")) ||
|
|
81
|
+
existsSync(join(projectPath, "vite.config.mts"))
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Runs Vite build for the project
|
|
87
|
+
* @param projectPath - Absolute path to project directory
|
|
88
|
+
* @throws JackError if build fails
|
|
89
|
+
*/
|
|
90
|
+
export async function runViteBuild(projectPath: string): Promise<void> {
|
|
91
|
+
// Jack controls the build for managed projects (omakase)
|
|
92
|
+
// Users wanting tsc can run `bun run build` manually before shipping
|
|
93
|
+
const buildResult = await $`bunx vite build`.cwd(projectPath).nothrow().quiet();
|
|
94
|
+
|
|
95
|
+
if (buildResult.exitCode !== 0) {
|
|
96
|
+
throw new JackError(
|
|
97
|
+
JackErrorCode.BUILD_FAILED,
|
|
98
|
+
"Vite build failed",
|
|
99
|
+
"Check your vite.config and source files for errors",
|
|
100
|
+
{
|
|
101
|
+
exitCode: buildResult.exitCode,
|
|
102
|
+
stderr: buildResult.stderr.toString(),
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Builds a Cloudflare Worker project using wrangler dry-run
|
|
110
|
+
* @param options - Build options with project path and optional reporter
|
|
111
|
+
* @returns BuildOutput containing build artifacts and metadata
|
|
112
|
+
* @throws JackError if build fails
|
|
113
|
+
*/
|
|
114
|
+
export async function buildProject(options: BuildOptions): Promise<BuildOutput> {
|
|
115
|
+
const { projectPath, reporter } = options;
|
|
116
|
+
|
|
117
|
+
// Parse wrangler config first
|
|
118
|
+
const config = await parseWranglerConfig(projectPath);
|
|
119
|
+
|
|
120
|
+
// Check if Vite build is needed and run it
|
|
121
|
+
const hasVite = await needsViteBuild(projectPath);
|
|
122
|
+
if (hasVite) {
|
|
123
|
+
reporter?.start("Building with Vite...");
|
|
124
|
+
await runViteBuild(projectPath);
|
|
125
|
+
reporter?.stop();
|
|
126
|
+
reporter?.success("Built with Vite");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Create unique temp directory for build output
|
|
130
|
+
const buildId = `jack-build-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
131
|
+
const outDir = join(tmpdir(), buildId);
|
|
132
|
+
await mkdir(outDir, { recursive: true });
|
|
133
|
+
|
|
134
|
+
// Run wrangler dry-run to build without deploying
|
|
135
|
+
reporter?.start("Building worker...");
|
|
136
|
+
|
|
137
|
+
const dryRunResult = await $`wrangler deploy --dry-run --outdir=${outDir}`
|
|
138
|
+
.cwd(projectPath)
|
|
139
|
+
.nothrow()
|
|
140
|
+
.quiet();
|
|
141
|
+
|
|
142
|
+
if (dryRunResult.exitCode !== 0) {
|
|
143
|
+
reporter?.stop();
|
|
144
|
+
reporter?.error("Worker build failed");
|
|
145
|
+
throw new JackError(
|
|
146
|
+
JackErrorCode.BUILD_FAILED,
|
|
147
|
+
"Worker build failed",
|
|
148
|
+
"Check your wrangler.jsonc and worker code for errors",
|
|
149
|
+
{
|
|
150
|
+
exitCode: dryRunResult.exitCode,
|
|
151
|
+
stderr: dryRunResult.stderr.toString(),
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
reporter?.stop();
|
|
157
|
+
reporter?.success("Built worker");
|
|
158
|
+
|
|
159
|
+
const entrypoint = await resolveEntrypoint(outDir, config.main);
|
|
160
|
+
|
|
161
|
+
// Determine assets directory if configured
|
|
162
|
+
let assetsDir: string | null = null;
|
|
163
|
+
if (config.assets) {
|
|
164
|
+
// Default to "dist" if assets binding exists but directory not specified (Vite convention)
|
|
165
|
+
const directory = config.assets.directory || "dist";
|
|
166
|
+
const assetsDirPath = join(projectPath, directory);
|
|
167
|
+
if (existsSync(assetsDirPath)) {
|
|
168
|
+
assetsDir = assetsDirPath;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
outDir,
|
|
174
|
+
entrypoint,
|
|
175
|
+
assetsDir,
|
|
176
|
+
compatibilityDate: config.compatibility_date || "2024-01-01",
|
|
177
|
+
compatibilityFlags: config.compatibility_flags || [],
|
|
178
|
+
moduleFormat: "esm",
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async function resolveEntrypoint(outDir: string, main?: string): Promise<string> {
|
|
183
|
+
const candidates: string[] = [];
|
|
184
|
+
|
|
185
|
+
if (main) {
|
|
186
|
+
const base = basename(main).replace(/\.[^.]+$/, "");
|
|
187
|
+
if (base) {
|
|
188
|
+
candidates.push(`${base}.js`, `${base}.mjs`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
candidates.push("index.js", "worker.js");
|
|
193
|
+
|
|
194
|
+
for (const candidate of candidates) {
|
|
195
|
+
if (existsSync(join(outDir, candidate))) {
|
|
196
|
+
return candidate;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const files = await readdir(outDir);
|
|
201
|
+
const jsFiles = files.filter((file) => file.endsWith(".js"));
|
|
202
|
+
if (jsFiles.length === 1) {
|
|
203
|
+
return jsFiles[0] as string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
throw new JackError(
|
|
207
|
+
JackErrorCode.BUILD_FAILED,
|
|
208
|
+
"Could not determine build entrypoint",
|
|
209
|
+
"Ensure wrangler outputs a single entry file (index.js or worker.js)",
|
|
210
|
+
);
|
|
211
|
+
}
|
|
@@ -64,6 +64,30 @@ export async function deleteDatabase(dbName: string): Promise<void> {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* List D1 databases for the current account
|
|
69
|
+
*/
|
|
70
|
+
export async function listD1Databases(): Promise<Array<{ name?: string; uuid?: string }>> {
|
|
71
|
+
const result = await $`wrangler d1 list --json`.nothrow().quiet();
|
|
72
|
+
|
|
73
|
+
if (result.exitCode !== 0) {
|
|
74
|
+
const stderr = result.stderr.toString().trim();
|
|
75
|
+
throw new Error(stderr || "Failed to list D1 databases");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const output = result.stdout.toString().trim();
|
|
80
|
+
const parsed = JSON.parse(output);
|
|
81
|
+
if (Array.isArray(parsed)) return parsed;
|
|
82
|
+
if (Array.isArray(parsed?.result)) return parsed.result;
|
|
83
|
+
if (Array.isArray(parsed?.databases)) return parsed.databases;
|
|
84
|
+
} catch {
|
|
85
|
+
// Fall through to empty list
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
|
|
67
91
|
/**
|
|
68
92
|
* List all workers for the current account
|
|
69
93
|
* Parses the output of `wrangler deployments list` to extract worker names
|
package/src/lib/config.ts
CHANGED
|
@@ -6,12 +6,11 @@ import { join } from "node:path";
|
|
|
6
6
|
/**
|
|
7
7
|
* Agent configuration stored in jack config
|
|
8
8
|
*/
|
|
9
|
-
export type AgentLaunchConfig =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
9
|
+
export type AgentLaunchConfig = {
|
|
10
|
+
type: "cli";
|
|
11
|
+
command: string;
|
|
12
|
+
args?: string[];
|
|
13
|
+
};
|
|
15
14
|
|
|
16
15
|
export interface AgentConfig {
|
|
17
16
|
active: boolean;
|