@cardelli/ambit 0.1.2 → 0.1.4
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/esm/deno.d.ts +52 -0
- package/esm/deno.d.ts.map +1 -0
- package/esm/deno.js +50 -0
- package/esm/deps/jsr.io/@std/cli/1.0.28/_data.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.js +17 -3
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts +2 -2
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.js +30 -20
- package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.js +1 -1
- package/esm/lib/result.d.ts +8 -0
- package/esm/lib/result.d.ts.map +1 -0
- package/esm/lib/result.js +1 -0
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +3 -2
- package/esm/src/cli/commands/create.js +1 -1
- package/esm/src/cli/commands/deploy.js +138 -23
- package/esm/src/cli/commands/destroy.js +224 -29
- package/esm/src/cli/commands/doctor.js +1 -1
- package/esm/src/cli/commands/list.js +1 -1
- package/esm/src/cli/commands/status.js +1 -1
- package/esm/src/cli/mod.d.ts.map +1 -1
- package/esm/src/cli/mod.js +6 -4
- package/esm/src/discovery.d.ts +10 -0
- package/esm/src/discovery.d.ts.map +1 -1
- package/esm/src/discovery.js +28 -0
- package/esm/src/template.d.ts +40 -0
- package/esm/src/template.d.ts.map +1 -0
- package/esm/src/template.js +167 -0
- package/package.json +2 -2
- package/esm/deps/jsr.io/@std/cli/1.0.27/_data.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts +0 -6
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.js +0 -18
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.js +0 -0
package/esm/src/discovery.d.ts
CHANGED
|
@@ -25,6 +25,16 @@ export interface RouterTailscaleInfo {
|
|
|
25
25
|
export declare const listRouterApps: (fly: FlyProvider, org: string) => Promise<RouterApp[]>;
|
|
26
26
|
/** Find the router app for a specific network. */
|
|
27
27
|
export declare const findRouterApp: (fly: FlyProvider, org: string, network: string) => Promise<RouterApp | null>;
|
|
28
|
+
/** A workload (non-router) app discovered from the Fly REST API. */
|
|
29
|
+
export interface WorkloadApp {
|
|
30
|
+
appName: string;
|
|
31
|
+
network: string;
|
|
32
|
+
org: string;
|
|
33
|
+
}
|
|
34
|
+
/** List all non-router apps on a specific custom network in an org. */
|
|
35
|
+
export declare const listWorkloadAppsOnNetwork: (fly: FlyProvider, org: string, network: string) => Promise<WorkloadApp[]>;
|
|
36
|
+
/** Find a specific workload app by name, optionally verifying network. */
|
|
37
|
+
export declare const findWorkloadApp: (fly: FlyProvider, org: string, appName: string, network?: string) => Promise<WorkloadApp | null>;
|
|
28
38
|
/** Get machine info for a router app. Returns null if no machines exist. */
|
|
29
39
|
export declare const getRouterMachineInfo: (fly: FlyProvider, appName: string) => Promise<RouterMachineInfo | null>;
|
|
30
40
|
/** Get tailscale device info for a router. Returns null if not found. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/src/discovery.ts"],"names":[],"mappings":"AAcA,OAAO,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAaD,wDAAwD;AACxD,eAAO,MAAM,cAAc,GACzB,KAAK,WAAW,EAChB,KAAK,MAAM,KACV,OAAO,CAAC,SAAS,EAAE,CAcrB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,SAAS,MAAM,KACd,OAAO,CAAC,SAAS,GAAG,IAAI,CAG1B,CAAC;AAMF,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,GAC/B,KAAK,WAAW,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAclC,CAAC;AAMF,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,GACjC,WAAW,iBAAiB,EAC5B,SAAS,MAAM,KACd,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAcpC,CAAC"}
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/src/discovery.ts"],"names":[],"mappings":"AAcA,OAAO,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAOlE,qDAAqD;AACrD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,2CAA2C;AAC3C,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAaD,wDAAwD;AACxD,eAAO,MAAM,cAAc,GACzB,KAAK,WAAW,EAChB,KAAK,MAAM,KACV,OAAO,CAAC,SAAS,EAAE,CAcrB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,SAAS,MAAM,KACd,OAAO,CAAC,SAAS,GAAG,IAAI,CAG1B,CAAC;AAMF,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,GACpC,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,SAAS,MAAM,KACd,OAAO,CAAC,WAAW,EAAE,CAcvB,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,eAAe,GAC1B,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,SAAS,MAAM,EACf,UAAU,MAAM,KACf,OAAO,CAAC,WAAW,GAAG,IAAI,CAmB5B,CAAC;AAMF,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,GAC/B,KAAK,WAAW,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAclC,CAAC;AAMF,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,GACjC,WAAW,iBAAiB,EAC5B,SAAS,MAAM,KACd,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAcpC,CAAC"}
|
package/esm/src/discovery.js
CHANGED
|
@@ -39,6 +39,34 @@ export const findRouterApp = async (fly, org, network) => {
|
|
|
39
39
|
const apps = await listRouterApps(fly, org);
|
|
40
40
|
return apps.find((a) => a.network === network) ?? null;
|
|
41
41
|
};
|
|
42
|
+
/** List all non-router apps on a specific custom network in an org. */
|
|
43
|
+
export const listWorkloadAppsOnNetwork = async (fly, org, network) => {
|
|
44
|
+
const apps = await fly.listAppsWithNetwork(org);
|
|
45
|
+
return apps
|
|
46
|
+
.filter((app) => !app.name.startsWith(ROUTER_APP_PREFIX) &&
|
|
47
|
+
app.network === network)
|
|
48
|
+
.map((app) => ({
|
|
49
|
+
appName: app.name,
|
|
50
|
+
network: app.network,
|
|
51
|
+
org: app.organization?.slug ?? org,
|
|
52
|
+
}));
|
|
53
|
+
};
|
|
54
|
+
/** Find a specific workload app by name, optionally verifying network. */
|
|
55
|
+
export const findWorkloadApp = async (fly, org, appName, network) => {
|
|
56
|
+
const apps = await fly.listAppsWithNetwork(org);
|
|
57
|
+
const workloads = apps
|
|
58
|
+
.filter((app) => !app.name.startsWith(ROUTER_APP_PREFIX) &&
|
|
59
|
+
app.network !== DEFAULT_NETWORK)
|
|
60
|
+
.map((app) => ({
|
|
61
|
+
appName: app.name,
|
|
62
|
+
network: app.network,
|
|
63
|
+
org: app.organization?.slug ?? org,
|
|
64
|
+
}));
|
|
65
|
+
if (network) {
|
|
66
|
+
return workloads.find((a) => a.appName === appName && a.network === network) ?? null;
|
|
67
|
+
}
|
|
68
|
+
return workloads.find((a) => a.appName === appName) ?? null;
|
|
69
|
+
};
|
|
42
70
|
// =============================================================================
|
|
43
71
|
// 2. What's the machine state? (Fly Machines API)
|
|
44
72
|
// =============================================================================
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Result } from "../lib/result.js";
|
|
2
|
+
/** Kinds of errors that can occur when fetching a template from GitHub. */
|
|
3
|
+
export type TemplateErrorKind = "NotFound" | "RateLimited" | "HttpError" | "ExtractionFailed" | "PathNotFound" | "PathNotDirectory" | "EmptyArchive" | "NetworkError";
|
|
4
|
+
/** Parsed GitHub template reference. */
|
|
5
|
+
export interface TemplateRef {
|
|
6
|
+
owner: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
path: string;
|
|
9
|
+
ref: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
/** Result of fetching a template from GitHub. */
|
|
12
|
+
export type TemplateFetchResult = Result<{
|
|
13
|
+
tempDir: string;
|
|
14
|
+
templateDir: string;
|
|
15
|
+
}, TemplateErrorKind>;
|
|
16
|
+
/**
|
|
17
|
+
* Parse a template reference string into its components.
|
|
18
|
+
* Returns null if the format is invalid.
|
|
19
|
+
*
|
|
20
|
+
* Format: owner/repo[/path][@ref]
|
|
21
|
+
*
|
|
22
|
+
* The first two segments are always owner/repo. Everything after the second
|
|
23
|
+
* slash up to an optional @ref is the path within the repository. When no
|
|
24
|
+
* path is provided, the repository root is used as the template directory.
|
|
25
|
+
* This is unambiguous because GitHub owner and repo names cannot contain
|
|
26
|
+
* slashes.
|
|
27
|
+
*/
|
|
28
|
+
export declare const parseTemplateRef: (raw: string) => TemplateRef | null;
|
|
29
|
+
/**
|
|
30
|
+
* Download a template from GitHub and extract the target subdirectory
|
|
31
|
+
* to a temp directory.
|
|
32
|
+
*
|
|
33
|
+
* On success, returns the temp dir (for cleanup) and the path to the
|
|
34
|
+
* extracted template directory. The caller is responsible for removing
|
|
35
|
+
* tempDir when done.
|
|
36
|
+
*
|
|
37
|
+
* On failure, cleans up the temp dir and returns a typed error.
|
|
38
|
+
*/
|
|
39
|
+
export declare const fetchTemplate: (ref: TemplateRef) => Promise<TemplateFetchResult>;
|
|
40
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/src/template.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM/C,2EAA2E;AAC3E,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,aAAa,GACb,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,kBAAkB,GAClB,cAAc,GACd,cAAc,CAAC;AAMnB,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EACxC,iBAAiB,CAClB,CAAC;AAgCF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,WAAW,GAAG,IAyB5D,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,KACf,OAAO,CAAC,mBAAmB,CAsH7B,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Template - Fetch Deploy Templates from GitHub Repositories
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Downloads a subdirectory from a GitHub repository for use as a deploy
|
|
6
|
+
// template. Templates are expected to contain at least a fly.toml and
|
|
7
|
+
// typically a Dockerfile.
|
|
8
|
+
//
|
|
9
|
+
// Reference format: owner/repo[/path][@ref]
|
|
10
|
+
//
|
|
11
|
+
// ToxicPine/ambit-openclaw → repo root, default branch
|
|
12
|
+
// ToxicPine/ambit-templates/cdp → subdirectory, default branch
|
|
13
|
+
// ToxicPine/ambit-templates/cdp@v1.0 → tagged release
|
|
14
|
+
// ToxicPine/ambit-templates/cdp@main → explicit branch
|
|
15
|
+
//
|
|
16
|
+
// =============================================================================
|
|
17
|
+
import * as dntShim from "../_dnt.shims.js";
|
|
18
|
+
import { join } from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
19
|
+
import { runCommand } from "../lib/command.js";
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Internal Helpers
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/** Shorthand for returning a typed fetch error. */
|
|
24
|
+
const fail = (kind, message) => ({
|
|
25
|
+
ok: false,
|
|
26
|
+
kind,
|
|
27
|
+
message,
|
|
28
|
+
});
|
|
29
|
+
/** Format a template reference for display. */
|
|
30
|
+
const formatRef = (ref) => {
|
|
31
|
+
const base = ref.path === "."
|
|
32
|
+
? `${ref.owner}/${ref.repo}`
|
|
33
|
+
: `${ref.owner}/${ref.repo}/${ref.path}`;
|
|
34
|
+
return base + (ref.ref ? `@${ref.ref}` : "");
|
|
35
|
+
};
|
|
36
|
+
/** Format owner/repo with optional ref for display. */
|
|
37
|
+
const formatRepo = (ref) => `${ref.owner}/${ref.repo}` + (ref.ref ? `@${ref.ref}` : "");
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// Parse Template Reference
|
|
40
|
+
// =============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Parse a template reference string into its components.
|
|
43
|
+
* Returns null if the format is invalid.
|
|
44
|
+
*
|
|
45
|
+
* Format: owner/repo[/path][@ref]
|
|
46
|
+
*
|
|
47
|
+
* The first two segments are always owner/repo. Everything after the second
|
|
48
|
+
* slash up to an optional @ref is the path within the repository. When no
|
|
49
|
+
* path is provided, the repository root is used as the template directory.
|
|
50
|
+
* This is unambiguous because GitHub owner and repo names cannot contain
|
|
51
|
+
* slashes.
|
|
52
|
+
*/
|
|
53
|
+
export const parseTemplateRef = (raw) => {
|
|
54
|
+
// Split off @ref suffix
|
|
55
|
+
const atIndex = raw.lastIndexOf("@");
|
|
56
|
+
let body;
|
|
57
|
+
let ref;
|
|
58
|
+
if (atIndex > 0) {
|
|
59
|
+
body = raw.slice(0, atIndex);
|
|
60
|
+
ref = raw.slice(atIndex + 1);
|
|
61
|
+
if (!ref)
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
body = raw;
|
|
66
|
+
}
|
|
67
|
+
// Need at least owner/repo
|
|
68
|
+
const parts = body.split("/");
|
|
69
|
+
if (parts.length < 2)
|
|
70
|
+
return null;
|
|
71
|
+
const owner = parts[0];
|
|
72
|
+
const repo = parts[1];
|
|
73
|
+
const path = parts.length > 2 ? parts.slice(2).join("/") : ".";
|
|
74
|
+
if (!owner || !repo || !path)
|
|
75
|
+
return null;
|
|
76
|
+
return { owner, repo, path, ref };
|
|
77
|
+
};
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// Fetch Template
|
|
80
|
+
// =============================================================================
|
|
81
|
+
/**
|
|
82
|
+
* Download a template from GitHub and extract the target subdirectory
|
|
83
|
+
* to a temp directory.
|
|
84
|
+
*
|
|
85
|
+
* On success, returns the temp dir (for cleanup) and the path to the
|
|
86
|
+
* extracted template directory. The caller is responsible for removing
|
|
87
|
+
* tempDir when done.
|
|
88
|
+
*
|
|
89
|
+
* On failure, cleans up the temp dir and returns a typed error.
|
|
90
|
+
*/
|
|
91
|
+
export const fetchTemplate = async (ref) => {
|
|
92
|
+
const tempDir = dntShim.Deno.makeTempDirSync({ prefix: "ambit-template-" });
|
|
93
|
+
const cleanup = () => {
|
|
94
|
+
try {
|
|
95
|
+
dntShim.Deno.removeSync(tempDir, { recursive: true });
|
|
96
|
+
}
|
|
97
|
+
catch { /* ignore */ }
|
|
98
|
+
};
|
|
99
|
+
const cleanFail = (kind, message) => {
|
|
100
|
+
cleanup();
|
|
101
|
+
return fail(kind, message);
|
|
102
|
+
};
|
|
103
|
+
try {
|
|
104
|
+
const url = ref.ref
|
|
105
|
+
? `https://api.github.com/repos/${ref.owner}/${ref.repo}/tarball/${ref.ref}`
|
|
106
|
+
: `https://api.github.com/repos/${ref.owner}/${ref.repo}/tarball`;
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
headers: {
|
|
109
|
+
Accept: "application/vnd.github+json",
|
|
110
|
+
"User-Agent": "ambit-cli",
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
const repo = formatRepo(ref);
|
|
115
|
+
if (response.status === 404) {
|
|
116
|
+
return cleanFail("NotFound", `Template Repository Not Found: ${repo}. ` +
|
|
117
|
+
"Check that the repository exists and is public.");
|
|
118
|
+
}
|
|
119
|
+
if (response.status === 403) {
|
|
120
|
+
return cleanFail("RateLimited", "GitHub API Rate Limit Exceeded. Try again later.");
|
|
121
|
+
}
|
|
122
|
+
return cleanFail("HttpError", `GitHub API Returned HTTP ${response.status} for ${repo}`);
|
|
123
|
+
}
|
|
124
|
+
// Write tarball to disk
|
|
125
|
+
const tarballPath = join(tempDir, "template.tar.gz");
|
|
126
|
+
const tarball = new Uint8Array(await response.arrayBuffer());
|
|
127
|
+
dntShim.Deno.writeFileSync(tarballPath, tarball);
|
|
128
|
+
// Extract
|
|
129
|
+
const extractDir = join(tempDir, "extract");
|
|
130
|
+
dntShim.Deno.mkdirSync(extractDir);
|
|
131
|
+
const extractResult = await runCommand([
|
|
132
|
+
"tar",
|
|
133
|
+
"xzf",
|
|
134
|
+
tarballPath,
|
|
135
|
+
"-C",
|
|
136
|
+
extractDir,
|
|
137
|
+
]);
|
|
138
|
+
if (!extractResult.success) {
|
|
139
|
+
return cleanFail("ExtractionFailed", "Failed to Extract Template Archive");
|
|
140
|
+
}
|
|
141
|
+
// GitHub tarballs have a single top-level dir (owner-repo-commitish/)
|
|
142
|
+
const entries = [...dntShim.Deno.readDirSync(extractDir)];
|
|
143
|
+
const topLevel = entries.find((e) => e.isDirectory);
|
|
144
|
+
if (!topLevel) {
|
|
145
|
+
return cleanFail("EmptyArchive", "Template Archive Has No Top-Level Directory");
|
|
146
|
+
}
|
|
147
|
+
// Locate the template subdirectory
|
|
148
|
+
const templateDir = join(extractDir, topLevel.name, ref.path);
|
|
149
|
+
try {
|
|
150
|
+
const stat = dntShim.Deno.statSync(templateDir);
|
|
151
|
+
if (!stat.isDirectory) {
|
|
152
|
+
return cleanFail("PathNotDirectory", `Template Path '${ref.path}' Is Not a Directory in ${formatRepo(ref)}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return cleanFail("PathNotFound", `Template Path '${ref.path}' Not Found in ${formatRepo(ref)}`);
|
|
157
|
+
}
|
|
158
|
+
return { ok: true, tempDir, templateDir };
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
if (e instanceof TypeError) {
|
|
162
|
+
return cleanFail("NetworkError", "Network Error: Could Not Reach GitHub");
|
|
163
|
+
}
|
|
164
|
+
cleanup();
|
|
165
|
+
throw e;
|
|
166
|
+
}
|
|
167
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardelli/ambit",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Deploy apps to the cloud that only you and your AI agents can reach",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "./esm/src/providers/fly.js",
|
|
7
7
|
"exports": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_data.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/jsr.io/@std/cli/1.0.27/_data.js"],"names":[],"mappings":""}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filters the given array, removing all elements that do not match the given predicate
|
|
3
|
-
* **in place. This means `array` will be modified!**.
|
|
4
|
-
*/
|
|
5
|
-
export declare function filterInPlace<T>(array: Array<T>, predicate: (el: T) => boolean): Array<T>;
|
|
6
|
-
//# sourceMappingURL=_utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/jsr.io/@std/collections/1.1.3/_utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,GAC5B,KAAK,CAAC,CAAC,CAAC,CAeV"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
2
|
-
// This module is browser compatible.
|
|
3
|
-
/**
|
|
4
|
-
* Filters the given array, removing all elements that do not match the given predicate
|
|
5
|
-
* **in place. This means `array` will be modified!**.
|
|
6
|
-
*/
|
|
7
|
-
export function filterInPlace(array, predicate) {
|
|
8
|
-
let outputIndex = 0;
|
|
9
|
-
for (const cur of array) {
|
|
10
|
-
if (!predicate(cur)) {
|
|
11
|
-
continue;
|
|
12
|
-
}
|
|
13
|
-
array[outputIndex] = cur;
|
|
14
|
-
outputIndex += 1;
|
|
15
|
-
}
|
|
16
|
-
array.splice(outputIndex);
|
|
17
|
-
return array;
|
|
18
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|