@vercel/board 0.0.0-stage → 0.15.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.
Files changed (126) hide show
  1. package/README.md +179 -2
  2. package/dist/a2-5EG8FkZ8.d.mts +3359 -0
  3. package/dist/a2-DYGYankn.mjs +3045 -0
  4. package/dist/access-CJU2-vaa.mjs +226 -0
  5. package/dist/access-CV96SYgr.d.mts +32 -0
  6. package/dist/access.d.mts +29 -0
  7. package/dist/access.mjs +4 -0
  8. package/dist/actors-rdN4dDTU.mjs +223 -0
  9. package/dist/attempts-BQUp9MKO.mjs +919 -0
  10. package/dist/auth-COzc09sn.mjs +276 -0
  11. package/dist/auth-wHFcAte3.d.mts +203 -0
  12. package/dist/backend-a2/blob-vercel.d.mts +8 -0
  13. package/dist/backend-a2/blob-vercel.mjs +81 -0
  14. package/dist/backend-a2/contract.d.mts +18 -0
  15. package/dist/backend-a2/contract.mjs +5 -0
  16. package/dist/backend-a2/scheduler-local.d.mts +11 -0
  17. package/dist/backend-a2/scheduler-local.mjs +2 -0
  18. package/dist/backend-a2/scheduler-qstash.d.mts +2 -0
  19. package/dist/backend-a2/scheduler-qstash.mjs +2 -0
  20. package/dist/backend-a2/scheduler-vercel.d.mts +2 -0
  21. package/dist/backend-a2/scheduler-vercel.mjs +2 -0
  22. package/dist/backend-a2/store-memory.d.mts +11 -0
  23. package/dist/backend-a2/store-memory.mjs +19 -0
  24. package/dist/backend-a2/store-postgres.d.mts +38 -0
  25. package/dist/backend-a2/store-postgres.mjs +110 -0
  26. package/dist/backend-a2/store-redis-http.d.mts +17 -0
  27. package/dist/backend-a2/store-redis-http.mjs +32 -0
  28. package/dist/backend-a2/store-redis.d.mts +23 -0
  29. package/dist/backend-a2/store-redis.mjs +39 -0
  30. package/dist/backend-a2/store-sqlite.d.mts +12 -0
  31. package/dist/backend-a2/store-sqlite.mjs +31 -0
  32. package/dist/backend-a2.d.mts +4 -0
  33. package/dist/backend-a2.mjs +2 -0
  34. package/dist/backend-http-8ex5g7Wv.d.mts +630 -0
  35. package/dist/backend-http-BsDSgmeo.mjs +613 -0
  36. package/dist/backend-http-Cv6xbEy9.mjs +469 -0
  37. package/dist/backend-http.d.mts +10 -0
  38. package/dist/backend-http.mjs +2 -0
  39. package/dist/backend-http.node.d.mts +10 -0
  40. package/dist/backend-http.node.mjs +2 -0
  41. package/dist/blob-C0J3wbGv.d.mts +39 -0
  42. package/dist/bots-CGkO76qH.mjs +67 -0
  43. package/dist/chat-provider-XCnQlxq6.d.mts +140 -0
  44. package/dist/chat-provider-jFSeyNmB.mjs +389 -0
  45. package/dist/cli.d.mts +1 -0
  46. package/dist/cli.mjs +2252 -0
  47. package/dist/client-DGDPaN7U.mjs +380 -0
  48. package/dist/conformance-DRR23YNy.mjs +512 -0
  49. package/dist/conformance.d.mts +30 -0
  50. package/dist/conformance.mjs +2 -0
  51. package/dist/contract-CuJmlrhw.mjs +566 -0
  52. package/dist/emoji-CTLpvH-A.mjs +445 -0
  53. package/dist/engine-3EvQ8idk.mjs +1449 -0
  54. package/dist/errors-DX3hpwWt.mjs +64 -0
  55. package/dist/exports-BpgyEdh6.d.mts +4 -0
  56. package/dist/exports-CyY3_FjZ.mjs +1285 -0
  57. package/dist/files-SniSmeEr.mjs +47 -0
  58. package/dist/index.d.mts +13 -0
  59. package/dist/index.default-BZ3lItjH.mjs +12 -0
  60. package/dist/index.mjs +19 -0
  61. package/dist/index.node.d.mts +14 -0
  62. package/dist/index.node.mjs +5 -0
  63. package/dist/inspect/app.js +416 -0
  64. package/dist/inspect/engine.js +5 -0
  65. package/dist/local-Cr_dSjvs.mjs +44 -0
  66. package/dist/own-OwgPWdmh.mjs +15 -0
  67. package/dist/project-CFiArraX.mjs +124 -0
  68. package/dist/provider-BGjz-mDa.d.mts +2473 -0
  69. package/dist/provider-CuewcDNZ.mjs +205 -0
  70. package/dist/redis-tables-B35vv4CZ.mjs +842 -0
  71. package/dist/reducers-B_vUGQRp.d.mts +1172 -0
  72. package/dist/reducers-mUPFuFJV.mjs +293 -0
  73. package/dist/schemas-Be08nyfW.mjs +74 -0
  74. package/dist/schemas-CWxs3ECJ.d.mts +50 -0
  75. package/dist/serve-Ccbb2LSb.mjs +170 -0
  76. package/dist/server-Cxey38B-.mjs +17 -0
  77. package/dist/serving-BNbzc96L.mjs +2 -0
  78. package/dist/sql-DbiEnqM0.mjs +571 -0
  79. package/dist/sqlite-db-Cbj03vmp.mjs +70 -0
  80. package/dist/sync-github.d.mts +473 -0
  81. package/dist/sync-github.mjs +603 -0
  82. package/dist/sync-kapso.d.mts +175 -0
  83. package/dist/sync-kapso.mjs +86 -0
  84. package/dist/sync-slack.d.mts +364 -0
  85. package/dist/sync-slack.mjs +728 -0
  86. package/dist/sync.chat.d.mts +2 -0
  87. package/dist/sync.chat.mjs +2 -0
  88. package/dist/sync.d.mts +3 -0
  89. package/dist/sync.mjs +4 -0
  90. package/dist/targets-ojFEXEyN.mjs +94 -0
  91. package/dist/tokens-DKLn5P9B.mjs +256 -0
  92. package/dist/types-BHCjTZdB.d.mts +104 -0
  93. package/dist/users-Dls7_ANV.mjs +42 -0
  94. package/dist/watch-spec-W0c7ypHJ.mjs +787 -0
  95. package/dist/watchers-hash-D9hbHLKB.mjs +225 -0
  96. package/docs/01-board/01-mounting.md +506 -0
  97. package/docs/01-board/02-database.md +258 -0
  98. package/docs/01-board/03-identity.md +262 -0
  99. package/docs/01-board/04-messages.md +192 -0
  100. package/docs/01-board/05-reading.md +177 -0
  101. package/docs/01-board/06-watchers.md +249 -0
  102. package/docs/01-board/07-schedules.md +133 -0
  103. package/docs/01-board/08-middleware.md +139 -0
  104. package/docs/01-board/09-access.md +499 -0
  105. package/docs/01-quickstart.md +196 -0
  106. package/docs/02-sync/01-overview.md +290 -0
  107. package/docs/02-sync/02-callbacks.md +265 -0
  108. package/docs/02-sync/03-slack.md +248 -0
  109. package/docs/02-sync/04-github.md +201 -0
  110. package/docs/02-sync/05-whatsapp.md +148 -0
  111. package/docs/02-sync/06-providers.md +228 -0
  112. package/docs/03-guides/01-coding-agents.md +226 -0
  113. package/docs/03-guides/02-inspector.md +104 -0
  114. package/docs/03-guides/03-ci.md +251 -0
  115. package/docs/03-guides/04-triage.md +233 -0
  116. package/docs/03-guides/05-agent-factory.md +142 -0
  117. package/docs/04-reference/01-cli.md +606 -0
  118. package/docs/04-reference/02-board.md +579 -0
  119. package/docs/04-reference/03-http.md +489 -0
  120. package/docs/04-reference/04-log.md +250 -0
  121. package/docs/04-reference/05-conformance.md +97 -0
  122. package/docs/index.md +186 -0
  123. package/package.json +165 -3
  124. package/sql/postgres/board.sql +145 -0
  125. package/sql/postgres/notifications.sql +24 -0
  126. package/sql/postgres/schema.sql +451 -0
