@browserlessapi/inferlo 0.6.0 → 0.8.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 (140) hide show
  1. package/README.md +9 -5
  2. package/dist/ai/ai-sdk.d.ts +48 -0
  3. package/dist/ai/ai-sdk.js +235 -0
  4. package/dist/ai/ai-sdk.js.map +1 -0
  5. package/dist/ai/index.d.ts +37 -3
  6. package/dist/ai/index.js +96 -7
  7. package/dist/ai/index.js.map +1 -1
  8. package/dist/ai/public.d.ts +5 -1
  9. package/dist/ai/public.js +2 -0
  10. package/dist/ai/public.js.map +1 -1
  11. package/dist/ai/ui.d.ts +47 -0
  12. package/dist/ai/ui.js +33 -0
  13. package/dist/ai/ui.js.map +1 -0
  14. package/dist/app.d.ts +55 -4
  15. package/dist/app.js +439 -39
  16. package/dist/app.js.map +1 -1
  17. package/dist/astro.d.ts +60 -0
  18. package/dist/astro.js +68 -0
  19. package/dist/astro.js.map +1 -0
  20. package/dist/audit.d.ts +8 -1
  21. package/dist/audit.js +9 -2
  22. package/dist/audit.js.map +1 -1
  23. package/dist/auth.d.ts +1 -0
  24. package/dist/auth.js +1 -0
  25. package/dist/auth.js.map +1 -1
  26. package/dist/authjs.d.ts +70 -0
  27. package/dist/authjs.js +94 -0
  28. package/dist/authjs.js.map +1 -0
  29. package/dist/azure.d.ts +66 -0
  30. package/dist/azure.js +119 -0
  31. package/dist/azure.js.map +1 -0
  32. package/dist/better-auth.d.ts +89 -0
  33. package/dist/better-auth.js +75 -0
  34. package/dist/better-auth.js.map +1 -0
  35. package/dist/cache.d.ts +13 -9
  36. package/dist/cache.js +11 -9
  37. package/dist/cache.js.map +1 -1
  38. package/dist/cli/main.js +5 -5
  39. package/dist/cli/main.js.map +1 -1
  40. package/dist/client-ip.d.ts +41 -1
  41. package/dist/client-ip.js +85 -1
  42. package/dist/client-ip.js.map +1 -1
  43. package/dist/cross-site.d.ts +14 -0
  44. package/dist/cross-site.js +56 -0
  45. package/dist/cross-site.js.map +1 -0
  46. package/dist/db/memory.js +2 -1
  47. package/dist/db/memory.js.map +1 -1
  48. package/dist/db/postgres.js +23 -6
  49. package/dist/db/postgres.js.map +1 -1
  50. package/dist/db/table.d.ts +37 -5
  51. package/dist/db/table.js +96 -15
  52. package/dist/db/table.js.map +1 -1
  53. package/dist/db/types.d.ts +2 -0
  54. package/dist/describe.d.ts +23 -5
  55. package/dist/describe.js +20 -2
  56. package/dist/describe.js.map +1 -1
  57. package/dist/disk-storage.d.ts +6 -0
  58. package/dist/disk-storage.js +96 -0
  59. package/dist/disk-storage.js.map +1 -0
  60. package/dist/events.d.ts +134 -0
  61. package/dist/events.js +196 -0
  62. package/dist/events.js.map +1 -0
  63. package/dist/files.d.ts +23 -0
  64. package/dist/files.js +168 -0
  65. package/dist/files.js.map +1 -0
  66. package/dist/index.d.ts +26 -8
  67. package/dist/index.js +10 -2
  68. package/dist/index.js.map +1 -1
  69. package/dist/jobs.d.ts +56 -10
  70. package/dist/jobs.js +71 -13
  71. package/dist/jobs.js.map +1 -1
  72. package/dist/jwt.d.ts +83 -0
  73. package/dist/jwt.js +312 -0
  74. package/dist/jwt.js.map +1 -0
  75. package/dist/langchain.d.ts +58 -0
  76. package/dist/langchain.js +220 -0
  77. package/dist/langchain.js.map +1 -0
  78. package/dist/model.d.ts +23 -6
  79. package/dist/model.js +41 -7
  80. package/dist/model.js.map +1 -1
  81. package/dist/oidc.d.ts +70 -0
  82. package/dist/oidc.js +379 -0
  83. package/dist/oidc.js.map +1 -0
  84. package/dist/openapi.js +17 -2
  85. package/dist/openapi.js.map +1 -1
  86. package/dist/passport.d.ts +54 -0
  87. package/dist/passport.js +68 -0
  88. package/dist/passport.js.map +1 -0
  89. package/dist/postgres-js.d.ts +39 -0
  90. package/dist/postgres-js.js +71 -0
  91. package/dist/postgres-js.js.map +1 -0
  92. package/dist/rate-limit.d.ts +5 -3
  93. package/dist/rate-limit.js +3 -3
  94. package/dist/rate-limit.js.map +1 -1
  95. package/dist/redis-events.d.ts +27 -0
  96. package/dist/redis-events.js +163 -0
  97. package/dist/redis-events.js.map +1 -0
  98. package/dist/redis-jobs.d.ts +24 -0
  99. package/dist/redis-jobs.js +203 -0
  100. package/dist/redis-jobs.js.map +1 -0
  101. package/dist/redis-sockets.d.ts +24 -0
  102. package/dist/redis-sockets.js +75 -0
  103. package/dist/redis-sockets.js.map +1 -0
  104. package/dist/redis.d.ts +30 -0
  105. package/dist/redis.js +106 -0
  106. package/dist/redis.js.map +1 -0
  107. package/dist/response-body.d.ts +6 -0
  108. package/dist/response-body.js +7 -0
  109. package/dist/response-body.js.map +1 -0
  110. package/dist/route.d.ts +117 -3
  111. package/dist/route.js +27 -0
  112. package/dist/route.js.map +1 -1
  113. package/dist/schema.d.ts +23 -3
  114. package/dist/schema.js +70 -0
  115. package/dist/schema.js.map +1 -1
  116. package/dist/serve.d.ts +24 -1
  117. package/dist/serve.js +200 -8
  118. package/dist/serve.js.map +1 -1
  119. package/dist/service-client.d.ts +91 -0
  120. package/dist/service-client.js +177 -0
  121. package/dist/service-client.js.map +1 -0
  122. package/dist/sessions.d.ts +2 -0
  123. package/dist/sessions.js +36 -4
  124. package/dist/sessions.js.map +1 -1
  125. package/dist/sockets.d.ts +58 -0
  126. package/dist/sockets.js +111 -0
  127. package/dist/sockets.js.map +1 -0
  128. package/dist/storage.d.ts +47 -0
  129. package/dist/storage.js +123 -0
  130. package/dist/storage.js.map +1 -0
  131. package/dist/tracing.d.ts +7 -3
  132. package/dist/tracing.js +8 -2
  133. package/dist/tracing.js.map +1 -1
  134. package/dist/websocket.d.ts +81 -0
  135. package/dist/websocket.js +251 -0
  136. package/dist/websocket.js.map +1 -0
  137. package/llms.txt +2 -0
  138. package/package.json +77 -5
  139. package/templates/app/AGENTS.md +9 -5
  140. package/templates/app/test/notes.test.ts +2 -0
