@heychunky/core 0.1.1 → 0.2.1
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/apps.d.ts +20 -5
- package/dist/admin/apps.d.ts.map +1 -1
- package/dist/admin/apps.js +8 -24
- package/dist/admin/apps.js.map +1 -1
- package/dist/admin/master.d.ts +24 -7
- package/dist/admin/master.d.ts.map +1 -1
- package/dist/admin/master.js +17 -8
- package/dist/admin/master.js.map +1 -1
- package/dist/admin/services/neon.d.ts.map +1 -1
- package/dist/admin/services/neon.js +30 -8
- package/dist/admin/services/neon.js.map +1 -1
- package/dist/admin/users.d.ts +16 -3
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +4 -18
- package/dist/admin/users.js.map +1 -1
- package/dist/http/errors.d.ts +11 -0
- package/dist/http/errors.d.ts.map +1 -1
- package/dist/http/errors.js +15 -0
- package/dist/http/errors.js.map +1 -1
- package/package.json +1 -1
package/dist/admin/apps.d.ts
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The register of apps the factory has made.
|
|
3
|
+
*
|
|
4
|
+
* This used to be JSON files under ~/.heychunky/runs, which is exactly right
|
|
5
|
+
* for one operator on one machine and wrong for everything after: a second
|
|
6
|
+
* machine knows nothing, the worker cannot see what exists, and no row anywhere
|
|
7
|
+
* says whose an app is. It lives in the factory's own database now.
|
|
8
|
+
*
|
|
9
|
+
* `owner_id` is the tenancy boundary. Every question about what a developer may
|
|
10
|
+
* see is a `where owner_id = $1`, and superadmin is the role that omits it —
|
|
11
|
+
* which is why that column exists before there is a second user to put in it.
|
|
12
|
+
*
|
|
13
|
+
* The local history is not replaced by this: it records what a *run* did, step
|
|
14
|
+
* by step, and stays useful for exactly that. This records what an app *is*.
|
|
15
|
+
*/
|
|
16
|
+
import type { Register } from "./master.ts";
|
|
2
17
|
export interface App {
|
|
3
18
|
id: string;
|
|
4
19
|
name: string;
|
|
@@ -23,7 +38,7 @@ export interface AppRecord {
|
|
|
23
38
|
neonProject?: string | undefined;
|
|
24
39
|
}
|
|
25
40
|
/** The user id for an email, or the sole superadmin when none is named. */
|
|
26
|
-
export declare function ownerId(email: string | undefined,
|
|
41
|
+
export declare function ownerId(email: string | undefined, register: Register): Promise<string>;
|
|
27
42
|
/**
|
|
28
43
|
* Refuse before anything is created, if the owner is at their limit.
|
|
29
44
|
*
|
|
@@ -35,7 +50,7 @@ export declare function ownerId(email: string | undefined, ctx: RunContext): Pro
|
|
|
35
50
|
* not billing — it is the thing that makes inviting someone a bounded
|
|
36
51
|
* decision, which is what lets invitations be given out at all.
|
|
37
52
|
*/
|
|
38
|
-
export declare function assertCanCreate(owner: string,
|
|
53
|
+
export declare function assertCanCreate(owner: string, register: Register): Promise<void>;
|
|
39
54
|
/**
|
|
40
55
|
* Record an app, or update what is known about one.
|
|
41
56
|
*
|
|
@@ -43,7 +58,7 @@ export declare function assertCanCreate(owner: string, ctx: RunContext): Promise
|
|
|
43
58
|
* Vercel project and a database all carry it. Re-running provisioning fills in
|
|
44
59
|
* what a first, partial run could not, rather than making a second row.
|
|
45
60
|
*/
|
|
46
|
-
export declare function recordApp(app: AppRecord,
|
|
61
|
+
export declare function recordApp(app: AppRecord, register: Register): Promise<App>;
|
|
47
62
|
/** Apps an owner has, or every app when none is named. */
|
|
48
|
-
export declare function listApps(owner: string | undefined,
|
|
63
|
+
export declare function listApps(owner: string | undefined, register: Register): Promise<App[]>;
|
|
49
64
|
//# sourceMappingURL=apps.d.ts.map
|
package/dist/admin/apps.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/admin/apps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/admin/apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,sEAAsE;AACtE,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBACX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAKzC;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,2EAA2E;AAC3E,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAc5F;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAYtF;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAehF;AAED,0DAA0D;AAC1D,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAU5F"}
|
package/dist/admin/apps.js
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The register of apps the factory has made.
|
|
3
|
-
*
|
|
4
|
-
* This used to be JSON files under ~/.heychunky/runs, which is exactly right
|
|
5
|
-
* for one operator on one machine and wrong for everything after: a second
|
|
6
|
-
* machine knows nothing, the worker cannot see what exists, and no row anywhere
|
|
7
|
-
* says whose an app is. It lives in the factory's own database now.
|
|
8
|
-
*
|
|
9
|
-
* `owner_id` is the tenancy boundary. Every question about what a developer may
|
|
10
|
-
* see is a `where owner_id = $1`, and superadmin is the role that omits it —
|
|
11
|
-
* which is why that column exists before there is a second user to put in it.
|
|
12
|
-
*
|
|
13
|
-
* The local history is not replaced by this: it records what a *run* did, step
|
|
14
|
-
* by step, and stays useful for exactly that. This records what an app *is*.
|
|
15
|
-
*/
|
|
16
|
-
import { master } from "./master.js";
|
|
17
1
|
/** Refused because the owner already has as many apps as they may. */
|
|
18
2
|
export class AppLimitError extends Error {
|
|
19
3
|
limit;
|
|
@@ -24,8 +8,8 @@ export class AppLimitError extends Error {
|
|
|
24
8
|
}
|
|
25
9
|
}
|
|
26
10
|
/** The user id for an email, or the sole superadmin when none is named. */
|
|
27
|
-
export async function ownerId(email,
|
|
28
|
-
const conn =
|
|
11
|
+
export async function ownerId(email, register) {
|
|
12
|
+
const conn = register;
|
|
29
13
|
if (email) {
|
|
30
14
|
const { rows } = await conn.query("select id from users where lower(email) = lower($1)", [email]);
|
|
31
15
|
const id = rows[0]?.["id"];
|
|
@@ -52,8 +36,8 @@ export async function ownerId(email, ctx) {
|
|
|
52
36
|
* not billing — it is the thing that makes inviting someone a bounded
|
|
53
37
|
* decision, which is what lets invitations be given out at all.
|
|
54
38
|
*/
|
|
55
|
-
export async function assertCanCreate(owner,
|
|
56
|
-
const conn =
|
|
39
|
+
export async function assertCanCreate(owner, register) {
|
|
40
|
+
const conn = register;
|
|
57
41
|
const { rows } = await conn.query(`select u.email, u.app_limit,
|
|
58
42
|
(select count(*) from apps a where a.owner_id = u.id) as owned
|
|
59
43
|
from users u where u.id = $1`, [owner]);
|
|
@@ -71,8 +55,8 @@ export async function assertCanCreate(owner, ctx) {
|
|
|
71
55
|
* Vercel project and a database all carry it. Re-running provisioning fills in
|
|
72
56
|
* what a first, partial run could not, rather than making a second row.
|
|
73
57
|
*/
|
|
74
|
-
export async function recordApp(app,
|
|
75
|
-
const conn =
|
|
58
|
+
export async function recordApp(app, register) {
|
|
59
|
+
const conn = register;
|
|
76
60
|
const { rows } = await conn.write(`insert into apps (name, owner_id, org, repo, vercel_project, neon_project)
|
|
77
61
|
values ($1, $2, $3, $4, $5, $6)
|
|
78
62
|
on conflict (lower(name)) do update set
|
|
@@ -85,8 +69,8 @@ export async function recordApp(app, ctx) {
|
|
|
85
69
|
return rows[0];
|
|
86
70
|
}
|
|
87
71
|
/** Apps an owner has, or every app when none is named. */
|
|
88
|
-
export async function listApps(owner,
|
|
89
|
-
const conn =
|
|
72
|
+
export async function listApps(owner, register) {
|
|
73
|
+
const conn = register;
|
|
90
74
|
const { rows } = owner
|
|
91
75
|
? await conn.query(`select a.*, u.email as owner_email from apps a join users u on u.id = a.owner_id
|
|
92
76
|
where a.owner_id = $1 order by a.created_at`, [owner])
|
package/dist/admin/apps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/admin/apps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/admin/apps.ts"],"names":[],"mappings":"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"}
|
package/dist/admin/master.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The database that holds the register — who exists, and what they own.
|
|
3
|
+
*
|
|
4
|
+
* Passed in rather than named here. This module used to hardcode
|
|
5
|
+
* heychunky-app's production database, which made every register function
|
|
6
|
+
* reach past whatever environment its caller was running in: an API serving
|
|
7
|
+
* its dev database looked up users in production and did not find them.
|
|
8
|
+
*
|
|
9
|
+
* The caller knows which database it means. The CLI means the factory's, and
|
|
10
|
+
* says so; an app means its own, which it already holds a connection string
|
|
11
|
+
* for. Neither has to agree with a constant in here.
|
|
12
|
+
*/
|
|
13
|
+
import { db } from "../services/db.ts";
|
|
1
14
|
import type { RunContext } from "./run.ts";
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
15
|
+
/** What the register needs of a database. Satisfied by `db()`. */
|
|
16
|
+
export type Register = Pick<ReturnType<typeof db>, "query" | "write">;
|
|
17
|
+
/**
|
|
18
|
+
* The factory's own register: heychunky-app in production.
|
|
19
|
+
*
|
|
20
|
+
* One register for the operator side, because a developer's laptop and the
|
|
21
|
+
* worker must not each have their own idea of what exists. An app running in
|
|
22
|
+
* dev is a different case and passes its own.
|
|
23
|
+
*/
|
|
24
|
+
export declare const FACTORY_REGISTER = "infisical://heychunky-apps/production/heychunky-app/DATABASE_URL";
|
|
25
|
+
export declare const factoryRegister: (ctx: RunContext) => Promise<Register>;
|
|
9
26
|
//# sourceMappingURL=master.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master.d.ts","sourceRoot":"","sources":["../../src/admin/master.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"master.d.ts","sourceRoot":"","sources":["../../src/admin/master.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,kEAAkE;AAClE,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,qEACuC,CAAC;AAErE,eAAO,MAAM,eAAe,GAAU,KAAK,UAAU,KAAG,OAAO,CAAC,QAAQ,CAC3B,CAAC"}
|
package/dist/admin/master.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The database that holds the register — who exists, and what they own.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Passed in rather than named here. This module used to hardcode
|
|
5
|
+
* heychunky-app's production database, which made every register function
|
|
6
|
+
* reach past whatever environment its caller was running in: an API serving
|
|
7
|
+
* its dev database looked up users in production and did not find them.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
* app
|
|
9
|
+
* The caller knows which database it means. The CLI means the factory's, and
|
|
10
|
+
* says so; an app means its own, which it already holds a connection string
|
|
11
|
+
* for. Neither has to agree with a constant in here.
|
|
10
12
|
*/
|
|
11
13
|
import { db } from "../services/db.js";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The factory's own register: heychunky-app in production.
|
|
16
|
+
*
|
|
17
|
+
* One register for the operator side, because a developer's laptop and the
|
|
18
|
+
* worker must not each have their own idea of what exists. An app running in
|
|
19
|
+
* dev is a different case and passes its own.
|
|
20
|
+
*/
|
|
21
|
+
export const FACTORY_REGISTER = "infisical://heychunky-apps/production/heychunky-app/DATABASE_URL";
|
|
22
|
+
export const factoryRegister = async (ctx) => db(await ctx.secrets.get(FACTORY_REGISTER));
|
|
14
23
|
//# sourceMappingURL=master.js.map
|
package/dist/admin/master.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master.js","sourceRoot":"","sources":["../../src/admin/master.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"master.js","sourceRoot":"","sources":["../../src/admin/master.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AAMvC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B,kEAAkE,CAAC;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,GAAe,EAAqB,EAAE,CAC1E,EAAE,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon.d.ts","sourceRoot":"","sources":["../../../src/admin/services/neon.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"neon.d.ts","sourceRoot":"","sources":["../../../src/admin/services/neon.ts"],"names":[],"mappings":"AAQA,OAAO,EAAsB,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAIrG,MAAM,WAAW,WAAW;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAChG,MAAM,WAAW,UAAU;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE;AAEvH,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM;;YAKQ,MAAM;cAAQ,MAAM;cAAQ,MAAM;;oBAE/C,OAAO,CAAC,WAAW,EAAE,CAAC;wBAShB,MAAM,KAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;0BAelE,MAAM,SAAQ;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KACtD,OAAO,CAAC,WAAW,CAAC;0BAYY,MAAM;8BAqB5B,MAAM,QAAQ,MAAM,aAAa,MAAM,KACjD,OAAO,CAAC,UAAU,CAAC;iCAkET,MAAM,YAAY,MAAM,QAAQ;QAAE,SAAS,EAAE,IAAI,CAAA;KAAE,KAC7D,OAAO,CAAC,IAAI,CAAC;8BA9BH,MAAM,YAAY,MAAM,QAAQ;QAAE,SAAS,EAAE,IAAI,CAAA;KAAE,KAC7D,OAAO,CAAC,IAAI,CAAC;+BAYH,MAAM,YAAY,MAAM,SAC7B;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KACzC,OAAO,CAAC,MAAM,CAAC;cAoCA,OAAO,CAAC,aAAa,CAAC;cAOtB,OAAO,CAAC,aAAa,CAAC;EAyBzC"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* string and never for this key.
|
|
6
6
|
*/
|
|
7
7
|
import { request } from "../../http/request.js";
|
|
8
|
+
import { HttpError } from "../../http/errors.js";
|
|
8
9
|
import { probe, probeAccess } from "../../services/types.js";
|
|
9
10
|
const API = "https://console.neon.tech/api/v2";
|
|
10
11
|
export function neon(token) {
|
|
@@ -52,15 +53,36 @@ export function neon(token) {
|
|
|
52
53
|
* environment. The endpoint is what makes it a database rather than a
|
|
53
54
|
* snapshot.
|
|
54
55
|
*/
|
|
56
|
+
/**
|
|
57
|
+
* Create a branch, waiting out the project if it is still busy.
|
|
58
|
+
*
|
|
59
|
+
* A project created moments ago is still settling, and Neon refuses a branch
|
|
60
|
+
* during that window with 423 rather than queuing it. Provisioning creates a
|
|
61
|
+
* project and immediately asks for five branches, so this is the ordinary
|
|
62
|
+
* case rather than an unlucky one — and failing there leaves an app with a
|
|
63
|
+
* database and no environments.
|
|
64
|
+
*/
|
|
55
65
|
async function createBranch(projectId, name, parentId) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
const body = {
|
|
67
|
+
branch: { name, ...(parentId ? { parent_id: parentId } : {}) },
|
|
68
|
+
endpoints: [{ type: "read_write" }],
|
|
69
|
+
};
|
|
70
|
+
let wait = 1000;
|
|
71
|
+
for (let attempt = 0;; attempt++) {
|
|
72
|
+
try {
|
|
73
|
+
const { branch } = await request(`${API}/projects/${projectId}/branches`, { ...o, method: "POST", body });
|
|
74
|
+
return { id: branch.id, name: branch.name, parent_id: branch.parent_id, default: branch.default };
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// Only what the provider called transient, and only for a while: a
|
|
78
|
+
// project that is still busy after half a minute is a real failure.
|
|
79
|
+
const busy = err instanceof HttpError && err.retryable && err.status === 423;
|
|
80
|
+
if (!busy || attempt >= 6)
|
|
81
|
+
throw err;
|
|
82
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
83
|
+
wait = Math.min(wait * 2, 8000);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
64
86
|
}
|
|
65
87
|
/**
|
|
66
88
|
* Refresh one branch from its parent — copy-on-write, no dump, no transfer.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon.js","sourceRoot":"","sources":["../../../src/admin/services/neon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAoB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,WAAW,EAA0C,MAAM,yBAAyB,CAAC;AAErG,MAAM,GAAG,GAAG,kCAAkC,CAAC;AAK/C,MAAM,UAAU,IAAI,CAAC,KAAa;IAChC,MAAM,KAAK,GAAgB,EAAE,KAAK,EAAE,CAAC;IACrC,MAAM,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IAEjC,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE,CAC/B,CAAC,MAAM,OAAO,CAAkE,GAAG,GAAG,yBAAyB,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;IAErI,KAAK,UAAU,QAAQ;QACrB,MAAM,GAAG,GAAkB,EAAE,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,aAAa,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,MAAM,OAAO,CAA8B,GAAG,GAAG,oBAAoB,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5F,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,EAAE,IAAY,EAAoC,EAAE,CAC3E,CAAC,MAAM,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAElD;;;;;;;;;;OAUG;IACH,KAAK,UAAU,aAAa,CAC1B,IAAY,EAAE,OAA4C,EAAE;QAE5D,MAAM,QAAQ,GAAG,MAAM,QAAQ,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACzD,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,eAAe,CAAC;QACxE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,MAAM,OAAO,CAA2B,GAAG,GAAG,WAAW,EAAE;YAChF,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM;YACpB,IAAI,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE;SAC5D,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,EAAE,SAAiB,EAAE,EAAE,CAC3C,CAAC,MAAM,OAAO,CAA6B,GAAG,GAAG,aAAa,SAAS,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC;IAEzG;;;;;;;OAOG;IACH,KAAK,UAAU,YAAY,CACzB,SAAiB,EAAE,IAAY,EAAE,QAAiB;QAElD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAC9B,GAAG,GAAG,aAAa,SAAS,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"neon.js","sourceRoot":"","sources":["../../../src/admin/services/neon.ts"],"names":[],"mappings":"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"}
|
package/dist/admin/users.d.ts
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Who may use the factory.
|
|
3
|
+
*
|
|
4
|
+
* Accounts are made, never self-served. Provisioning creates real
|
|
5
|
+
* repositories, databases and projects in the factory's accounts and on its
|
|
6
|
+
* bill, so an open sign-up form would let a stranger spend someone else's
|
|
7
|
+
* money. Opening it later is a decision; un-provisioning what strangers made
|
|
8
|
+
* is not.
|
|
9
|
+
*
|
|
10
|
+
* There is exactly one superadmin, and the database says so rather than this
|
|
11
|
+
* file — a partial unique index on the role. Inviting a second is refused by
|
|
12
|
+
* Postgres, which is the only place a rule like that survives a rewrite.
|
|
13
|
+
*/
|
|
14
|
+
import type { Register } from "./master.ts";
|
|
2
15
|
export type Role = "superadmin" | "developer";
|
|
3
16
|
export interface User {
|
|
4
17
|
id: string;
|
|
@@ -21,7 +34,7 @@ export declare function inviteUser(invite: {
|
|
|
21
34
|
email: string;
|
|
22
35
|
name?: string | undefined;
|
|
23
36
|
role?: Role;
|
|
24
|
-
},
|
|
37
|
+
}, register: Register): Promise<User>;
|
|
25
38
|
/** Everyone with an account. Never their sessions or codes. */
|
|
26
|
-
export declare function listUsers(
|
|
39
|
+
export declare function listUsers(register: Register): Promise<User[]>;
|
|
27
40
|
//# sourceMappingURL=users.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/admin/users.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/admin/users.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,MAAM,IAAI,GAAG,YAAY,GAAG,WAAW,CAAC;AAE9C,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,IAAI,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,KAAK,EAAE,MAAM;CAI1B;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,IAAI,CAAA;CAAE,EACjE,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAef;AAED,+DAA+D;AAC/D,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAMnE"}
|
package/dist/admin/users.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Who may use the factory.
|
|
3
|
-
*
|
|
4
|
-
* Accounts are made, never self-served. Provisioning creates real
|
|
5
|
-
* repositories, databases and projects in the factory's accounts and on its
|
|
6
|
-
* bill, so an open sign-up form would let a stranger spend someone else's
|
|
7
|
-
* money. Opening it later is a decision; un-provisioning what strangers made
|
|
8
|
-
* is not.
|
|
9
|
-
*
|
|
10
|
-
* There is exactly one superadmin, and the database says so rather than this
|
|
11
|
-
* file — a partial unique index on the role. Inviting a second is refused by
|
|
12
|
-
* Postgres, which is the only place a rule like that survives a rewrite.
|
|
13
|
-
*/
|
|
14
|
-
import { master } from "./master.js";
|
|
15
1
|
export class DuplicateUserError extends Error {
|
|
16
2
|
constructor(email) {
|
|
17
3
|
super(`${email} already has an account`);
|
|
@@ -25,11 +11,11 @@ export class DuplicateUserError extends Error {
|
|
|
25
11
|
* unique index on `lower(email)` enforces — one person, one account, however
|
|
26
12
|
* they typed it.
|
|
27
13
|
*/
|
|
28
|
-
export async function inviteUser(invite,
|
|
14
|
+
export async function inviteUser(invite, register) {
|
|
29
15
|
const email = invite.email.trim();
|
|
30
16
|
if (!email.includes("@"))
|
|
31
17
|
throw new Error(`Not an email address: ${email}`);
|
|
32
|
-
const conn =
|
|
18
|
+
const conn = register;
|
|
33
19
|
const { rows } = await conn.write(`insert into users (email, name, role) values ($1, $2, $3)
|
|
34
20
|
on conflict do nothing
|
|
35
21
|
returning id, email, name, role, created_at`, [email, invite.name ?? null, invite.role ?? "developer"]);
|
|
@@ -40,8 +26,8 @@ export async function inviteUser(invite, ctx) {
|
|
|
40
26
|
return rows[0];
|
|
41
27
|
}
|
|
42
28
|
/** Everyone with an account. Never their sessions or codes. */
|
|
43
|
-
export async function listUsers(
|
|
44
|
-
const conn =
|
|
29
|
+
export async function listUsers(register) {
|
|
30
|
+
const conn = register;
|
|
45
31
|
const { rows } = await conn.query("select id, email, name, role, created_at from users order by created_at");
|
|
46
32
|
return rows;
|
|
47
33
|
}
|
package/dist/admin/users.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/admin/users.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../src/admin/users.ts"],"names":[],"mappings":"AAyBA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,KAAa;QACvB,KAAK,CAAC,GAAG,KAAK,yBAAyB,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAiE,EACjE,QAAkB;IAElB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;IAE5E,MAAM,IAAI,GAAG,QAAQ,CAAC;IACtB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAC/B;;iDAE6C,EAC7C,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,CACzD,CAAC;IACF,6EAA6E;IAC7E,wDAAwD;IACxD,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,IAAI,CAAC,CAAC,CAAoB,CAAC;AACpC,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC;IACtB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAC/B,yEAAyE,CAC1E,CAAC;IACF,OAAO,IAAyB,CAAC;AACnC,CAAC"}
|
package/dist/http/errors.d.ts
CHANGED
|
@@ -28,6 +28,17 @@ export declare class ValidationError extends HttpError {
|
|
|
28
28
|
constructor(status: number, url: string, body: string);
|
|
29
29
|
get retryable(): boolean;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Busy with something else. The same request will work shortly.
|
|
33
|
+
*
|
|
34
|
+
* Neon answers 423 while a project it just created is still settling, and a
|
|
35
|
+
* branch asked for in that window is refused rather than queued. It reads like
|
|
36
|
+
* a client error and is not one — the request is correct and merely early.
|
|
37
|
+
*/
|
|
38
|
+
export declare class BusyError extends HttpError {
|
|
39
|
+
constructor(status: number, url: string, body: string);
|
|
40
|
+
get retryable(): boolean;
|
|
41
|
+
}
|
|
31
42
|
/** Slow down. Carries the provider's own advice on how long to wait. */
|
|
32
43
|
export declare class RateLimitError extends HttpError {
|
|
33
44
|
/** Seconds to wait, when the provider said. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8BAAsB,SAAU,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAQpF,qEAAqE;IACrE,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC;CACnC;AAED,8EAA8E;AAC9E,qBAAa,SAAU,SAAQ,SAAS;gBAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED,8DAA8D;AAC9D,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrC,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED,wEAAwE;AACxE,qBAAa,cAAe,SAAQ,SAAS;IAC3C,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE5B,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAI1D,IAAI,SAAS,IAAI,OAAO,CAAiB;CAC1C;AAED,8CAA8C;AAC9C,qBAAa,YAAa,SAAQ,SAAS;gBAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAiB;CAC1C;AAED,2CAA2C;AAC3C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8BAAsB,SAAU,SAAQ,KAAK;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAQpF,qEAAqE;IACrE,QAAQ,KAAK,SAAS,IAAI,OAAO,CAAC;CACnC;AAED,8EAA8E;AAC9E,qBAAa,SAAU,SAAQ,SAAS;gBAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED,8DAA8D;AAC9D,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrC,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED,sEAAsE;AACtE,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAkB;CAC3C;AAED;;;;;;GAMG;AACH,qBAAa,SAAU,SAAQ,SAAS;gBAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAiB;CAC1C;AAED,wEAAwE;AACxE,qBAAa,cAAe,SAAQ,SAAS;IAC3C,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE5B,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAI1D,IAAI,SAAS,IAAI,OAAO,CAAiB;CAC1C;AAED,8CAA8C;AAC9C,qBAAa,YAAa,SAAQ,SAAS;gBAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAGrD,IAAI,SAAS,IAAI,OAAO,CAAiB;CAC1C;AAED,2CAA2C;AAC3C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAOlG"}
|
package/dist/http/errors.js
CHANGED
|
@@ -38,6 +38,19 @@ export class ValidationError extends HttpError {
|
|
|
38
38
|
}
|
|
39
39
|
get retryable() { return false; }
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Busy with something else. The same request will work shortly.
|
|
43
|
+
*
|
|
44
|
+
* Neon answers 423 while a project it just created is still settling, and a
|
|
45
|
+
* branch asked for in that window is refused rather than queued. It reads like
|
|
46
|
+
* a client error and is not one — the request is correct and merely early.
|
|
47
|
+
*/
|
|
48
|
+
export class BusyError extends HttpError {
|
|
49
|
+
constructor(status, url, body) {
|
|
50
|
+
super("BusyError", `Busy (${status}) — the resource is mid-operation`, status, url, body);
|
|
51
|
+
}
|
|
52
|
+
get retryable() { return true; }
|
|
53
|
+
}
|
|
41
54
|
/** Slow down. Carries the provider's own advice on how long to wait. */
|
|
42
55
|
export class RateLimitError extends HttpError {
|
|
43
56
|
/** Seconds to wait, when the provider said. */
|
|
@@ -61,6 +74,8 @@ export function errorFor(status, url, body, retryAfter) {
|
|
|
61
74
|
return new AuthError(status, url, body);
|
|
62
75
|
if (status === 404)
|
|
63
76
|
return new NotFoundError(url, body);
|
|
77
|
+
if (status === 423)
|
|
78
|
+
return new BusyError(status, url, body);
|
|
64
79
|
if (status === 429)
|
|
65
80
|
return new RateLimitError(url, body, retryAfter);
|
|
66
81
|
if (status >= 500)
|
package/dist/http/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"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"}
|