@midsummer-ai/sdk 0.0.0-stage → 0.1.0-next.1723

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 (79) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +4 -2
  3. package/agents/contract.d.mts +9 -0
  4. package/agents/contract.mjs +221 -0
  5. package/agents/index.d.mts +128 -0
  6. package/agents/index.mjs +203 -0
  7. package/agents/stand-in.d.mts +35 -0
  8. package/agents/stand-in.mjs +149 -0
  9. package/ai/contract.d.mts +10 -0
  10. package/ai/contract.mjs +77 -0
  11. package/ai/index.d.mts +94 -0
  12. package/ai/index.mjs +193 -0
  13. package/ai/stand-in.d.mts +7 -0
  14. package/ai/stand-in.mjs +41 -0
  15. package/build-SQ44jwSa.d.mts +41 -0
  16. package/client.d.mts +45 -0
  17. package/client.mjs +106 -0
  18. package/connection-BHjDaLYA.mjs +2009 -0
  19. package/contract.d.mts +10 -0
  20. package/contract.mjs +469 -0
  21. package/database/build.d.mts +2 -0
  22. package/database/build.mjs +579 -0
  23. package/database/client.d.mts +60 -0
  24. package/database/client.mjs +133 -0
  25. package/database/contract.d.mts +11 -0
  26. package/database/contract.mjs +164 -0
  27. package/database/errors.d.mts +23 -0
  28. package/database/errors.mjs +13 -0
  29. package/database/server.d.mts +3 -0
  30. package/database/server.mjs +320 -0
  31. package/database/stand-in.d.mts +99 -0
  32. package/database/stand-in.mjs +430 -0
  33. package/email/client.d.mts +34 -0
  34. package/email/client.mjs +131 -0
  35. package/email/contract.d.mts +11 -0
  36. package/email/contract.mjs +99 -0
  37. package/email/index.d.mts +74 -0
  38. package/email/index.mjs +59 -0
  39. package/email/smtp.d.mts +22 -0
  40. package/email/smtp.mjs +296 -0
  41. package/email/stand-in.d.mts +13 -0
  42. package/email/stand-in.mjs +51 -0
  43. package/index-DdoK0y7D.d.mts +192 -0
  44. package/index-sgdyoA2P.d.mts +212 -0
  45. package/index.d.mts +2 -0
  46. package/index.mjs +137 -0
  47. package/names-DfCBKupJ.mjs +115 -0
  48. package/package.json +152 -4
  49. package/predict-Drfm_8pO.mjs +179 -0
  50. package/queues/contract.d.mts +13 -0
  51. package/queues/contract.mjs +278 -0
  52. package/queues/index.d.mts +184 -0
  53. package/queues/index.mjs +126 -0
  54. package/queues/stand-in.d.mts +7 -0
  55. package/queues/stand-in.mjs +110 -0
  56. package/queues/wire.d.mts +9 -0
  57. package/queues/wire.mjs +199 -0
  58. package/s3.d.mts +43 -0
  59. package/s3.mjs +1003 -0
  60. package/schema-BF-Y1EVu.mjs +142 -0
  61. package/schema-DS8x1Dn8.mjs +115 -0
  62. package/schema-f7E9uzUn.d.mts +74 -0
  63. package/server-C7O7CICU.d.mts +182 -0
  64. package/socket.d.mts +67 -0
  65. package/socket.mjs +263 -0
  66. package/stand-in.d.mts +7 -0
  67. package/stand-in.mjs +185 -0
  68. package/store-BA8K-bAR.mjs +237 -0
  69. package/tabs-DEeMee7M.mjs +457 -0
  70. package/vector/contract.d.mts +10 -0
  71. package/vector/contract.mjs +635 -0
  72. package/vector/index.d.mts +2 -0
  73. package/vector/index.mjs +108 -0
  74. package/vector/stand-in.d.mts +11 -0
  75. package/vector/stand-in.mjs +169 -0
  76. package/vector/wire.d.mts +25 -0
  77. package/vector/wire.mjs +175 -0
  78. package/wire.d.mts +54 -0
  79. package/wire.mjs +731 -0
