@develit-io/backend-sdk 5.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/README.md +70 -0
- package/dist/index.cjs +464 -0
- package/dist/index.d.cts +330 -0
- package/dist/index.d.mts +330 -0
- package/dist/index.d.ts +330 -0
- package/dist/index.mjs +423 -0
- package/package.json +39 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright 2025 Develit.io s.r.o.
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
4
|
+
|
|
5
|
+
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Develit Backend SDK
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for building Cloudflare Workers with database integration, command patterns, and automatic audit logging.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @develit-io/backend-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Core Features
|
|
12
|
+
|
|
13
|
+
- **Worker Framework**: Decorator-based actions with `@action()` and `@service()`
|
|
14
|
+
- **Database Integration**: Built-in Drizzle ORM with `initializeDB()`
|
|
15
|
+
- **Command Pattern**: Reusable, parameterized database operations
|
|
16
|
+
- **Atomic Audit Logging**: Audit logs included in same database batch
|
|
17
|
+
- **Type Safety**: Full TypeScript support throughout
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
@service('user-service')
|
|
23
|
+
export default class UserService extends develitWorker(WorkerEntrypoint<UserEnv>) {
|
|
24
|
+
|
|
25
|
+
constructor(env: Env, ctx: ExecutionContext) {
|
|
26
|
+
super(env, ctx)
|
|
27
|
+
// Setup audit logging
|
|
28
|
+
const auditWriter = createAuditLogWriter(tables.auditLog)
|
|
29
|
+
this.initializeDB(env.USER_DB, tables, auditWriter)
|
|
30
|
+
// Now available: this.db
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@action('create-user')
|
|
34
|
+
async createUser(input: CreateUserInput): Promise<IRPCResponse<CreateUserOutput>> {
|
|
35
|
+
return this.handleAction(
|
|
36
|
+
{data: input, schema: createUserInputSchema},
|
|
37
|
+
{successMessage: 'User created successfully'},
|
|
38
|
+
() => {
|
|
39
|
+
await this.db.execute(createUserCommand(userData))
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Key Exports
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Core functionality
|
|
49
|
+
export { develitWorker, action, service } from '@develit-io/workers-sdk'
|
|
50
|
+
export { defineCommand, DatabaseTransaction, createAuditLogWriter } from '@develit-io/workers-sdk'
|
|
51
|
+
|
|
52
|
+
// Built-in worker properties after initializeDB():
|
|
53
|
+
// - this.db: DatabaseTransaction
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
- **[defineCommand Usage](./examples/define-command.md)** - Creating parameterized commands
|
|
59
|
+
- **[DatabaseTransaction Usage](./examples/database-transaction.md)** - Transaction and audit logging
|
|
60
|
+
|
|
61
|
+
## Requirements
|
|
62
|
+
|
|
63
|
+
- Node.js 18+
|
|
64
|
+
- TypeScript 5.0+
|
|
65
|
+
- Cloudflare Workers environment
|
|
66
|
+
- Drizzle ORM setup
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
ISC License - see package.json for details.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const drizzleOrm = require('drizzle-orm');
|
|
4
|
+
const pgCore = require('drizzle-orm/pg-core');
|
|
5
|
+
const sqliteCore = require('drizzle-orm/sqlite-core');
|
|
6
|
+
require('http-status-codes');
|
|
7
|
+
const z = require('zod/v4/core');
|
|
8
|
+
const h3 = require('h3');
|
|
9
|
+
const consola = require('consola');
|
|
10
|
+
const drizzleKit = require('drizzle-kit');
|
|
11
|
+
const superjson = require('superjson');
|
|
12
|
+
|
|
13
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
14
|
+
|
|
15
|
+
function _interopNamespaceCompat(e) {
|
|
16
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
17
|
+
const n = Object.create(null);
|
|
18
|
+
if (e) {
|
|
19
|
+
for (const k in e) {
|
|
20
|
+
n[k] = e[k];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return n;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const z__namespace = /*#__PURE__*/_interopNamespaceCompat(z);
|
|
28
|
+
const superjson__default = /*#__PURE__*/_interopDefaultCompat(superjson);
|
|
29
|
+
|
|
30
|
+
const base = {
|
|
31
|
+
id: sqliteCore.text("id").primaryKey(),
|
|
32
|
+
createdAt: sqliteCore.integer("created_at", { mode: "timestamp_ms" }).default(
|
|
33
|
+
drizzleOrm.sql`(unixepoch('subsec') * 1000)`
|
|
34
|
+
),
|
|
35
|
+
modifiedAt: sqliteCore.integer("modified_at", { mode: "timestamp_ms" }).default(drizzleOrm.sql`null`).$onUpdate(() => /* @__PURE__ */ new Date())
|
|
36
|
+
};
|
|
37
|
+
const basePostgres = {
|
|
38
|
+
id: pgCore.uuid("id").primaryKey(),
|
|
39
|
+
createdAt: pgCore.timestamp("created_at", { mode: "date", withTimezone: false }).defaultNow().notNull(),
|
|
40
|
+
modifiedAt: pgCore.timestamp("modified_at", { mode: "date", withTimezone: false }).default(drizzleOrm.sql`null`).$onUpdate(() => /* @__PURE__ */ new Date())
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const ibanZodSchema = new z__namespace.$ZodString({
|
|
44
|
+
type: "string",
|
|
45
|
+
checks: [
|
|
46
|
+
new z__namespace.$ZodCheckMinLength({
|
|
47
|
+
check: "min_length",
|
|
48
|
+
minimum: 1
|
|
49
|
+
}),
|
|
50
|
+
new z__namespace.$ZodCheckRegex({
|
|
51
|
+
check: "string_format",
|
|
52
|
+
format: "regex",
|
|
53
|
+
pattern: /^([A-Z]{2}[0-9]{2})([A-Z0-9]{4})([A-Z0-9]{4})([A-Z0-9]{4})([A-Z0-9]{4})?$/
|
|
54
|
+
})
|
|
55
|
+
]
|
|
56
|
+
});
|
|
57
|
+
const swiftZodSchema = new z__namespace.$ZodString({
|
|
58
|
+
type: "string",
|
|
59
|
+
checks: [
|
|
60
|
+
new z__namespace.$ZodCheckMinLength({
|
|
61
|
+
check: "min_length",
|
|
62
|
+
minimum: 1
|
|
63
|
+
}),
|
|
64
|
+
new z__namespace.$ZodCheckRegex({
|
|
65
|
+
check: "string_format",
|
|
66
|
+
format: "regex",
|
|
67
|
+
pattern: /^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$/
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const handleActionResponse = ({
|
|
73
|
+
error,
|
|
74
|
+
status,
|
|
75
|
+
message,
|
|
76
|
+
data
|
|
77
|
+
}) => {
|
|
78
|
+
if (error) {
|
|
79
|
+
throw h3.createError({ status, message });
|
|
80
|
+
}
|
|
81
|
+
if (data === void 0 || data === null) {
|
|
82
|
+
throw h3.createError({
|
|
83
|
+
statusCode: 500,
|
|
84
|
+
message: "Could not process the request. (ACTION_RESPONSE_FAILED)"
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return data;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const createInternalError = (error, details) => {
|
|
91
|
+
return {
|
|
92
|
+
status: details?.status || 500,
|
|
93
|
+
code: details?.code || "UNKNOWN_ERROR",
|
|
94
|
+
message: details?.message || (error instanceof Error ? error.message : "An unexpected error occurred.")
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
const isInternalError = (error) => {
|
|
98
|
+
return typeof error === "object" && error !== null && "message" in error && "code" in error;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const RPCResponse = {
|
|
102
|
+
/**
|
|
103
|
+
* ✅ Constructs a successful RPC response.
|
|
104
|
+
*
|
|
105
|
+
* This method wraps the provided data in a standardized response format,
|
|
106
|
+
* ensuring consistency across API responses.
|
|
107
|
+
*
|
|
108
|
+
* @template T - The type of the response data.
|
|
109
|
+
* @param message - Response message
|
|
110
|
+
* @param detail - Optional -> Contains data and status code
|
|
111
|
+
* @returns An `IRPCResponse<T>` with the provided data and no error.
|
|
112
|
+
*/
|
|
113
|
+
ok(message, detail) {
|
|
114
|
+
return {
|
|
115
|
+
status: detail?.status || 200,
|
|
116
|
+
data: detail?.data,
|
|
117
|
+
error: false,
|
|
118
|
+
message
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
/**
|
|
122
|
+
* ❌ Constructs a generic service error response.
|
|
123
|
+
*
|
|
124
|
+
* This method logs the error and returns a standardized error response.
|
|
125
|
+
*
|
|
126
|
+
* @template T - The expected response type (typically ignored in errors).
|
|
127
|
+
* @param error - An `RPCError` containing error details.
|
|
128
|
+
* @returns An `IRPCResponse<T>` with `null` data and the provided error.
|
|
129
|
+
*/
|
|
130
|
+
serviceError(error) {
|
|
131
|
+
consola.consola.error(error.message);
|
|
132
|
+
return {
|
|
133
|
+
status: error.status,
|
|
134
|
+
message: error.message,
|
|
135
|
+
data: null,
|
|
136
|
+
error: true
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
/**
|
|
140
|
+
* ❌ Constructs a validation error response (HTTP 400).
|
|
141
|
+
*
|
|
142
|
+
* This is a convenience method for returning validation errors.
|
|
143
|
+
* It internally delegates to `serviceError()`.
|
|
144
|
+
*
|
|
145
|
+
* @template T - The expected response type (typically ignored in errors).
|
|
146
|
+
* @param error - An `RPCError` representing a validation failure.
|
|
147
|
+
* @returns An `IRPCResponse<T>` with `null` data and the provided error.
|
|
148
|
+
*/
|
|
149
|
+
validationError(error) {
|
|
150
|
+
return RPCResponse.serviceError(error);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const useResult = async (promise) => {
|
|
155
|
+
try {
|
|
156
|
+
return [await promise, null];
|
|
157
|
+
} catch (error) {
|
|
158
|
+
return [null, isInternalError(error) ? error : createInternalError(error)];
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const useResultSync = (fn) => {
|
|
162
|
+
try {
|
|
163
|
+
return [fn(), null];
|
|
164
|
+
} catch (error) {
|
|
165
|
+
return [null, isInternalError(error) ? error : createInternalError(error)];
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
async function handleAction(worker, input, options = {}, actionExecution) {
|
|
170
|
+
const {
|
|
171
|
+
successMessage = "Operation completed successfully.",
|
|
172
|
+
logOutputTransform,
|
|
173
|
+
logInputTransform,
|
|
174
|
+
skipValidation = false,
|
|
175
|
+
skipLogging = false
|
|
176
|
+
} = options;
|
|
177
|
+
try {
|
|
178
|
+
if (!skipLogging && input) {
|
|
179
|
+
const inputToLog = logInputTransform ? logInputTransform(input.data) : input;
|
|
180
|
+
worker.logInput(inputToLog);
|
|
181
|
+
}
|
|
182
|
+
let validatedInput = input?.data || null;
|
|
183
|
+
if (!skipValidation && input) {
|
|
184
|
+
validatedInput = worker.handleInput({
|
|
185
|
+
input: input.data,
|
|
186
|
+
schema: input.schema
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const [data, error] = await useResult(
|
|
190
|
+
actionExecution(validatedInput)
|
|
191
|
+
);
|
|
192
|
+
if (error) {
|
|
193
|
+
worker.logError(error);
|
|
194
|
+
return RPCResponse.serviceError(error);
|
|
195
|
+
}
|
|
196
|
+
if (!skipLogging) {
|
|
197
|
+
const outputToLog = logOutputTransform ? logOutputTransform(data) : data;
|
|
198
|
+
worker.logOutput(outputToLog);
|
|
199
|
+
}
|
|
200
|
+
return RPCResponse.ok(successMessage, { data });
|
|
201
|
+
} catch (error) {
|
|
202
|
+
const internalError = createInternalError(error);
|
|
203
|
+
worker.logError(internalError);
|
|
204
|
+
return RPCResponse.serviceError(internalError);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const drizzleConfig = drizzleKit.defineConfig({
|
|
209
|
+
dialect: "sqlite",
|
|
210
|
+
schema: "./src/database/schema/",
|
|
211
|
+
out: "./src/database/migrations/"
|
|
212
|
+
});
|
|
213
|
+
function first(rows) {
|
|
214
|
+
return rows.length > 0 ? rows[0] : void 0;
|
|
215
|
+
}
|
|
216
|
+
function firstOrError(rows) {
|
|
217
|
+
if (rows.length === 0) {
|
|
218
|
+
throw new Error("Query did not return any data.");
|
|
219
|
+
}
|
|
220
|
+
return rows[0];
|
|
221
|
+
}
|
|
222
|
+
const uuidv4 = () => crypto.randomUUID();
|
|
223
|
+
|
|
224
|
+
const calculateExponentialBackoff = (attempts, baseDelaySeconds) => {
|
|
225
|
+
return baseDelaySeconds ** attempts;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const asNonEmpty = (arr) => {
|
|
229
|
+
return arr.length > 0 ? [arr[0], ...arr.slice(1)] : null;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
class DatabaseTransaction {
|
|
233
|
+
constructor(db, serviceName, auditLogWriter) {
|
|
234
|
+
this.db = db;
|
|
235
|
+
this.serviceName = serviceName;
|
|
236
|
+
this.auditLogWriter = auditLogWriter;
|
|
237
|
+
}
|
|
238
|
+
commands = [];
|
|
239
|
+
logs = [];
|
|
240
|
+
ids = [];
|
|
241
|
+
enqueue(commands) {
|
|
242
|
+
return (Array.isArray(commands) ? commands : [commands]).map((cmd) => {
|
|
243
|
+
const commandItem = cmd.handler(this.db);
|
|
244
|
+
const auditLogPayload = {
|
|
245
|
+
...commandItem.logPayload,
|
|
246
|
+
service: this.serviceName || "unknown-service"
|
|
247
|
+
};
|
|
248
|
+
this.commands.push(commandItem.command);
|
|
249
|
+
this.logs.push(auditLogPayload);
|
|
250
|
+
if (commandItem.id) {
|
|
251
|
+
this.ids.push(commandItem.id);
|
|
252
|
+
}
|
|
253
|
+
return commandItem;
|
|
254
|
+
}).reduce((acc, curr) => {
|
|
255
|
+
acc.push(curr.id);
|
|
256
|
+
return acc;
|
|
257
|
+
}, []);
|
|
258
|
+
}
|
|
259
|
+
async execute(commandItem) {
|
|
260
|
+
this.enqueue(commandItem);
|
|
261
|
+
await this.executeAll();
|
|
262
|
+
}
|
|
263
|
+
async executeAll() {
|
|
264
|
+
let allCommands = [...this.commands];
|
|
265
|
+
if (this.auditLogWriter && this.logs.length > 0) {
|
|
266
|
+
const auditCommands = this.auditLogWriter(this.logs, this.db);
|
|
267
|
+
allCommands.push(...auditCommands);
|
|
268
|
+
}
|
|
269
|
+
const batchItems = asNonEmpty(allCommands);
|
|
270
|
+
if (batchItems) {
|
|
271
|
+
await this.db.batch(batchItems);
|
|
272
|
+
}
|
|
273
|
+
this.commands = [];
|
|
274
|
+
this.logs = [];
|
|
275
|
+
this.ids = [];
|
|
276
|
+
}
|
|
277
|
+
getLogs() {
|
|
278
|
+
return [...this.logs];
|
|
279
|
+
}
|
|
280
|
+
getIds() {
|
|
281
|
+
return [...this.ids];
|
|
282
|
+
}
|
|
283
|
+
getCommandsCount() {
|
|
284
|
+
return this.commands.length;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const defineCommand = (handler) => {
|
|
289
|
+
return (params) => ({
|
|
290
|
+
handler: (db) => handler(db, params)
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
function createAuditLogWriter(table) {
|
|
295
|
+
return (logs, db) => {
|
|
296
|
+
if (logs.length === 0) return [];
|
|
297
|
+
const auditRecords = logs.map((log) => ({
|
|
298
|
+
...log,
|
|
299
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
300
|
+
id: crypto.randomUUID()
|
|
301
|
+
}));
|
|
302
|
+
return [db.insert(table).values(auditRecords)];
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const service = (serviceName) => {
|
|
307
|
+
return function(constructor) {
|
|
308
|
+
return class extends constructor {
|
|
309
|
+
name = `${serviceName}-service`;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const action = (name) => {
|
|
315
|
+
return (_target, _propertyKey, descriptor) => {
|
|
316
|
+
const originalMethod = descriptor.value;
|
|
317
|
+
descriptor.value = function(...args) {
|
|
318
|
+
this.action = name;
|
|
319
|
+
return originalMethod.apply(this, args);
|
|
320
|
+
};
|
|
321
|
+
return descriptor;
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
function cloudflareQueue(options) {
|
|
326
|
+
return (_target, _propertyKey, descriptor) => {
|
|
327
|
+
const originalMethod = descriptor.value;
|
|
328
|
+
descriptor.value = async function(...args) {
|
|
329
|
+
const batch = args[0];
|
|
330
|
+
let retriedCount = 0;
|
|
331
|
+
batch.messages.forEach((msg) => {
|
|
332
|
+
const originalRetry = msg.retry?.bind(msg);
|
|
333
|
+
msg.retry = () => {
|
|
334
|
+
retriedCount++;
|
|
335
|
+
return originalRetry({
|
|
336
|
+
delaySeconds: calculateExponentialBackoff(
|
|
337
|
+
msg.attempts,
|
|
338
|
+
options.baseDelay
|
|
339
|
+
)
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
const result = await originalMethod.apply(this, args);
|
|
344
|
+
if (typeof this.logQueueRetries === "function") {
|
|
345
|
+
this.logQueueRetries({
|
|
346
|
+
message: `Retried ${retriedCount} out of ${batch.messages.length} messages`
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
return result;
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function develitWorker(Worker) {
|
|
355
|
+
class DevelitWorker extends Worker {
|
|
356
|
+
name = "not-set";
|
|
357
|
+
action = "not-set";
|
|
358
|
+
// public db!: DatabaseTransaction<string>
|
|
359
|
+
async fetch() {
|
|
360
|
+
return new Response("Service is up and running!");
|
|
361
|
+
}
|
|
362
|
+
// initializeDB<TAuditAction = string>(
|
|
363
|
+
// database: D1Database,
|
|
364
|
+
// schema: Record<string, unknown>,
|
|
365
|
+
// auditLogWriter?: AuditLogWriter<TAuditAction>,
|
|
366
|
+
// ): void {
|
|
367
|
+
// const drizzleInstance = drizzle(database, {
|
|
368
|
+
// schema,
|
|
369
|
+
// }) as DrizzleD1Database<Record<string, unknown>>
|
|
370
|
+
// this.db = new DatabaseTransaction<TAuditAction>(
|
|
371
|
+
// drizzleInstance,
|
|
372
|
+
// this.name,
|
|
373
|
+
// auditLogWriter,
|
|
374
|
+
// ) as unknown as DatabaseTransaction<string>
|
|
375
|
+
// }
|
|
376
|
+
handleInput({
|
|
377
|
+
input,
|
|
378
|
+
schema
|
|
379
|
+
}) {
|
|
380
|
+
this.logInput({ input });
|
|
381
|
+
const parseResult = z__namespace.safeParse(schema, input);
|
|
382
|
+
if (!parseResult.success) {
|
|
383
|
+
const parseError = {
|
|
384
|
+
status: 400,
|
|
385
|
+
code: "INVALID_ACTION_INPUT",
|
|
386
|
+
message: z__namespace.prettifyError(parseResult.error)
|
|
387
|
+
};
|
|
388
|
+
this.logError(parseError);
|
|
389
|
+
throw RPCResponse.validationError(parseError);
|
|
390
|
+
}
|
|
391
|
+
if (!parseResult.data) {
|
|
392
|
+
throw createInternalError({
|
|
393
|
+
message: "The provided input could not be processed."
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return parseResult.data;
|
|
397
|
+
}
|
|
398
|
+
log(data, identifier) {
|
|
399
|
+
const name = identifier ?? `${this.name}:${this.action}:log`;
|
|
400
|
+
console.log(name, {
|
|
401
|
+
entrypoint: this.name,
|
|
402
|
+
action: this.action,
|
|
403
|
+
identifier: name,
|
|
404
|
+
data: superjson__default.stringify(data)
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
logQueuePush(data) {
|
|
408
|
+
this.log(data, `${this.name}:${this.action}:queue-push`);
|
|
409
|
+
}
|
|
410
|
+
logQueuePull(data) {
|
|
411
|
+
this.log(data, `${this.name}:${this.action}:queue-pull`);
|
|
412
|
+
}
|
|
413
|
+
logQueueRetries(data) {
|
|
414
|
+
this.log(data, `${this.name}:${this.action}:queue-retries`);
|
|
415
|
+
}
|
|
416
|
+
logInput(data) {
|
|
417
|
+
this.log(data, `${this.name}:${this.action}:input`);
|
|
418
|
+
}
|
|
419
|
+
logOutput(data) {
|
|
420
|
+
this.log(data, `${this.name}:${this.action}:output`);
|
|
421
|
+
}
|
|
422
|
+
logError(error) {
|
|
423
|
+
this.log(error, `${this.name}:${this.action}:error`);
|
|
424
|
+
}
|
|
425
|
+
pushToQueue(queue, message) {
|
|
426
|
+
if (!Array.isArray(message))
|
|
427
|
+
return queue.send(message, { contentType: "v8" });
|
|
428
|
+
return queue.sendBatch(
|
|
429
|
+
message.map((m) => ({
|
|
430
|
+
body: m,
|
|
431
|
+
contentType: "v8"
|
|
432
|
+
}))
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
async handleAction(input, options = {}, actionExecution) {
|
|
436
|
+
return handleAction(this, input, options, actionExecution);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return DevelitWorker;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
exports.DatabaseTransaction = DatabaseTransaction;
|
|
443
|
+
exports.RPCResponse = RPCResponse;
|
|
444
|
+
exports.action = action;
|
|
445
|
+
exports.base = base;
|
|
446
|
+
exports.basePostgres = basePostgres;
|
|
447
|
+
exports.calculateExponentialBackoff = calculateExponentialBackoff;
|
|
448
|
+
exports.cloudflareQueue = cloudflareQueue;
|
|
449
|
+
exports.createAuditLogWriter = createAuditLogWriter;
|
|
450
|
+
exports.createInternalError = createInternalError;
|
|
451
|
+
exports.defineCommand = defineCommand;
|
|
452
|
+
exports.develitWorker = develitWorker;
|
|
453
|
+
exports.drizzleConfig = drizzleConfig;
|
|
454
|
+
exports.first = first;
|
|
455
|
+
exports.firstOrError = firstOrError;
|
|
456
|
+
exports.handleAction = handleAction;
|
|
457
|
+
exports.handleActionResponse = handleActionResponse;
|
|
458
|
+
exports.ibanZodSchema = ibanZodSchema;
|
|
459
|
+
exports.isInternalError = isInternalError;
|
|
460
|
+
exports.service = service;
|
|
461
|
+
exports.swiftZodSchema = swiftZodSchema;
|
|
462
|
+
exports.useResult = useResult;
|
|
463
|
+
exports.useResultSync = useResultSync;
|
|
464
|
+
exports.uuidv4 = uuidv4;
|