@celsoft/platform 0.1.0 → 0.3.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/adapters/cloudflare.d.ts +7 -1
- package/dist/adapters/cloudflare.js +39 -0
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/process.d.ts +2 -0
- package/dist/adapters/process.js +35 -2
- package/dist/adapters/process.js.map +1 -1
- package/dist/adapters/resend.d.ts +14 -0
- package/dist/adapters/resend.js +50 -0
- package/dist/adapters/resend.js.map +1 -0
- package/dist/cli.js +42 -12
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -2
- package/dist/config.js +44 -9
- package/dist/config.js.map +1 -1
- package/dist/fakes.d.ts +47 -1
- package/dist/fakes.js +69 -2
- package/dist/fakes.js.map +1 -1
- package/dist/init.d.ts +6 -3
- package/dist/init.js +37 -10
- package/dist/init.js.map +1 -1
- package/dist/lifecycle.d.ts +4 -0
- package/dist/lifecycle.js +94 -3
- package/dist/lifecycle.js.map +1 -1
- package/dist/ports.d.ts +32 -0
- package/dist/runtime/auth.d.ts +15 -0
- package/dist/runtime/auth.js +35 -0
- package/dist/runtime/auth.js.map +1 -0
- package/dist/runtime/email.d.ts +15 -0
- package/dist/runtime/email.js +22 -0
- package/dist/runtime/email.js.map +1 -0
- package/dist/runtime/index.d.ts +11 -1
- package/dist/runtime/index.js +30 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/secrets.d.ts +3 -1
- package/dist/secrets.js +15 -8
- package/dist/secrets.js.map +1 -1
- package/dist/workflow.d.ts +3 -1
- package/dist/workflow.js +9 -5
- package/dist/workflow.js.map +1 -1
- package/dist/wrangler-config.d.ts +2 -1
- package/dist/wrangler-config.js +2 -1
- package/dist/wrangler-config.js.map +1 -1
- package/package.json +12 -3
- package/schema.json +50 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Cloudflare, Hyperdrive, Zone } from "../ports.js";
|
|
1
|
+
import type { Cloudflare, DnsRecord, Hyperdrive, Zone, ZoneRecord } from "../ports.js";
|
|
2
2
|
export declare class CloudflareApi implements Cloudflare {
|
|
3
3
|
private readonly client;
|
|
4
4
|
private account;
|
|
@@ -11,4 +11,10 @@ export declare class CloudflareApi implements Cloudflare {
|
|
|
11
11
|
deleteHyperdrive(id: string): Promise<void>;
|
|
12
12
|
findWorker(name: string): Promise<boolean>;
|
|
13
13
|
deleteWorker(name: string): Promise<void>;
|
|
14
|
+
workerSecretNames(worker: string): Promise<string[]>;
|
|
15
|
+
dnsRecords(zoneId: string, name: string): Promise<ZoneRecord[]>;
|
|
16
|
+
managedDnsRecords(zoneId: string): Promise<ZoneRecord[]>;
|
|
17
|
+
deleteDnsRecord(zoneId: string, id: string): Promise<void>;
|
|
18
|
+
private listRecords;
|
|
19
|
+
createDnsRecord(zoneId: string, record: DnsRecord): Promise<void>;
|
|
14
20
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import CloudflareClient from "cloudflare";
|
|
2
|
+
import { MANAGED_COMMENT } from "../lifecycle.js";
|
|
2
3
|
import { originOf } from "../target.js";
|
|
3
4
|
export class CloudflareApi {
|
|
4
5
|
client;
|
|
@@ -63,6 +64,44 @@ export class CloudflareApi {
|
|
|
63
64
|
async deleteWorker(name) {
|
|
64
65
|
await this.client.workers.scripts.delete(name, { account_id: await this.accountId(), force: true });
|
|
65
66
|
}
|
|
67
|
+
async workerSecretNames(worker) {
|
|
68
|
+
if (!(await this.findWorker(worker)))
|
|
69
|
+
return [];
|
|
70
|
+
const names = [];
|
|
71
|
+
for await (const secret of this.client.workers.scripts.secrets.list(worker, { account_id: await this.accountId() })) {
|
|
72
|
+
if (secret.name)
|
|
73
|
+
names.push(secret.name);
|
|
74
|
+
}
|
|
75
|
+
return names;
|
|
76
|
+
}
|
|
77
|
+
async dnsRecords(zoneId, name) {
|
|
78
|
+
return this.listRecords({ zone_id: zoneId, name: { exact: name } });
|
|
79
|
+
}
|
|
80
|
+
async managedDnsRecords(zoneId) {
|
|
81
|
+
return this.listRecords({ zone_id: zoneId, comment: { exact: MANAGED_COMMENT } });
|
|
82
|
+
}
|
|
83
|
+
async deleteDnsRecord(zoneId, id) {
|
|
84
|
+
await this.client.dns.records.delete(id, { zone_id: zoneId });
|
|
85
|
+
}
|
|
86
|
+
async listRecords(params) {
|
|
87
|
+
const records = [];
|
|
88
|
+
for await (const r of this.client.dns.records.list(params)) {
|
|
89
|
+
const priority = "priority" in r ? r.priority : undefined;
|
|
90
|
+
records.push({ id: r.id, type: r.type, name: r.name, content: String(r.content ?? ""), ...(priority !== undefined && { priority }), managed: r.comment === MANAGED_COMMENT });
|
|
91
|
+
}
|
|
92
|
+
return records;
|
|
93
|
+
}
|
|
94
|
+
async createDnsRecord(zoneId, record) {
|
|
95
|
+
await this.client.dns.records.create({
|
|
96
|
+
zone_id: zoneId,
|
|
97
|
+
type: record.type,
|
|
98
|
+
name: record.name,
|
|
99
|
+
content: record.content,
|
|
100
|
+
ttl: 1,
|
|
101
|
+
comment: MANAGED_COMMENT,
|
|
102
|
+
...(record.priority !== undefined && { priority: record.priority }),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
66
105
|
}
|
|
67
106
|
function originParams(connectionUri) {
|
|
68
107
|
const url = new URL(connectionUri);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/adapters/cloudflare.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/adapters/cloudflare.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,11 @@ export declare class WranglerCli implements Wrangler {
|
|
|
6
6
|
CLOUDFLARE_API_TOKEN: string;
|
|
7
7
|
});
|
|
8
8
|
deploy(config: object, secrets: Record<string, string>): Promise<void>;
|
|
9
|
+
dev(config: object, secrets: Record<string, string>, databaseUrl: string | undefined): Promise<void>;
|
|
9
10
|
}
|
|
10
11
|
export declare class ShellMigrator implements Migrator {
|
|
11
12
|
private readonly appDir;
|
|
12
13
|
constructor(appDir: string);
|
|
13
14
|
migrate(command: string, databaseUrl: string): Promise<void>;
|
|
15
|
+
migrateAuth(databaseUrl: string): Promise<void>;
|
|
14
16
|
}
|
package/dist/adapters/process.js
CHANGED
|
@@ -2,6 +2,8 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
+
import { getMigrations } from "better-auth/db/migration";
|
|
6
|
+
import { authOptions, authPool } from "../runtime/auth.js";
|
|
5
7
|
export class WranglerCli {
|
|
6
8
|
appDir;
|
|
7
9
|
env;
|
|
@@ -15,8 +17,7 @@ export class WranglerCli {
|
|
|
15
17
|
await writeFile(configFile, JSON.stringify(config, null, 2));
|
|
16
18
|
await writeFile(secretsFile, JSON.stringify(secrets), { mode: 0o600 });
|
|
17
19
|
try {
|
|
18
|
-
|
|
19
|
-
await run("wrangler deploy", process.execPath, [wrangler, "deploy", "--config", configFile, "--secrets-file", secretsFile], {
|
|
20
|
+
await run("wrangler deploy", process.execPath, [wranglerBin(), "deploy", "--config", configFile, "--secrets-file", secretsFile], {
|
|
20
21
|
cwd: this.appDir,
|
|
21
22
|
env: { ...process.env, ...this.env },
|
|
22
23
|
});
|
|
@@ -26,6 +27,27 @@ export class WranglerCli {
|
|
|
26
27
|
await rm(configFile, { force: true });
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
// wrangler dev reads secrets from a .dev.vars file beside its config, and takes the local
|
|
31
|
+
// database through an environment variable in place of the Hyperdrive binding.
|
|
32
|
+
async dev(config, secrets, databaseUrl) {
|
|
33
|
+
const configFile = join(this.appDir, ".platform-wrangler.json");
|
|
34
|
+
const devVars = join(this.appDir, ".dev.vars");
|
|
35
|
+
await writeFile(configFile, JSON.stringify(config, null, 2));
|
|
36
|
+
await writeFile(devVars, Object.entries(secrets).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join("\n") + "\n", { mode: 0o600 });
|
|
37
|
+
try {
|
|
38
|
+
await run("wrangler dev", process.execPath, [wranglerBin(), "dev", "--config", configFile], {
|
|
39
|
+
cwd: this.appDir,
|
|
40
|
+
env: { ...process.env, ...this.env, ...(databaseUrl && { CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_DB: databaseUrl }) },
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
await rm(devVars, { force: true });
|
|
45
|
+
await rm(configFile, { force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function wranglerBin() {
|
|
50
|
+
return join(dirname(createRequire(import.meta.url).resolve("wrangler/package.json")), "bin", "wrangler.js");
|
|
29
51
|
}
|
|
30
52
|
export class ShellMigrator {
|
|
31
53
|
appDir;
|
|
@@ -35,6 +57,17 @@ export class ShellMigrator {
|
|
|
35
57
|
async migrate(command, databaseUrl) {
|
|
36
58
|
await run(`migrations (${command})`, command, [], { cwd: this.appDir, env: { ...process.env, DATABASE_URL: databaseUrl }, shell: true });
|
|
37
59
|
}
|
|
60
|
+
async migrateAuth(databaseUrl) {
|
|
61
|
+
const pool = authPool(databaseUrl);
|
|
62
|
+
try {
|
|
63
|
+
const options = authOptions({ pool, secret: "migrations-only", baseURL: "http://localhost", email: { send: async () => { } }, requireVerification: false });
|
|
64
|
+
const { runMigrations } = await getMigrations(options);
|
|
65
|
+
await runMigrations();
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
await pool.end();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
38
71
|
}
|
|
39
72
|
function run(label, command, args, options) {
|
|
40
73
|
return new Promise((resolve, reject) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/adapters/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/adapters/process.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Mail, MailDomain } from "../ports.js";
|
|
2
|
+
export declare class ResendApi implements Mail {
|
|
3
|
+
private readonly apiKey;
|
|
4
|
+
private readonly fetcher;
|
|
5
|
+
constructor(apiKey: string, fetcher?: typeof fetch);
|
|
6
|
+
findDomain(name: string): Promise<MailDomain | undefined>;
|
|
7
|
+
createDomain(name: string): Promise<MailDomain>;
|
|
8
|
+
verifyDomain(id: string): Promise<void>;
|
|
9
|
+
findApiKey(name: string): Promise<string | undefined>;
|
|
10
|
+
createSendKey(name: string, domainId: string): Promise<string>;
|
|
11
|
+
deleteApiKey(id: string): Promise<void>;
|
|
12
|
+
private toDomain;
|
|
13
|
+
private call;
|
|
14
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export class ResendApi {
|
|
2
|
+
apiKey;
|
|
3
|
+
fetcher;
|
|
4
|
+
constructor(apiKey, fetcher = fetch) {
|
|
5
|
+
this.apiKey = apiKey;
|
|
6
|
+
this.fetcher = fetcher;
|
|
7
|
+
}
|
|
8
|
+
async findDomain(name) {
|
|
9
|
+
const { data } = await this.call("GET", "/domains");
|
|
10
|
+
const found = data.find((d) => d.name === name);
|
|
11
|
+
return found && this.toDomain(await this.call("GET", `/domains/${found.id}`));
|
|
12
|
+
}
|
|
13
|
+
async createDomain(name) {
|
|
14
|
+
return this.toDomain(await this.call("POST", "/domains", { name }));
|
|
15
|
+
}
|
|
16
|
+
async verifyDomain(id) {
|
|
17
|
+
await this.call("POST", `/domains/${id}/verify`);
|
|
18
|
+
}
|
|
19
|
+
async findApiKey(name) {
|
|
20
|
+
const { data } = await this.call("GET", "/api-keys");
|
|
21
|
+
return data.find((k) => k.name === name)?.id;
|
|
22
|
+
}
|
|
23
|
+
async createSendKey(name, domainId) {
|
|
24
|
+
const { token } = await this.call("POST", "/api-keys", { name, permission: "sending_access", domain_id: domainId });
|
|
25
|
+
return token;
|
|
26
|
+
}
|
|
27
|
+
async deleteApiKey(id) {
|
|
28
|
+
await this.call("DELETE", `/api-keys/${id}`);
|
|
29
|
+
}
|
|
30
|
+
toDomain(d) {
|
|
31
|
+
return {
|
|
32
|
+
id: d.id,
|
|
33
|
+
name: d.name,
|
|
34
|
+
verified: d.status === "verified",
|
|
35
|
+
records: (d.records ?? []).map((r) => ({ type: r.type, name: r.name, content: r.value, ...(r.priority !== undefined && { priority: r.priority }) })),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async call(method, path, body) {
|
|
39
|
+
const response = await this.fetcher(`https://api.resend.com${path}`, {
|
|
40
|
+
method,
|
|
41
|
+
headers: { authorization: `Bearer ${this.apiKey}`, "content-type": "application/json" },
|
|
42
|
+
...(body && { body: JSON.stringify(body) }),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok)
|
|
45
|
+
throw new Error(`Resend ${method} ${path} failed: ${response.status} ${await response.text()}`);
|
|
46
|
+
const text = await response.text();
|
|
47
|
+
return (text ? JSON.parse(text) : {});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=resend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resend.js","sourceRoot":"","sources":["../../src/adapters/resend.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,SAAS;IAED,MAAM;IACN,OAAO;IAF1B,YACmB,MAAc,EACd,OAAO,GAAiB,KAAK;sBAD7B,MAAM;uBACN,OAAO;IACvB,CAAC;IAEJ,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAA2B,KAAK,EAAE,UAAU,CAAC,CAAC;QAC9E,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAChD,OAAO,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAe,KAAK,EAAE,YAAY,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAe,MAAM,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAU;QAC3B,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAA2C,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/F,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY,EAAE,QAAgB;QAChD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAoB,MAAM,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvI,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAU;QAC3B,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAEO,QAAQ,CAAC,CAAe;QAC9B,OAAO;YACL,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,MAAM,KAAK,UAAU;YACjC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;SACrJ,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,IAAI,CAAc,MAAc,EAAE,IAAY,EAAE,IAAa;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,yBAAyB,IAAI,EAAE,EAAE;YACnE,MAAM;YACN,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YACvF,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;SAC5C,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,IAAI,IAAI,YAAY,QAAQ,CAAC,MAAM,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAM,CAAC;IAC7C,CAAC;CACF"}
|
package/dist/cli.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFileSync } from "node:child_process";
|
|
3
3
|
import { readFile } from "node:fs/promises";
|
|
4
|
-
import { resolve } from "node:path";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
5
|
import { parseArgs } from "node:util";
|
|
6
6
|
import { CloudflareApi } from "./adapters/cloudflare.js";
|
|
7
7
|
import { commentPreviewLink, GhCli } from "./adapters/github.js";
|
|
8
8
|
import { NeonApi } from "./adapters/neon.js";
|
|
9
|
+
import { ResendApi } from "./adapters/resend.js";
|
|
9
10
|
import { ShellMigrator, WranglerCli } from "./adapters/process.js";
|
|
10
|
-
import { ConfigError,
|
|
11
|
-
import { checkWorkflow, init } from "./init.js";
|
|
12
|
-
import { cleanup, deploy, PreflightError } from "./lifecycle.js";
|
|
11
|
+
import { CONFIG_FILE, ConfigError, configVariables, parseConfig, readConfigText } from "./config.js";
|
|
12
|
+
import { checkWorkflow, init, tokenNames } from "./init.js";
|
|
13
|
+
import { cleanup, deploy, dev, PreflightError } from "./lifecycle.js";
|
|
13
14
|
import { Run } from "./run.js";
|
|
14
|
-
import { loadSecrets } from "./secrets.js";
|
|
15
|
+
import { loadSecrets, loadVars } from "./secrets.js";
|
|
15
16
|
const usage = `usage: platform <command> [--dry-run] [--dir <app dir>]
|
|
16
17
|
|
|
17
18
|
commands:
|
|
18
19
|
init set up GitHub secrets, Environments and the deploy workflow
|
|
20
|
+
dev run the app locally against its own Neon branch
|
|
19
21
|
deploy deploy prod
|
|
20
22
|
preview <pr> create or update the preview for a pull request
|
|
21
23
|
cleanup <pr> delete the preview for a pull request
|
|
@@ -39,27 +41,34 @@ async function main(argv) {
|
|
|
39
41
|
return;
|
|
40
42
|
}
|
|
41
43
|
if (command.name === "init") {
|
|
42
|
-
const config = await
|
|
44
|
+
const { config, variables } = await loadApp(appDir);
|
|
43
45
|
await init({
|
|
44
46
|
repoRoot: repoRoot(appDir),
|
|
45
47
|
appDir,
|
|
46
48
|
config,
|
|
49
|
+
variables,
|
|
47
50
|
run: new Run(dryRun, (line) => console.log(line)),
|
|
48
51
|
connect: (tokens) => ({
|
|
49
52
|
cloudflare: new CloudflareApi(tokens.CLOUDFLARE_API_TOKEN),
|
|
50
53
|
neon: new NeonApi(tokens.NEON_API_KEY ?? ""),
|
|
54
|
+
mail: new ResendApi(tokens.RESEND_API_KEY ?? ""),
|
|
51
55
|
github: new GhCli(repoRoot(appDir)),
|
|
52
56
|
}),
|
|
53
57
|
});
|
|
54
58
|
return;
|
|
55
59
|
}
|
|
60
|
+
const app = await loadApp(appDir);
|
|
56
61
|
if (inCi)
|
|
57
|
-
await checkWorkflow(repoRoot(appDir), appDir);
|
|
58
|
-
const ctx = await context(appDir, dryRun);
|
|
62
|
+
await checkWorkflow(repoRoot(appDir), appDir, app.config, Object.keys(app.variables));
|
|
63
|
+
const ctx = await context(appDir, app.config, dryRun);
|
|
59
64
|
if (command.name === "cleanup") {
|
|
60
65
|
await cleanup(ctx, command.pr);
|
|
61
66
|
return;
|
|
62
67
|
}
|
|
68
|
+
if (command.name === "dev") {
|
|
69
|
+
await dev(ctx);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
63
72
|
const { hostname } = await deploy(ctx, command.name === "deploy" ? { kind: "prod" } : { kind: "preview", pr: command.pr });
|
|
64
73
|
if (dryRun)
|
|
65
74
|
return;
|
|
@@ -71,7 +80,7 @@ async function main(argv) {
|
|
|
71
80
|
}
|
|
72
81
|
}
|
|
73
82
|
function parseCommand([name, pr]) {
|
|
74
|
-
if (name === "init" || name === "deploy")
|
|
83
|
+
if (name === "init" || name === "dev" || name === "deploy")
|
|
75
84
|
return { name };
|
|
76
85
|
if (name === "preview" || name === "cleanup")
|
|
77
86
|
return { name, pr: prNumber(pr) };
|
|
@@ -89,11 +98,19 @@ async function commandForGitHubEvent() {
|
|
|
89
98
|
return event.action === "closed" ? { name: "cleanup", pr: event.number } : { name: "preview", pr: event.number, sha: event.pull_request?.head?.sha };
|
|
90
99
|
return undefined;
|
|
91
100
|
}
|
|
92
|
-
async function
|
|
93
|
-
const
|
|
94
|
-
const
|
|
101
|
+
async function loadApp(appDir) {
|
|
102
|
+
const text = await readConfigText(appDir);
|
|
103
|
+
const names = configVariables(text);
|
|
104
|
+
const vars = await loadVars(appDir, names);
|
|
105
|
+
const variables = Object.fromEntries(names.filter((name) => vars[name]).map((name) => [name, vars[name]]));
|
|
106
|
+
maskInCi(Object.values(variables));
|
|
107
|
+
return { config: parseConfig(text, join(appDir, CONFIG_FILE), variables), variables };
|
|
108
|
+
}
|
|
109
|
+
async function context(appDir, config, dryRun) {
|
|
110
|
+
const secrets = await loadSecrets(appDir, [...tokenNames(config), ...config.secrets]);
|
|
95
111
|
const cloudflareToken = requireToken(secrets, "CLOUDFLARE_API_TOKEN");
|
|
96
112
|
const neonKey = config.database ? requireToken(secrets, "NEON_API_KEY") : "";
|
|
113
|
+
const resendKey = config.email ? requireToken(secrets, "RESEND_API_KEY") : "";
|
|
97
114
|
return {
|
|
98
115
|
config,
|
|
99
116
|
secrets,
|
|
@@ -101,6 +118,7 @@ async function context(appDir, dryRun) {
|
|
|
101
118
|
ports: {
|
|
102
119
|
cloudflare: new CloudflareApi(cloudflareToken),
|
|
103
120
|
neon: new NeonApi(neonKey),
|
|
121
|
+
mail: new ResendApi(resendKey),
|
|
104
122
|
wrangler: new WranglerCli(appDir, { CLOUDFLARE_API_TOKEN: cloudflareToken }),
|
|
105
123
|
migrator: new ShellMigrator(appDir),
|
|
106
124
|
},
|
|
@@ -126,6 +144,18 @@ function prNumber(value) {
|
|
|
126
144
|
throw new UsageError(`expected a pull request number, got ${value ?? "nothing"}`);
|
|
127
145
|
return pr;
|
|
128
146
|
}
|
|
147
|
+
// GitHub only hides secrets in logs; variables keep values out of the repo, so keep them out of
|
|
148
|
+
// public logs too, along with each parent domain of a hostname so preview hostnames are hidden.
|
|
149
|
+
function maskInCi(values) {
|
|
150
|
+
if (process.env.GITHUB_ACTIONS !== "true")
|
|
151
|
+
return;
|
|
152
|
+
for (const value of values) {
|
|
153
|
+
const labels = value.split(".");
|
|
154
|
+
const parents = labels.slice(1, -1).map((_, i) => labels.slice(i + 1).join("."));
|
|
155
|
+
for (const masked of [value, ...parents])
|
|
156
|
+
console.log(`::add-mask::${masked}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
129
159
|
class UsageError extends Error {
|
|
130
160
|
}
|
|
131
161
|
main(process.argv.slice(2)).catch((error) => {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -13,11 +13,15 @@ export declare const configSchema: z.ZodObject<{
|
|
|
13
13
|
neonProject: z.ZodString;
|
|
14
14
|
migrate: z.ZodString;
|
|
15
15
|
}, z.core.$strict>>;
|
|
16
|
+
email: z.ZodDefault<z.ZodBoolean>;
|
|
17
|
+
auth: z.ZodDefault<z.ZodBoolean>;
|
|
16
18
|
secrets: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
17
19
|
}, z.core.$strict>;
|
|
18
20
|
export type Config = z.output<typeof configSchema>;
|
|
19
21
|
export declare class ConfigError extends Error {
|
|
20
22
|
}
|
|
21
|
-
export declare function
|
|
22
|
-
export declare function
|
|
23
|
+
export declare function configVariables(text: string): string[];
|
|
24
|
+
export declare function parseConfig(text: string, source?: string, vars?: Record<string, string>): Config;
|
|
25
|
+
export declare function readConfigText(dir: string): Promise<string>;
|
|
26
|
+
export declare function loadConfig(dir: string, vars?: Record<string, string>): Promise<Config>;
|
|
23
27
|
export declare function configJsonSchema(): object;
|
package/dist/config.js
CHANGED
|
@@ -19,23 +19,35 @@ export const configSchema = z
|
|
|
19
19
|
frontend: z.string().min(1).optional().describe("Directory holding the built static files"),
|
|
20
20
|
database: z
|
|
21
21
|
.object({
|
|
22
|
-
neonProject: z.string().regex(/^[a-z]+-[a-z]+-\d+$/, "must be a Neon project id such as
|
|
22
|
+
neonProject: z.string().regex(/^[a-z]+-[a-z]+-\d+$/, "must be a Neon project id such as quiet-meadow-12345678, not a branch id"),
|
|
23
23
|
migrate: z.string().min(1).describe("Command that runs migrations against $DATABASE_URL"),
|
|
24
24
|
})
|
|
25
25
|
.strict()
|
|
26
26
|
.optional(),
|
|
27
|
+
email: z.boolean().default(false).describe("Send email through Resend from noreply@ the app's own hostname; the app only sends"),
|
|
28
|
+
auth: z.boolean().default(false).describe("Sign-up and login with email and password; needs database and email"),
|
|
27
29
|
secrets: z.array(z.string().regex(/^[A-Z][A-Z0-9_]*$/, "must be an UPPER_SNAKE_CASE name")).default([]),
|
|
28
30
|
})
|
|
29
|
-
.strict()
|
|
31
|
+
.strict()
|
|
32
|
+
.refine((c) => !c.auth || (c.database && c.email), { message: "auth needs both database and email", path: ["auth"] });
|
|
30
33
|
export class ConfigError extends Error {
|
|
31
34
|
}
|
|
32
|
-
|
|
35
|
+
const VARIABLE = /\$\{([A-Z][A-Z0-9_]*)\}/g;
|
|
36
|
+
export function configVariables(text) {
|
|
37
|
+
return [...new Set([...text.matchAll(VARIABLE)].map((m) => m[1]))];
|
|
38
|
+
}
|
|
39
|
+
export function parseConfig(text, source = CONFIG_FILE, vars = {}) {
|
|
33
40
|
const errors = [];
|
|
34
|
-
const
|
|
41
|
+
const parsed = parse(text, errors, { allowTrailingComma: true });
|
|
35
42
|
if (errors.length > 0) {
|
|
36
43
|
const first = errors[0];
|
|
37
44
|
throw new ConfigError(`${source}: ${printParseErrorCode(first.error)} at offset ${first.offset}`);
|
|
38
45
|
}
|
|
46
|
+
const missing = configVariables(text).filter((name) => !vars[name]);
|
|
47
|
+
if (missing.length > 0) {
|
|
48
|
+
throw new ConfigError(`${source} uses ${missing.join(", ")}; set them in .env, then run \`platform init\` to copy them to GitHub`);
|
|
49
|
+
}
|
|
50
|
+
const raw = substitute(parsed, vars);
|
|
39
51
|
if (isObject(raw) && typeof raw.version === "number" && raw.version < CONFIG_VERSION) {
|
|
40
52
|
throw new ConfigError(`${source}: version ${raw.version} is older than this platform's ${CONFIG_VERSION}; run \`platform upgrade\``);
|
|
41
53
|
}
|
|
@@ -46,19 +58,42 @@ export function parseConfig(text, source = CONFIG_FILE) {
|
|
|
46
58
|
}
|
|
47
59
|
return result.data;
|
|
48
60
|
}
|
|
49
|
-
export async function
|
|
61
|
+
export async function readConfigText(dir) {
|
|
50
62
|
const path = join(dir, CONFIG_FILE);
|
|
51
|
-
let text;
|
|
52
63
|
try {
|
|
53
|
-
|
|
64
|
+
return await readFile(path, "utf8");
|
|
54
65
|
}
|
|
55
66
|
catch {
|
|
56
67
|
throw new ConfigError(`${path} not found; run \`platform init\``);
|
|
57
68
|
}
|
|
58
|
-
|
|
69
|
+
}
|
|
70
|
+
export async function loadConfig(dir, vars = {}) {
|
|
71
|
+
return parseConfig(await readConfigText(dir), join(dir, CONFIG_FILE), vars);
|
|
59
72
|
}
|
|
60
73
|
export function configJsonSchema() {
|
|
61
|
-
return z.toJSONSchema(configSchema, { io: "input" });
|
|
74
|
+
return allowVariables(z.toJSONSchema(configSchema, { io: "input" }));
|
|
75
|
+
}
|
|
76
|
+
function substitute(value, vars) {
|
|
77
|
+
if (typeof value === "string")
|
|
78
|
+
return value.replace(VARIABLE, (_, name) => vars[name]);
|
|
79
|
+
if (Array.isArray(value))
|
|
80
|
+
return value.map((item) => substitute(item, vars));
|
|
81
|
+
if (isObject(value))
|
|
82
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, substitute(v, vars)]));
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
// Editors validate the file before substitution, so a patterned string may also be a ${NAME} reference.
|
|
86
|
+
function allowVariables(schema) {
|
|
87
|
+
if (Array.isArray(schema))
|
|
88
|
+
return schema.map(allowVariables);
|
|
89
|
+
if (!isObject(schema))
|
|
90
|
+
return schema;
|
|
91
|
+
const out = Object.fromEntries(Object.entries(schema).map(([k, v]) => [k, allowVariables(v)]));
|
|
92
|
+
if (typeof out.pattern === "string") {
|
|
93
|
+
const { pattern, ...rest } = out;
|
|
94
|
+
return { ...rest, anyOf: [{ pattern }, { pattern: "^\\$\\{[A-Z][A-Z0-9_]*\\}$" }] };
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
62
97
|
}
|
|
63
98
|
function isObject(value) {
|
|
64
99
|
return typeof value === "object" && value !== null;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAmB,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAG,CAAC;KACf,MAAM,EAAE;KACR,KAAK,CAAC,mEAAmE,EAAE,sDAAsD,CAAC,CAAC;AAEtI,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAClC,qFAAqF;IACrF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,wBAAwB,EAAE,6EAA6E,CAAC;IAC/H,QAAQ;IACR,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,+DAA+D,CAAC;IACnG,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,mCAAmC,CAAC;IAC/F,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC3F,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAmB,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,QAAQ,GAAG,CAAC;KACf,MAAM,EAAE;KACR,KAAK,CAAC,mEAAmE,EAAE,sDAAsD,CAAC,CAAC;AAEtI,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAClC,qFAAqF;IACrF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,wBAAwB,EAAE,6EAA6E,CAAC;IAC/H,QAAQ;IACR,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,+DAA+D,CAAC;IACnG,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,mCAAmC,CAAC;IAC/F,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAC3F,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,0EAA0E,CAAC;QAChI,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oDAAoD,CAAC;KAC1F,CAAC;SACD,MAAM,EAAE;SACR,QAAQ,EAAE;IACb,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,oFAAoF,CAAC;IAChI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,qEAAqE,CAAC;IAChH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,EAAE,kCAAkC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxG,CAAC;KACD,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,oCAAoC,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAIxH,MAAM,OAAO,WAAY,SAAQ,KAAK;CAAG;AAEzC,MAAM,QAAQ,GAAG,0BAA0B,CAAC;AAE5C,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAM,GAAG,WAAW,EAAE,IAAI,GAA2B,EAAE;IAC/F,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAY,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACzB,MAAM,IAAI,WAAW,CAAC,GAAG,MAAM,KAAK,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,WAAW,CAAC,GAAG,MAAM,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;IACrI,CAAC;IACD,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAErC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,GAAG,cAAc,EAAE,CAAC;QACrF,MAAM,IAAI,WAAW,CAAC,GAAG,MAAM,aAAa,GAAG,CAAC,OAAO,kCAAkC,cAAc,4BAA4B,CAAC,CAAC;IACvI,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5G,MAAM,IAAI,WAAW,CAAC,GAAG,MAAM,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,GAAW;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CAAC,GAAG,IAAI,mCAAmC,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,IAAI,GAA2B,EAAE;IAC7E,OAAO,WAAW,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,UAAU,CAAC,KAAc,EAAE,IAA4B;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC,CAAC;IAChG,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7E,IAAI,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wGAAwG;AACxG,SAAS,cAAc,CAAC,MAAe;IACrC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC7D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,MAAgB,CAAC;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;QACjC,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC,EAAE,CAAC;IACtF,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC"}
|
package/dist/fakes.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Branch, Cloudflare, Hyperdrive, Migrator, Neon, Wrangler, Zone } from "./ports.js";
|
|
1
|
+
import type { Branch, Cloudflare, DnsRecord, Hyperdrive, Mail, MailDomain, Migrator, Neon, Wrangler, Zone, ZoneRecord } from "./ports.js";
|
|
2
2
|
export declare class FakeNeon implements Neon {
|
|
3
3
|
branches: Branch[];
|
|
4
4
|
private next;
|
|
@@ -16,6 +16,8 @@ export declare class FakeCloudflare implements Cloudflare {
|
|
|
16
16
|
zones: Zone[];
|
|
17
17
|
hyperdrives: Hyperdrive[];
|
|
18
18
|
workers: Set<string>;
|
|
19
|
+
workerSecrets: Map<string, Set<string>>;
|
|
20
|
+
records: ZoneRecord[];
|
|
19
21
|
private next;
|
|
20
22
|
accountId(): Promise<string>;
|
|
21
23
|
findZone(hostname: string): Promise<Zone | undefined>;
|
|
@@ -30,6 +32,41 @@ export declare class FakeCloudflare implements Cloudflare {
|
|
|
30
32
|
deleteHyperdrive(id: string): Promise<void>;
|
|
31
33
|
findWorker(name: string): Promise<boolean>;
|
|
32
34
|
deleteWorker(name: string): Promise<void>;
|
|
35
|
+
workerSecretNames(worker: string): Promise<string[]>;
|
|
36
|
+
dnsRecords(_zoneId: string, name: string): Promise<ZoneRecord[]>;
|
|
37
|
+
managedDnsRecords(): Promise<ZoneRecord[]>;
|
|
38
|
+
deleteDnsRecord(_zoneId: string, id: string): Promise<void>;
|
|
39
|
+
createDnsRecord(_zoneId: string, record: DnsRecord): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export declare class FakeMail implements Mail {
|
|
42
|
+
domains: MailDomain[];
|
|
43
|
+
keys: {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
domainId: string;
|
|
47
|
+
}[];
|
|
48
|
+
private next;
|
|
49
|
+
findDomain(name: string): Promise<MailDomain | undefined>;
|
|
50
|
+
createDomain(name: string): Promise<{
|
|
51
|
+
id: string;
|
|
52
|
+
name: string;
|
|
53
|
+
verified: boolean;
|
|
54
|
+
records: ({
|
|
55
|
+
type: string;
|
|
56
|
+
name: string;
|
|
57
|
+
content: string;
|
|
58
|
+
priority?: undefined;
|
|
59
|
+
} | {
|
|
60
|
+
type: string;
|
|
61
|
+
name: string;
|
|
62
|
+
content: string;
|
|
63
|
+
priority: number;
|
|
64
|
+
})[];
|
|
65
|
+
}>;
|
|
66
|
+
verifyDomain(id: string): Promise<void>;
|
|
67
|
+
findApiKey(name: string): Promise<string | undefined>;
|
|
68
|
+
createSendKey(name: string, domainId: string): Promise<string>;
|
|
69
|
+
deleteApiKey(id: string): Promise<void>;
|
|
33
70
|
}
|
|
34
71
|
export declare class FakeWrangler implements Wrangler {
|
|
35
72
|
private readonly cloudflare;
|
|
@@ -37,17 +74,26 @@ export declare class FakeWrangler implements Wrangler {
|
|
|
37
74
|
config: Record<string, unknown>;
|
|
38
75
|
secrets: Record<string, string>;
|
|
39
76
|
}[];
|
|
77
|
+
devRuns: {
|
|
78
|
+
config: Record<string, unknown>;
|
|
79
|
+
secrets: Record<string, string>;
|
|
80
|
+
databaseUrl: string | undefined;
|
|
81
|
+
}[];
|
|
40
82
|
constructor(cloudflare: FakeCloudflare);
|
|
83
|
+
dev(config: object, secrets: Record<string, string>, databaseUrl: string | undefined): Promise<void>;
|
|
41
84
|
deploy(config: object, secrets: Record<string, string>): Promise<void>;
|
|
42
85
|
}
|
|
43
86
|
export declare class FakeMigrator implements Migrator {
|
|
44
87
|
runs: string[];
|
|
88
|
+
authRuns: string[];
|
|
45
89
|
failWith: Error | undefined;
|
|
46
90
|
migrate(_command: string, databaseUrl: string): Promise<void>;
|
|
91
|
+
migrateAuth(databaseUrl: string): Promise<void>;
|
|
47
92
|
}
|
|
48
93
|
export declare function fakePorts(): {
|
|
49
94
|
neon: FakeNeon;
|
|
50
95
|
cloudflare: FakeCloudflare;
|
|
96
|
+
mail: FakeMail;
|
|
51
97
|
wrangler: FakeWrangler;
|
|
52
98
|
migrator: FakeMigrator;
|
|
53
99
|
};
|