@@ -0,0 +1,38 @@
1
+ import { t as BoardStore } from "../types-BHCjTZdB.mjs";
2
+ //#region src/store/postgres-db.d.ts
3
+ /** What the tables need of a `pg` Pool, or of anything shaped like one. */
4
+ type PgQueryable = {
5
+ query(text: string, values?: unknown[]): Promise<{
6
+ rows: Record<string, unknown>[];
7
+ rowCount: number | null;
8
+ }>;
9
+ };
10
+ type PgPool = PgQueryable & {
11
+ connect(): Promise<PgQueryable & {
12
+ release(): void;
13
+ }>;
14
+ end(): Promise<void>;
15
+ };
16
+ //#endregion
17
+ //#region src/store/postgres.d.ts
18
+ export type PostgresOptions = {
19
+ /** A direct connection to the same database, for live updates by notification. */
20
+ listenConnectionString?: string;
21
+ } & ({
22
+ /** The database: A2's log and board's tables, which `schema.sql` creates. */
23
+ connectionString: string;
24
+ /** Connections board's own pool may open; A2 keeps a pool of its own. Default 5. */
25
+ max?: number;
26
+ } | {
27
+ /**
28
+ * A `pg` Pool you made, shared by A2's log and board's tables: for a password
29
+ * that comes from a callback, say. Closing the store ends it.
30
+ */
31
+ client: PgPool;
32
+ });
33
+ /**
34
+ * A board on Postgres (`npm i pg`). Apply `node_modules/@vercel/board/sql/postgres/schema.sql`
35
+ * before the first deploy: neither A2 nor board creates tables in Postgres.
36
+ */
37
+ export declare function postgres(options: PostgresOptions): BoardStore;
38
+ //#endregion
@@ -0,0 +1,110 @@
1
+ import { r as sqlTables } from "../sql-DbiEnqM0.mjs";
2
+ import { postgres as postgres$1 } from "experimental-a2/store-postgres";
3
+ //#region src/store/postgres-db.ts
4
+ const SCHEMA_FILE = "node_modules/@vercel/board/sql/postgres/schema.sql";
5
+ /** The board's own error for tables that aren't there: the fix is a file to apply. */
6
+ var TablesNotConfiguredError = class extends Error {
7
+ code = "STORE_NOT_CONFIGURED";
8
+ };
9
+ /** Missing tables or columns (42P01, 42703), or missing grants (42501), say what to apply. */
10
+ function explain(error) {
11
+ const code = error?.code;
12
+ if (code === "42P01" || code === "42703") return new TablesNotConfiguredError(`board's tables aren't in this database: apply ${SCHEMA_FILE}`, { cause: error });
13
+ if (code === "42501") return new TablesNotConfiguredError(`this database role can't use board's tables: grant it select, insert, update, and delete on them`, { cause: error });
14
+ return error;
15
+ }
16
+ /**
17
+ * The tables on Postgres, through a pool that `pool()` makes the first time it's
18
+ * needed. `owned`: closing the tables ends the pool.
19
+ */
20
+ function postgresDb(pool, options = { owned: true }) {
21
+ const run = async (queryable, query) => {
22
+ try {
23
+ return await queryable.query(query.text, query.values);
24
+ } catch (error) {
25
+ throw explain(error);
26
+ }
27
+ };
28
+ /** Runs `body` in a transaction, which commits when it returns true and rolls back otherwise. */
29
+ async function transaction(begin, body) {
30
+ const client = await (await pool()).connect();
31
+ try {
32
+ await client.query(begin);
33
+ const keep = await body(client);
34
+ await client.query(keep ? "commit" : "rollback");
35
+ return keep;
36
+ } catch (error) {
37
+ await client.query("rollback").catch(() => {});
38
+ throw error;
39
+ } finally {
40
+ client.release();
41
+ }
42
+ }
43
+ return {
44
+ dialect: "postgres",
45
+ all: async (query) => (await run(await pool(), query)).rows,
46
+ async read(queries) {
47
+ const rows = [];
48
+ await transaction("begin isolation level repeatable read read only", async (client) => {
49
+ for (const query of queries) rows.push((await run(client, query)).rows);
50
+ return true;
51
+ });
52
+ return rows;
53
+ },
54
+ commit: (claim, writes) => transaction("begin", async (client) => {
55
+ if ((await run(client, claim)).rows.length === 0) return false;
56
+ for (const write of writes) await run(client, write);
57
+ return true;
58
+ }),
59
+ async close() {
60
+ if (options.owned) await (await pool()).end();
61
+ }
62
+ };
63
+ }
64
+ //#endregion
65
+ //#region src/store/postgres.ts
66
+ /** `pg` is an optional peer, installed by the apps that use Postgres. */
67
+ const PG = "pg";
68
+ /**
69
+ * A board on Postgres (`npm i pg`). Apply `node_modules/@vercel/board/sql/postgres/schema.sql`
70
+ * before the first deploy: neither A2 nor board creates tables in Postgres.
71
+ */
72
+ function postgres(options) {
73
+ const listen = options.listenConnectionString ? { listenConnectionString: options.listenConnectionString } : {};
74
+ if ("client" in options) {
75
+ if (typeof options.client.connect !== "function") throw new TypeError("postgres({ client }) takes a pg Pool, which has connect()");
76
+ const log = postgres$1({
77
+ client: options.client,
78
+ ...listen
79
+ });
80
+ return {
81
+ log,
82
+ tables: sqlTables(postgresDb(async () => options.client, { owned: false })),
83
+ close: () => log.close()
84
+ };
85
+ }
86
+ const log = postgres$1({
87
+ connectionString: options.connectionString,
88
+ ...listen
89
+ });
90
+ let pool = null;
91
+ const open = () => pool ??= import(PG).then(({ default: pg }) => {
92
+ const opened = new pg.Pool({
93
+ connectionString: options.connectionString,
94
+ max: options.max ?? 5
95
+ });
96
+ opened.on("error", () => {});
97
+ return opened;
98
+ });
99
+ const tables = sqlTables(postgresDb(open));
100
+ return {
101
+ log,
102
+ tables,
103
+ async close() {
104
+ if (pool) await tables.close();
105
+ await log.close();
106
+ }
107
+ };
108
+ }
109
+ //#endregion
110
+ export { postgres };
@@ -0,0 +1,17 @@
1
+ import { t as BoardStore } from "../types-BHCjTZdB.mjs";
2
+ //#region src/store/redis-http.d.ts
3
+ export type RedisHttpOptions = {
4
+ /** The REST endpoint, e.g. `process.env.UPSTASH_REDIS_REST_URL`. */
5
+ url: string;
6
+ /** Its bearer token, e.g. `process.env.UPSTASH_REDIS_REST_TOKEN`. */
7
+ token: string;
8
+ /**
9
+ * Isolates boards on one Redis: A2's log and board's tables both live under it. Default `'a2'`.
10
+ * It can't contain braces. board 0.14 (A2 0.22) names every key differently, so a board moves
11
+ * to a new prefix and starts with an empty log: on one board 0.13 wrote, every request answers 503.
12
+ */
13
+ keyPrefix?: string;
14
+ };
15
+ /** A board on Redis over Upstash's REST API: no connection to keep, so it suits functions. */
16
+ export declare function redisHttp(options: RedisHttpOptions): BoardStore;
17
+ //#endregion
@@ -0,0 +1,32 @@
1
+ import { t as redisTables } from "../redis-tables-B35vv4CZ.mjs";
2
+ import { redisHttp as redisHttp$1 } from "experimental-a2/store-redis-http";
3
+ //#region src/store/redis-http.ts
4
+ /** A board on Redis over Upstash's REST API: no connection to keep, so it suits functions. */
5
+ function redisHttp(options) {
6
+ const keyPrefix = options.keyPrefix ?? "a2";
7
+ const log = redisHttp$1({
8
+ url: options.url,
9
+ token: options.token,
10
+ keyPrefix
11
+ });
12
+ const call = async (command, ...args) => {
13
+ const response = await fetch(options.url, {
14
+ method: "POST",
15
+ headers: {
16
+ authorization: `Bearer ${options.token}`,
17
+ "content-type": "application/json"
18
+ },
19
+ body: JSON.stringify([command, ...args.map(String)])
20
+ });
21
+ const body = await response.json().catch(() => null);
22
+ if (body === null || !response.ok || body.error !== void 0) throw new Error(`redis rest command failed: ${body?.error ?? `status ${response.status}`}`);
23
+ return body.result;
24
+ };
25
+ return {
26
+ log,
27
+ tables: redisTables(call, keyPrefix),
28
+ close: () => log.close()
29
+ };
30
+ }
31
+ //#endregion
32
+ export { redisHttp };
@@ -0,0 +1,23 @@
1
+ import { t as BoardStore } from "../types-BHCjTZdB.mjs";
2
+ import { RedisConnection } from "experimental-a2/store-redis";
3
+ //#region src/store/redis.d.ts
4
+ export type RedisOptions = {
5
+ /**
6
+ * Isolates boards on one Redis: A2's log and board's tables both live under it. Default `'a2'`.
7
+ * It can't contain braces. board 0.14 (A2 0.22) names every key differently, so a board moves
8
+ * to a new prefix and starts with an empty log: on one board 0.13 wrote, every request answers 503.
9
+ */
10
+ keyPrefix?: string;
11
+ } & ({
12
+ /** The Redis server, as `ioredis` takes it: `redis://…` or `rediss://…`. */
13
+ url: string;
14
+ } | {
15
+ /** A client you made, shared by A2's log and board's tables. Closing the store ends it. */
16
+ client: RedisConnection;
17
+ });
18
+ /**
19
+ * A board on Redis over TCP (`npm i ioredis`): a single server or a provider
20
+ * without cluster mode, since each write is one script across many keys.
21
+ */
22
+ export declare function redis(options: RedisOptions): BoardStore;
23
+ //#endregion
@@ -0,0 +1,39 @@
1
+ import { t as redisTables } from "../redis-tables-B35vv4CZ.mjs";
2
+ import { redis as redis$1 } from "experimental-a2/store-redis";
3
+ //#region src/store/redis.ts
4
+ /** `ioredis` is an optional peer, installed by the apps that use Redis over TCP. */
5
+ const IOREDIS = "ioredis";
6
+ /**
7
+ * A board on Redis over TCP (`npm i ioredis`): a single server or a provider
8
+ * without cluster mode, since each write is one script across many keys.
9
+ */
10
+ function redis(options) {
11
+ const keyPrefix = options.keyPrefix ?? "a2";
12
+ if ("client" in options) {
13
+ const log = redis$1({
14
+ client: options.client,
15
+ keyPrefix
16
+ });
17
+ return {
18
+ log,
19
+ tables: redisTables((command, ...args) => options.client.call(command, ...args), keyPrefix),
20
+ close: () => log.close()
21
+ };
22
+ }
23
+ const log = redis$1({
24
+ url: options.url,
25
+ keyPrefix
26
+ });
27
+ let client = null;
28
+ const open = () => client ??= import(IOREDIS).then(({ default: Redis }) => new Redis(options.url));
29
+ return {
30
+ log,
31
+ tables: redisTables(async (command, ...args) => (await open()).call(command, ...args), keyPrefix),
32
+ async close() {
33
+ if (client) (await client).disconnect();
34
+ await log.close();
35
+ }
36
+ };
37
+ }
38
+ //#endregion
39
+ export { redis };
@@ -0,0 +1,12 @@
1
+ import { t as BoardStore } from "../types-BHCjTZdB.mjs";
2
+ //#region src/store/sqlite.d.ts
3
+ /**
4
+ * A board in one SQLite file, A2's log and board's tables side by side: `a2()`'s
5
+ * store when it's given none, for development, `vb serve`, and a single
6
+ * long-running server. It creates its tables when it opens, and a serverless
7
+ * function, whose files are read-only, can't open it.
8
+ */
9
+ export declare function sqlite(options?: {
10
+ path?: string;
11
+ }): BoardStore;
12
+ //#endregion
@@ -0,0 +1,31 @@
1
+ import { r as sqlTables } from "../sql-DbiEnqM0.mjs";
2
+ import { t as sqliteDb } from "../sqlite-db-Cbj03vmp.mjs";
3
+ import { sqlite as sqlite$1 } from "experimental-a2/store-sqlite";
4
+ //#region src/store/sqlite.ts
5
+ /**
6
+ * A board in one SQLite file, A2's log and board's tables side by side: `a2()`'s
7
+ * store when it's given none, for development, `vb serve`, and a single
8
+ * long-running server. It creates its tables when it opens, and a serverless
9
+ * function, whose files are read-only, can't open it.
10
+ */
11
+ function sqlite(options = {}) {
12
+ const path = options.path ?? ".a2/dev.db";
13
+ const log = sqlite$1({ path });
14
+ let tables;
15
+ try {
16
+ tables = sqlTables(sqliteDb(path));
17
+ } catch (error) {
18
+ log.close();
19
+ throw error;
20
+ }
21
+ return {
22
+ log,
23
+ tables,
24
+ async close() {
25
+ await tables.close();
26
+ log.close();
27
+ }
28
+ };
29
+ }
30
+ //#endregion
31
+ export { sqlite };
@@ -0,0 +1,4 @@
1
+ import { n as A2Options, r as a2, t as A2Backend } from "./a2-5EG8FkZ8.mjs";
2
+ import { t as BoardStore } from "./types-BHCjTZdB.mjs";
3
+ import { n as fsBlob, r as memoryBlob, t as BlobStore } from "./blob-C0J3wbGv.mjs";
4
+ export { type A2Backend, type A2Options, type BlobStore, type BoardStore, a2, fsBlob, memoryBlob };
@@ -0,0 +1,2 @@
1
+ import { n as fsBlob, r as memoryBlob, t as a2 } from "./a2-DYGYankn.mjs";
2
+ export { a2, fsBlob, memoryBlob };