@@ -0,0 +1,142 @@
1
+ //#region src/database/schema.ts
2
+ /** A table's name: a leading `_` is the Database's own. */
3
+ const TABLE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/u;
4
+ const v = Object.freeze({
5
+ string: () => "string",
6
+ number: () => "number",
7
+ boolean: () => "boolean",
8
+ /** Any JSON value, at any depth. */
9
+ document: () => "document",
10
+ /** May be left out or null. */
11
+ optional: (shape) => ({ optional: shape }),
12
+ array: (shape) => ({ array: shape }),
13
+ object: (fields) => ({ object: fields }),
14
+ int64: () => "int64",
15
+ bytes: () => "bytes",
16
+ timestamp: () => "timestamp",
17
+ decimal: () => "decimal",
18
+ literal: (value) => ({ literal: value }),
19
+ union: (...shapes) => ({ union: shapes }),
20
+ record: (shape) => ({ record: shape }),
21
+ id: (table) => ({ id: String(table) })
22
+ });
23
+ const INDEX = /^[A-Za-z][A-Za-z0-9_]{0,63}$/u;
24
+ const INDEX_FIELDS = 8;
25
+ const RESERVED_INDEXES = /* @__PURE__ */ new Set(["by_id", "by_creation_time"]);
26
+ /** Whether an index may order a field of this shape: what the Database orders, its keys comparing as their values do. */
27
+ function orderable(shape) {
28
+ const inner = shape && typeof shape === "object" && "optional" in shape ? shape.optional : shape;
29
+ if (typeof inner === "string") return [
30
+ "string",
31
+ "number",
32
+ "boolean",
33
+ "int64",
34
+ "timestamp"
35
+ ].includes(inner);
36
+ if (!inner) return false;
37
+ if ("id" in inner) return true;
38
+ if ("literal" in inner) return [
39
+ "string",
40
+ "number",
41
+ "boolean"
42
+ ].includes(typeof inner.literal);
43
+ if ("union" in inner) return inner.union.every(orderable);
44
+ return false;
45
+ }
46
+ function tableOf(fields, indexes) {
47
+ return Object.freeze({
48
+ fields,
49
+ indexes,
50
+ index(name, field, { unique = false } = {}) {
51
+ if (typeof name !== "string" || !INDEX.test(name) || RESERVED_INDEXES.has(name)) throw new TypeError(`index ${JSON.stringify(name)}: a name of [A-Za-z][A-Za-z0-9_]{0,63}, not by_id or by_creation_time`);
52
+ if (name in indexes) throw new TypeError(`index ${name}: declared twice`);
53
+ const list = Array.isArray(field) ? field : [field];
54
+ if (!list.length || list.length > INDEX_FIELDS || new Set(list).size !== list.length) throw new TypeError(`index ${name}: a field, or a list of up to ${INDEX_FIELDS} different fields`);
55
+ for (const one of list) {
56
+ if (typeof one !== "string" || !(one in fields)) throw new TypeError(`index ${name}: ${JSON.stringify(one)} is not a field of the table`);
57
+ if (!orderable(fields[one])) throw new TypeError(`index ${name}: ${one} is not a string, number or boolean`);
58
+ }
59
+ const on = list.length === 1 ? list[0] : Object.freeze([...list]);
60
+ return tableOf(fields, Object.freeze({
61
+ ...indexes,
62
+ [name]: unique ? Object.freeze({
63
+ fields: on,
64
+ unique: true
65
+ }) : on
66
+ }));
67
+ },
68
+ searchIndex(name) {
69
+ throw new TypeError(`searchIndex ${JSON.stringify(name)}: not available yet`);
70
+ },
71
+ vectorIndex(name) {
72
+ throw new TypeError(`vectorIndex ${JSON.stringify(name)}: not available yet`);
73
+ }
74
+ });
75
+ }
76
+ /** An index's fields in order. */
77
+ function indexFields(declared) {
78
+ const fields = declared !== null && typeof declared === "object" && !Array.isArray(declared) ? declared.fields : declared;
79
+ return Array.isArray(fields) ? [...fields] : [fields];
80
+ }
81
+ function defineTable(fields) {
82
+ if (fields === null || typeof fields !== "object" || Array.isArray(fields)) throw new TypeError("defineTable({ <field>: v.<shape>() })");
83
+ for (const [field, shape] of Object.entries(fields)) {
84
+ if (field.startsWith("_")) throw new TypeError(`defineTable: ${field}: a leading _ is the Database's`);
85
+ if (shapeError(shape, void 0, field)?.endsWith("not a shape")) throw new TypeError(`defineTable: ${field}: not a shape`);
86
+ }
87
+ return tableOf(Object.freeze({ ...fields }), Object.freeze({}));
88
+ }
89
+ function defineSchema(tables) {
90
+ if (tables === null || typeof tables !== "object" || Array.isArray(tables)) throw new TypeError("defineSchema({ <table>: defineTable(...) })");
91
+ const out = {};
92
+ const indexes = {};
93
+ for (const [name, table] of Object.entries(tables)) {
94
+ if (!TABLE.test(name)) throw new TypeError(`defineSchema: "${name}" is not a table name`);
95
+ if (!table?.fields) throw new TypeError(`defineSchema: "${name}" is not a defineTable(...)`);
96
+ out[name] = table.fields;
97
+ indexes[name] = table.indexes ?? Object.freeze({});
98
+ }
99
+ return Object.freeze({
100
+ schema: true,
101
+ tables: Object.freeze(out),
102
+ indexes: Object.freeze(indexes)
103
+ });
104
+ }
105
+ /** Whether `value` fits `shape`: null, or the reason. An id is a non-empty string. */
106
+ function shapeError(shape, value, at = "the value") {
107
+ const wrong = (what) => `${at}: ${what} expected`;
108
+ if (shape === "document") return null;
109
+ if (typeof shape === "string") switch (shape) {
110
+ case "string": return typeof value === "string" ? null : wrong("a string");
111
+ case "number": return typeof value === "number" && Number.isFinite(value) ? null : wrong("a number");
112
+ case "boolean": return typeof value === "boolean" ? null : wrong("a boolean");
113
+ case "int64": return Number.isSafeInteger(value) || typeof value === "string" && /^-?\d{1,19}$/u.test(value) ? null : wrong("a whole number of 64 bits");
114
+ case "bytes": return typeof value === "string" && /^[A-Za-z0-9+/=_-]*$/u.test(value) ? null : wrong("bytes as base64");
115
+ case "timestamp": return typeof value === "number" && Number.isFinite(value) ? null : wrong("a timestamp (milliseconds)");
116
+ case "decimal": return typeof value === "string" && /^-?\d+(\.\d+)?$/u.test(value) ? null : wrong("a decimal as a string");
117
+ default: return `${at}: no shape ${String(shape)}`;
118
+ }
119
+ if (shape && typeof shape === "object") {
120
+ if ("optional" in shape) return value === void 0 || value === null ? null : shapeError(shape.optional, value, at);
121
+ if ("array" in shape) return Array.isArray(value) ? value.map((item, k) => shapeError(shape.array, item, `${at}[${k}]`)).find(Boolean) ?? null : wrong("an array");
122
+ if ("object" in shape) {
123
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return wrong("an object");
124
+ const record = value;
125
+ for (const key of Object.keys(record)) if (!(key in shape.object)) return `${at}.${key}: no such field`;
126
+ for (const [key, inner] of Object.entries(shape.object)) {
127
+ if (record[key] === void 0 && inner && typeof inner === "object" && "optional" in inner) continue;
128
+ if (record[key] === void 0) return `${at}.${key}: missing`;
129
+ const why = shapeError(inner, record[key], `${at}.${key}`);
130
+ if (why) return why;
131
+ }
132
+ return null;
133
+ }
134
+ if ("literal" in shape) return JSON.stringify(value) === JSON.stringify(shape.literal) ? null : wrong(`the value ${JSON.stringify(shape.literal)}`);
135
+ if ("union" in shape) return shape.union.some((one) => shapeError(one, value, at) === null) ? null : wrong("one of the union's shapes");
136
+ if ("record" in shape) return value !== null && typeof value === "object" && !Array.isArray(value) ? Object.entries(value).map(([k, item]) => shapeError(shape.record, item, `${at}.${k}`)).find(Boolean) ?? null : wrong("an object");
137
+ if ("id" in shape) return typeof value === "string" && value.length > 0 && value.length <= 256 ? null : wrong(`an id of ${shape.id}`);
138
+ }
139
+ return `${at}: not a shape`;
140
+ }
141
+ //#endregion
142
+ export { shapeError as a, indexFields as i, defineSchema as n, v as o, defineTable as r, TABLE as t };
@@ -0,0 +1,115 @@
1
+ import { z } from "zod";
2
+ //#region src/vector/errors.ts
3
+ const vectorErrorCodes = [
4
+ "invalid",
5
+ "not_found",
6
+ "conflict",
7
+ "forbidden",
8
+ "unavailable"
9
+ ];
10
+ var VectorError = class extends Error {
11
+ code;
12
+ constructor(code, why) {
13
+ super(why);
14
+ this.code = code;
15
+ this.name = "VectorError";
16
+ }
17
+ };
18
+ //#endregion
19
+ //#region src/vector/schema.ts
20
+ /**
21
+ * What Vector DB accepts, as zod schemas: the client checks a call with them before it leaves the
22
+ * caller, and `serve` checks every frame with them again, because a frame comes from the network.
23
+ * A limit lives here once, so both edges hold the same one.
24
+ */
25
+ /** Most numbers a Vector holds. */
26
+ const MAX_DIMENSION = 4096;
27
+ /** Most Vectors one upsert takes, and most ids one fetch or delete names. */
28
+ const MAX_BATCH = 1e3;
29
+ /** The most matches one query returns. */
30
+ const MAX_TOP_K = 100;
31
+ /** Most characters a text to embed has. */
32
+ const MAX_TEXT = 3e4;
33
+ /** Most bytes a Vector's metadata takes, as JSON. */
34
+ const MAX_METADATA_BYTES = 10240;
35
+ /** 1 to 63 lowercase letters, digits and hyphens, starting with a letter or digit. */
36
+ const NamespaceName = z.string().regex(/^[a-z0-9][a-z0-9-]{0,62}$/, "a Vector namespace's name is 1 to 63 lowercase letters, digits and hyphens, starting with a letter or digit");
37
+ /** How closeness is measured, fixed when a Vector namespace is made. */
38
+ const Metric = z.enum([
39
+ "cosine",
40
+ "euclidean",
41
+ "dot"
42
+ ]);
43
+ const Dimension = z.number().int().min(1).max(MAX_DIMENSION);
44
+ const VectorId = z.string().min(1).max(512);
45
+ const Scalar = z.union([
46
+ z.string().max(2048),
47
+ z.number().refine(Number.isFinite, "a number in metadata is finite"),
48
+ z.boolean()
49
+ ]);
50
+ const FieldName = z.string().min(1).max(64).refine((name) => !name.startsWith("$") && !name.includes("."), "a metadata field's name does not start with $ or hold a dot");
51
+ const Metadata = z.record(FieldName, Scalar).refine((metadata) => new TextEncoder().encode(JSON.stringify(metadata)).length <= MAX_METADATA_BYTES, `metadata is at most ${MAX_METADATA_BYTES} bytes as JSON`);
52
+ /**
53
+ * The largest value a Vector holds. Engines keep values and scores as 32-bit floats, and within it
54
+ * every score of 4,096 values is one, finite: a squared distance is at most 4,096 · (2e17)², about
55
+ * 1.6e38, under a 32-bit float's 3.4e38. Scores are exact to a 32-bit float's precision for values
56
+ * from 1e-17 up.
57
+ */
58
+ const MAX_VALUE = 0x16345785d8a0000;
59
+ const Values = z.array(z.number().refine((value) => Number.isFinite(value) && Math.abs(value) <= 0x16345785d8a0000, `a Vector's values are finite numbers of at most ${MAX_VALUE} in size`)).min(1).max(MAX_DIMENSION);
60
+ const Vector = z.object({
61
+ id: VectorId,
62
+ values: Values,
63
+ metadata: Metadata.optional()
64
+ }).strict();
65
+ const Text = z.string().max(MAX_TEXT).refine((text) => text.trim().length > 0, "a text to embed is not empty or all spaces");
66
+ const TextVector = z.object({
67
+ id: VectorId,
68
+ text: Text,
69
+ metadata: Metadata.optional()
70
+ }).strict();
71
+ const Vectors = z.array(z.union([Vector, TextVector])).min(1).max(MAX_BATCH).refine((vectors) => new Set(vectors.map((v) => v.id)).size === vectors.length, "each id is upserted once a call");
72
+ const Ids = z.array(VectorId).min(1).max(MAX_BATCH);
73
+ const Bound = z.union([z.string().max(2048), z.number().refine(Number.isFinite)]);
74
+ const Condition = z.union([Scalar, z.object({
75
+ $eq: Scalar.optional(),
76
+ $ne: Scalar.optional(),
77
+ $in: z.array(Scalar).min(1).max(100).optional(),
78
+ $nin: z.array(Scalar).min(1).max(100).optional(),
79
+ $gt: Bound.optional(),
80
+ $gte: Bound.optional(),
81
+ $lt: Bound.optional(),
82
+ $lte: Bound.optional()
83
+ }).strict().refine((condition) => Object.keys(condition).length > 0, "a condition names an operator")]);
84
+ /** Each field's condition, all of which must hold. A bare value is `$eq`. */
85
+ const Filter = z.record(FieldName, Condition).refine((filter) => Object.keys(filter).length <= 20, "a filter names at most 20 fields");
86
+ const QueryOptions = {
87
+ topK: z.number().int().min(1).max(100),
88
+ filter: Filter.optional(),
89
+ includeValues: z.boolean(),
90
+ includeMetadata: z.boolean(),
91
+ consistency: z.enum(["strong", "eventual"]).optional()
92
+ };
93
+ const Query = z.union([z.object({
94
+ vector: Values,
95
+ ...QueryOptions
96
+ }).strict(), z.object({
97
+ text: Text,
98
+ ...QueryOptions
99
+ }).strict()]);
100
+ /** An embedding model's name, as the platform offers it. */
101
+ const EmbeddingModel = z.string().min(1).max(100);
102
+ const Settings = z.object({
103
+ dimension: Dimension,
104
+ metric: Metric,
105
+ embed: EmbeddingModel.optional()
106
+ }).strict();
107
+ /** `value` as `schema` reads it, or `invalid` with why not. */
108
+ function checked(schema, value) {
109
+ const parsed = schema.safeParse(value);
110
+ if (parsed.success) return parsed.data;
111
+ const issue = parsed.error.issues[0];
112
+ throw new VectorError("invalid", `${issue && issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue?.message ?? "not valid"}`);
113
+ }
114
+ //#endregion
115
+ export { MAX_TEXT as a, NamespaceName as c, Vectors as d, checked as f, MAX_METADATA_BYTES as i, Query as l, vectorErrorCodes as m, MAX_BATCH as n, MAX_TOP_K as o, VectorError as p, MAX_DIMENSION as r, MAX_VALUE as s, Ids as t, Settings as u };
@@ -0,0 +1,74 @@
1
+ //#region src/database/schema.d.ts
2
+ /**
3
+ * A Database's shapes: `v`, `defineTable`, `defineSchema`, and the check of a value against a
4
+ * shape. Plain data and pure functions, the same as the engine's, so a schema built here is the one
5
+ * the Database builds.
6
+ *
7
+ * export default defineSchema({
8
+ * messages: defineTable({ channel: v.string(), body: v.string() }).index("by_channel", "channel"),
9
+ * })
10
+ */
11
+ /** A shape, as `v` makes it: a name for the simple ones, an object for the rest. */
12
+ type Shape = "string" | "number" | "boolean" | "document" | "int64" | "bytes" | "timestamp" | "decimal" | {
13
+ readonly optional: Shape;
14
+ } | {
15
+ readonly array: Shape;
16
+ } | {
17
+ readonly object: Readonly<Record<string, Shape>>;
18
+ } | {
19
+ readonly literal: unknown;
20
+ } | {
21
+ readonly union: ReadonlyArray<Shape>;
22
+ } | {
23
+ readonly record: Shape;
24
+ } | {
25
+ readonly id: string;
26
+ };
27
+ declare const v: Readonly<{
28
+ string: () => Shape;
29
+ number: () => Shape;
30
+ boolean: () => Shape;
31
+ /** Any JSON value, at any depth. */
32
+ document: () => Shape;
33
+ /** May be left out or null. */
34
+ optional: (shape: Shape) => Shape;
35
+ array: (shape: Shape) => Shape;
36
+ object: (fields: Record<string, Shape>) => Shape;
37
+ int64: () => Shape;
38
+ bytes: () => Shape;
39
+ timestamp: () => Shape;
40
+ decimal: () => Shape;
41
+ literal: (value: string | number | boolean) => Shape;
42
+ union: (...shapes: Shape[]) => Shape;
43
+ record: (shape: Shape) => Shape;
44
+ id: (table: string) => Shape;
45
+ }>;
46
+ /** An index as declared: one field, a list of them for a compound index, or either with `unique`. */
47
+ type IndexDeclaration = string | ReadonlyArray<string> | {
48
+ readonly fields: string | ReadonlyArray<string>;
49
+ readonly unique: true;
50
+ };
51
+ interface Table {
52
+ readonly fields: Readonly<Record<string, Shape>>;
53
+ readonly indexes: Readonly<Record<string, IndexDeclaration>>;
54
+ /** A new table with the index added: one field, or a list for a compound index; `{ unique: true }` lets no two rows share its key. */
55
+ index(name: string, field: string | ReadonlyArray<string>, options?: {
56
+ readonly unique?: boolean;
57
+ }): Table;
58
+ searchIndex(name: string): never;
59
+ vectorIndex(name: string): never;
60
+ }
61
+ interface Schema {
62
+ readonly schema: true;
63
+ readonly tables: Readonly<Record<string, Readonly<Record<string, Shape>>>>;
64
+ /** Every table's indexes, by name; a table with none has `{}`. */
65
+ readonly indexes: Readonly<Record<string, Readonly<Record<string, IndexDeclaration>>>>;
66
+ }
67
+ /** An index's fields in order. */
68
+ declare function indexFields(declared: IndexDeclaration): string[];
69
+ declare function defineTable(fields: Record<string, Shape>): Table;
70
+ declare function defineSchema(tables: Record<string, Table>): Schema;
71
+ /** Whether `value` fits `shape`: null, or the reason. An id is a non-empty string. */
72
+ declare function shapeError(shape: Shape, value: unknown, at?: string): string | null;
73
+ //#endregion
74
+ export { defineSchema as a, shapeError as c, Table as i, v as l, Schema as n, defineTable as o, Shape as r, indexFields as s, IndexDeclaration as t };
@@ -0,0 +1,182 @@
1
+ import { r as Shape } from "./schema-f7E9uzUn.mjs";
2
+ //#region src/database/server.d.ts
3
+ /** A row as the Database keeps it: its fields, and its own `_`-fields. */
4
+ type Row = Readonly<Record<string, unknown>>;
5
+ /** A row as a function reads it. */
6
+ type Document = Readonly<Record<string, unknown>> & {
7
+ readonly _id: string;
8
+ readonly _version: number;
9
+ };
10
+ /** A range's bounds on an index's first field, its order, and at most `limit` rows. */
11
+ interface RangeOptions {
12
+ readonly eq?: unknown;
13
+ readonly gte?: unknown;
14
+ readonly gt?: unknown;
15
+ readonly lte?: unknown;
16
+ readonly lt?: unknown;
17
+ readonly order?: "asc" | "desc";
18
+ readonly limit?: number;
19
+ }
20
+ /** A scheduled run, as `ctx.scheduler.status` returns it. */
21
+ interface ScheduledRun {
22
+ readonly name: string;
23
+ readonly args: unknown;
24
+ readonly at: number;
25
+ readonly state: string;
26
+ readonly error?: string;
27
+ }
28
+ /**
29
+ * What a Database gives a query or mutation to run against: its rows, the caller and the call. The
30
+ * Stand-in is one such; the Database's engine is another. Every read returns at once.
31
+ */
32
+ interface Rows {
33
+ get(table: string, id: string): Row | null;
34
+ set(table: string, id: string, fields: Row): void;
35
+ delete(table: string, id: string): void;
36
+ /** The rows of `index` ("_id" for the table's order) within the bounds, each with its `_id`. Bounds are lists, one value for each of the index's leading fields. */
37
+ range(table: string, index: string, options: {
38
+ readonly eq?: ReadonlyArray<unknown>;
39
+ readonly gte?: unknown;
40
+ readonly gt?: unknown;
41
+ readonly lte?: unknown;
42
+ readonly lt?: unknown;
43
+ readonly order?: "asc" | "desc";
44
+ readonly limit: number;
45
+ }): ReadonlyArray<Row & {
46
+ readonly _id: string;
47
+ }>;
48
+ /** The call's own time. */
49
+ readonly now: number;
50
+ /** The signed-in caller, by the Project's sign-in's subject; null for none. */
51
+ readonly user: string | null;
52
+ /** Whether the Project's own server code, or the Database itself, is the caller. */
53
+ readonly server: boolean;
54
+ /** The sign-in provider the Database trusts, when it trusts exactly one. */
55
+ readonly issuer?: string | null;
56
+ /** The call's identity: a mutation's inserted ids come from it, so a run again makes the same ids. */
57
+ readonly call?: string | null;
58
+ /** Whether another function is the caller, which may call internal ones. */
59
+ readonly internal?: boolean;
60
+ /** The tables the schema declares, by field; none: every write is admitted. */
61
+ readonly schema?: Readonly<Record<string, Readonly<Record<string, Shape>>>> | null;
62
+ runAfter(ms: number, name: string, args: unknown): string;
63
+ scheduledRow(id: string): {
64
+ readonly name: string;
65
+ readonly args?: unknown;
66
+ readonly due: number;
67
+ readonly state: string;
68
+ readonly error?: string;
69
+ } | null;
70
+ cancelScheduled(id: string): boolean;
71
+ }
72
+ /** What a Database gives an action: reads that may wait, the network, and the other functions. */
73
+ interface Capabilities {
74
+ get(table: string, id: string): Promise<Row | null>;
75
+ range(table: string, index: string, options: Parameters<Rows["range"]>[2]): Promise<ReadonlyArray<Row & {
76
+ readonly _id: string;
77
+ }>>;
78
+ readonly user: string | null;
79
+ readonly server: boolean;
80
+ readonly issuer?: string | null;
81
+ readonly internal?: boolean;
82
+ fetch(url: URL, init?: RequestInit): Promise<Response>;
83
+ now(): number;
84
+ random(bytes: number): Uint8Array;
85
+ run(name: string, args: unknown): Promise<unknown>;
86
+ schedule(ms: number, name: string, args: unknown): Promise<string>;
87
+ scheduled(id: string): Promise<ScheduledRun | null>;
88
+ cancel(id: string): Promise<boolean>;
89
+ }
90
+ type FunctionKind = "query" | "mutation" | "action";
91
+ /** A function as defined: its name (none until it is exported under one), what runs it, and its options. */
92
+ interface RegisteredFunction {
93
+ readonly name: string | null;
94
+ readonly handler: (on: Rows & Capabilities, args: unknown) => unknown;
95
+ readonly options: {
96
+ readonly kind: FunctionKind;
97
+ readonly args: {
98
+ readonly object: Readonly<Record<string, Shape>>;
99
+ } | null;
100
+ readonly returns: Shape | null;
101
+ readonly internal: boolean;
102
+ readonly cron: string | null;
103
+ };
104
+ }
105
+ /** A function's reference, as `api.<file>.<export>` holds it: its name and kind. */
106
+ interface FunctionReference<Kind extends FunctionKind = FunctionKind> {
107
+ readonly name: string;
108
+ readonly kind: Kind;
109
+ }
110
+ declare const OPERATOR: unique symbol;
111
+ interface Operator {
112
+ readonly [OPERATOR]: "increment" | "take" | "give";
113
+ readonly n: number;
114
+ }
115
+ /** A field's value plus `n` (a field not yet there counts as 0). */
116
+ declare const increment: (n?: number) => Operator;
117
+ /** A field's value minus `n`; below zero the whole mutation fails with `InsufficientError` and writes nothing. */
118
+ declare const take: (n?: number) => Operator;
119
+ /** A field's value plus `n`: the inverse of `take`. */
120
+ declare const give: (n?: number) => Operator;
121
+ /** A `take` asked for more than the field holds: the mutation wrote nothing. */
122
+ declare class InsufficientError extends Error {
123
+ readonly detail: {
124
+ readonly table: string;
125
+ readonly id: string;
126
+ readonly field: string;
127
+ readonly has: number;
128
+ readonly asked: number;
129
+ };
130
+ constructor(detail: {
131
+ readonly table: string;
132
+ readonly id: string;
133
+ readonly field: string;
134
+ readonly has: number;
135
+ readonly asked: number;
136
+ });
137
+ }
138
+ /** A mutation patched or replaced a row that is not there. */
139
+ declare class NotFoundError extends Error {
140
+ readonly detail: {
141
+ readonly table: string;
142
+ readonly id: string;
143
+ };
144
+ constructor(detail: {
145
+ readonly table: string;
146
+ readonly id: string;
147
+ });
148
+ }
149
+ /** A call the Database refused: `why` is its reason, as the client's `DatabaseError` carries it. */
150
+ declare class Refusal extends Error {
151
+ readonly why: string;
152
+ readonly detail?: unknown;
153
+ constructor(why: string, message: string, detail?: unknown);
154
+ }
155
+ type Definition = {
156
+ readonly args?: Record<string, Shape>;
157
+ readonly returns?: Shape;
158
+ readonly cron?: string;
159
+ readonly handler: (ctx: any, args: any) => unknown;
160
+ };
161
+ /** A function that reads rows and never writes them: `export const list = query({ args, returns, handler: (ctx, args) => ... })`. */
162
+ declare function query(name: string | Definition, given?: Definition, extra?: {
163
+ internal?: boolean;
164
+ }): RegisteredFunction;
165
+ /** One serializable transaction: `export const send = mutation({ args, returns, handler: (ctx, args) => ... })`. */
166
+ declare function mutation(name: string | Definition, given?: Definition, extra?: {
167
+ internal?: boolean;
168
+ }): RegisteredFunction;
169
+ /** May wait on the network: `export const charge = action({ args, returns, handler: async (ctx, args) => ... })`. */
170
+ declare function action(name: string | Definition, given?: Definition, extra?: {
171
+ internal?: boolean;
172
+ }): RegisteredFunction;
173
+ /** As `query`, callable only by another function, never a client. */
174
+ declare const internalQuery: (name: string | Definition, given?: Definition) => RegisteredFunction;
175
+ /** As `mutation`, callable only by another function, never a client. */
176
+ declare const internalMutation: (name: string | Definition, given?: Definition) => RegisteredFunction;
177
+ /** As `action`, callable only by another function, never a client. */
178
+ declare const internalAction: (name: string | Definition, given?: Definition) => RegisteredFunction;
179
+ /** Whether a value is a function defined here, as a module of `db/` exports it. */
180
+ declare const isFunction: (value: unknown) => value is RegisteredFunction;
181
+ //#endregion
182
+ export { take as C, query as S, internalAction as _, InsufficientError as a, isFunction as b, RangeOptions as c, Row as d, Rows as f, increment as g, give as h, FunctionReference as i, Refusal as l, action as m, Document as n, NotFoundError as o, ScheduledRun as p, FunctionKind as r, Operator as s, Capabilities as t, RegisteredFunction as u, internalMutation as v, mutation as x, internalQuery as y };
package/socket.d.mts ADDED
@@ -0,0 +1,67 @@
1
+ import { m as StorageEngine } from "./index-sgdyoA2P.mjs";
2
+ import { S3Credential } from "./s3.mjs";
3
+ import { Transport } from "./wire.mjs";
4
+ //#region src/socket.d.ts
5
+ declare function sign(secret: string, challenge: string): Promise<string>;
6
+ declare function sameHex(a: string, b: string): boolean;
7
+ /** The browser's WebSocket, or one with the same shape. */
8
+ type SocketLike = {
9
+ binaryType: string;
10
+ readonly readyState: number;
11
+ send(data: string | Uint8Array): void;
12
+ close(code?: number, reason?: string): void;
13
+ addEventListener(type: "message", listener: (event: {
14
+ data: unknown;
15
+ }) => void): void;
16
+ addEventListener(type: "close" | "error", listener: () => void): void;
17
+ };
18
+ /**
19
+ * A transport over WebSockets to `url` (`connections` of them, 16 when not given), each call sent on
20
+ * the one with the fewest calls in flight: one connection is one invocation on the server, so a few
21
+ * carry more at once. Each opens on its first call and again after it closes. A call in flight when its
22
+ * connection drops (a server going away on deploy closes every connection) is sent again on a new one
23
+ * when the wire says repeating it is safe (`repeatable`), and is otherwise `unavailable`, since it may
24
+ * have been carried out. Where no connection opens, or the runtime has no WebSocket, calls go over
25
+ * `fallback` for a minute, then a connection is tried again; without one they are `unavailable`.
26
+ */
27
+ declare function socket(url: string, options: {
28
+ readonly key: string;
29
+ readonly secret: string;
30
+ readonly connections?: number;
31
+ readonly fallback?: Transport;
32
+ readonly WebSocket?: new (url: string) => SocketLike;
33
+ readonly clock?: () => number;
34
+ }): Transport & {
35
+ close(): void;
36
+ };
37
+ /**
38
+ * `engine` as a Storage Key reaches it: its Buckets by name (every Bucket, under its own name, when it
39
+ * names none), reading always, writing only with `write` access and while the Bucket's writes are not
40
+ * paused. Metering is the platform's, never a key's.
41
+ */
42
+ declare function keyed(engine: StorageEngine, credential: Omit<S3Credential, "secret">): StorageEngine;
43
+ /**
44
+ * One connection's server side: send `greeting` first, then pass each message to `receive` and send
45
+ * what it returns. After `life` milliseconds send `closing`, and close once `idle` resolves.
46
+ */
47
+ interface SocketSession {
48
+ readonly greeting: string;
49
+ readonly closing: string;
50
+ /** How long the connection may live, in milliseconds. */
51
+ readonly life: number;
52
+ /** Whether the connection has carried as many calls as one should, and should close as at the end of its life. */
53
+ spent(): boolean;
54
+ /** After `closing` is sent: resolves once every frame received has had its reply. */
55
+ idle(): Promise<void>;
56
+ /** The answer to a message: text during the handshake, a tagged frame after; null for none. */
57
+ receive(message: unknown): Promise<string | Uint8Array | null>;
58
+ /** Settles once the key is accepted or refused; a refused connection should then be closed. */
59
+ readonly settled: Promise<"ready" | "refused">;
60
+ }
61
+ /** A server's side of one connection: the handshake against `credentials`, then each frame served by `engine` as the key reaches it. */
62
+ declare function socketSession(options: {
63
+ readonly engine: StorageEngine;
64
+ readonly credentials: (accessKeyId: string) => S3Credential | null | Promise<S3Credential | null>;
65
+ }): SocketSession;
66
+ //#endregion
67
+ export { SocketSession, keyed, sameHex, sign, socket, socketSession };