ocel 0.0.1-alpha.0 → 0.0.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.
Files changed (271) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +98 -0
  4. package/dist/binding/binding.d.ts +22 -0
  5. package/dist/binding/binding.js +60 -0
  6. package/dist/binding/unprovisioned.d.ts +17 -0
  7. package/dist/binding/unprovisioned.js +25 -0
  8. package/dist/bucket/bucket-client.d.ts +4 -0
  9. package/dist/bucket/bucket-client.js +5 -0
  10. package/dist/bucket/bucket-context.d.ts +8 -0
  11. package/dist/bucket/bucket-context.js +10 -0
  12. package/dist/bucket/bucket.d.ts +60 -0
  13. package/dist/bucket/bucket.js +91 -0
  14. package/dist/bucket/client.d.ts +49 -0
  15. package/dist/bucket/client.js +95 -0
  16. package/dist/bucket/errors.d.ts +12 -0
  17. package/dist/bucket/errors.js +20 -0
  18. package/dist/bucket/express.d.ts +10 -0
  19. package/dist/bucket/express.js +24 -0
  20. package/dist/bucket/hono.d.ts +18 -0
  21. package/dist/bucket/hono.js +13 -0
  22. package/dist/bucket/index.d.ts +8 -0
  23. package/dist/bucket/index.js +6 -0
  24. package/dist/bucket/keys.d.ts +5 -0
  25. package/dist/bucket/keys.js +24 -0
  26. package/dist/bucket/metadata.d.ts +6 -0
  27. package/dist/bucket/metadata.js +6 -0
  28. package/dist/bucket/next.d.ts +15 -0
  29. package/dist/bucket/next.js +11 -0
  30. package/dist/bucket/objects.d.ts +130 -0
  31. package/dist/bucket/objects.js +350 -0
  32. package/dist/bucket/route.d.ts +13 -0
  33. package/dist/bucket/route.js +247 -0
  34. package/dist/bucket/server-only.js +5 -0
  35. package/dist/bucket/types.d.ts +63 -0
  36. package/dist/bucket/uploader.d.ts +3 -0
  37. package/dist/bucket/uploader.js +6 -0
  38. package/dist/build-env.d.ts +17 -0
  39. package/dist/build-env.js +41 -0
  40. package/dist/config.d.ts +30 -0
  41. package/dist/config.js +9 -0
  42. package/dist/declaration/callsite.d.ts +15 -0
  43. package/dist/declaration/callsite.js +43 -0
  44. package/dist/declaration/component.d.ts +4 -0
  45. package/dist/declaration/component.js +1 -0
  46. package/dist/declaration/defer.d.ts +5 -0
  47. package/dist/declaration/defer.js +9 -0
  48. package/dist/delivery/duration.d.ts +13 -0
  49. package/dist/delivery/duration.js +36 -0
  50. package/dist/delivery/lane.d.ts +4 -0
  51. package/dist/delivery/lane.js +15 -0
  52. package/dist/delivery/payload.d.ts +6 -0
  53. package/dist/delivery/payload.js +14 -0
  54. package/dist/delivery/retry.d.ts +16 -0
  55. package/dist/delivery/retry.js +10 -0
  56. package/dist/delivery/schema.d.ts +10 -0
  57. package/dist/delivery/schema.js +20 -0
  58. package/dist/dns.d.ts +11 -0
  59. package/dist/dns.js +4 -0
  60. package/dist/edge.d.ts +4 -0
  61. package/dist/edge.js +4 -0
  62. package/dist/env/access.d.ts +22 -0
  63. package/dist/env/access.js +49 -0
  64. package/dist/env/client.d.ts +5 -0
  65. package/dist/env/client.js +10 -0
  66. package/dist/env/declare.d.ts +2 -0
  67. package/dist/env/declare.js +83 -0
  68. package/dist/env/definition.d.ts +46 -0
  69. package/dist/env/definition.js +164 -0
  70. package/dist/env/deployment.d.ts +23 -0
  71. package/dist/env/deployment.js +13 -0
  72. package/dist/env/edge.d.ts +10 -0
  73. package/dist/env/edge.js +30 -0
  74. package/dist/env/errors.d.ts +9 -0
  75. package/dist/env/errors.js +9 -0
  76. package/dist/env/file.d.ts +1 -0
  77. package/dist/env/file.js +27 -0
  78. package/dist/env/index.d.ts +10 -0
  79. package/dist/env/index.js +63 -0
  80. package/dist/env/live.d.ts +3 -0
  81. package/dist/env/live.js +12 -0
  82. package/dist/env/schema.d.ts +27 -0
  83. package/dist/env/schema.js +43 -0
  84. package/dist/env/scope.d.ts +7 -0
  85. package/dist/env/scope.js +45 -0
  86. package/dist/env/standard.d.ts +10 -0
  87. package/dist/env/standard.js +21 -0
  88. package/dist/env/value.d.ts +5 -0
  89. package/dist/env/value.js +26 -0
  90. package/dist/env-source.d.ts +17 -0
  91. package/dist/env-source.js +16 -0
  92. package/dist/gen/proto/app/bucket/v1/bucket_pb.d.ts +911 -0
  93. package/dist/gen/proto/app/bucket/v1/bucket_pb.js +253 -0
  94. package/dist/gen/proto/app/realtime/v1/realtime_pb.d.ts +50 -0
  95. package/dist/gen/proto/app/realtime/v1/realtime_pb.js +23 -0
  96. package/dist/gen/proto/app/resources/v1/resources_pb.d.ts +554 -0
  97. package/dist/gen/proto/app/resources/v1/resources_pb.js +214 -0
  98. package/dist/gen/proto/app/resources/v1/variables_pb.d.ts +231 -0
  99. package/dist/gen/proto/app/resources/v1/variables_pb.js +101 -0
  100. package/dist/gen/proto/app/task/v1/task_pb.d.ts +498 -0
  101. package/dist/gen/proto/app/task/v1/task_pb.js +151 -0
  102. package/dist/gen/proto/app/topic/v1/topic_pb.d.ts +456 -0
  103. package/dist/gen/proto/app/topic/v1/topic_pb.js +125 -0
  104. package/dist/gen/proto/buf/validate/validate_pb.d.ts +4833 -0
  105. package/dist/gen/proto/buf/validate/validate_pb.js +356 -0
  106. package/dist/gen/proto/common/bindings/v1/bindings_pb.d.ts +378 -0
  107. package/dist/gen/proto/common/bindings/v1/bindings_pb.js +140 -0
  108. package/dist/generated/config.d.ts +428 -0
  109. package/dist/generated/config.js +2 -0
  110. package/dist/kv/entries.d.ts +193 -0
  111. package/dist/kv/entries.js +325 -0
  112. package/dist/kv/errors.d.ts +12 -0
  113. package/dist/kv/errors.js +14 -0
  114. package/dist/kv/index.d.ts +6 -0
  115. package/dist/kv/index.js +3 -0
  116. package/dist/kv/ioredis.d.ts +2 -0
  117. package/dist/kv/ioredis.js +20 -0
  118. package/dist/kv/kv.d.ts +84 -0
  119. package/dist/kv/kv.js +177 -0
  120. package/dist/kv/pattern.d.ts +27 -0
  121. package/dist/kv/pattern.js +73 -0
  122. package/dist/kv/ttl.d.ts +22 -0
  123. package/dist/kv/ttl.js +21 -0
  124. package/dist/postgres/index.d.ts +21 -2
  125. package/dist/postgres/index.js +73 -2
  126. package/dist/postgres/pg.d.ts +5 -4
  127. package/dist/postgres/pg.js +16 -12
  128. package/dist/providers/aws/dns.d.ts +11 -0
  129. package/dist/providers/aws/dns.js +4 -0
  130. package/dist/providers/aws/edge.d.ts +6 -0
  131. package/dist/providers/aws/edge.js +8 -0
  132. package/dist/providers/aws/index.d.ts +4 -0
  133. package/dist/providers/aws/index.js +4 -0
  134. package/dist/providers/gcp/edge.d.ts +14 -0
  135. package/dist/providers/gcp/edge.js +14 -0
  136. package/dist/providers/gcp/index.d.ts +9 -0
  137. package/dist/providers/gcp/index.js +9 -0
  138. package/dist/providers/vps/index.d.ts +4 -0
  139. package/dist/providers/vps/index.js +4 -0
  140. package/dist/realtime/client-error.d.ts +30 -0
  141. package/dist/realtime/client-error.js +17 -0
  142. package/dist/realtime/client-event-socket.d.ts +8 -0
  143. package/dist/realtime/client-event-socket.js +169 -0
  144. package/dist/realtime/client-transport.d.ts +29 -0
  145. package/dist/realtime/client-transport.js +13 -0
  146. package/dist/realtime/client.d.ts +150 -0
  147. package/dist/realtime/client.js +345 -0
  148. package/dist/realtime/express.d.ts +18 -0
  149. package/dist/realtime/express.js +83 -0
  150. package/dist/realtime/handler.d.ts +56 -0
  151. package/dist/realtime/handler.js +287 -0
  152. package/dist/realtime/hono.d.ts +19 -0
  153. package/dist/realtime/hono.js +24 -0
  154. package/dist/realtime/index.d.ts +2 -0
  155. package/dist/realtime/index.js +2 -0
  156. package/dist/realtime/next.d.ts +26 -0
  157. package/dist/realtime/next.js +16 -0
  158. package/dist/realtime/realtime.d.ts +181 -0
  159. package/dist/realtime/realtime.js +205 -0
  160. package/dist/realtime/token.d.ts +20 -0
  161. package/dist/realtime/token.js +45 -0
  162. package/dist/realtime/transport.d.ts +11 -0
  163. package/dist/realtime/transport.js +15 -0
  164. package/dist/realtime/wire.d.ts +30 -0
  165. package/dist/realtime/wire.js +104 -0
  166. package/dist/runtime/dev-server.d.ts +8 -0
  167. package/dist/runtime/dev-server.js +8 -0
  168. package/dist/runtime/rpc.d.ts +23 -0
  169. package/dist/runtime/rpc.js +24 -0
  170. package/dist/runtime/transport.d.ts +11 -0
  171. package/dist/runtime/transport.js +35 -0
  172. package/dist/task/errors.d.ts +7 -0
  173. package/dist/task/errors.js +7 -0
  174. package/dist/task/hooks.d.ts +57 -0
  175. package/dist/task/hooks.js +1 -0
  176. package/dist/task/index.d.ts +9 -0
  177. package/dist/task/index.js +4 -0
  178. package/dist/task/runs.d.ts +74 -0
  179. package/dist/task/runs.js +82 -0
  180. package/dist/task/task.d.ts +117 -0
  181. package/dist/task/task.js +109 -0
  182. package/dist/topic/dead-letters.d.ts +53 -0
  183. package/dist/topic/dead-letters.js +62 -0
  184. package/dist/topic/index.d.ts +8 -0
  185. package/dist/topic/index.js +4 -0
  186. package/dist/topic/topic.d.ts +85 -0
  187. package/dist/topic/topic.js +117 -0
  188. package/dist/version.d.ts +2 -0
  189. package/dist/version.js +2 -0
  190. package/dist/worker/context.d.ts +36 -0
  191. package/dist/worker/context.js +1 -0
  192. package/dist/worker/deliver.d.ts +13 -0
  193. package/dist/worker/deliver.js +258 -0
  194. package/dist/worker/index.d.ts +4 -0
  195. package/dist/worker/index.js +2 -0
  196. package/dist/worker/registry.d.ts +28 -0
  197. package/dist/worker/registry.js +22 -0
  198. package/dist/worker/semaphore.d.ts +7 -0
  199. package/dist/worker/semaphore.js +36 -0
  200. package/dist/worker/worker.d.ts +21 -0
  201. package/dist/worker/worker.js +32 -0
  202. package/package.json +158 -57
  203. package/bin/run.js +0 -39
  204. package/dist/blob/bucket.d.ts +0 -55
  205. package/dist/blob/bucket.js +0 -65
  206. package/dist/blob/index.d.ts +0 -8
  207. package/dist/blob/index.js +0 -13
  208. package/dist/blob/integrations/client.d.ts +0 -25
  209. package/dist/blob/integrations/client.js +0 -71
  210. package/dist/blob/integrations/hono.d.ts +0 -31
  211. package/dist/blob/integrations/hono.js +0 -11
  212. package/dist/blob/mime-types.d.ts +0 -1
  213. package/dist/blob/parse.d.ts +0 -16
  214. package/dist/blob/parse.js +0 -69
  215. package/dist/blob/s3-listener.d.ts +0 -7
  216. package/dist/blob/s3-listener.js +0 -35
  217. package/dist/blob/types.d.ts +0 -128
  218. package/dist/blob/types.js +0 -1
  219. package/dist/blob/upload-error.d.ts +0 -35
  220. package/dist/blob/upload-error.js +0 -54
  221. package/dist/blob/uploader.d.ts +0 -67
  222. package/dist/blob/uploader.js +0 -323
  223. package/dist/internal/db/index.d.ts +0 -68
  224. package/dist/internal/db/index.js +0 -73
  225. package/dist/lambda/index.d.ts +0 -2
  226. package/dist/lambda/index.js +0 -4
  227. package/dist/lambda/integrations/express.d.ts +0 -3
  228. package/dist/lambda/integrations/express.js +0 -13
  229. package/dist/lambda/integrations/hono.d.ts +0 -3
  230. package/dist/lambda/integrations/hono.js +0 -13
  231. package/dist/lambda/lambda.d.ts +0 -43
  232. package/dist/lambda/lambda.js +0 -30
  233. package/dist/utils/component.d.ts +0 -3
  234. package/dist/utils/constants.d.ts +0 -2
  235. package/dist/utils/constants.js +0 -2
  236. package/dist/utils/nanoid.d.ts +0 -1
  237. package/dist/utils/nanoid.js +0 -6
  238. package/dist/utils/rpc.d.ts +0 -11
  239. package/dist/utils/rpc.js +0 -17
  240. package/dist/utils/stack.d.ts +0 -4
  241. package/dist/utils/stack.js +0 -23
  242. package/dist/workflow/index.d.ts +0 -3
  243. package/dist/workflow/index.js +0 -4
  244. package/dist/workflow/workflow.d.ts +0 -34
  245. package/dist/workflow/workflow.js +0 -146
  246. package/src/blob/bucket.ts +0 -92
  247. package/src/blob/index.ts +0 -34
  248. package/src/blob/integrations/client.ts +0 -127
  249. package/src/blob/integrations/hono.ts +0 -16
  250. package/src/blob/mime-types.ts +0 -68
  251. package/src/blob/parse.ts +0 -93
  252. package/src/blob/s3-listener.ts +0 -48
  253. package/src/blob/types.ts +0 -142
  254. package/src/blob/upload-error.ts +0 -67
  255. package/src/blob/uploader.ts +0 -426
  256. package/src/internal/db/index.ts +0 -78
  257. package/src/lambda/index.ts +0 -8
  258. package/src/lambda/integrations/express.ts +0 -25
  259. package/src/lambda/integrations/hono.ts +0 -25
  260. package/src/lambda/lambda.ts +0 -94
  261. package/src/postgres/index.ts +0 -5
  262. package/src/postgres/pg.ts +0 -33
  263. package/src/utils/component.ts +0 -3
  264. package/src/utils/constants.ts +0 -2
  265. package/src/utils/nanoid.ts +0 -9
  266. package/src/utils/rpc.ts +0 -28
  267. package/src/utils/stack.ts +0 -26
  268. package/src/workflow/index.ts +0 -9
  269. package/src/workflow/workflow.ts +0 -235
  270. /package/dist/{blob/mime-types.js → bucket/server-only.d.ts} +0 -0
  271. /package/dist/{utils/component.js → bucket/types.js} +0 -0
