abxbus 2.5.4 → 2.5.9
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/cjs/BaseEvent.d.ts +53 -28
- package/dist/cjs/BaseEvent.js +148 -28
- package/dist/cjs/BaseEvent.js.map +2 -2
- package/dist/cjs/LockManager.js +1 -1
- package/dist/cjs/LockManager.js.map +2 -2
- package/dist/cjs/events_suck.d.ts +8 -15
- package/dist/cjs/events_suck.js +1 -1
- package/dist/cjs/events_suck.js.map +2 -2
- package/dist/cjs/jsonschema.d.ts +6 -0
- package/dist/cjs/jsonschema.js +155 -0
- package/dist/cjs/jsonschema.js.map +7 -0
- package/dist/cjs/retry.d.ts +2 -0
- package/dist/cjs/retry.js +110 -35
- package/dist/cjs/retry.js.map +3 -3
- package/dist/cjs/types.d.ts +6 -10
- package/dist/cjs/types.js +9 -16
- package/dist/cjs/types.js.map +2 -2
- package/dist/esm/BaseEvent.js +148 -28
- package/dist/esm/BaseEvent.js.map +2 -2
- package/dist/esm/LockManager.js +1 -1
- package/dist/esm/LockManager.js.map +2 -2
- package/dist/esm/events_suck.js +1 -1
- package/dist/esm/events_suck.js.map +2 -2
- package/dist/esm/jsonschema.js +135 -0
- package/dist/esm/jsonschema.js.map +7 -0
- package/dist/esm/retry.js +110 -35
- package/dist/esm/retry.js.map +3 -3
- package/dist/esm/types.js +8 -15
- package/dist/esm/types.js.map +2 -2
- package/dist/types/BaseEvent.d.ts +53 -28
- package/dist/types/events_suck.d.ts +8 -15
- package/dist/types/jsonschema.d.ts +6 -0
- package/dist/types/retry.d.ts +2 -0
- package/dist/types/types.d.ts +6 -10
- package/package.json +1 -1
- package/src/BaseEvent.ts +321 -80
- package/src/LockManager.ts +1 -1
- package/src/events_suck.ts +20 -22
- package/src/jsonschema.ts +146 -0
- package/src/retry.ts +132 -38
- package/src/types.ts +10 -19
|
@@ -1,28 +1,21 @@
|
|
|
1
1
|
import { EventBus } from './EventBus.js';
|
|
2
2
|
import { BaseEvent } from './BaseEvent.js';
|
|
3
3
|
import type { EventClass, EventResultType } from './types.js';
|
|
4
|
-
type EventMap = Record<string, EventClass<BaseEvent>>;
|
|
5
|
-
type
|
|
6
|
-
type FunctionMap = Record<string, AnyFn>;
|
|
4
|
+
type EventMap = Record<string, EventClass<BaseEvent, never>>;
|
|
5
|
+
type FunctionMap = Record<string, (...args: never[]) => unknown>;
|
|
7
6
|
type ExtraDict = Record<string, unknown>;
|
|
8
|
-
type EventFieldsFromFn<TFunc extends
|
|
9
|
-
type
|
|
10
|
-
|
|
11
|
-
__event_result_type__?: Awaited<ReturnType<TFunc>>;
|
|
12
|
-
};
|
|
13
|
-
new (data: EventFieldsFromFn<TFunc> & ExtraDict): BaseEvent & EventFieldsFromFn<TFunc> & {
|
|
14
|
-
__event_result_type__?: Awaited<ReturnType<TFunc>>;
|
|
15
|
-
};
|
|
16
|
-
event_type?: string;
|
|
7
|
+
type EventFieldsFromFn<TFunc extends FunctionMap[string]> = Parameters<TFunc> extends [infer TArg, ...unknown[]] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict;
|
|
8
|
+
type EventFromFn<TFunc extends FunctionMap[string]> = BaseEvent & EventFieldsFromFn<TFunc> & {
|
|
9
|
+
__event_result_type__?: Awaited<ReturnType<TFunc>>;
|
|
17
10
|
};
|
|
18
11
|
export type GeneratedEvents<TEvents extends FunctionMap> = {
|
|
19
12
|
by_name: {
|
|
20
|
-
[K in keyof TEvents]:
|
|
13
|
+
[K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict>;
|
|
21
14
|
};
|
|
22
15
|
} & {
|
|
23
|
-
[K in keyof TEvents]:
|
|
16
|
+
[K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict>;
|
|
24
17
|
};
|
|
25
|
-
type EventInit<TEventClass extends EventClass<BaseEvent>> = ConstructorParameters<TEventClass> extends [
|
|
18
|
+
type EventInit<TEventClass extends EventClass<BaseEvent>> = [ConstructorParameters<TEventClass>[0]] extends [undefined] ? {} : NonNullable<ConstructorParameters<TEventClass>[0]>;
|
|
26
19
|
type EventMethodArgs<TEventClass extends EventClass<BaseEvent>> = {} extends EventInit<TEventClass> ? [init?: EventInit<TEventClass>, extra?: Record<string, unknown>] : [init: EventInit<TEventClass>, extra?: Record<string, unknown>];
|
|
27
20
|
type EventMethodResult<TEventClass extends EventClass<BaseEvent>> = EventResultType<InstanceType<TEventClass>> | undefined;
|
|
28
21
|
export type EventsSuckClient<TEvents extends EventMap> = {
|
package/dist/cjs/events_suck.js
CHANGED
|
@@ -47,7 +47,7 @@ const wrap = (class_name, methods) => {
|
|
|
47
47
|
Object.defineProperty(WrappedClient.prototype, method_name, {
|
|
48
48
|
value: async function(init, extra) {
|
|
49
49
|
const payload = { ...init ?? {}, ...extra ?? {} };
|
|
50
|
-
return await this.bus.emit(
|
|
50
|
+
return await this.bus.emit(EventCtor(payload)).now({ first_result: true }).eventResult();
|
|
51
51
|
},
|
|
52
52
|
writable: true,
|
|
53
53
|
configurable: true
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/events_suck.ts"],
|
|
4
|
-
"sourcesContent": ["import { EventBus } from './EventBus.js'\nimport { BaseEvent } from './BaseEvent.js'\n\nimport type { EventClass, EventResultType } from './types.js'\n\ntype EventMap = Record<string, EventClass<BaseEvent>>\ntype
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyB;AACzB,uBAA0B;
|
|
4
|
+
"sourcesContent": ["import { EventBus } from './EventBus.js'\nimport { BaseEvent } from './BaseEvent.js'\n\nimport type { EventClass, EventResultType } from './types.js'\n\ntype EventMap = Record<string, EventClass<BaseEvent, never>>\ntype FunctionMap = Record<string, (...args: never[]) => unknown>\ntype ExtraDict = Record<string, unknown>\n\ntype EventFieldsFromFn<TFunc extends FunctionMap[string]> =\n Parameters<TFunc> extends [infer TArg, ...unknown[]] ? (TArg extends Record<string, unknown> ? TArg : ExtraDict) : ExtraDict\n\ntype EventFromFn<TFunc extends FunctionMap[string]> = BaseEvent &\n EventFieldsFromFn<TFunc> & {\n __event_result_type__?: Awaited<ReturnType<TFunc>>\n }\n\nexport type GeneratedEvents<TEvents extends FunctionMap> = {\n by_name: { [K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict> }\n} & {\n [K in keyof TEvents]: EventClass<EventFromFn<TEvents[K]>, EventFieldsFromFn<TEvents[K]> & ExtraDict>\n}\n\ntype EventInit<TEventClass extends EventClass<BaseEvent>> = [ConstructorParameters<TEventClass>[0]] extends [undefined]\n ? {}\n : NonNullable<ConstructorParameters<TEventClass>[0]>\n\ntype EventMethodArgs<TEventClass extends EventClass<BaseEvent>> =\n {} extends EventInit<TEventClass>\n ? [init?: EventInit<TEventClass>, extra?: Record<string, unknown>]\n : [init: EventInit<TEventClass>, extra?: Record<string, unknown>]\n\ntype EventMethodResult<TEventClass extends EventClass<BaseEvent>> = EventResultType<InstanceType<TEventClass>> | undefined\n\nexport type EventsSuckClient<TEvents extends EventMap> = {\n bus: EventBus\n} & {\n [K in keyof TEvents]: (...args: EventMethodArgs<TEvents[K]>) => Promise<EventMethodResult<TEvents[K]>>\n}\n\nexport type EventsSuckClientClass<TEvents extends EventMap> = new (bus?: EventBus) => EventsSuckClient<TEvents>\n\ntype DynamicWrappedClient = {\n bus: EventBus\n} & Record<string, (...args: unknown[]) => Promise<unknown>>\n\nexport const make_events = <TEvents extends FunctionMap>(events: TEvents): GeneratedEvents<TEvents> => {\n const by_name = {} as GeneratedEvents<TEvents>['by_name']\n for (const [event_name] of Object.entries(events) as Array<[keyof TEvents, TEvents[keyof TEvents]]>) {\n if (!/^[A-Za-z_$][\\w$]*$/.test(String(event_name))) {\n throw new Error(`Invalid event name: ${String(event_name)}`)\n }\n by_name[event_name] = BaseEvent.extend(String(event_name), {}) as unknown as GeneratedEvents<TEvents>['by_name'][typeof event_name]\n }\n return Object.assign({ by_name }, by_name) as GeneratedEvents<TEvents>\n}\n\nexport const wrap = <TEvents extends EventMap>(class_name: string, methods: TEvents): EventsSuckClientClass<TEvents> => {\n class WrappedClient {\n bus: EventBus\n\n constructor(bus?: EventBus) {\n this.bus = bus ?? new EventBus(`${class_name}Bus`)\n }\n }\n\n Object.defineProperty(WrappedClient, 'name', { value: class_name })\n\n for (const [method_name, EventCtor] of Object.entries(methods)) {\n Object.defineProperty(WrappedClient.prototype, method_name, {\n value: async function (this: DynamicWrappedClient, init?: Record<string, unknown>, extra?: Record<string, unknown>) {\n const payload = { ...(init ?? {}), ...(extra ?? {}) }\n return await this.bus\n .emit((EventCtor as EventClass<BaseEvent, Record<string, unknown>>)(payload))\n .now({ first_result: true })\n .eventResult()\n },\n writable: true,\n configurable: true,\n })\n }\n\n return WrappedClient as unknown as EventsSuckClientClass<TEvents>\n}\n\n// Intentionally no make_event()/make_handler() helpers in TypeScript.\n// Prefer the explicit inline pattern:\n// const FooCreateEvent = BaseEvent.extend('FooCreateEvent', {\n// id: z.string().nullable().optional(),\n// name: z.string(),\n// age: z.number(),\n// })\n// bus.on(FooCreateEvent, ({ id, name, age, ...extra }) => impl.create(id, { name, age }))\nexport const events_suck = { make_events, wrap } as const\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyB;AACzB,uBAA0B;AA6CnB,MAAM,cAAc,CAA8B,WAA8C;AACrG,QAAM,UAAU,CAAC;AACjB,aAAW,CAAC,UAAU,KAAK,OAAO,QAAQ,MAAM,GAAqD;AACnG,QAAI,CAAC,qBAAqB,KAAK,OAAO,UAAU,CAAC,GAAG;AAClD,YAAM,IAAI,MAAM,uBAAuB,OAAO,UAAU,CAAC,EAAE;AAAA,IAC7D;AACA,YAAQ,UAAU,IAAI,2BAAU,OAAO,OAAO,UAAU,GAAG,CAAC,CAAC;AAAA,EAC/D;AACA,SAAO,OAAO,OAAO,EAAE,QAAQ,GAAG,OAAO;AAC3C;AAEO,MAAM,OAAO,CAA2B,YAAoB,YAAqD;AAAA,EACtH,MAAM,cAAc;AAAA,IAClB;AAAA,IAEA,YAAY,KAAgB;AAC1B,WAAK,MAAM,OAAO,IAAI,yBAAS,GAAG,UAAU,KAAK;AAAA,IACnD;AAAA,EACF;AAEA,SAAO,eAAe,eAAe,QAAQ,EAAE,OAAO,WAAW,CAAC;AAElE,aAAW,CAAC,aAAa,SAAS,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC9D,WAAO,eAAe,cAAc,WAAW,aAAa;AAAA,MAC1D,OAAO,eAA4C,MAAgC,OAAiC;AAClH,cAAM,UAAU,EAAE,GAAI,QAAQ,CAAC,GAAI,GAAI,SAAS,CAAC,EAAG;AACpD,eAAO,MAAM,KAAK,IACf,KAAM,UAA6D,OAAO,CAAC,EAC3E,IAAI,EAAE,cAAc,KAAK,CAAC,EAC1B,YAAY;AAAA,MACjB;AAAA,MACA,UAAU;AAAA,MACV,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAUO,MAAM,cAAc,EAAE,aAAa,KAAK;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type JsonSchema = boolean | z.core.JSONSchema.JSONSchema;
|
|
3
|
+
export declare const isJsonSchema: (value: unknown) => value is JsonSchema;
|
|
4
|
+
export declare const normalizeJsonSchema: (schema: JsonSchema) => JsonSchema;
|
|
5
|
+
export declare const toJsonSchema: (schema: z.core.$ZodType) => JsonSchema;
|
|
6
|
+
export declare const fromJsonSchema: (schema: JsonSchema) => z.ZodTypeAny;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var jsonschema_exports = {};
|
|
20
|
+
__export(jsonschema_exports, {
|
|
21
|
+
fromJsonSchema: () => fromJsonSchema,
|
|
22
|
+
isJsonSchema: () => isJsonSchema,
|
|
23
|
+
normalizeJsonSchema: () => normalizeJsonSchema,
|
|
24
|
+
toJsonSchema: () => toJsonSchema
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(jsonschema_exports);
|
|
27
|
+
var import_zod = require("zod");
|
|
28
|
+
const isJsonSchemaObject = (value) => {
|
|
29
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
30
|
+
};
|
|
31
|
+
const isJsonSchema = (value) => {
|
|
32
|
+
if (typeof value === "boolean") {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
if (!isJsonSchemaObject(value)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if ("_zod" in value || "_def" in value || "~standard" in value) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
const nullUnionCandidates = (schema) => {
|
|
44
|
+
if (Array.isArray(schema.type) && schema.type.includes("null")) {
|
|
45
|
+
const non_null_types = schema.type.filter((item) => typeof item === "string" && item !== "null");
|
|
46
|
+
if (non_null_types.length > 0) {
|
|
47
|
+
return [{ type: non_null_types.length === 1 ? non_null_types[0] : non_null_types }, { type: "null" }];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
};
|
|
52
|
+
const normalizeJsonSchema = (schema) => {
|
|
53
|
+
const normalized = normalizeJsonSchemaValue(schema);
|
|
54
|
+
if (!isJsonSchemaObject(normalized)) {
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
const schema_record = { ...normalized };
|
|
58
|
+
const definitions = schema_record.$defs;
|
|
59
|
+
const root_ref = rootRefForSchema(schema_record, definitions);
|
|
60
|
+
if (!root_ref || !definitions) {
|
|
61
|
+
schema_record.$schema ??= "https://json-schema.org/draft/2020-12/schema";
|
|
62
|
+
return schema_record;
|
|
63
|
+
}
|
|
64
|
+
const root_name = root_ref.slice("#/$defs/".length);
|
|
65
|
+
const root_schema = definitions[root_name];
|
|
66
|
+
if (!isJsonSchemaObject(root_schema)) {
|
|
67
|
+
schema_record.$schema ??= "https://json-schema.org/draft/2020-12/schema";
|
|
68
|
+
return schema_record;
|
|
69
|
+
}
|
|
70
|
+
const rewritten_root = rewriteJsonSchemaRefs(root_schema, { [root_ref]: "#" });
|
|
71
|
+
const remaining_defs = Object.fromEntries(Object.entries(definitions).filter(([name]) => name !== root_name));
|
|
72
|
+
if (Object.keys(remaining_defs).length > 0) {
|
|
73
|
+
rewritten_root.$defs = rewriteJsonSchemaRefs(remaining_defs, { [root_ref]: "#" });
|
|
74
|
+
}
|
|
75
|
+
rewritten_root.$schema ??= schema_record.$schema ?? "https://json-schema.org/draft/2020-12/schema";
|
|
76
|
+
setTitleFromInlinedRootDefinition(rewritten_root, root_name);
|
|
77
|
+
return rewritten_root;
|
|
78
|
+
};
|
|
79
|
+
const rootRefForSchema = (schema, definitions) => {
|
|
80
|
+
if (typeof schema.$ref === "string" && schema.$ref.startsWith("#/$defs/")) {
|
|
81
|
+
return schema.$ref;
|
|
82
|
+
}
|
|
83
|
+
if (!definitions) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const root = schemaWithoutSchemaAndDefinitions(schema);
|
|
87
|
+
for (const [name, definition] of Object.entries(definitions)) {
|
|
88
|
+
if (JSON.stringify(definition) === JSON.stringify(root)) {
|
|
89
|
+
return `#/$defs/${name}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
};
|
|
94
|
+
const schemaWithoutSchemaAndDefinitions = (schema) => {
|
|
95
|
+
const root = {};
|
|
96
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
97
|
+
if (key !== "$schema" && key !== "$defs") {
|
|
98
|
+
root[key] = value;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return root;
|
|
102
|
+
};
|
|
103
|
+
const setTitleFromInlinedRootDefinition = (schema, root_name) => {
|
|
104
|
+
if (root_name.startsWith("__schema")) return;
|
|
105
|
+
schema.title ??= root_name;
|
|
106
|
+
};
|
|
107
|
+
const rewriteJsonSchemaRefs = (schema, refs) => {
|
|
108
|
+
if (Array.isArray(schema)) {
|
|
109
|
+
return schema.map((item) => rewriteJsonSchemaRefs(item, refs));
|
|
110
|
+
}
|
|
111
|
+
if (!isJsonSchemaObject(schema)) {
|
|
112
|
+
return schema;
|
|
113
|
+
}
|
|
114
|
+
const rewritten = {};
|
|
115
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
116
|
+
rewritten[key] = rewriteJsonSchemaRefs(value, refs);
|
|
117
|
+
}
|
|
118
|
+
if (typeof rewritten.$ref === "string" && rewritten.$ref in refs) {
|
|
119
|
+
rewritten.$ref = refs[rewritten.$ref];
|
|
120
|
+
}
|
|
121
|
+
return rewritten;
|
|
122
|
+
};
|
|
123
|
+
const normalizeJsonSchemaValue = (schema) => {
|
|
124
|
+
if (Array.isArray(schema)) {
|
|
125
|
+
return schema.map((item) => normalizeJsonSchemaValue(item));
|
|
126
|
+
}
|
|
127
|
+
if (!isJsonSchemaObject(schema)) {
|
|
128
|
+
return schema;
|
|
129
|
+
}
|
|
130
|
+
const normalized = {};
|
|
131
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
132
|
+
normalized[key] = normalizeJsonSchemaValue(value);
|
|
133
|
+
}
|
|
134
|
+
if (Array.isArray(normalized.required) && normalized.required.every((item) => typeof item === "string")) {
|
|
135
|
+
normalized.required = [...normalized.required].sort();
|
|
136
|
+
}
|
|
137
|
+
const null_union_candidates = nullUnionCandidates(normalized);
|
|
138
|
+
if (null_union_candidates !== null) {
|
|
139
|
+
const merged = { anyOf: normalizeJsonSchemaValue(null_union_candidates) };
|
|
140
|
+
for (const [key, value] of Object.entries(normalized)) {
|
|
141
|
+
if (key !== "type") {
|
|
142
|
+
merged[key] = value;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return merged;
|
|
146
|
+
}
|
|
147
|
+
return normalized;
|
|
148
|
+
};
|
|
149
|
+
const toJsonSchema = (schema) => {
|
|
150
|
+
return normalizeJsonSchema(import_zod.z.toJSONSchema(schema));
|
|
151
|
+
};
|
|
152
|
+
const fromJsonSchema = (schema) => {
|
|
153
|
+
return import_zod.z.fromJSONSchema(schema);
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=jsonschema.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/jsonschema.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\nexport type JsonSchema = boolean | z.core.JSONSchema.JSONSchema\ntype JsonSchemaObject = z.core.JSONSchema.JSONSchema\n\nconst isJsonSchemaObject = (value: unknown): value is JsonSchemaObject => {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport const isJsonSchema = (value: unknown): value is JsonSchema => {\n if (typeof value === 'boolean') {\n return true\n }\n if (!isJsonSchemaObject(value)) {\n return false\n }\n if ('_zod' in value || '_def' in value || '~standard' in value) {\n return false\n }\n return true\n}\n\nconst nullUnionCandidates = (schema: Record<string, unknown>): Record<string, unknown>[] | null => {\n if (Array.isArray(schema.type) && schema.type.includes('null')) {\n const non_null_types = schema.type.filter((item): item is string => typeof item === 'string' && item !== 'null')\n if (non_null_types.length > 0) {\n return [{ type: non_null_types.length === 1 ? non_null_types[0] : non_null_types }, { type: 'null' }]\n }\n }\n\n return null\n}\n\nexport const normalizeJsonSchema = (schema: JsonSchema): JsonSchema => {\n const normalized = normalizeJsonSchemaValue(schema)\n if (!isJsonSchemaObject(normalized)) {\n return normalized as JsonSchema\n }\n const schema_record = { ...normalized } as JsonSchemaObject\n const definitions = schema_record.$defs\n const root_ref = rootRefForSchema(schema_record, definitions)\n if (!root_ref || !definitions) {\n schema_record.$schema ??= 'https://json-schema.org/draft/2020-12/schema'\n return schema_record\n }\n const root_name = root_ref.slice('#/$defs/'.length)\n const root_schema = definitions[root_name]\n if (!isJsonSchemaObject(root_schema)) {\n schema_record.$schema ??= 'https://json-schema.org/draft/2020-12/schema'\n return schema_record\n }\n const rewritten_root = rewriteJsonSchemaRefs(root_schema, { [root_ref]: '#' }) as JsonSchemaObject\n const remaining_defs = Object.fromEntries(Object.entries(definitions).filter(([name]) => name !== root_name))\n if (Object.keys(remaining_defs).length > 0) {\n rewritten_root.$defs = rewriteJsonSchemaRefs(remaining_defs, { [root_ref]: '#' }) as Record<string, JsonSchemaObject>\n }\n rewritten_root.$schema ??= schema_record.$schema ?? 'https://json-schema.org/draft/2020-12/schema'\n setTitleFromInlinedRootDefinition(rewritten_root, root_name)\n return rewritten_root\n}\n\nconst rootRefForSchema = (schema: JsonSchemaObject, definitions: Record<string, JsonSchemaObject> | undefined): string | null => {\n if (typeof schema.$ref === 'string' && schema.$ref.startsWith('#/$defs/')) {\n return schema.$ref\n }\n if (!definitions) {\n return null\n }\n const root = schemaWithoutSchemaAndDefinitions(schema)\n for (const [name, definition] of Object.entries(definitions)) {\n if (JSON.stringify(definition) === JSON.stringify(root)) {\n return `#/$defs/${name}`\n }\n }\n return null\n}\n\nconst schemaWithoutSchemaAndDefinitions = (schema: JsonSchemaObject): Record<string, unknown> => {\n const root: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(schema)) {\n if (key !== '$schema' && key !== '$defs') {\n root[key] = value\n }\n }\n return root\n}\n\nconst setTitleFromInlinedRootDefinition = (schema: JsonSchemaObject, root_name: string): void => {\n if (root_name.startsWith('__schema')) return\n schema.title ??= root_name\n}\n\nconst rewriteJsonSchemaRefs = (schema: unknown, refs: Record<string, string>): unknown => {\n if (Array.isArray(schema)) {\n return schema.map((item) => rewriteJsonSchemaRefs(item, refs))\n }\n if (!isJsonSchemaObject(schema)) {\n return schema\n }\n const rewritten: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(schema)) {\n rewritten[key] = rewriteJsonSchemaRefs(value, refs)\n }\n if (typeof rewritten.$ref === 'string' && rewritten.$ref in refs) {\n rewritten.$ref = refs[rewritten.$ref]\n }\n return rewritten\n}\n\nconst normalizeJsonSchemaValue = (schema: unknown): unknown => {\n if (Array.isArray(schema)) {\n return schema.map((item) => normalizeJsonSchemaValue(item))\n }\n if (!isJsonSchemaObject(schema)) {\n return schema\n }\n\n const normalized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(schema)) {\n normalized[key] = normalizeJsonSchemaValue(value)\n }\n if (Array.isArray(normalized.required) && normalized.required.every((item) => typeof item === 'string')) {\n normalized.required = [...normalized.required].sort()\n }\n\n const null_union_candidates = nullUnionCandidates(normalized)\n if (null_union_candidates !== null) {\n const merged: Record<string, unknown> = { anyOf: normalizeJsonSchemaValue(null_union_candidates) }\n for (const [key, value] of Object.entries(normalized)) {\n if (key !== 'type') {\n merged[key] = value\n }\n }\n return merged\n }\n\n return normalized\n}\n\nexport const toJsonSchema = (schema: z.core.$ZodType): JsonSchema => {\n return normalizeJsonSchema(z.toJSONSchema(schema) as JsonSchema)\n}\n\nexport const fromJsonSchema = (schema: JsonSchema): z.ZodTypeAny => {\n return z.fromJSONSchema(schema)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/cjs/retry.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export interface RetryOptions {
|
|
|
19
19
|
retry_on_errors?: Array<(new (...args: any[]) => Error) | string | RegExp>;
|
|
20
20
|
/** Per-attempt timeout in seconds. Default: undefined (no per-attempt timeout) */
|
|
21
21
|
timeout?: number | null;
|
|
22
|
+
/** Emit a warning when a decorated call exceeds this many seconds. Default: undefined (disabled) */
|
|
23
|
+
slow_timeout?: number | null;
|
|
22
24
|
/** Maximum concurrent executions sharing this semaphore. Default: undefined (no concurrency limit) */
|
|
23
25
|
semaphore_limit?: number | null;
|
|
24
26
|
/** Semaphore identifier. Functions with the same name share the same concurrency slot pool. Default: function name.
|
package/dist/cjs/retry.js
CHANGED
|
@@ -28,6 +28,8 @@ var import_async_context = require("./async_context.js");
|
|
|
28
28
|
var import_optional_deps = require("./optional_deps.js");
|
|
29
29
|
const MULTIPROCESS_SEMAPHORE_DIRNAME = "browser_use_semaphores";
|
|
30
30
|
const MULTIPROCESS_STALE_LOCK_MS = 5 * 60 * 1e3;
|
|
31
|
+
const RETRY_SLOW_WARNING_THROTTLE_MS = 2e3;
|
|
32
|
+
const RETRY_SLOW_WARNING_ARGS_MAX_LENGTH = 80;
|
|
31
33
|
let multiprocess_fallback_reason_logged = null;
|
|
32
34
|
class RetryTimeoutError extends Error {
|
|
33
35
|
timeout_seconds;
|
|
@@ -133,16 +135,20 @@ function retry(options = {}) {
|
|
|
133
135
|
retry_backoff_factor = 1,
|
|
134
136
|
retry_on_errors,
|
|
135
137
|
timeout,
|
|
138
|
+
slow_timeout,
|
|
136
139
|
semaphore_limit,
|
|
137
140
|
semaphore_name: semaphore_name_option,
|
|
138
141
|
semaphore_lax = true,
|
|
139
142
|
semaphore_scope = "global",
|
|
140
143
|
semaphore_timeout
|
|
141
144
|
} = options;
|
|
142
|
-
const decorateFunction = (target, _context) => {
|
|
143
|
-
const
|
|
145
|
+
const decorateFunction = (target, _context, owner_name) => {
|
|
146
|
+
const base_fn_name = target.name || _context?.name || "anonymous";
|
|
147
|
+
let fn_name = owner_name ? `${owner_name}.${base_fn_name}` : base_fn_name;
|
|
144
148
|
const effective_max_attempts = Math.max(1, max_attempts);
|
|
145
149
|
const effective_retry_after = Math.max(0, retry_after);
|
|
150
|
+
const effective_slow_timeout_ms = slow_timeout != null && slow_timeout > 0 ? slow_timeout * 1e3 : null;
|
|
151
|
+
let last_slow_warning_at = 0;
|
|
146
152
|
const shouldRetry = (error) => {
|
|
147
153
|
if (!retry_on_errors || retry_on_errors.length === 0) return true;
|
|
148
154
|
return retry_on_errors.some(
|
|
@@ -161,6 +167,13 @@ function retry(options = {}) {
|
|
|
161
167
|
sleepSync(delay_seconds * 1e3);
|
|
162
168
|
}
|
|
163
169
|
};
|
|
170
|
+
const emitSlowWarningIfDue = (args, start_time) => {
|
|
171
|
+
if (effective_slow_timeout_ms == null) return;
|
|
172
|
+
const now = Date.now();
|
|
173
|
+
if (now - last_slow_warning_at < RETRY_SLOW_WARNING_THROTTLE_MS) return;
|
|
174
|
+
last_slow_warning_at = now;
|
|
175
|
+
console.warn(`Warning: ${fn_name}(${formatRetrySlowWarningArgs(args)}) slow (${((now - start_time) / 1e3).toFixed(1)}s)`);
|
|
176
|
+
};
|
|
164
177
|
const runRetryLoopFromThenable = async (this_arg, args, first_thenable, first_attempt) => {
|
|
165
178
|
let current_result = first_thenable;
|
|
166
179
|
for (let attempt = first_attempt; attempt <= effective_max_attempts; attempt++) {
|
|
@@ -240,20 +253,35 @@ function retry(options = {}) {
|
|
|
240
253
|
new_held.add(scoped_key);
|
|
241
254
|
}
|
|
242
255
|
const runRetryLoop = async () => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
256
|
+
const call_started_at = Date.now();
|
|
257
|
+
const warning_args = [...args];
|
|
258
|
+
const slow_warning_timer = effective_slow_timeout_ms == null ? null : setTimeout(() => emitSlowWarningIfDue(warning_args, call_started_at), effective_slow_timeout_ms);
|
|
259
|
+
const finishSlowWarning = () => {
|
|
260
|
+
if (slow_warning_timer !== null) {
|
|
261
|
+
clearTimeout(slow_warning_timer);
|
|
262
|
+
}
|
|
263
|
+
if (effective_slow_timeout_ms != null && Date.now() - call_started_at >= effective_slow_timeout_ms) {
|
|
264
|
+
emitSlowWarningIfDue(warning_args, call_started_at);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
try {
|
|
268
|
+
for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
|
|
269
|
+
try {
|
|
270
|
+
if (timeout != null && timeout > 0) {
|
|
271
|
+
return await _runWithTimeout(() => Promise.resolve(target.apply(this, args)), timeout * 1e3, attempt);
|
|
272
|
+
} else {
|
|
273
|
+
return await Promise.resolve(target.apply(this, args));
|
|
274
|
+
}
|
|
275
|
+
} catch (error) {
|
|
276
|
+
if (!shouldRetry(error)) throw error;
|
|
277
|
+
if (attempt >= effective_max_attempts) throw error;
|
|
278
|
+
await asyncRetryDelay(attempt);
|
|
249
279
|
}
|
|
250
|
-
} catch (error) {
|
|
251
|
-
if (!shouldRetry(error)) throw error;
|
|
252
|
-
if (attempt >= effective_max_attempts) throw error;
|
|
253
|
-
await asyncRetryDelay(attempt);
|
|
254
280
|
}
|
|
281
|
+
throw new Error(`retry(${fn_name}): unexpected end of retry loop`);
|
|
282
|
+
} finally {
|
|
283
|
+
finishSlowWarning();
|
|
255
284
|
}
|
|
256
|
-
throw new Error(`retry(${fn_name}): unexpected end of retry loop`);
|
|
257
285
|
};
|
|
258
286
|
try {
|
|
259
287
|
return await runWithHeldSemaphores(new_held, runRetryLoop);
|
|
@@ -303,27 +331,48 @@ function retry(options = {}) {
|
|
|
303
331
|
}
|
|
304
332
|
};
|
|
305
333
|
const runRetryLoop = () => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
334
|
+
const call_started_at = Date.now();
|
|
335
|
+
const warning_args = [...args];
|
|
336
|
+
const slow_warning_timer = effective_slow_timeout_ms == null ? null : setTimeout(() => emitSlowWarningIfDue(warning_args, call_started_at), effective_slow_timeout_ms);
|
|
337
|
+
const finishSlowWarning = () => {
|
|
338
|
+
if (slow_warning_timer !== null) {
|
|
339
|
+
clearTimeout(slow_warning_timer);
|
|
340
|
+
}
|
|
341
|
+
if (effective_slow_timeout_ms != null && Date.now() - call_started_at >= effective_slow_timeout_ms) {
|
|
342
|
+
emitSlowWarningIfDue(warning_args, call_started_at);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
let finish_on_return = true;
|
|
346
|
+
try {
|
|
347
|
+
for (let attempt = 1; attempt <= effective_max_attempts; attempt++) {
|
|
348
|
+
const attempt_started_at = Date.now();
|
|
349
|
+
try {
|
|
350
|
+
const result = target.apply(this, args);
|
|
351
|
+
if (isThenable(result)) {
|
|
352
|
+
finish_on_return = false;
|
|
353
|
+
return runRetryLoopFromThenable(this, args, result, attempt).finally(finishSlowWarning);
|
|
354
|
+
}
|
|
355
|
+
if (timeout != null && timeout > 0 && Date.now() - attempt_started_at > timeout * 1e3) {
|
|
356
|
+
throw new RetryTimeoutError(`Timed out after ${timeout}s (attempt ${attempt})`, {
|
|
357
|
+
timeout_seconds: timeout,
|
|
358
|
+
attempt
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return result;
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (!shouldRetry(error)) throw error;
|
|
364
|
+
if (attempt >= effective_max_attempts) {
|
|
365
|
+
throw error;
|
|
366
|
+
}
|
|
367
|
+
syncRetryDelay(attempt);
|
|
318
368
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
369
|
+
}
|
|
370
|
+
throw new Error(`retry(${fn_name}): unexpected end of retry loop`);
|
|
371
|
+
} finally {
|
|
372
|
+
if (finish_on_return) {
|
|
373
|
+
finishSlowWarning();
|
|
324
374
|
}
|
|
325
375
|
}
|
|
326
|
-
throw new Error(`retry(${fn_name}): unexpected end of retry loop`);
|
|
327
376
|
};
|
|
328
377
|
try {
|
|
329
378
|
const result = runWithHeldSemaphores(new_held, runRetryLoop);
|
|
@@ -341,9 +390,10 @@ function retry(options = {}) {
|
|
|
341
390
|
Object.defineProperty(retryWrapper, "name", { value: fn_name, configurable: true });
|
|
342
391
|
if (_context?.kind === "method" && typeof _context.addInitializer === "function") {
|
|
343
392
|
_context.addInitializer(function() {
|
|
344
|
-
const
|
|
345
|
-
if (
|
|
346
|
-
|
|
393
|
+
const owner_name2 = findDecoratedMethodOwnerName(this, _context, retryWrapper);
|
|
394
|
+
if (owner_name2) {
|
|
395
|
+
fn_name = `${owner_name2}.${target.name || _context.name || "anonymous"}`;
|
|
396
|
+
Object.defineProperty(retryWrapper, "name", { value: fn_name, configurable: true });
|
|
347
397
|
}
|
|
348
398
|
});
|
|
349
399
|
}
|
|
@@ -351,7 +401,8 @@ function retry(options = {}) {
|
|
|
351
401
|
};
|
|
352
402
|
function decorator(target, context_or_property_key, descriptor) {
|
|
353
403
|
if (descriptor?.value && typeof descriptor.value === "function") {
|
|
354
|
-
|
|
404
|
+
const owner_name = target && (typeof target === "object" || typeof target === "function") ? typeof target === "function" ? target.name : target.constructor?.name : null;
|
|
405
|
+
descriptor.value = decorateFunction(descriptor.value, void 0, owner_name);
|
|
355
406
|
return descriptor;
|
|
356
407
|
}
|
|
357
408
|
if (typeof target === "function") {
|
|
@@ -398,6 +449,30 @@ function isAsyncFunction(fn) {
|
|
|
398
449
|
function isThenable(value) {
|
|
399
450
|
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
|
|
400
451
|
}
|
|
452
|
+
function formatRetrySlowWarningArgs(args) {
|
|
453
|
+
const preview = args.map(formatRetrySlowWarningValue).join(", ");
|
|
454
|
+
if (preview.length > RETRY_SLOW_WARNING_ARGS_MAX_LENGTH) {
|
|
455
|
+
return `${preview.slice(0, RETRY_SLOW_WARNING_ARGS_MAX_LENGTH - 3).replace(/,?\s*$/, "")}...`;
|
|
456
|
+
}
|
|
457
|
+
return preview;
|
|
458
|
+
}
|
|
459
|
+
function formatRetrySlowWarningValue(value) {
|
|
460
|
+
let text;
|
|
461
|
+
if (typeof value === "string") {
|
|
462
|
+
text = value;
|
|
463
|
+
} else if (value === null || value === void 0) {
|
|
464
|
+
text = String(value);
|
|
465
|
+
} else if (typeof value === "object") {
|
|
466
|
+
try {
|
|
467
|
+
text = JSON.stringify(value);
|
|
468
|
+
} catch {
|
|
469
|
+
text = String(value);
|
|
470
|
+
}
|
|
471
|
+
} else {
|
|
472
|
+
text = String(value);
|
|
473
|
+
}
|
|
474
|
+
return text.replace(/['"]/g, "").slice(0, 3);
|
|
475
|
+
}
|
|
401
476
|
async function acquireWithTimeout(semaphore, timeout_ms) {
|
|
402
477
|
return new Promise((resolve) => {
|
|
403
478
|
let settled = false;
|