@develit-io/backend-sdk 12.6.1 → 12.7.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.
package/dist/index.d.mts CHANGED
@@ -9,6 +9,7 @@ export { ContentfulStatusCode as InternalResponseStatus } from 'hono/utils/http-
9
9
  import { Queue, MessageBatch } from '@cloudflare/workers-types';
10
10
  import { BatchItem } from 'drizzle-orm/batch';
11
11
  import { DrizzleD1Database } from 'drizzle-orm/d1';
12
+ export { E as ErrorReportContext, a as ErrorReporter, r as reportError, s as setErrorReporter } from './shared/backend-sdk.D6_sG5co.mjs';
12
13
 
13
14
  declare const ENVIRONMENT: string[];
14
15
 
@@ -1020,6 +1021,7 @@ interface InternalError {
1020
1021
  status: InternalErrorResponseStatus;
1021
1022
  code: string;
1022
1023
  message: string;
1024
+ cause?: Error;
1023
1025
  }
1024
1026
  interface IRPCResponse<T> {
1025
1027
  status: ContentfulStatusCode;
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export { ContentfulStatusCode as InternalResponseStatus } from 'hono/utils/http-
9
9
  import { Queue, MessageBatch } from '@cloudflare/workers-types';
10
10
  import { BatchItem } from 'drizzle-orm/batch';
11
11
  import { DrizzleD1Database } from 'drizzle-orm/d1';
12
+ export { E as ErrorReportContext, a as ErrorReporter, r as reportError, s as setErrorReporter } from './shared/backend-sdk.D6_sG5co.js';
12
13
 
13
14
  declare const ENVIRONMENT: string[];
14
15
 
@@ -1020,6 +1021,7 @@ interface InternalError {
1020
1021
  status: InternalErrorResponseStatus;
1021
1022
  code: string;
1022
1023
  message: string;
1024
+ cause?: Error;
1023
1025
  }
1024
1026
  interface IRPCResponse<T> {
1025
1027
  status: ContentfulStatusCode;
package/dist/index.mjs CHANGED
@@ -6,6 +6,8 @@ import { COUNTRY_CODES_2, CURRENCY_CODES, BANK_CODES } from '@develit-io/general
6
6
  import { createInsertSchema as createInsertSchema$1, createSelectSchema as createSelectSchema$1 } from 'drizzle-orm/zod';
7
7
  import { z as z$1 } from 'zod';
8
8
  import * as z from 'zod/v4/core';
9
+ import { i as isInternalError, c as createInternalError, t as toErrorStatus, r as reportError } from './shared/backend-sdk.e9CWR7-E.mjs';
10
+ export { s as setErrorReporter } from './shared/backend-sdk.e9CWR7-E.mjs';
9
11
  import Cloudflare from 'cloudflare';
10
12
  import { parse } from 'comment-json';
11
13
  import crypto$1 from 'node:crypto';
@@ -283,23 +285,6 @@ const paginationSchema = new z.$ZodObject({
283
285
  }
284
286
  });
285
287
 
286
- const createInternalError = (error, details) => {
287
- return {
288
- status: details?.status || 500,
289
- code: details?.code || "UNKNOWN_ERROR",
290
- message: details?.message || (error instanceof Error ? error.message : "An unexpected error occurred.")
291
- };
292
- };
293
- const isInternalError = (error) => {
294
- return typeof error === "object" && error !== null && "message" in error && "code" in error;
295
- };
296
- const toErrorStatus = (status) => {
297
- if (status >= 400 && status < 600) {
298
- return status;
299
- }
300
- return 500;
301
- };
302
-
303
288
  const REDACTED = "[REDACTED]";
304
289
  const DEFAULT_SENSITIVE_KEYS = [
305
290
  "password",
@@ -980,6 +965,12 @@ function cloudflareQueue(options) {
980
965
  };
981
966
  }
982
967
 
968
+ const composeLogEntry = (worker, identifier, data) => ({
969
+ entrypoint: worker.name,
970
+ action: worker.action,
971
+ identifier,
972
+ data: serializeLog(data)
973
+ });
983
974
  function develitWorker(Worker) {
984
975
  class DevelitWorker extends Worker {
985
976
  name = "not-set";
@@ -1002,7 +993,9 @@ function develitWorker(Worker) {
1002
993
  throw RPCResponse.validationError(parseError);
1003
994
  }
1004
995
  if (!parseResult.data) {
1005
- throw createInternalError({
996
+ throw createInternalError(null, {
997
+ status: 400,
998
+ code: "DEFORMED_ACTION_INPUT",
1006
999
  message: "The provided input could not be processed."
1007
1000
  });
1008
1001
  }
@@ -1010,12 +1003,7 @@ function develitWorker(Worker) {
1010
1003
  }
1011
1004
  log(data, identifier) {
1012
1005
  const name = identifier ?? `${this.name}:${this.action}:log`;
1013
- console.log(name, {
1014
- entrypoint: this.name,
1015
- action: this.action,
1016
- identifier: name,
1017
- data: serializeLog(data)
1018
- });
1006
+ console.log(name, composeLogEntry(this, name, data));
1019
1007
  }
1020
1008
  transformLogData(data) {
1021
1009
  return data;
@@ -1048,10 +1036,12 @@ function develitWorker(Worker) {
1048
1036
  );
1049
1037
  }
1050
1038
  logError(error) {
1051
- this.log(
1052
- this.transformLogData(error),
1053
- `${this.name}:${this.action}:error`
1039
+ const name = `${this.name}:${this.action}:error`;
1040
+ console.error(
1041
+ name,
1042
+ composeLogEntry(this, name, this.transformLogData(error))
1054
1043
  );
1044
+ reportError(error, { service: this.name, action: this.action });
1055
1045
  }
1056
1046
  async pushToQueue(queue, message) {
1057
1047
  return pushToQueue(queue, message);
@@ -1070,4 +1060,4 @@ function develitWorker(Worker) {
1070
1060
  return DevelitWorker;
1071
1061
  }
1072
1062
 
1073
- export { DLQ_ALERT_DEFAULT_MAX_INTERVAL, DLQ_ALERT_DEFAULT_MIN_SIZE, DatabaseTransaction, ENVIRONMENT, RPCResponse, USER_ROLES, action, asNonEmpty, bankAccount, bankAccountMetadataSchema, base, bicSchema, buildDlqAlert, buildMultiFilterConditions, buildRangeFilterConditions, buildSearchConditions, calculateExponentialBackoff, chunkQueueMessages, cloudflareQueue, composeWranglerBase, createAuditLogWriter, createInsertSchema, createInternalError, createPatchSchema, createSelectSchema, createUpdateSchema, defineCommand, derivePortFromId, develitWorker, durableObjectNamespaceIdFromName, first, firstOrError, getD1Credentials, getDrizzleD1Config, getLocalD1DatabaseIdFromWrangler, getSecret, handleAction, handleDlqBatch, ibanSchema, isDlqQueue, isInternalError, nullToOptional, optionalToNull, paginationQuerySchema, paginationSchema, parseDlqAlertRecipients, pushToQueue, queryInChunks, redact, resolveColumn, service, shouldAlertDlq, structuredAddressSchema, useFetch, useResult, useResultSync, workflowInstanceStatusSchema };
1063
+ export { DLQ_ALERT_DEFAULT_MAX_INTERVAL, DLQ_ALERT_DEFAULT_MIN_SIZE, DatabaseTransaction, ENVIRONMENT, RPCResponse, USER_ROLES, action, asNonEmpty, bankAccount, bankAccountMetadataSchema, base, bicSchema, buildDlqAlert, buildMultiFilterConditions, buildRangeFilterConditions, buildSearchConditions, calculateExponentialBackoff, chunkQueueMessages, cloudflareQueue, composeWranglerBase, createAuditLogWriter, createInsertSchema, createInternalError, createPatchSchema, createSelectSchema, createUpdateSchema, defineCommand, derivePortFromId, develitWorker, durableObjectNamespaceIdFromName, first, firstOrError, getD1Credentials, getDrizzleD1Config, getLocalD1DatabaseIdFromWrangler, getSecret, handleAction, handleDlqBatch, ibanSchema, isDlqQueue, isInternalError, nullToOptional, optionalToNull, paginationQuerySchema, paginationSchema, parseDlqAlertRecipients, pushToQueue, queryInChunks, redact, reportError, resolveColumn, service, shouldAlertDlq, structuredAddressSchema, useFetch, useResult, useResultSync, workflowInstanceStatusSchema };
@@ -0,0 +1,23 @@
1
+ import * as Sentry from '@sentry/cloudflare';
2
+ import { CloudflareOptions } from '@sentry/cloudflare';
3
+ import { a as ErrorReporter } from './shared/backend-sdk.D6_sG5co.mjs';
4
+
5
+ type ServiceEntrypoint = Parameters<typeof Sentry.withSentry>[1];
6
+ type DurableObjectClass = Parameters<typeof Sentry.instrumentDurableObjectWithSentry>[1];
7
+ type WorkflowClass = Parameters<typeof Sentry.instrumentWorkflowWithSentry>[1];
8
+ declare const instrumentService: <T extends ServiceEntrypoint>(Service: T) => T;
9
+ declare const instrumentDurableObject: <T extends DurableObjectClass>(DurableObject: T) => T;
10
+ declare const instrumentWorkflow: <T extends WorkflowClass>(Workflow: T) => T;
11
+
12
+ type SentryEnv = {
13
+ ENVIRONMENT?: string;
14
+ SENTRY_DSN?: string;
15
+ CF_VERSION_METADATA?: {
16
+ id: string;
17
+ };
18
+ };
19
+ declare const sentryOptions: (env: SentryEnv) => CloudflareOptions;
20
+
21
+ declare const reportServiceErrorToSentry: ErrorReporter;
22
+
23
+ export { instrumentDurableObject, instrumentService, instrumentWorkflow, reportServiceErrorToSentry, sentryOptions };
@@ -0,0 +1,23 @@
1
+ import * as Sentry from '@sentry/cloudflare';
2
+ import { CloudflareOptions } from '@sentry/cloudflare';
3
+ import { a as ErrorReporter } from './shared/backend-sdk.D6_sG5co.js';
4
+
5
+ type ServiceEntrypoint = Parameters<typeof Sentry.withSentry>[1];
6
+ type DurableObjectClass = Parameters<typeof Sentry.instrumentDurableObjectWithSentry>[1];
7
+ type WorkflowClass = Parameters<typeof Sentry.instrumentWorkflowWithSentry>[1];
8
+ declare const instrumentService: <T extends ServiceEntrypoint>(Service: T) => T;
9
+ declare const instrumentDurableObject: <T extends DurableObjectClass>(DurableObject: T) => T;
10
+ declare const instrumentWorkflow: <T extends WorkflowClass>(Workflow: T) => T;
11
+
12
+ type SentryEnv = {
13
+ ENVIRONMENT?: string;
14
+ SENTRY_DSN?: string;
15
+ CF_VERSION_METADATA?: {
16
+ id: string;
17
+ };
18
+ };
19
+ declare const sentryOptions: (env: SentryEnv) => CloudflareOptions;
20
+
21
+ declare const reportServiceErrorToSentry: ErrorReporter;
22
+
23
+ export { instrumentDurableObject, instrumentService, instrumentWorkflow, reportServiceErrorToSentry, sentryOptions };
@@ -0,0 +1,92 @@
1
+ import * as Sentry from '@sentry/cloudflare';
2
+ import { i as isInternalError, U as UNKNOWN_ERROR_CODE, s as setErrorReporter } from './shared/backend-sdk.e9CWR7-E.mjs';
3
+
4
+ const isNonRetryableError = (error) => error instanceof Error && error.name === "NonRetryableError";
5
+ const isFinalAttempt = ({ attempt, config }) => typeof config?.retries?.limit !== "number" || attempt > config.retries.limit;
6
+ const captureNonRetryable = (callback) => async (ctx) => {
7
+ try {
8
+ return await callback(ctx);
9
+ } catch (error) {
10
+ if (isNonRetryableError(error) && !isFinalAttempt(ctx)) {
11
+ Sentry.captureException(error, {
12
+ mechanism: { handled: true, type: "auto.faas.cloudflare.workflow" }
13
+ });
14
+ }
15
+ throw error;
16
+ }
17
+ };
18
+ const reportNonRetryableStepErrors = (step) => new Proxy(step, {
19
+ get(target, prop, receiver) {
20
+ if (prop !== "do") return Reflect.get(target, prop, receiver);
21
+ return (name, configOrCallback, callbackOrRollback, ...rest) => typeof configOrCallback === "function" ? Reflect.apply(target.do, target, [
22
+ name,
23
+ captureNonRetryable(configOrCallback),
24
+ callbackOrRollback,
25
+ ...rest
26
+ ]) : Reflect.apply(target.do, target, [
27
+ name,
28
+ configOrCallback,
29
+ callbackOrRollback && captureNonRetryable(callbackOrRollback),
30
+ ...rest
31
+ ]);
32
+ }
33
+ });
34
+
35
+ const sentryOptions = (env) => ({
36
+ dsn: env.SENTRY_DSN,
37
+ environment: env.ENVIRONMENT,
38
+ release: env.CF_VERSION_METADATA?.id,
39
+ enabled: Boolean(env.SENTRY_DSN),
40
+ tracesSampleRate: env.ENVIRONMENT === "production" ? 0.1 : 0.2,
41
+ dataCollection: {
42
+ userInfo: false,
43
+ cookies: false,
44
+ httpHeaders: { request: { allow: ["user-agent"] }, response: false },
45
+ httpBodies: [],
46
+ urlQueryParams: false
47
+ },
48
+ integrations: (defaults) => defaults.filter(({ name }) => name !== "Console")
49
+ });
50
+
51
+ const reportServiceErrorToSentry = (error, { service, action }) => {
52
+ const status = isInternalError(error) ? error.status : 500;
53
+ if (status < 500) return;
54
+ const logged = error;
55
+ const code = logged.code ?? UNKNOWN_ERROR_CODE;
56
+ const message = logged.message ?? `${service}:${action} failed`;
57
+ const thrown = error instanceof Error ? error : logged.cause instanceof Error ? logged.cause : void 0;
58
+ Sentry.captureException(thrown ?? new Error(message), {
59
+ tags: {
60
+ service,
61
+ action,
62
+ error_code: code,
63
+ error_status: String(status)
64
+ },
65
+ extra: { code, message, status },
66
+ fingerprint: thrown ? void 0 : ["service-error", service, action, code]
67
+ });
68
+ };
69
+
70
+ const instrumentService = (Service) => {
71
+ setErrorReporter(reportServiceErrorToSentry);
72
+ return Sentry.withSentry(sentryOptions, Service);
73
+ };
74
+ const instrumentDurableObject = (DurableObject) => {
75
+ setErrorReporter(reportServiceErrorToSentry);
76
+ return Sentry.instrumentDurableObjectWithSentry(sentryOptions, DurableObject);
77
+ };
78
+ const withNonRetryableStepReporting = (Workflow) => {
79
+ const Base = Workflow;
80
+ class NonRetryableStepReportingWorkflow extends Base {
81
+ run(...[event, step]) {
82
+ return super.run(event, reportNonRetryableStepErrors(step));
83
+ }
84
+ }
85
+ return NonRetryableStepReportingWorkflow;
86
+ };
87
+ const instrumentWorkflow = (Workflow) => Sentry.instrumentWorkflowWithSentry(
88
+ sentryOptions,
89
+ withNonRetryableStepReporting(Workflow)
90
+ );
91
+
92
+ export { instrumentDurableObject, instrumentService, instrumentWorkflow, reportServiceErrorToSentry, sentryOptions };
@@ -0,0 +1,10 @@
1
+ type ErrorReportContext = {
2
+ service: string;
3
+ action: string;
4
+ };
5
+ type ErrorReporter = (error: object, context: ErrorReportContext) => void;
6
+ declare const setErrorReporter: (reporter: ErrorReporter | undefined) => void;
7
+ declare const reportError: (error: object, context: ErrorReportContext) => void;
8
+
9
+ export { reportError as r, setErrorReporter as s };
10
+ export type { ErrorReportContext as E, ErrorReporter as a };
@@ -0,0 +1,10 @@
1
+ type ErrorReportContext = {
2
+ service: string;
3
+ action: string;
4
+ };
5
+ type ErrorReporter = (error: object, context: ErrorReportContext) => void;
6
+ declare const setErrorReporter: (reporter: ErrorReporter | undefined) => void;
7
+ declare const reportError: (error: object, context: ErrorReportContext) => void;
8
+
9
+ export { reportError as r, setErrorReporter as s };
10
+ export type { ErrorReportContext as E, ErrorReporter as a };
@@ -0,0 +1,39 @@
1
+ const UNKNOWN_ERROR_CODE = "UNKNOWN_ERROR";
2
+ const createInternalError = (error, details) => {
3
+ const internalError = {
4
+ status: details?.status || 500,
5
+ code: details?.code || UNKNOWN_ERROR_CODE,
6
+ message: details?.message || (error instanceof Error ? error.message : "An unexpected error occurred.")
7
+ };
8
+ if (error instanceof Error) {
9
+ Object.defineProperty(internalError, "cause", {
10
+ value: error,
11
+ enumerable: false
12
+ });
13
+ }
14
+ return internalError;
15
+ };
16
+ const isInternalError = (error) => {
17
+ return typeof error === "object" && error !== null && "message" in error && "code" in error;
18
+ };
19
+ const toErrorStatus = (status) => {
20
+ if (status >= 400 && status < 600) {
21
+ return status;
22
+ }
23
+ return 500;
24
+ };
25
+
26
+ let errorReporter;
27
+ const setErrorReporter = (reporter) => {
28
+ errorReporter = reporter;
29
+ };
30
+ const reportError = (error, context) => {
31
+ if (!errorReporter) return;
32
+ try {
33
+ errorReporter(error, context);
34
+ } catch (reporterError) {
35
+ console.error("Error reporter failed", reporterError);
36
+ }
37
+ };
38
+
39
+ export { UNKNOWN_ERROR_CODE as U, createInternalError as c, isInternalError as i, reportError as r, setErrorReporter as s, toErrorStatus as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@develit-io/backend-sdk",
3
- "version": "12.6.1",
3
+ "version": "12.7.1",
4
4
  "description": "Develit Backend SDK",
5
5
  "author": "Develit.io",
6
6
  "license": "ISC",
@@ -32,6 +32,11 @@
32
32
  "import": "./dist/utils/signature.util.mjs",
33
33
  "default": "./dist/utils/signature.util.mjs"
34
34
  },
35
+ "./sentry": {
36
+ "types": "./dist/sentry.d.ts",
37
+ "import": "./dist/sentry.mjs",
38
+ "default": "./dist/sentry.mjs"
39
+ },
35
40
  "./package.json": "./package.json"
36
41
  },
37
42
  "files": [
@@ -46,11 +51,18 @@
46
51
  "peerDependencies": {
47
52
  "@develit-io/general-codes": "^1.19.2",
48
53
  "drizzle-orm": "^1.0.0-rc.1",
54
+ "@sentry/cloudflare": "^11.9.0",
49
55
  "hono": "^4.12.7",
50
56
  "zod": "^4.3.6"
51
57
  },
58
+ "peerDependenciesMeta": {
59
+ "@sentry/cloudflare": {
60
+ "optional": true
61
+ }
62
+ },
52
63
  "devDependencies": {
53
64
  "@packages/shared": "workspace:*",
65
+ "@sentry/cloudflare": "11.9.0",
54
66
  "drizzle-orm": "1.0.0-rc.1"
55
67
  }
56
68
  }