@@ -1,323 +0,0 @@
1
- import slugify from "@sindresorhus/slugify";
2
- import { UploadError } from "./upload-error";
3
- import path from "node:path";
4
- import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
5
- import { getNanoid } from "../utils/nanoid";
6
- import { UploadSession } from "../internal/db";
7
- import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
8
- import { parseFileSize, parseReq } from "./parse";
9
- export class Uploader {
10
- bucket;
11
- name;
12
- config;
13
- pathGenerator = null;
14
- constructor(bucket, name, config) {
15
- this.bucket = bucket;
16
- this.name = name;
17
- this.config = config;
18
- const path = this.config.path;
19
- if (path) {
20
- if (typeof path === "function") {
21
- this.pathGenerator = path;
22
- }
23
- else {
24
- this.pathGenerator = this.createConfigBasedGenerator(path);
25
- }
26
- }
27
- }
28
- async handleUpload({ action, body, request, sessionId, }) {
29
- try {
30
- const req = parseReq(request);
31
- switch (action) {
32
- case "presign": {
33
- if (!("files" in body)) {
34
- throw UploadError.badRequest("Invalid presign body");
35
- }
36
- const presignBody = body;
37
- const rawInput = presignBody.input || {};
38
- const parser = this.config.input;
39
- let parsedInput;
40
- // TODO: error handling
41
- if (parser) {
42
- const parsed = parser.safeParse(rawInput);
43
- if (!parsed.success) {
44
- throw UploadError.badRequest(parsed.error.issues[0]?.message);
45
- }
46
- parsedInput = parsed.data;
47
- }
48
- const middleware = this.config.onBeforeUpload;
49
- const customMeta = await middleware?.({
50
- req: request,
51
- input: parsedInput,
52
- files: presignBody.files,
53
- });
54
- const metadata = {
55
- "x-ocel-path": req.path,
56
- "x-ocel-uploader": this.name,
57
- ...(customMeta
58
- ? { "x-ocel-metadata": JSON.stringify(customMeta) }
59
- : {}),
60
- };
61
- // TODO: validate files against uploader config (size, count, types, etc)
62
- this.validateFiles(presignBody.files, customMeta);
63
- const files = body.files.map((f) => {
64
- const name = slugify(f.name, { preserveCharacters: ["."] });
65
- return {
66
- ...f,
67
- key: this.pathGenerator?.({
68
- fileNameWithExt: name,
69
- metadata: customMeta,
70
- fileNameWithoutExt: name.replace(path.extname(name), ""),
71
- ext: path.extname(name),
72
- }) || name,
73
- disposition: "inline",
74
- metadata: {
75
- ...metadata,
76
- "x-ocel-original-filename": f.name,
77
- },
78
- };
79
- });
80
- const provider = this.getProvider();
81
- return provider.presign(files);
82
- }
83
- case "poll": {
84
- if (!sessionId) {
85
- throw UploadError.badRequest("sessionId is required for poll");
86
- }
87
- const result = await UploadSession.query
88
- .sessions({ sessionId })
89
- .go();
90
- const files = result.data.map((record) => {
91
- let parsedMeta = {};
92
- try {
93
- if (record.metadata) {
94
- parsedMeta = JSON.parse(record.metadata);
95
- }
96
- }
97
- catch {
98
- // ignore parse errors
99
- }
100
- return {
101
- fileKey: record.fileKey,
102
- status: record.status,
103
- file: record.status === "SUCCESS"
104
- ? {
105
- path: record.fileKey,
106
- contentDisposition: record.contentDisposition || "inline",
107
- contentType: record.contentType,
108
- }
109
- : undefined,
110
- metadata: parsedMeta,
111
- };
112
- });
113
- const allComplete = files.every((f) => f.status === "SUCCESS" || f.status === "FAILED");
114
- return {
115
- files,
116
- completed: allComplete,
117
- };
118
- }
119
- case "callback": {
120
- // TODO: validate callback body
121
- if (!("metadata" in body)) {
122
- throw UploadError.badRequest("Invalid callback body");
123
- }
124
- const data = body;
125
- await this.config.onUploadComplete?.(data);
126
- return {
127
- type: "UPLOAD_COMPLETED",
128
- response: "ok",
129
- };
130
- }
131
- default:
132
- throw UploadError.badRequest(`Unhandled action type: ${action}`);
133
- }
134
- }
135
- catch (err) {
136
- if (err instanceof UploadError) {
137
- this.config.onUploadError?.({ error: err });
138
- return {
139
- error: {
140
- message: err.message,
141
- code: err.code, // e.g. "FORBIDDEN"
142
- status: err.statusCode, // e.g. 403
143
- },
144
- };
145
- }
146
- return {
147
- error: {
148
- message: "Internal Server Error",
149
- code: "INTERNAL_SERVER_ERROR",
150
- status: 500,
151
- },
152
- };
153
- }
154
- }
155
- startPolling(sessionId) {
156
- const POLL_INTERVAL_MS = 1000;
157
- const MAX_DURATION_MS = 10 * 60 * 1000; // 10 minutes
158
- const startTime = Date.now();
159
- const tick = async () => {
160
- if (Date.now() - startTime > MAX_DURATION_MS) {
161
- return true;
162
- }
163
- const result = await UploadSession.query
164
- .sessions({ sessionId })
165
- .go();
166
- const allComplete = result.data.every((r) => r.status === "SUCCESS" || r.status === "FAILED");
167
- if (!allComplete) {
168
- return false;
169
- }
170
- // Session complete - invoke callbacks
171
- for (const record of result.data) {
172
- let parsedMeta = {};
173
- try {
174
- if (record.metadata) {
175
- parsedMeta = JSON.parse(record.metadata);
176
- }
177
- }
178
- catch {
179
- // ignore
180
- }
181
- if (record.status === "SUCCESS") {
182
- await this.config.onUploadComplete?.({
183
- metadata: parsedMeta,
184
- file: {
185
- path: record.fileKey,
186
- contentDisposition: record.contentDisposition || "inline",
187
- contentType: record.contentType,
188
- },
189
- });
190
- }
191
- else if (record.status === "FAILED" && this.config.onUploadError) {
192
- this.config.onUploadError({
193
- error: new UploadError(`Upload failed for ${record.fileKey}`, 500, "UPLOAD_FAILED"),
194
- });
195
- }
196
- }
197
- return true;
198
- };
199
- const intervalId = setInterval(async () => {
200
- try {
201
- const done = await tick();
202
- if (done) {
203
- clearInterval(intervalId);
204
- }
205
- }
206
- catch {
207
- clearInterval(intervalId);
208
- }
209
- }, POLL_INTERVAL_MS);
210
- }
211
- getProvider() {
212
- const bucket = this.bucket;
213
- const bucketId = bucket.__name();
214
- return {
215
- presign: async (files) => {
216
- const s3Client = new S3Client();
217
- const sessionId = getNanoid(8);
218
- const presignedFiles = await Promise.all(files.map(async (file) => {
219
- const metadataWithSession = {
220
- ...file.metadata,
221
- "x-ocel-session-id": sessionId,
222
- };
223
- await UploadSession.create({
224
- sessionId,
225
- bucketName: bucketId,
226
- fileKey: file.key,
227
- createdAt: new Date().toISOString(),
228
- status: "PENDING",
229
- contentType: file.mimeType,
230
- contentDisposition: file.disposition,
231
- fileSize: file.size,
232
- metadata: file.metadata
233
- ? JSON.stringify(file.metadata)
234
- : undefined,
235
- }).go();
236
- const url = await getSignedUrl(s3Client, new PutObjectCommand({
237
- Key: file.key,
238
- Bucket: bucketId,
239
- ContentType: file.mimeType,
240
- Metadata: metadataWithSession,
241
- }), { expiresIn: 3600 });
242
- return {
243
- url,
244
- key: file.key,
245
- name: file.name,
246
- };
247
- }));
248
- this.startPolling(sessionId);
249
- return {
250
- files: presignedFiles,
251
- sessionId,
252
- };
253
- },
254
- };
255
- }
256
- createConfigBasedGenerator(config) {
257
- return (ctx) => {
258
- let key = ctx.fileNameWithoutExt;
259
- // random suffix
260
- if (config.randomSuffix) {
261
- key += `-${Math.random().toString(36).slice(2, 10)}`;
262
- }
263
- // static suffix
264
- else if (config.suffix) {
265
- key += `-${config.suffix}`;
266
- }
267
- // add extension
268
- key += ctx.ext;
269
- // prefix
270
- if (config.prefix) {
271
- return `${config.prefix.replace(/\/$/, "")}/${key}`;
272
- }
273
- return key;
274
- };
275
- }
276
- validateFiles(files, metadata) {
277
- const { accept, limits } = this.config;
278
- if (limits?.maxFileCount !== undefined) {
279
- const max = typeof limits.maxFileCount === "function"
280
- ? limits.maxFileCount({ metadata })
281
- : limits.maxFileCount;
282
- if (files.length > max) {
283
- throw UploadError.badRequest(`File limit exceeded. Maximum files allowed: ${max}.`);
284
- }
285
- }
286
- if (limits?.minFileCount !== undefined) {
287
- const min = typeof limits.minFileCount === "function"
288
- ? limits.minFileCount({ metadata })
289
- : limits.minFileCount;
290
- if (files.length < min) {
291
- throw UploadError.badRequest(`File limit not met. Minimum files required: ${min}.`);
292
- }
293
- }
294
- // 2. Per-File Validation (Size and MIME Type)
295
- for (const file of files) {
296
- // MIME Type Validation
297
- if (accept && accept.length > 0) {
298
- const isAccepted = accept.some((allowedType) => {
299
- // Simple check for wildcards (*/*) and direct matches (image/png)
300
- if (allowedType.endsWith("/*")) {
301
- const typeGroup = allowedType.slice(0, -2);
302
- return file.mimeType.startsWith(typeGroup);
303
- }
304
- return file.mimeType === allowedType;
305
- });
306
- if (!isAccepted) {
307
- throw UploadError.badRequest(`File type not allowed: ${file.mimeType}. Must be one of: ${accept.join(", ")}.`);
308
- }
309
- }
310
- // Max File Size Validation
311
- if (limits?.maxFileSize !== undefined) {
312
- const sizeValue = typeof limits.maxFileSize === "function"
313
- ? limits.maxFileSize({ metadata })
314
- : limits.maxFileSize;
315
- const maxSizeInBytes = parseFileSize(sizeValue);
316
- if (file.size > maxSizeInBytes) {
317
- // You might want to convert maxSize from bytes to KB/MB for a better error message
318
- throw UploadError.badRequest(`File size too large. Maximum size: ${maxSizeInBytes} bytes.`);
319
- }
320
- }
321
- }
322
- }
323
- }
@@ -1,68 +0,0 @@
1
- import { Entity } from "electrodb";
2
- export declare const UploadSession: Entity<string, string, string, {
3
- model: {
4
- entity: string;
5
- version: string;
6
- service: string;
7
- };
8
- attributes: {
9
- sessionId: {
10
- type: "string";
11
- required: true;
12
- };
13
- bucketName: {
14
- type: "string";
15
- required: true;
16
- };
17
- fileKey: {
18
- type: "string";
19
- required: true;
20
- };
21
- contentType: {
22
- type: "string";
23
- required: true;
24
- };
25
- contentDisposition: {
26
- type: "string";
27
- required: false;
28
- };
29
- fileSize: {
30
- type: "number";
31
- required: true;
32
- };
33
- createdAt: {
34
- type: "string";
35
- required: true;
36
- default: () => string;
37
- };
38
- updatedAt: {
39
- type: "string";
40
- required: true;
41
- default: () => string;
42
- set: () => string;
43
- };
44
- status: {
45
- type: readonly ["PENDING", "SUCCESS", "FAILED"];
46
- required: true;
47
- default: string;
48
- };
49
- metadata: {
50
- type: "string";
51
- required: false;
52
- };
53
- };
54
- indexes: {
55
- sessions: {
56
- pk: {
57
- field: string;
58
- composite: "sessionId"[];
59
- template: string;
60
- };
61
- sk: {
62
- field: string;
63
- composite: ("bucketName" | "fileKey")[];
64
- template: string;
65
- };
66
- };
67
- };
68
- }>;
@@ -1,73 +0,0 @@
1
- import { Entity } from "electrodb";
2
- import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
3
- const client = new DynamoDBClient({});
4
- export const UploadSession = new Entity({
5
- model: {
6
- entity: "upload-session",
7
- version: "1",
8
- service: "blob",
9
- },
10
- attributes: {
11
- sessionId: {
12
- type: "string",
13
- required: true,
14
- },
15
- bucketName: {
16
- type: "string",
17
- required: true,
18
- },
19
- fileKey: {
20
- type: "string",
21
- required: true,
22
- },
23
- contentType: {
24
- type: "string",
25
- required: true,
26
- },
27
- contentDisposition: {
28
- type: "string",
29
- required: false,
30
- },
31
- fileSize: {
32
- type: "number",
33
- required: true,
34
- },
35
- createdAt: {
36
- type: "string",
37
- required: true,
38
- default: () => new Date().toISOString(),
39
- },
40
- updatedAt: {
41
- type: "string",
42
- required: true,
43
- default: () => new Date().toISOString(),
44
- set: () => new Date().toISOString(),
45
- },
46
- status: {
47
- type: ["PENDING", "SUCCESS", "FAILED"],
48
- required: true,
49
- default: "PENDING",
50
- },
51
- metadata: {
52
- type: "string",
53
- required: false,
54
- },
55
- },
56
- indexes: {
57
- sessions: {
58
- pk: {
59
- field: "pk",
60
- composite: ["sessionId"],
61
- template: "SESSION#${sessionId}",
62
- },
63
- sk: {
64
- field: "sk",
65
- composite: ["bucketName", "fileKey"],
66
- template: "FILE#${bucketName}#${fileKey}",
67
- },
68
- },
69
- },
70
- }, {
71
- client,
72
- table: "OcelTable", // required for all ocel logic
73
- });
@@ -1,2 +0,0 @@
1
- import { Lambda, type LambdaConfig, type TriggerMap } from "./lambda";
2
- export declare function lambda<T extends keyof TriggerMap>(id: string, config: LambdaConfig<T>): Lambda<T>;
@@ -1,4 +0,0 @@
1
- import { Lambda } from "./lambda";
2
- export function lambda(id, config) {
3
- return new Lambda(id, config);
4
- }
@@ -1,3 +0,0 @@
1
- import { Lambda, type LambdaConfig, type TriggerMap } from "../lambda";
2
- import type { Express } from "express";
3
- export declare function lambda<T extends keyof TriggerMap>(id: string, app: Express, config?: Omit<LambdaConfig<T>, "trigger" | "handler">): Lambda<T>;
@@ -1,13 +0,0 @@
1
- import { Lambda, } from "../lambda";
2
- import sls from "serverless-http";
3
- export function lambda(id, app, config) {
4
- const handler = sls(app);
5
- return new Lambda(id, {
6
- ...config,
7
- handler: handler,
8
- trigger: {
9
- type: "url",
10
- config: {},
11
- },
12
- });
13
- }
@@ -1,3 +0,0 @@
1
- import { Lambda, type LambdaConfig, type TriggerMap } from "../lambda";
2
- import type { Hono } from "hono";
3
- export declare function lambda<T extends keyof TriggerMap>(id: string, app: Hono, config?: Omit<LambdaConfig<T>, "trigger" | "handler">): Lambda<T>;
@@ -1,13 +0,0 @@
1
- import { Lambda, } from "../lambda";
2
- import { handle } from "hono/aws-lambda";
3
- export function lambda(id, app, config) {
4
- const handler = handle(app);
5
- return new Lambda(id, {
6
- ...config,
7
- handler: handler,
8
- trigger: {
9
- type: "url",
10
- config: {},
11
- },
12
- });
13
- }
@@ -1,43 +0,0 @@
1
- import type { Component } from "../utils/component";
2
- import type { Context, APIGatewayEvent, S3Event, LambdaFunctionURLEvent } from "aws-lambda";
3
- export type TriggerMap = {
4
- s3: {
5
- bucket: string;
6
- events: string[];
7
- };
8
- cron: {
9
- schedule: string;
10
- };
11
- url: {
12
- streaming?: boolean;
13
- };
14
- api: {
15
- id?: string;
16
- path: string;
17
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "*";
18
- };
19
- };
20
- export type TriggerUnion = {
21
- [K in keyof TriggerMap]: {
22
- type: K;
23
- config: TriggerMap[K];
24
- };
25
- }[keyof TriggerMap];
26
- export type LambdaHandlerOutput<T extends keyof TriggerMap> = T extends "api" ? {
27
- statusCode: number;
28
- headers: Record<string, string>;
29
- body: string;
30
- } : any;
31
- export type LambdaEvent<T extends keyof TriggerMap> = T extends "s3" ? S3Event : T extends "api" ? APIGatewayEvent : T extends "url" ? LambdaFunctionURLEvent : any;
32
- export interface LambdaConfig<T extends keyof TriggerMap> {
33
- handler: (event: LambdaEvent<T>, context: Context) => Promise<LambdaHandlerOutput<T>> | LambdaHandlerOutput<T>;
34
- trigger: Extract<TriggerUnion, {
35
- type: T;
36
- }>;
37
- link?: Component[];
38
- }
39
- export declare class Lambda<T extends keyof TriggerMap> implements Component {
40
- id: string;
41
- constructor(id: string, config: LambdaConfig<T>);
42
- __id(): string;
43
- }
@@ -1,30 +0,0 @@
1
- import { rpc } from "../utils/rpc";
2
- import { getCallerFile } from "../utils/stack";
3
- export class Lambda {
4
- id;
5
- constructor(id, config) {
6
- this.id = id;
7
- // remove non-serializable stuff
8
- const { handler, link, ...rest } = config;
9
- const links = link?.map((component) => component.__id()) || [];
10
- // @ts-expect-error - accessed by cli during build
11
- this.__handler = handler;
12
- // @ts-expect-error - accessed by cli during build
13
- this[Symbol.for("ocel:lambda:id")] = id;
14
- if (process.env.OCEL_PHASE === "discovery") {
15
- const source = getCallerFile();
16
- if (!source) {
17
- throw new Error("Could not determine caller file for lambda registration");
18
- }
19
- rpc.register({
20
- id: this.id,
21
- type: "lambda",
22
- source,
23
- config: { ...rest, links },
24
- });
25
- }
26
- }
27
- __id() {
28
- return this.id;
29
- }
30
- }
@@ -1,3 +0,0 @@
1
- export interface Component {
2
- __id(): string;
3
- }
@@ -1,2 +0,0 @@
1
- export declare const IS_DISCOVERY_PHASE: boolean;
2
- export declare const IS_DEV_MODE: boolean;
@@ -1,2 +0,0 @@
1
- export const IS_DISCOVERY_PHASE = process.env.OCEL_PHASE === "discovery";
2
- export const IS_DEV_MODE = process.env.OCEL_DEV === "1";
@@ -1 +0,0 @@
1
- export declare function getNanoid(length?: number): string;
@@ -1,6 +0,0 @@
1
- import { customAlphabet } from "nanoid";
2
- export function getNanoid(length = 7) {
3
- const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4
- const nanoid = customAlphabet(alphabet, length);
5
- return nanoid();
6
- }
@@ -1,11 +0,0 @@
1
- declare global {
2
- var __ocelRegister: Promise<unknown>[];
3
- }
4
- export declare const rpc: {
5
- register: (args: {
6
- id: string;
7
- type: "lambda" | "bucket" | "workflow" | "postgres";
8
- source: string;
9
- config?: Record<string, unknown>;
10
- }) => Promise<void>;
11
- };
package/dist/utils/rpc.js DELETED
@@ -1,17 +0,0 @@
1
- export const rpc = {
2
- register: async (args) => {
3
- const SERVER_URL = process.env.OCEL_SERVER;
4
- if (!SERVER_URL) {
5
- throw new Error("OCEL_SERVER environment variable is not set");
6
- }
7
- const p = fetch(`${SERVER_URL}/register`, {
8
- method: "POST",
9
- headers: {
10
- "Content-Type": "application/json",
11
- },
12
- body: JSON.stringify(args),
13
- });
14
- globalThis.__ocelRegister ??= [];
15
- globalThis.__ocelRegister.push(p);
16
- },
17
- };
@@ -1,4 +0,0 @@
1
- /**
2
- * Returns absolute path of the caller file.
3
- */
4
- export declare function getCallerFile(depth?: number): string | null;
@@ -1,23 +0,0 @@
1
- /**
2
- * Returns absolute path of the caller file.
3
- */
4
- export function getCallerFile(depth = 1) {
5
- const original = Error.prepareStackTrace;
6
- try {
7
- Error.prepareStackTrace = (_, stack) => stack;
8
- const err = new Error();
9
- const frames = err.stack;
10
- // index 0 = getCallerFile
11
- // index 1 = the function that called getCallerFile
12
- return (frames[2 + depth]
13
- ?.getFileName()
14
- ?.replace("file://", "")
15
- ?.split("?")?.[0] ?? null);
16
- }
17
- catch {
18
- return null;
19
- }
20
- finally {
21
- Error.prepareStackTrace = original;
22
- }
23
- }
@@ -1,3 +0,0 @@
1
- import type { ZodType } from "zod";
2
- import { Workflow, type WorkflowConfig } from "./workflow";
3
- export declare function workflow<TInput extends ZodType = never>(id: string, config: WorkflowConfig<TInput>): Workflow<TInput>;