package/dist/files.js ADDED
@@ -0,0 +1,168 @@
1
+ /**
2
+ * File uploads: t.file() fields in multipart/form-data route bodies.
3
+ *
4
+ * route.post("/avatar", { body: t.object({ avatar: t.file({ maxBytes: 2_000_000, types: ["image/png", "image/jpeg"] }) }) })
5
+ * .handle(async ({ body }) => ({ name: body.avatar.name, size: body.avatar.size }))
6
+ *
7
+ * The body is read with a byte limit (maxBodySize plus every file field's maxBytes), so a too large upload is cut off
8
+ * while it streams in, and every size, type and content check runs before the handler.
9
+ */
10
+ import { InferloError } from "./errors.js";
11
+ import { containsFile } from "./schema.js";
12
+ /** Where a t.file() is allowed in a route, checked once by createApp. */
13
+ export function checkFileFields(route) {
14
+ const options = route.options;
15
+ const where = `${route.method} ${route.path}`;
16
+ for (const key of ["query", "params", "response", "message"]) {
17
+ const schema = options[key];
18
+ if (schema && containsFile(schema)) {
19
+ throw new InferloError("IL1004", `Route ${where} uses t.file() in its ${key} schema; files can only be sent in a request body.`, {
20
+ fix: "Move the t.file() field to body: t.object({ file: t.file() }); the client sends it as multipart/form-data.",
21
+ });
22
+ }
23
+ }
24
+ const body = options.body;
25
+ if (!body || !containsFile(body))
26
+ return;
27
+ if (body.def.kind !== "object") {
28
+ throw new InferloError("IL1004", `Route ${where}: a body with files must be t.object({ ... }) with t.file() fields.`, {
29
+ fix: "Use body: t.object({ file: t.file(), title: t.string() }).",
30
+ });
31
+ }
32
+ for (const [name, field] of Object.entries(body.def.shape ?? {})) {
33
+ if (!containsFile(field))
34
+ continue;
35
+ const d = field.def;
36
+ if (d.kind === "file")
37
+ continue;
38
+ if (d.kind === "array" && d.item.def.kind === "file") {
39
+ if (d.max === undefined) {
40
+ throw new InferloError("IL1004", `Route ${where}: the file list "${name}" has no .max(n), so the size of an upload would have no limit.`, {
41
+ fix: `Limit the number of files: ${name}: t.array(t.file({ maxBytes: 5_000_000 })).max(10).`,
42
+ });
43
+ }
44
+ continue;
45
+ }
46
+ throw new InferloError("IL1004", `Route ${where}: "${name}" nests t.file() inside another schema; multipart form fields are flat.`, {
47
+ fix: `Make it a top-level field of the body: ${name}: t.file(), or ${name}: t.array(t.file()).max(10) for several files.`,
48
+ });
49
+ }
50
+ if (options.tool) {
51
+ throw new InferloError("IL1004", `Route ${where} takes files, so it cannot be an MCP or AI tool (tools send JSON).`, {
52
+ fix: "Remove tool from this route, or add a route that takes a URL or text instead of the file for agents.",
53
+ });
54
+ }
55
+ }
56
+ /** Bytes the file fields of a body may add on top of maxBodySize (0 without files). */
57
+ export function fileBudget(body) {
58
+ if (!body || body.def.kind !== "object")
59
+ return 0;
60
+ let total = 0;
61
+ for (const field of Object.values(body.def.shape ?? {})) {
62
+ const d = field.def;
63
+ if (d.kind === "file")
64
+ total += d.max ?? 0;
65
+ else if (d.kind === "array" && d.item.def.kind === "file")
66
+ total += (d.item.def.max ?? 0) * (d.max ?? 0);
67
+ }
68
+ return total;
69
+ }
70
+ export function isMultipart(contentType) {
71
+ return contentType.toLowerCase().startsWith("multipart/form-data");
72
+ }
73
+ /**
74
+ * The fields of a multipart/form-data body as an object for the body schema. Repeated fields become lists, a single
75
+ * value of a list field becomes a one-item list, empty file inputs (no file chosen) count as left out, and the
76
+ * sessions() CSRF field _csrf is dropped.
77
+ */
78
+ export async function readMultipart(bytes, contentType, body) {
79
+ const invalid = () => new InferloError("IL2015", "Request body is not valid multipart/form-data.", {
80
+ status: 400,
81
+ fix: "Send a FormData body without setting Content-Type yourself (fetch adds the boundary), or a form with enctype=\"multipart/form-data\".",
82
+ });
83
+ if (bytes.byteLength === 0)
84
+ return {};
85
+ // Runtimes differ on bodies that are not multipart at all (some read them as an empty form), so the
86
+ // boundary is checked here: the body starts with it (after an optional preamble) and ends with its close.
87
+ const boundary = /boundary=(?:"([^"]+)"|([^;\s]+))/i.exec(contentType);
88
+ const delimiter = boundary ? `--${boundary[1] ?? boundary[2]}` : undefined;
89
+ const latin1 = new TextDecoder("latin1");
90
+ const head = latin1.decode(bytes.subarray(0, 1024));
91
+ const tail = latin1.decode(bytes.subarray(Math.max(0, bytes.byteLength - 1024)));
92
+ if (!delimiter || !head.includes(delimiter) || !tail.trimEnd().endsWith(`${delimiter}--`))
93
+ throw invalid();
94
+ let form;
95
+ try {
96
+ form = await new Response(bytes, { headers: { "content-type": contentType } }).formData();
97
+ }
98
+ catch {
99
+ throw invalid();
100
+ }
101
+ const shape = body.def.kind === "object" ? (body.def.shape ?? {}) : {};
102
+ const out = {};
103
+ for (const [key, value] of form.entries()) {
104
+ if (key === "_csrf")
105
+ continue;
106
+ // A file input with no file chosen is sent as an empty part with an empty filename, which some runtimes read
107
+ // as an empty file and others as an empty string.
108
+ if (typeof value !== "string" ? value.size === 0 && !value.name : value === "" && shape[key] && containsFile(shape[key]))
109
+ continue;
110
+ const current = out[key];
111
+ if (current === undefined)
112
+ out[key] = value;
113
+ else if (Array.isArray(current))
114
+ current.push(value);
115
+ else
116
+ out[key] = [current, value];
117
+ }
118
+ for (const [key, value] of Object.entries(out)) {
119
+ if (shape[key]?.def.kind === "array" && !Array.isArray(value))
120
+ out[key] = [value];
121
+ }
122
+ return out;
123
+ }
124
+ // The first bytes of the types whose content is checked against the declared type.
125
+ const SIGNATURES = {
126
+ "image/png": (b) => starts(b, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
127
+ "image/jpeg": (b) => starts(b, [0xff, 0xd8, 0xff]),
128
+ "image/gif": (b) => ascii(b, 0, "GIF87a") || ascii(b, 0, "GIF89a"),
129
+ "image/webp": (b) => ascii(b, 0, "RIFF") && ascii(b, 8, "WEBP"),
130
+ "application/pdf": (b) => ascii(b, 0, "%PDF-"),
131
+ "application/zip": (b) => starts(b, [0x50, 0x4b, 0x03, 0x04]) || starts(b, [0x50, 0x4b, 0x05, 0x06]),
132
+ };
133
+ function starts(bytes, prefix) {
134
+ return prefix.every((b, i) => bytes[i] === b);
135
+ }
136
+ function ascii(bytes, offset, text) {
137
+ for (let i = 0; i < text.length; i++)
138
+ if (bytes[offset + i] !== text.charCodeAt(i))
139
+ return false;
140
+ return true;
141
+ }
142
+ /** Media types whose first bytes Inferlo checks when a t.file() field limits its types. */
143
+ export const CHECKED_FILE_TYPES = Object.keys(SIGNATURES);
144
+ /**
145
+ * Checks that files of a field with types declare a type whose content matches (a PNG is a PNG), so a client cannot
146
+ * pass a script off as an image by naming its type. Returns validation issues; empty when every file passes.
147
+ */
148
+ export async function checkFileContents(body, value) {
149
+ const issues = [];
150
+ for (const [key, field] of Object.entries(body.def.shape ?? {})) {
151
+ const fileDef = field.def.kind === "file" ? field.def : field.def.kind === "array" && field.def.item.def.kind === "file" ? field.def.item.def : undefined;
152
+ if (!fileDef?.fileTypes?.length)
153
+ continue;
154
+ const files = Array.isArray(value[key]) ? value[key] : value[key] === undefined || value[key] === null ? [] : [value[key]];
155
+ for (const [i, file] of files.entries()) {
156
+ const declared = file.type.split(";")[0].trim().toLowerCase();
157
+ const matches = SIGNATURES[declared];
158
+ if (!matches)
159
+ continue;
160
+ const head = new Uint8Array(await file.slice(0, 16).arrayBuffer());
161
+ if (!matches(head)) {
162
+ issues.push({ path: Array.isArray(value[key]) ? [key, i] : [key], code: "file_content", message: `File content does not match its type ${declared}.` });
163
+ }
164
+ }
165
+ }
166
+ return issues;
167
+ }
168
+ //# sourceMappingURL=files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -13,41 +13,59 @@ export type { Module, ModuleOptions, AnyModule, ModuleModels } from "./module.ts
13
13
  export { apiVersion } from "./api-version.ts";
14
14
  export type { ApiVersionOptions } from "./api-version.ts";
15
15
  export { route, isRoute } from "./route.ts";
16
- export type { Register, Context, RouteDef, RouteOptions, Auth, Method, ToolOptions, AppUser, AppDb, AppPermission } from "./route.ts";
16
+ export type { Register, Context, RouteDef, RouteInput, RouteOptions, Auth, Method, ToolOptions, AppUser, AppDb, AppPermission, Socket, SocketContext, SocketRouteOptions } from "./route.ts";
17
17
  export { t, Schema, ObjectSchema, ArraySchema, RefSchema, ValidationError, toJSONSchema } from "./schema.ts";
18
- export type { Infer, InferInput, Issue, JSONSchema, ParseResult, Shape, AnySchema } from "./schema.ts";
18
+ export type { Infer, InferInput, Issue, JSONSchema, ParseResult, Shape, AnySchema, FileOptions } from "./schema.ts";
19
19
  export { model, Model, columnName } from "./model.ts";
20
- export type { Row, CreateInput, UpdateInput, AnyModel } from "./model.ts";
20
+ export type { Row, CreateInput, UpdateInput, AnyModel, ModelOptions } from "./model.ts";
21
21
  export { memory } from "./db/memory.ts";
22
22
  export { createDb, Table } from "./db/table.ts";
23
- export type { Db, Where, OrderBy, FindManyOptions, FindOptions, PaginateOptions, Page, Include, Relations, ReverseRelations, WithInclude } from "./db/table.ts";
23
+ export type { Db, PgClient, Where, OrderBy, FindManyOptions, FindOptions, PaginateOptions, Page, Include, Relations, ReverseRelations, WithInclude } from "./db/table.ts";
24
24
  export type { Adapter, Condition, Query, DbRecord } from "./db/types.ts";
25
25
  export { planMigration, applyMigrations } from "./db/migrate.ts";
26
26
  export type { ApplyMigrationsOptions, Migration, MigrationPlan, MigrationSnapshot, MigrationSnapshotColumn, MigrationSnapshotV1, PlanMigrationOptions, } from "./db/migrate.ts";
27
- export { createAI, cosineSimilarity, extractJson, openai, openaiCompatible, anthropic, gemini, ollama, mockProvider, ProviderError } from "./ai/index.ts";
27
+ export { createAI, cosineSimilarity, extractJson, openai, openaiCompatible, anthropic, gemini, ollama, mockProvider, ProviderError, uiChatBody, fromUIMessages } from "./ai/index.ts";
28
28
  export { tool, isTool, ToolBuilder } from "./ai/tool.ts";
29
+ export { aiSdk } from "./ai/ai-sdk.ts";
30
+ export type { AISdkProvider, AISdkLanguageModel, AISdkEmbeddingModel, AISdkOptions } from "./ai/ai-sdk.ts";
29
31
  export type { ToolDef, FunctionToolOptions, ToolContext } from "./ai/tool.ts";
30
- export type { AI, AIConfig, GenerateOptions, GenerateResult, StreamResult, Usage, Pricing, Provider, ProviderRequest, ProviderResponse, Image, ImageMediaType, Message, MockReply, Step, ToolCall, ToolCallResult, ToolSpec, } from "./ai/index.ts";
32
+ export type { AI, AIConfig, GenerateOptions, GenerateResult, StreamResult, StreamResponseInit, UIChatMessage, Usage, Pricing, Provider, ProviderRequest, ProviderResponse, Image, ImageMediaType, Message, MockReply, Step, ToolCall, ToolCallResult, ToolSpec, } from "./ai/index.ts";
31
33
  export type { RateLimit, RateLimitConfig } from "./rate-limit.ts";
34
+ export type { RedisClient } from "./redis.ts";
32
35
  export { job, isJob, retryDelayMs } from "./jobs.ts";
33
36
  export { cron, isCron } from "./cron.ts";
37
+ export { event, isEvent, on } from "./events.ts";
38
+ export type { AppEvents, EventDef, EventMessage, EventOptions, EventPayload, Events, EventsConfig, EventTransport, OnDef, PublishedEvent, PublishOptions } from "./events.ts";
34
39
  export type { CronDef } from "./cron.ts";
35
40
  export type { JobTraceContext } from "./tracing.ts";
36
41
  export type { JobDef, JobOptions, JobContext, JobInput, JobRecord, JobStatus, JobSource, JobQueueConfig, Jobs, AppJobs, EnqueueOptions, RunResult, Worker } from "./jobs.ts";
37
42
  export { AuditLog, auditChanges } from "./audit.ts";
38
43
  export type { Audit, AuditEntry, AuditChange } from "./audit.ts";
39
44
  export type { Cache, CacheConfig, CacheSetOptions, RouteCache } from "./cache.ts";
45
+ export { memoryStorage } from "./storage.ts";
46
+ export type { Storage, StorageStore, StoredFile, StoragePutOptions } from "./storage.ts";
47
+ export { diskStorage } from "./disk-storage.ts";
48
+ export type { DiskStorageOptions } from "./disk-storage.ts";
40
49
  export { permissions, isPermissions } from "./permissions.ts";
41
50
  export type { Permissions, PermissionRule, PermissionInput } from "./permissions.ts";
42
51
  export { bearer, hashToken, createToken, hashPassword, verifyPassword, safeEqual } from "./auth.ts";
43
52
  export { sessions } from "./sessions.ts";
53
+ export { jwt } from "./jwt.ts";
54
+ export { oidc } from "./oidc.ts";
55
+ export type { Oidc, OidcOptions, OidcClaims, OidcTokens } from "./oidc.ts";
56
+ export type { JwtOptions, JwtClaims, JwtAlgorithm } from "./jwt.ts";
44
57
  export type { TracingConfig, OtelApi, OtelSpan } from "./tracing.ts";
45
58
  export type { Sessions, SessionsOptions, SessionData, SessionCookieOptions, SessionResponseContext } from "./sessions.ts";
46
59
  export { env, setEnv } from "./env.ts";
47
60
  export { config } from "./config.ts";
48
61
  export type { Config, ConfigOptions } from "./config.ts";
49
62
  export { InferloError, httpError, notFound, forbidden, badRequest, docsUrl } from "./errors.ts";
50
- export { serve, toNodeHandler, fromNodeRequest } from "./serve.ts";
51
- export type { ServeOptions, Server, NodeRequest, NodeResponse, NodeHandler, NodeHandlerOptions, FromNodeRequestOptions } from "./serve.ts";
63
+ export { serviceClient, ServiceCallError } from "./service-client.ts";
64
+ export type { ServiceClient, ServiceClientOptions, CallInput, CallOptions, CallContext, CallResult, TypedRoute } from "./service-client.ts";
65
+ export { serve, toNodeHandler, toNodeUpgradeHandler, fromNodeRequest } from "./serve.ts";
66
+ export { bunWebSocket } from "./websocket.ts";
67
+ export type { Sockets, AppSockets, BroadcastOptions } from "./sockets.ts";
68
+ export type { SocketsConfig, RedisSubscriber } from "./redis-sockets.ts";
69
+ export type { ServeOptions, Server, NodeRequest, NodeResponse, NodeHandler, NodeHandlerOptions, FromNodeRequestOptions, NodeUpgradeHandler, NodeSocket } from "./serve.ts";
52
70
  export { INFERLO_VERSION } from "./describe.ts";
53
71
  export type { AppDescription } from "./describe.ts";
package/dist/index.js CHANGED
@@ -11,17 +11,25 @@ export { model, Model, columnName } from "./model.js";
11
11
  export { memory } from "./db/memory.js";
12
12
  export { createDb, Table } from "./db/table.js";
13
13
  export { planMigration, applyMigrations } from "./db/migrate.js";
14
- export { createAI, cosineSimilarity, extractJson, openai, openaiCompatible, anthropic, gemini, ollama, mockProvider, ProviderError } from "./ai/index.js";
14
+ export { createAI, cosineSimilarity, extractJson, openai, openaiCompatible, anthropic, gemini, ollama, mockProvider, ProviderError, uiChatBody, fromUIMessages } from "./ai/index.js";
15
15
  export { tool, isTool, ToolBuilder } from "./ai/tool.js";
16
+ export { aiSdk } from "./ai/ai-sdk.js";
16
17
  export { job, isJob, retryDelayMs } from "./jobs.js";
17
18
  export { cron, isCron } from "./cron.js";
19
+ export { event, isEvent, on } from "./events.js";
18
20
  export { AuditLog, auditChanges } from "./audit.js";
21
+ export { memoryStorage } from "./storage.js";
22
+ export { diskStorage } from "./disk-storage.js";
19
23
  export { permissions, isPermissions } from "./permissions.js";
20
24
  export { bearer, hashToken, createToken, hashPassword, verifyPassword, safeEqual } from "./auth.js";
21
25
  export { sessions } from "./sessions.js";
26
+ export { jwt } from "./jwt.js";
27
+ export { oidc } from "./oidc.js";
22
28
  export { env, setEnv } from "./env.js";
23
29
  export { config } from "./config.js";
24
30
  export { InferloError, httpError, notFound, forbidden, badRequest, docsUrl } from "./errors.js";
25
- export { serve, toNodeHandler, fromNodeRequest } from "./serve.js";
31
+ export { serviceClient, ServiceCallError } from "./service-client.js";
32
+ export { serve, toNodeHandler, toNodeUpgradeHandler, fromNodeRequest } from "./serve.js";
33
+ export { bunWebSocket } from "./websocket.js";
26
34
  export { INFERLO_VERSION } from "./describe.js";
27
35
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAOrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7G,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAWjE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1J,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAwBzD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAIzC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAOrC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7G,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAWjE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACtL,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AA4BvC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAKjD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAKjC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/dist/jobs.d.ts CHANGED
@@ -13,9 +13,12 @@
13
13
  import type { AI } from "./ai/index.ts";
14
14
  import type { Audit } from "./audit.ts";
15
15
  import type { Cache } from "./cache.ts";
16
+ import { type Storage } from "./storage.ts";
16
17
  import { type CronDef } from "./cron.ts";
17
18
  import type { Adapter } from "./db/types.ts";
19
+ import { type AppEvents, type EventTransport, type Events, type OnDef } from "./events.ts";
18
20
  import type { AppDb } from "./route.ts";
21
+ import { type SocketHub, type Sockets } from "./sockets.ts";
19
22
  import { type AnySchema, type Infer, type InferInput } from "./schema.ts";
20
23
  import type { JobTraceContext, JobTracing } from "./tracing.ts";
21
24
  export interface JobOptions<I extends AnySchema> {
@@ -33,12 +36,23 @@ export interface JobContext<Input> {
33
36
  ai: AI;
34
37
  /** Enqueue follow-up jobs. */
35
38
  jobs: Jobs;
39
+ /** Publish events: await events.publish(orderPaid, { orderId }) queues the jobs subscribed with on(event, job). */
40
+ events: Events;
36
41
  /** The app cache, the same as ctx.cache in routes and app.cache. */
37
42
  cache: Cache;
43
+ /** Files (createApp({ storage })), the same as ctx.storage in routes and app.storage. */
44
+ storage: Storage;
45
+ /** Send to WebSocket rooms of this process (the job's tenant's rooms with a tenant): await sockets.broadcast(room, data). */
46
+ sockets: Sockets;
38
47
  /** Job id. */
39
48
  id: string;
40
49
  /** 1 on the first run, 2 on the first retry, and so on. */
41
50
  attempt: number;
51
+ /**
52
+ * The tenant the job works for (the tenant of the request or job that queued it, or enqueue's tenantId), or null.
53
+ * ctx.db is scoped to it, and jobs and events queued from this job keep it.
54
+ */
55
+ tenantId: string | null;
42
56
  /**
43
57
  * Write an audit log entry (needs AuditLog in createApp({ models })). Jobs have no signed-in user: pass the
44
58
  * userId of the user who asked for the work, or leave it out for work the system does on its own.
@@ -58,6 +72,11 @@ export type JobInput<J> = J extends JobDef<infer I, any> ? I : never;
58
72
  export interface EnqueueOptions {
59
73
  /** Run no earlier than this time. Default: now. */
60
74
  runAt?: Date;
75
+ /**
76
+ * The tenant the job works for: its ctx.db is scoped to it (tenant-scoped models). Default: the tenant of the
77
+ * request or job that enqueues it, none from app.jobs. Pass null to queue it without a tenant.
78
+ */
79
+ tenantId?: string | null;
61
80
  }
62
81
  export type JobStatus = "pending" | "running" | "done" | "failed";
63
82
  export interface JobRecord {
@@ -76,6 +95,8 @@ export interface JobRecord {
76
95
  lastError?: string;
77
96
  /** With createApp({ tracing }): the trace (W3C traceparent and tracestate) of the request or job that enqueued it, which its runs continue. */
78
97
  trace?: JobTraceContext;
98
+ /** The tenant the job works for (multi-tenancy): its ctx.db is scoped to it. */
99
+ tenantId?: string;
79
100
  createdAt: Date;
80
101
  updatedAt: Date;
81
102
  }
@@ -87,8 +108,9 @@ export interface JobQueueConfig {
87
108
  /**
88
109
  * Where queued jobs are kept. "memory" (default): in this process, for development and tests.
89
110
  * "database": in the inferlo_jobs table of the app's Postgres database, shared by every instance.
111
+ * "redis": in the Redis of createApp({ redis }), shared by every instance.
90
112
  */
91
- store?: "memory" | "database";
113
+ store?: "memory" | "database" | "redis";
92
114
  }
93
115
  /** Where queued jobs are kept. */
94
116
  export interface JobStore {
@@ -98,7 +120,7 @@ export interface JobStore {
98
120
  claim(now: Date, limit: number, names: readonly string[]): Promise<JobRecord[]>;
99
121
  update(id: string, patch: Partial<Pick<JobRecord, "status" | "runAt" | "lastError">>): Promise<void>;
100
122
  get(id: string): Promise<JobRecord | null>;
101
- /** Record that a running job is still alive (database store), so it is not picked up again as stuck. */
123
+ /** Record that a running job is still alive (database and Redis stores), so it is not picked up again as stuck. */
102
124
  touch?(id: string): Promise<void>;
103
125
  }
104
126
  export interface RunResult {
@@ -120,14 +142,17 @@ export interface AppJobs extends Jobs {
120
142
  /** The registered crons: cron(schedule, job) values in createApp({ jobs }). */
121
143
  readonly crons: readonly CronDef[];
122
144
  /** Where queued jobs are kept (createApp({ jobQueue: { store } })). */
123
- readonly queue: "memory" | "database";
145
+ readonly queue: "memory" | "database" | "redis";
124
146
  /** A queued job by id, or null. */
125
147
  get(id: string): Promise<JobRecord | null>;
126
148
  /** Run every job that is due now (or at options.now), one after another, including follow-ups they enqueue, then return. For tests and scripts. */
127
149
  runDue(options?: {
128
150
  now?: Date;
129
151
  }): Promise<RunResult>;
130
- /** Run due jobs in this process every pollMs (default 1000) until stop() is called. Also queues each cron's job at every tick after the start. */
152
+ /**
153
+ * Run due jobs in this process every pollMs (default 1000) until stop() is called. Also queues each cron's job at
154
+ * every tick after the start, and with an events transport, the jobs of the events it receives.
155
+ */
131
156
  start(options?: {
132
157
  pollMs?: number;
133
158
  }): Worker;
@@ -146,13 +171,15 @@ export declare class JobBuilder<I extends AnySchema> {
146
171
  /** Define a background job: job("send-email", { input: t.object({ to: t.email() }) }).handle(fn). */
147
172
  export declare function job<I extends AnySchema>(name: string, options: JobOptions<I>): JobBuilder<I>;
148
173
  export declare function isJob(value: unknown): value is JobDef;
149
- /** Anything that contains jobs: a job, a cron, an array, or a module (import * as jobs from "./jobs.ts"). */
150
- export type JobSource = JobDef | CronDef | readonly JobSource[] | {
174
+ /** Anything that contains jobs: a job, a cron, an event subscription (on), an array, or a module (import * as jobs from "./jobs.ts"). */
175
+ export type JobSource = JobDef | CronDef | OnDef | readonly JobSource[] | {
151
176
  readonly [name: string]: unknown;
152
177
  };
153
178
  /** The jobs and crons in createApp({ jobs }). A cron's job is registered with it. */
154
179
  export declare function collectJobs(sources: readonly JobSource[] | undefined): JobDef[];
155
180
  export declare function collectCrons(sources: readonly JobSource[] | undefined): CronDef[];
181
+ /** The event subscriptions, on(event, job), in createApp({ jobs }). */
182
+ export declare function collectSubscriptions(sources: readonly JobSource[] | undefined): OnDef[];
156
183
  /** Jobs kept in this process. They are lost when it stops, so use it for development and tests. */
157
184
  export declare function memoryJobStore(): JobStore;
158
185
  /** A running job whose worker has not reported for this long is treated as stuck (its process stopped) and run again. */
@@ -168,20 +195,24 @@ export declare const STOPPED_MESSAGE = "The worker stopped while running this jo
168
195
  export declare function databaseJobStore(adapter: Adapter, options?: {
169
196
  staleAfterMs?: number;
170
197
  }): JobStore;
171
- /** Pick the job store for createApp({ jobQueue }). Raises IL6011 for an unknown store, IL6012 for "database" without Postgres. */
172
- export declare function jobStoreFor(config: JobQueueConfig | undefined, adapter: Adapter): JobStore;
198
+ export declare function jobStoreFor(config: JobQueueConfig | undefined, adapter: Adapter, redis?: () => JobStore): JobStore;
173
199
  export interface JobRuntime {
174
200
  db: AppDb;
175
201
  ai: AI;
176
202
  cache: Cache;
203
+ /** Files (app.storage). Default: none (ctx.storage throws IL6037). */
204
+ storage?: Storage;
205
+ /** WebSocket rooms (app.sockets). */
206
+ sockets?: SocketHub;
177
207
  /** Builds ctx.audit for one run. */
178
208
  audit(job: {
179
209
  name: string;
180
210
  id: string;
211
+ tenantId: string | null;
181
212
  }): Audit;
182
213
  store: JobStore;
183
214
  /** Name of the store, shown as app.jobs.queue. Default "memory". */
184
- queue?: "memory" | "database";
215
+ queue?: "memory" | "database" | "redis";
185
216
  /** How often a running job is reported alive to stores that support it. Default HEARTBEAT_MS. */
186
217
  heartbeatMs?: number;
187
218
  logger: {
@@ -192,10 +223,25 @@ export interface JobRuntime {
192
223
  onRun?(name: string, outcome: keyof RunResult, durationMs: number): void;
193
224
  /** With createApp({ tracing }): a span per attempt that continues the trace the job was enqueued in. */
194
225
  tracing?: JobTracing;
226
+ /** With createApp({ events: { transport } }): carries published events between services. */
227
+ eventTransport?: EventTransport;
195
228
  }
196
229
  /** app.jobs plus what the framework tests reach directly. */
197
230
  export interface InternalJobs extends AppJobs {
198
231
  /** Queue the job of each cron's latest tick in (from, to]. */
199
232
  queueCrons(from: Date, to: Date): Promise<void>;
233
+ /** app.events: publishing queues the jobs subscribed with on(event, job). */
234
+ readonly events: AppEvents;
200
235
  }
201
- export declare function createJobs(list: readonly JobDef[], runtime: JobRuntime, crons?: readonly CronDef[]): InternalJobs;
236
+ export declare function createJobs(list: readonly JobDef[], runtime: JobRuntime, crons?: readonly CronDef[], subscriptions?: readonly OnDef[]): InternalJobs;
237
+ /**
238
+ * ctx.jobs and ctx.events for one tenant: jobs and events queued through them carry the tenant unless the call
239
+ * names another (tenantId) or none (null). Internal: used for requests and jobs with a tenant.
240
+ */
241
+ export declare function withTenant(base: {
242
+ jobs: Jobs;
243
+ events: Events;
244
+ }, tenantId: string): {
245
+ jobs: Jobs;
246
+ events: Events;
247
+ };