@heychunky/core 0.8.2 → 0.9.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/dist/admin/chunks.d.ts +53 -0
- package/dist/admin/chunks.d.ts.map +1 -1
- package/dist/admin/chunks.js +132 -20
- package/dist/admin/chunks.js.map +1 -1
- package/dist/admin/decommission.d.ts +40 -0
- package/dist/admin/decommission.d.ts.map +1 -0
- package/dist/admin/decommission.js +134 -0
- package/dist/admin/decommission.js.map +1 -0
- package/dist/admin/entrypoints.d.ts +16 -0
- package/dist/admin/entrypoints.d.ts.map +1 -0
- package/dist/admin/entrypoints.js +41 -0
- package/dist/admin/entrypoints.js.map +1 -0
- package/dist/admin/index.d.ts +2 -0
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +2 -0
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/provision.d.ts.map +1 -1
- package/dist/admin/provision.js +116 -4
- package/dist/admin/provision.js.map +1 -1
- package/dist/admin/services/bunny.d.ts +3 -0
- package/dist/admin/services/bunny.d.ts.map +1 -1
- package/dist/admin/services/bunny.js +12 -0
- package/dist/admin/services/bunny.js.map +1 -1
- package/dist/admin/services/cloudflare.d.ts +11 -0
- package/dist/admin/services/cloudflare.d.ts.map +1 -1
- package/dist/admin/services/cloudflare.js +19 -0
- package/dist/admin/services/cloudflare.js.map +1 -1
- package/dist/admin/services/github.d.ts +3 -0
- package/dist/admin/services/github.d.ts.map +1 -1
- package/dist/admin/services/github.js +29 -1
- package/dist/admin/services/github.js.map +1 -1
- package/dist/admin/services/neon.d.ts +3 -0
- package/dist/admin/services/neon.d.ts.map +1 -1
- package/dist/admin/services/neon.js +16 -0
- package/dist/admin/services/neon.js.map +1 -1
- package/dist/admin/services/vercel.d.ts +19 -9
- package/dist/admin/services/vercel.d.ts.map +1 -1
- package/dist/admin/services/vercel.js +40 -7
- package/dist/admin/services/vercel.js.map +1 -1
- package/dist/config/environments.d.ts +41 -1
- package/dist/config/environments.d.ts.map +1 -1
- package/dist/config/environments.js +50 -1
- package/dist/config/environments.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +8 -0
- package/dist/registry.js.map +1 -1
- package/package.json +4 -1
package/dist/admin/chunks.d.ts
CHANGED
|
@@ -25,6 +25,25 @@ export interface ChunkManifest {
|
|
|
25
25
|
tags: string[];
|
|
26
26
|
/** npm packages the chunk needs at runtime. Ours are files; these are not. */
|
|
27
27
|
dependencies: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Other chunks this one will not work without.
|
|
30
|
+
*
|
|
31
|
+
* A real dependency graph — sitenav does not render without coreui's button
|
|
32
|
+
* — and one that is kept shallow on purpose. A deep chunk graph reproduces
|
|
33
|
+
* the dependency hell the copy-and-own model exists to avoid, so a chunk
|
|
34
|
+
* that needs four others is usually one chunk pretending to be five.
|
|
35
|
+
*/
|
|
36
|
+
requires?: {
|
|
37
|
+
chunks?: string[];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Stylesheets the chunk ships, in the order they should be imported.
|
|
41
|
+
*
|
|
42
|
+
* Declared rather than inferred from the file list: a chunk's CSS has to be
|
|
43
|
+
* imported by something or it lands in the repository and styles nothing,
|
|
44
|
+
* which is exactly what happened to the first chunk on the shelf.
|
|
45
|
+
*/
|
|
46
|
+
styles?: string[];
|
|
28
47
|
/**
|
|
29
48
|
* SQL the chunk needs run against the app's own database, before its code
|
|
30
49
|
* is deployed. Written to be safe to run twice — `create table if not
|
|
@@ -51,6 +70,13 @@ export interface ChunkFile {
|
|
|
51
70
|
/** Path in the app, relative to its root. */
|
|
52
71
|
path: string;
|
|
53
72
|
content: string;
|
|
73
|
+
/**
|
|
74
|
+
* Set for files that are not text.
|
|
75
|
+
*
|
|
76
|
+
* A chunk that renders a logo has to ship the logo, and a PNG decoded as
|
|
77
|
+
* UTF-8 and written back is noise. Base64 passes through both ends untouched.
|
|
78
|
+
*/
|
|
79
|
+
encoding?: "base64";
|
|
54
80
|
}
|
|
55
81
|
export interface AddResult {
|
|
56
82
|
chunk: string;
|
|
@@ -84,6 +110,18 @@ export declare function readChunk(name: string, ctx: RunContext): Promise<{
|
|
|
84
110
|
manifest: ChunkManifest;
|
|
85
111
|
files: ChunkFile[];
|
|
86
112
|
}>;
|
|
113
|
+
/**
|
|
114
|
+
* A chunk and everything it will not work without, dependencies first.
|
|
115
|
+
*
|
|
116
|
+
* Depth-first so a dependency is always written before the chunk that imports
|
|
117
|
+
* it, and cycle-aware because a graph that can be declared can be declared
|
|
118
|
+
* wrong. Returned as one flat list: the caller writes them in a single commit,
|
|
119
|
+
* so an app never exists in a state where half a chunk's imports resolve.
|
|
120
|
+
*/
|
|
121
|
+
export declare function resolveChunk(name: string, ctx: RunContext, seen?: string[]): Promise<{
|
|
122
|
+
manifest: ChunkManifest;
|
|
123
|
+
files: ChunkFile[];
|
|
124
|
+
}[]>;
|
|
87
125
|
/** The config file, written from the chunk's own declared defaults. */
|
|
88
126
|
export declare function configFor(manifest: ChunkManifest): string | undefined;
|
|
89
127
|
export interface AddWatcher {
|
|
@@ -97,6 +135,21 @@ export interface AddWatcher {
|
|
|
97
135
|
* already there with the content it would be given, nothing is written and the
|
|
98
136
|
* run says so. That is what makes it safe to ask twice.
|
|
99
137
|
*/
|
|
138
|
+
/**
|
|
139
|
+
* Register a chunk's stylesheets with the app.
|
|
140
|
+
*
|
|
141
|
+
* A stylesheet that lands in the repository and is imported by nothing styles
|
|
142
|
+
* nothing — the first chunk on the shelf shipped four components and none of
|
|
143
|
+
* their CSS, and no part of the pipeline noticed. `index.css` is where an app
|
|
144
|
+
* collects its imports, and it holds only imports, which is what the CSS rule
|
|
145
|
+
* that `@import` must precede every other rule requires.
|
|
146
|
+
*
|
|
147
|
+
* Returns the file to write, or undefined when every import is already there.
|
|
148
|
+
*/
|
|
149
|
+
export declare function registerStyles(index: {
|
|
150
|
+
path: string;
|
|
151
|
+
content: string;
|
|
152
|
+
}, styles: string[], uiDir: string): ChunkFile | undefined;
|
|
100
153
|
export declare function addChunk(opts: {
|
|
101
154
|
chunk: string;
|
|
102
155
|
repo: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/admin/chunks.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/admin/chunks.ts"],"names":[],"mappings":"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"}
|
package/dist/admin/chunks.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { github } from "./services/github.js";
|
|
20
20
|
import { vercel } from "./services/vercel.js";
|
|
21
21
|
import { KEY_FOR } from "./run.js";
|
|
22
|
+
import { entryPoints } from "./entrypoints.js";
|
|
22
23
|
import { DEFAULT_BRANCH } from "../config/environments.js";
|
|
23
24
|
/**
|
|
24
25
|
* Where the chunks live. Folders in one repository, one per chunk.
|
|
@@ -29,6 +30,14 @@ import { DEFAULT_BRANCH } from "../config/environments.js";
|
|
|
29
30
|
* cannot happen here.
|
|
30
31
|
*/
|
|
31
32
|
export const CHUNKS_REPO = "heychunkydev/chunks";
|
|
33
|
+
/**
|
|
34
|
+
* What must not be decoded on the way through.
|
|
35
|
+
*
|
|
36
|
+
* By extension rather than by sniffing: a chunk's file list is known before
|
|
37
|
+
* anything is fetched, and guessing from content would mean downloading it
|
|
38
|
+
* wrongly first to find out.
|
|
39
|
+
*/
|
|
40
|
+
const BINARY = /\.(png|jpe?g|gif|webp|avif|ico|svgz|woff2?|ttf|otf|eot|mp4|webm|pdf|zip)$/i;
|
|
32
41
|
export class NoSuchChunk extends Error {
|
|
33
42
|
constructor(name) {
|
|
34
43
|
super(`No chunk called "${name}"`);
|
|
@@ -61,13 +70,39 @@ export async function readChunk(name, ctx) {
|
|
|
61
70
|
const manifest = JSON.parse(raw);
|
|
62
71
|
const files = [];
|
|
63
72
|
for (const path of await gh.listFiles(CHUNKS_REPO, `${root}/files`)) {
|
|
73
|
+
const binary = BINARY.test(path);
|
|
64
74
|
files.push({
|
|
65
75
|
path: path.slice(`${root}/files/`.length),
|
|
66
|
-
content: await gh.readFile(CHUNKS_REPO, path),
|
|
76
|
+
content: binary ? await gh.readBinaryFile(CHUNKS_REPO, path) : await gh.readFile(CHUNKS_REPO, path),
|
|
77
|
+
...(binary ? { encoding: "base64" } : {}),
|
|
67
78
|
});
|
|
68
79
|
}
|
|
69
80
|
return { manifest, files };
|
|
70
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* A chunk and everything it will not work without, dependencies first.
|
|
84
|
+
*
|
|
85
|
+
* Depth-first so a dependency is always written before the chunk that imports
|
|
86
|
+
* it, and cycle-aware because a graph that can be declared can be declared
|
|
87
|
+
* wrong. Returned as one flat list: the caller writes them in a single commit,
|
|
88
|
+
* so an app never exists in a state where half a chunk's imports resolve.
|
|
89
|
+
*/
|
|
90
|
+
export async function resolveChunk(name, ctx, seen = []) {
|
|
91
|
+
if (seen.includes(name)) {
|
|
92
|
+
throw new Error(`Chunk dependencies form a cycle: ${[...seen, name].join(" → ")}`);
|
|
93
|
+
}
|
|
94
|
+
const read = await readChunk(name, ctx);
|
|
95
|
+
const out = [];
|
|
96
|
+
for (const required of read.manifest.requires?.chunks ?? []) {
|
|
97
|
+
for (const dep of await resolveChunk(required, ctx, [...seen, name])) {
|
|
98
|
+
// A chunk two others need is read twice and written once.
|
|
99
|
+
if (!out.some((c) => c.manifest.name === dep.manifest.name))
|
|
100
|
+
out.push(dep);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
out.push(read);
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
71
106
|
/** The config file, written from the chunk's own declared defaults. */
|
|
72
107
|
export function configFor(manifest) {
|
|
73
108
|
if (!manifest.config || !manifest.options.length)
|
|
@@ -91,24 +126,97 @@ ${lines.join("\n")}
|
|
|
91
126
|
* already there with the content it would be given, nothing is written and the
|
|
92
127
|
* run says so. That is what makes it safe to ask twice.
|
|
93
128
|
*/
|
|
129
|
+
/**
|
|
130
|
+
* Register a chunk's stylesheets with the app.
|
|
131
|
+
*
|
|
132
|
+
* A stylesheet that lands in the repository and is imported by nothing styles
|
|
133
|
+
* nothing — the first chunk on the shelf shipped four components and none of
|
|
134
|
+
* their CSS, and no part of the pipeline noticed. `index.css` is where an app
|
|
135
|
+
* collects its imports, and it holds only imports, which is what the CSS rule
|
|
136
|
+
* that `@import` must precede every other rule requires.
|
|
137
|
+
*
|
|
138
|
+
* Returns the file to write, or undefined when every import is already there.
|
|
139
|
+
*/
|
|
140
|
+
export function registerStyles(index, styles, uiDir) {
|
|
141
|
+
let content = index.content;
|
|
142
|
+
let added = 0;
|
|
143
|
+
for (const style of styles) {
|
|
144
|
+
// Relative to index.css, which sits at the root of the ui directory.
|
|
145
|
+
const rel = `./${style.startsWith(`${uiDir}/`) ? style.slice(uiDir.length + 1) : style}`;
|
|
146
|
+
const line = `@import "${rel}";`;
|
|
147
|
+
if (content.includes(line))
|
|
148
|
+
continue;
|
|
149
|
+
const imports = [...content.matchAll(/^@import .*;$/gm)];
|
|
150
|
+
const last = imports.at(-1);
|
|
151
|
+
if (last?.index === undefined) {
|
|
152
|
+
content = `${line}\n${content}`;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const at = last.index + last[0].length;
|
|
156
|
+
content = `${content.slice(0, at)}\n${line}${content.slice(at)}`;
|
|
157
|
+
}
|
|
158
|
+
added += 1;
|
|
159
|
+
}
|
|
160
|
+
return added ? { path: index.path, content } : undefined;
|
|
161
|
+
}
|
|
162
|
+
/** Where this app keeps its stylesheets, as its own manifest declares. */
|
|
163
|
+
async function uiDirOf(repo, gh) {
|
|
164
|
+
try {
|
|
165
|
+
const raw = await gh.readFile(repo, "heychunky.json");
|
|
166
|
+
const ui = JSON.parse(raw).ui;
|
|
167
|
+
if (ui?.dir)
|
|
168
|
+
return ui.dir;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// An app without a manifest is one provisioned before the format had one.
|
|
172
|
+
}
|
|
173
|
+
return ".heychunky/ui";
|
|
174
|
+
}
|
|
94
175
|
export async function addChunk(opts, ctx, watch) {
|
|
95
176
|
const { gh, vc } = await clients(ctx);
|
|
96
177
|
watch?.start?.("read chunk");
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
178
|
+
// The chunk and everything it will not work without, dependencies first, so
|
|
179
|
+
// an app never exists in a state where half of an import resolves.
|
|
180
|
+
const resolved = await resolveChunk(opts.chunk, ctx);
|
|
181
|
+
const manifest = resolved.at(-1).manifest;
|
|
182
|
+
const all = [];
|
|
183
|
+
for (const { manifest: m, files } of resolved) {
|
|
184
|
+
all.push(...files);
|
|
185
|
+
// Generated only when the chunk does not ship one of its own. A chunk that
|
|
186
|
+
// hand-writes its config knows something the generator does not, and adding
|
|
187
|
+
// a second file at the same path put it in the list twice.
|
|
188
|
+
const shipped = m.config && files.some((f) => f.path === m.config);
|
|
189
|
+
const config = shipped ? undefined : configFor(m);
|
|
190
|
+
if (config && m.config) {
|
|
191
|
+
// And only if it is not already in the app: this file is the developer's
|
|
192
|
+
// once written, and rewriting it would silently undo their settings.
|
|
193
|
+
const existing = await gh.readFile(opts.repo, m.config).catch(() => undefined);
|
|
194
|
+
if (existing === undefined)
|
|
195
|
+
all.push({ path: m.config, content: config });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Stylesheets have to be imported by something. `index.css` is where an app
|
|
199
|
+
// collects them, and its location is the app's decision rather than ours.
|
|
200
|
+
const styles = resolved.flatMap((c) => c.manifest.styles ?? []);
|
|
201
|
+
if (styles.length) {
|
|
202
|
+
const uiDir = await uiDirOf(opts.repo, gh);
|
|
203
|
+
const path = `${uiDir}/index.css`;
|
|
204
|
+
const content = await gh.readFile(opts.repo, path).catch(() => undefined);
|
|
205
|
+
if (content === undefined) {
|
|
206
|
+
all.push({ path, content: styles.map((s) => `@import "./${s.slice(uiDir.length + 1)}";`).join("\n") + "\n" });
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const updated = registerStyles({ path, content }, styles, uiDir);
|
|
210
|
+
if (updated)
|
|
211
|
+
all.push(updated);
|
|
212
|
+
}
|
|
110
213
|
}
|
|
111
|
-
|
|
214
|
+
// `src/app/` is derived from the manifest, so anything the manifest gained
|
|
215
|
+
// and the target has not is regenerated in the same commit as the chunk.
|
|
216
|
+
// A route that exists in one and not the other is a page nobody can visit.
|
|
217
|
+
all.push(...(await entryPoints(opts.repo, gh)));
|
|
218
|
+
const named = resolved.map((c) => c.manifest.name).join(" → ");
|
|
219
|
+
watch?.done?.("read chunk", `${named} · ${all.length} files`);
|
|
112
220
|
watch?.start?.("check app");
|
|
113
221
|
const unchanged = [];
|
|
114
222
|
for (const file of all) {
|
|
@@ -124,9 +232,12 @@ export async function addChunk(opts, ctx, watch) {
|
|
|
124
232
|
// Before the code that needs them, so a deployment never lands on a schema
|
|
125
233
|
// that has not caught up. Failing here stops the run with nothing written.
|
|
126
234
|
let migrated = 0;
|
|
127
|
-
|
|
235
|
+
// In dependency order: a chunk's tables may reference a table its dependency
|
|
236
|
+
// creates, and resolveChunk already put them in that order.
|
|
237
|
+
const statements = resolved.flatMap((c) => c.manifest.sql ?? []);
|
|
238
|
+
if (statements.length) {
|
|
128
239
|
watch?.start?.("database");
|
|
129
|
-
for (const statement of
|
|
240
|
+
for (const statement of statements) {
|
|
130
241
|
await opts.migrate(statement);
|
|
131
242
|
migrated += 1;
|
|
132
243
|
}
|
|
@@ -142,11 +253,12 @@ export async function addChunk(opts, ctx, watch) {
|
|
|
142
253
|
// Named, not filled. A chunk cannot know somebody's Resend key; what it can
|
|
143
254
|
// do is say which are missing rather than let the app boot broken.
|
|
144
255
|
const missing = [];
|
|
145
|
-
|
|
256
|
+
const wanted = resolved.flatMap((c) => c.manifest.env ?? []);
|
|
257
|
+
if (wanted.length) {
|
|
146
258
|
watch?.start?.("settings");
|
|
147
259
|
const have = new Set(await opts.envKeys());
|
|
148
|
-
for (const e of
|
|
149
|
-
if (!have.has(e.key))
|
|
260
|
+
for (const e of wanted)
|
|
261
|
+
if (!have.has(e.key) && !missing.some((m) => m.key === e.key))
|
|
150
262
|
missing.push(e);
|
|
151
263
|
watch?.done?.("settings", missing.length
|
|
152
264
|
? `${missing.length} still needed: ${missing.map((m) => m.key).join(", ")}`
|
package/dist/admin/chunks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/admin/chunks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAmB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/admin/chunks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type RunContext } from "./run.ts";
|
|
2
|
+
import type { StepResult } from "./provision.ts";
|
|
3
|
+
export interface Teardown {
|
|
4
|
+
/** The app's name, as provisioning knew it. */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Its organisation. Defaults to the factory's, as provisioning does. */
|
|
7
|
+
org?: string;
|
|
8
|
+
/** The address it was given. Defaults to the apps-zone subdomain. */
|
|
9
|
+
domain?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Remove the repository too.
|
|
12
|
+
*
|
|
13
|
+
* Separate from the rest because it is the only irreversible loss that is
|
|
14
|
+
* not a cost: the infrastructure can be rebuilt from the code, and the code
|
|
15
|
+
* cannot be rebuilt from anything.
|
|
16
|
+
*/
|
|
17
|
+
repo?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface Removal {
|
|
20
|
+
app: string;
|
|
21
|
+
/** True when nothing was removed, because nothing was confirmed. */
|
|
22
|
+
planned: boolean;
|
|
23
|
+
steps: StepResult[];
|
|
24
|
+
/** Every step reached a good state. */
|
|
25
|
+
ok: boolean;
|
|
26
|
+
}
|
|
27
|
+
interface Watcher {
|
|
28
|
+
start?(step: string): void;
|
|
29
|
+
done?(step: string, detail: string): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* What has to go, and how to find it.
|
|
33
|
+
*
|
|
34
|
+
* Each step looks the resource up before touching it, so an app that was never
|
|
35
|
+
* fully provisioned — or was taken down halfway yesterday — reports "gone"
|
|
36
|
+
* rather than failing on something that was never there.
|
|
37
|
+
*/
|
|
38
|
+
export declare function decommission(spec: Teardown, ctx: RunContext, watch?: Watcher): Promise<Removal>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=decommission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decommission.d.ts","sourceRoot":"","sources":["../../src/admin/decommission.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,gBAAgB,CAAC;AAE5D,MAAM,WAAW,QAAQ;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uCAAuC;IACvC,EAAE,EAAE,OAAO,CAAC;CACb;AAED,UAAU,OAAO;IACf,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,UAAU,EACf,KAAK,CAAC,EAAE,OAAO,GACd,OAAO,CAAC,OAAO,CAAC,CAgHlB"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Taking an app down.
|
|
3
|
+
*
|
|
4
|
+
* The counterpart to `provision`, and the reason it had to exist: until this
|
|
5
|
+
* did, an app could be created and never removed. Every app ever made kept a
|
|
6
|
+
* Neon project, a Vercel project and a storage zone billing for as long as the
|
|
7
|
+
* account lived, and the only things that could be deleted — a repository and
|
|
8
|
+
* a DNS record — were the two that cost nothing.
|
|
9
|
+
*
|
|
10
|
+
* Order is deliberate and runs the opposite way to creation:
|
|
11
|
+
*
|
|
12
|
+
* 1. the address, so nothing is being served while the rest goes
|
|
13
|
+
* 2. the hosting project
|
|
14
|
+
* 3. the database
|
|
15
|
+
* 4. the storage
|
|
16
|
+
* 5. the repository, last, because the code is the one thing somebody might
|
|
17
|
+
* still want and the one thing nobody can rebuild
|
|
18
|
+
*
|
|
19
|
+
* A failure stops the run where it stands rather than pressing on, so a
|
|
20
|
+
* half-removed app is reported as exactly that and can be asked again.
|
|
21
|
+
*/
|
|
22
|
+
import { github } from "./services/github.js";
|
|
23
|
+
import { vercel } from "./services/vercel.js";
|
|
24
|
+
import { neon } from "./services/neon.js";
|
|
25
|
+
import { cloudflare } from "./services/cloudflare.js";
|
|
26
|
+
import { bunny } from "./services/bunny.js";
|
|
27
|
+
import { KEY_FOR } from "./run.js";
|
|
28
|
+
import { DEFAULT_ORG, defaultDomain, stagingDomain } from "../config/environments.js";
|
|
29
|
+
/**
|
|
30
|
+
* What has to go, and how to find it.
|
|
31
|
+
*
|
|
32
|
+
* Each step looks the resource up before touching it, so an app that was never
|
|
33
|
+
* fully provisioned — or was taken down halfway yesterday — reports "gone"
|
|
34
|
+
* rather than failing on something that was never there.
|
|
35
|
+
*/
|
|
36
|
+
export async function decommission(spec, ctx, watch) {
|
|
37
|
+
const key = (service) => ctx.secrets.get(ctx.reference(KEY_FOR[service]));
|
|
38
|
+
const [g, v, n, c, b] = await Promise.all([
|
|
39
|
+
key("github"), key("vercel"), key("neon"), key("cloudflare"), key("bunny"),
|
|
40
|
+
]);
|
|
41
|
+
const gh = github(g), vc = vercel(v), nn = neon(n), cf = cloudflare(c), bn = bunny(b);
|
|
42
|
+
const domain = spec.domain ?? defaultDomain(spec.name);
|
|
43
|
+
/**
|
|
44
|
+
* Every name this factory pointed at the app.
|
|
45
|
+
*
|
|
46
|
+
* Staging has an address of its own, and a record left behind in Cloudflare
|
|
47
|
+
* after the project it pointed at is gone is precisely the orphan this run
|
|
48
|
+
* exists to prevent — cheaper than a database, and just as much a lie about
|
|
49
|
+
* what still exists.
|
|
50
|
+
*/
|
|
51
|
+
const domains = [domain, stagingDomain(domain)];
|
|
52
|
+
const repo = `${spec.org ?? DEFAULT_ORG}/${spec.name}`;
|
|
53
|
+
const steps = [];
|
|
54
|
+
let ok = true;
|
|
55
|
+
const run = async (step, find, remove) => {
|
|
56
|
+
if (!ok)
|
|
57
|
+
return;
|
|
58
|
+
watch?.start?.(step);
|
|
59
|
+
try {
|
|
60
|
+
const found = await find();
|
|
61
|
+
if (found === undefined) {
|
|
62
|
+
settle(step, "exists", "gone already");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (!ctx.confirmed) {
|
|
66
|
+
settle(step, "would-create", `would remove ${found}`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
settle(step, "created", await remove());
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
ok = false;
|
|
73
|
+
settle(step, "failed", error instanceof Error ? error.message : String(error));
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const settle = (step, state, detail) => {
|
|
77
|
+
steps.push({ step, state, detail });
|
|
78
|
+
watch?.done?.(step, detail);
|
|
79
|
+
};
|
|
80
|
+
// The address first: whatever else fails, nothing is still being served.
|
|
81
|
+
const pointedHere = async () => {
|
|
82
|
+
const here = [];
|
|
83
|
+
for (const name of domains) {
|
|
84
|
+
const zone = await cf.zoneFor(name);
|
|
85
|
+
if (!zone)
|
|
86
|
+
continue;
|
|
87
|
+
if ((await cf.dnsRecords(zone.name)).some((r) => r.name === name))
|
|
88
|
+
here.push(name);
|
|
89
|
+
}
|
|
90
|
+
return here;
|
|
91
|
+
};
|
|
92
|
+
await run("dns record", async () => {
|
|
93
|
+
const here = await pointedHere();
|
|
94
|
+
return here.length ? here.join(", ") : undefined;
|
|
95
|
+
}, async () => {
|
|
96
|
+
let gone = 0;
|
|
97
|
+
const removed = [];
|
|
98
|
+
for (const name of await pointedHere()) {
|
|
99
|
+
const zone = (await cf.zoneFor(name));
|
|
100
|
+
gone += await cf.deleteDnsRecords(zone.name, name, { confirmed: true });
|
|
101
|
+
removed.push(name);
|
|
102
|
+
}
|
|
103
|
+
return `${gone} record${gone === 1 ? "" : "s"} for ${removed.join(", ")}`;
|
|
104
|
+
});
|
|
105
|
+
await run("vercel project", async () => (await vc.findProject(spec.name))?.name, async () => {
|
|
106
|
+
const project = (await vc.findProject(spec.name));
|
|
107
|
+
await vc.deleteProject(project.id, await vc.teamId(), { confirmed: true });
|
|
108
|
+
return project.name;
|
|
109
|
+
});
|
|
110
|
+
await run("neon project", async () => (await nn.projects()).find((p) => p.name === spec.name)?.name, async () => {
|
|
111
|
+
const project = (await nn.projects()).find((p) => p.name === spec.name);
|
|
112
|
+
await nn.deleteProject(project.id, { confirmed: true });
|
|
113
|
+
return `${project.name} · every branch with it`;
|
|
114
|
+
});
|
|
115
|
+
await run("storage zones", async () => {
|
|
116
|
+
const zones = await bn.zonesForApp(spec.name);
|
|
117
|
+
return zones.length ? zones.map((z) => z.Name).join(", ") : undefined;
|
|
118
|
+
}, async () => {
|
|
119
|
+
const zones = await bn.zonesForApp(spec.name);
|
|
120
|
+
for (const zone of zones)
|
|
121
|
+
await bn.deleteStorageZone(zone.Id, { confirmed: true });
|
|
122
|
+
return zones.map((z) => z.Name).join(", ");
|
|
123
|
+
});
|
|
124
|
+
// Last, and only when asked. Everything above can be rebuilt from what is
|
|
125
|
+
// in here; nothing can rebuild what is in here.
|
|
126
|
+
if (spec.repo) {
|
|
127
|
+
await run("github repo", async () => ((await gh.findRepo(repo)) ? repo : undefined), async () => {
|
|
128
|
+
await gh.deleteRepo(repo, { confirmed: true });
|
|
129
|
+
return repo;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return { app: spec.name, planned: !ctx.confirmed, steps, ok };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=decommission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decommission.js","sourceRoot":"","sources":["../../src/admin/decommission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAmB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAkCtF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAc,EACd,GAAe,EACf,KAAe;IAEf,MAAM,GAAG,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAE,CAAC,CAAC,CAAC;IACnF,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;KAC3E,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD;;;;;;;OAOG;IACH,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,WAAW,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IACvD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,EAAE,GAAG,IAAI,CAAC;IAEd,MAAM,GAAG,GAAG,KAAK,EAAE,IAAY,EAAE,IAAuC,EAAE,MAA6B,EAAE,EAAE;QACzG,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,KAAK,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAC;YAC3B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,gBAAgB,KAAK,EAAE,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,EAAE,GAAG,KAAK,CAAC;YACX,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACjF,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAgB,EAAE,MAAc,EAAE,EAAE;QAChE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACpC,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,yEAAyE;IACzE,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,MAAM,GAAG,CAAC,YAAY,EACpB,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,WAAW,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC,EACD,KAAK,IAAI,EAAE;QACT,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,MAAM,IAAI,IAAI,MAAM,WAAW,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAE,CAAC;YACvC,IAAI,IAAI,MAAM,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,GAAG,IAAI,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEL,MAAM,GAAG,CAAC,gBAAgB,EACxB,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EACnD,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE,CAAC;QACnD,MAAM,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC,CAAC,CAAC;IAEL,MAAM,GAAG,CAAC,cAAc,EACtB,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EACzE,KAAK,IAAI,EAAE;QACT,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAE,CAAC;QACzE,MAAM,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,OAAO,GAAG,OAAO,CAAC,IAAI,yBAAyB,CAAC;IAClD,CAAC,CAAC,CAAC;IAEL,MAAM,GAAG,CAAC,eAAe,EACvB,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,CAAC,EACD,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,MAAM,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEL,0EAA0E;IAC1E,gDAAgD;IAChD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,GAAG,CAAC,aAAa,EACrB,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,EAC1D,KAAK,IAAI,EAAE;YACT,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ChunkFile } from "./chunks.ts";
|
|
2
|
+
/** The app's own manifest, as its repository holds it. */
|
|
3
|
+
export declare const MANIFEST = "heychunky.json";
|
|
4
|
+
interface Reader {
|
|
5
|
+
readFile(repo: string, path: string): Promise<string>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What the framework target should contain, minus what it already does.
|
|
9
|
+
*
|
|
10
|
+
* Returns only files whose content differs, so a run that changes nothing
|
|
11
|
+
* commits nothing — the same rule the chunk installer follows, and the reason
|
|
12
|
+
* asking twice is safe.
|
|
13
|
+
*/
|
|
14
|
+
export declare function entryPoints(repo: string, gh: Reader): Promise<ChunkFile[]>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=entrypoints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../../src/admin/entrypoints.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,0DAA0D;AAC1D,eAAO,MAAM,QAAQ,mBAAmB,CAAC;AAEzC,UAAU,MAAM;IACd,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAgBhF"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeping an app's generated entry points in step with its manifest.
|
|
3
|
+
*
|
|
4
|
+
* `.heychunky/` is the app and `src/app/` is the framework's view of it. The
|
|
5
|
+
* second is derived from the first — two-line files that re-export the real
|
|
6
|
+
* implementation — which is what lets the same app be generated for another
|
|
7
|
+
* target later, and what stops anybody hand-maintaining a directory of shims.
|
|
8
|
+
*
|
|
9
|
+
* Derived, and therefore worth regenerating: a route added to the manifest and
|
|
10
|
+
* not to `src/app/` is a page that does not exist, and nothing would say so
|
|
11
|
+
* until somebody visited it.
|
|
12
|
+
*/
|
|
13
|
+
import { generate } from "@heychunky/framework";
|
|
14
|
+
/** The app's own manifest, as its repository holds it. */
|
|
15
|
+
export const MANIFEST = "heychunky.json";
|
|
16
|
+
/**
|
|
17
|
+
* What the framework target should contain, minus what it already does.
|
|
18
|
+
*
|
|
19
|
+
* Returns only files whose content differs, so a run that changes nothing
|
|
20
|
+
* commits nothing — the same rule the chunk installer follows, and the reason
|
|
21
|
+
* asking twice is safe.
|
|
22
|
+
*/
|
|
23
|
+
export async function entryPoints(repo, gh) {
|
|
24
|
+
let manifest;
|
|
25
|
+
try {
|
|
26
|
+
manifest = JSON.parse(await gh.readFile(repo, MANIFEST));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// An app with no manifest predates the format. Nothing to generate from,
|
|
30
|
+
// and guessing a route table would be worse than leaving it alone.
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const file of generate(manifest)) {
|
|
35
|
+
const there = await gh.readFile(repo, file.path).catch(() => undefined);
|
|
36
|
+
if (there !== file.contents)
|
|
37
|
+
out.push({ path: file.path, content: file.contents });
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=entrypoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../../src/admin/entrypoints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,QAAQ,EAAiB,MAAM,sBAAsB,CAAC;AAG/D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAMzC;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,EAAU;IACxD,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAa,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;QACzE,mEAAmE;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACxE,IAAI,KAAK,KAAK,IAAI,CAAC,QAAQ;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/admin/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export * from "./apps.ts";
|
|
|
11
11
|
export * from "./users.ts";
|
|
12
12
|
export * from "./run.ts";
|
|
13
13
|
export * from "./provision.ts";
|
|
14
|
+
export * from "./decommission.ts";
|
|
15
|
+
export * from "./entrypoints.ts";
|
|
14
16
|
export * from "./chunks.ts";
|
|
15
17
|
export * from "./services/github.ts";
|
|
16
18
|
export * from "./services/vercel.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAG5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAG5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
|
package/dist/admin/index.js
CHANGED
|
@@ -11,6 +11,8 @@ export * from "./apps.js";
|
|
|
11
11
|
export * from "./users.js";
|
|
12
12
|
export * from "./run.js";
|
|
13
13
|
export * from "./provision.js";
|
|
14
|
+
export * from "./decommission.js";
|
|
15
|
+
export * from "./entrypoints.js";
|
|
14
16
|
export * from "./chunks.js";
|
|
15
17
|
// One file per service, matching the registry.
|
|
16
18
|
export * from "./services/github.js";
|
package/dist/admin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAE5B,+CAA+C;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAE5B,+CAA+C;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC"}
|