@snail-js/api 0.1.28 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -605
- package/dist/adapter/plain.d.ts +12 -0
- package/dist/adapter/plain.d.ts.map +1 -0
- package/dist/adapter/react.d.ts +14 -0
- package/dist/adapter/react.d.ts.map +1 -0
- package/dist/adapter/registry.d.ts +16 -0
- package/dist/adapter/registry.d.ts.map +1 -0
- package/dist/adapter/vue.d.ts +15 -0
- package/dist/adapter/vue.d.ts.map +1 -0
- package/dist/chunks/custom-UchOSg_s.js +466 -0
- package/dist/chunks/custom-UchOSg_s.js.map +1 -0
- package/dist/chunks/download-lBC7oOTT.js +160 -0
- package/dist/chunks/download-lBC7oOTT.js.map +1 -0
- package/dist/chunks/object-Ct0w-h4i.js +74 -0
- package/dist/chunks/object-Ct0w-h4i.js.map +1 -0
- package/dist/chunks/plugin-D3RDffDG.js +742 -0
- package/dist/chunks/plugin-D3RDffDG.js.map +1 -0
- package/dist/chunks/react-C1em-gxy.js +62 -0
- package/dist/chunks/react-C1em-gxy.js.map +1 -0
- package/dist/chunks/request-qeRhihEF.js +40 -0
- package/dist/chunks/request-qeRhihEF.js.map +1 -0
- package/dist/chunks/response-D-ubkAFl.js +127 -0
- package/dist/chunks/response-D-ubkAFl.js.map +1 -0
- package/dist/chunks/use-download-FAjtdJ58.js +1816 -0
- package/dist/chunks/use-download-FAjtdJ58.js.map +1 -0
- package/dist/chunks/vue-Dd9EhkQ3.js +34 -0
- package/dist/chunks/vue-Dd9EhkQ3.js.map +1 -0
- package/dist/core/args.d.ts +54 -0
- package/dist/core/args.d.ts.map +1 -0
- package/dist/core/connection.d.ts +15 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/context.d.ts +124 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/http-stream.d.ts +28 -0
- package/dist/core/http-stream.d.ts.map +1 -0
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/metadata.d.ts +92 -0
- package/dist/core/metadata.d.ts.map +1 -0
- package/dist/core/metadata.keys.d.ts +41 -0
- package/dist/core/metadata.keys.d.ts.map +1 -0
- package/dist/core/method.d.ts +177 -0
- package/dist/core/method.d.ts.map +1 -0
- package/dist/core/plugin-manager.d.ts +106 -0
- package/dist/core/plugin-manager.d.ts.map +1 -0
- package/dist/core/plugin.d.ts +113 -0
- package/dist/core/plugin.d.ts.map +1 -0
- package/dist/core/reconnect.d.ts +22 -0
- package/dist/core/reconnect.d.ts.map +1 -0
- package/dist/core/resolve-stream.d.ts +45 -0
- package/dist/core/resolve-stream.d.ts.map +1 -0
- package/dist/core/resolve.d.ts +50 -0
- package/dist/core/resolve.d.ts.map +1 -0
- package/dist/core/response.d.ts +60 -0
- package/dist/core/response.d.ts.map +1 -0
- package/dist/core/server.d.ts +132 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/sse.d.ts +27 -0
- package/dist/core/sse.d.ts.map +1 -0
- package/dist/core/state-bag.d.ts +36 -0
- package/dist/core/state-bag.d.ts.map +1 -0
- package/dist/core/websocket.d.ts +29 -0
- package/dist/core/websocket.d.ts.map +1 -0
- package/dist/decorators/api.d.ts +24 -4
- package/dist/decorators/api.d.ts.map +1 -0
- package/dist/decorators/args.d.ts +77 -14
- package/dist/decorators/args.d.ts.map +1 -0
- package/dist/decorators/custom.d.ts +81 -0
- package/dist/decorators/custom.d.ts.map +1 -0
- package/dist/decorators/header.d.ts +22 -0
- package/dist/decorators/header.d.ts.map +1 -0
- package/dist/decorators/index.d.ts +17 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/methods.d.ts +33 -0
- package/dist/decorators/methods.d.ts.map +1 -0
- package/dist/decorators/progress.d.ts +24 -6
- package/dist/decorators/progress.d.ts.map +1 -0
- package/dist/decorators/server.d.ts +28 -7
- package/dist/decorators/server.d.ts.map +1 -0
- package/dist/decorators/stream.d.ts +113 -0
- package/dist/decorators/stream.d.ts.map +1 -0
- package/dist/default/options.d.ts +19 -0
- package/dist/default/options.d.ts.map +1 -0
- package/dist/error/base.d.ts +20 -0
- package/dist/error/base.d.ts.map +1 -0
- package/dist/error/decorator.d.ts +14 -0
- package/dist/error/decorator.d.ts.map +1 -0
- package/dist/error/hook.d.ts +14 -0
- package/dist/error/hook.d.ts.map +1 -0
- package/dist/error/index.d.ts +8 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/options.d.ts +12 -0
- package/dist/error/options.d.ts.map +1 -0
- package/dist/error/plugin.d.ts +11 -0
- package/dist/error/plugin.d.ts.map +1 -0
- package/dist/error/request.d.ts +29 -0
- package/dist/error/request.d.ts.map +1 -0
- package/dist/error/response.d.ts +36 -0
- package/dist/error/response.d.ts.map +1 -0
- package/dist/index.d.ts +56 -11
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2034 -0
- package/dist/index.js.map +1 -0
- package/dist/locale/en.d.ts +5 -0
- package/dist/locale/en.d.ts.map +1 -0
- package/dist/locale/index.d.ts +57 -0
- package/dist/locale/index.d.ts.map +1 -0
- package/dist/locale/types.d.ts +11 -0
- package/dist/locale/types.d.ts.map +1 -0
- package/dist/locale/zh.d.ts +5 -0
- package/dist/locale/zh.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/indexeddb.d.ts +52 -0
- package/dist/plugins/cache/adapters/indexeddb.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/memory.d.ts +60 -0
- package/dist/plugins/cache/adapters/memory.d.ts.map +1 -0
- package/dist/plugins/cache/adapters/web-storage.d.ts +43 -0
- package/dist/plugins/cache/adapters/web-storage.d.ts.map +1 -0
- package/dist/plugins/cache/decorators.d.ts +62 -0
- package/dist/plugins/cache/decorators.d.ts.map +1 -0
- package/dist/plugins/cache/index.d.ts +41 -0
- package/dist/plugins/cache/index.d.ts.map +1 -0
- package/dist/plugins/cache/key.d.ts +48 -0
- package/dist/plugins/cache/key.d.ts.map +1 -0
- package/dist/plugins/cache/manager.d.ts +124 -0
- package/dist/plugins/cache/manager.d.ts.map +1 -0
- package/dist/plugins/cache/plugin.d.ts +64 -0
- package/dist/plugins/cache/plugin.d.ts.map +1 -0
- package/dist/plugins/cache/type.d.ts +116 -0
- package/dist/plugins/cache/type.d.ts.map +1 -0
- package/dist/plugins/index.d.ts +75 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +2265 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/interceptor/decorators.d.ts +44 -0
- package/dist/plugins/interceptor/decorators.d.ts.map +1 -0
- package/dist/plugins/interceptor/index.d.ts +31 -0
- package/dist/plugins/interceptor/index.d.ts.map +1 -0
- package/dist/plugins/interceptor/manager.d.ts +27 -0
- package/dist/plugins/interceptor/manager.d.ts.map +1 -0
- package/dist/plugins/interceptor/plugin.d.ts +65 -0
- package/dist/plugins/interceptor/plugin.d.ts.map +1 -0
- package/dist/plugins/interceptor/type.d.ts +45 -0
- package/dist/plugins/interceptor/type.d.ts.map +1 -0
- package/dist/plugins/pool/index.d.ts +26 -0
- package/dist/plugins/pool/index.d.ts.map +1 -0
- package/dist/plugins/pool/plugin.d.ts +83 -0
- package/dist/plugins/pool/plugin.d.ts.map +1 -0
- package/dist/plugins/pool/scheduler.d.ts +153 -0
- package/dist/plugins/pool/scheduler.d.ts.map +1 -0
- package/dist/plugins/pool/type.d.ts +38 -0
- package/dist/plugins/pool/type.d.ts.map +1 -0
- package/dist/plugins/react/index.d.ts +20 -0
- package/dist/plugins/react/index.d.ts.map +1 -0
- package/dist/plugins/react/index.js +145 -0
- package/dist/plugins/react/index.js.map +1 -0
- package/dist/plugins/react/plugin.d.ts +33 -0
- package/dist/plugins/react/plugin.d.ts.map +1 -0
- package/dist/plugins/react/type.d.ts +32 -0
- package/dist/plugins/react/type.d.ts.map +1 -0
- package/dist/plugins/transform/decorators.d.ts +54 -0
- package/dist/plugins/transform/decorators.d.ts.map +1 -0
- package/dist/plugins/transform/hydrate.d.ts +47 -0
- package/dist/plugins/transform/hydrate.d.ts.map +1 -0
- package/dist/plugins/transform/index.d.ts +41 -0
- package/dist/plugins/transform/index.d.ts.map +1 -0
- package/dist/plugins/transform/plugin.d.ts +20 -0
- package/dist/plugins/transform/plugin.d.ts.map +1 -0
- package/dist/plugins/transform/type.d.ts +67 -0
- package/dist/plugins/transform/type.d.ts.map +1 -0
- package/dist/plugins/validate/decorators.d.ts +24 -0
- package/dist/plugins/validate/decorators.d.ts.map +1 -0
- package/dist/plugins/validate/index.d.ts +40 -0
- package/dist/plugins/validate/index.d.ts.map +1 -0
- package/dist/plugins/validate/plugin.d.ts +13 -0
- package/dist/plugins/validate/plugin.d.ts.map +1 -0
- package/dist/plugins/validate/type.d.ts +54 -0
- package/dist/plugins/validate/type.d.ts.map +1 -0
- package/dist/plugins/version/decorators.d.ts +22 -0
- package/dist/plugins/version/decorators.d.ts.map +1 -0
- package/dist/plugins/version/index.d.ts +23 -0
- package/dist/plugins/version/index.d.ts.map +1 -0
- package/dist/plugins/version/plugin.d.ts +13 -0
- package/dist/plugins/version/plugin.d.ts.map +1 -0
- package/dist/plugins/version/type.d.ts +47 -0
- package/dist/plugins/version/type.d.ts.map +1 -0
- package/dist/plugins/vue/index.d.ts +21 -0
- package/dist/plugins/vue/index.d.ts.map +1 -0
- package/dist/plugins/vue/index.js +114 -0
- package/dist/plugins/vue/index.js.map +1 -0
- package/dist/plugins/vue/plugin.d.ts +15 -0
- package/dist/plugins/vue/plugin.d.ts.map +1 -0
- package/dist/plugins/vue/type.d.ts +34 -0
- package/dist/plugins/vue/type.d.ts.map +1 -0
- package/dist/strategies/index.d.ts +2 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +29 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/strategies/plain.d.ts +2 -0
- package/dist/strategies/plain.d.ts.map +1 -0
- package/dist/strategies/plain.js +23 -0
- package/dist/strategies/plain.js.map +1 -0
- package/dist/strategies/react.d.ts +2 -0
- package/dist/strategies/react.d.ts.map +1 -0
- package/dist/strategies/react.js +30 -0
- package/dist/strategies/react.js.map +1 -0
- package/dist/strategies/shared/adapter.d.ts +23 -0
- package/dist/strategies/shared/adapter.d.ts.map +1 -0
- package/dist/strategies/shared/dom.d.ts +53 -0
- package/dist/strategies/shared/dom.d.ts.map +1 -0
- package/dist/strategies/shared/error.d.ts +30 -0
- package/dist/strategies/shared/error.d.ts.map +1 -0
- package/dist/strategies/shared/method.d.ts +51 -0
- package/dist/strategies/shared/method.d.ts.map +1 -0
- package/dist/strategies/shared/public.d.ts +33 -0
- package/dist/strategies/shared/public.d.ts.map +1 -0
- package/dist/strategies/shared/queue.d.ts +30 -0
- package/dist/strategies/shared/queue.d.ts.map +1 -0
- package/dist/strategies/shared/retry.d.ts +51 -0
- package/dist/strategies/shared/retry.d.ts.map +1 -0
- package/dist/strategies/shared/state.d.ts +117 -0
- package/dist/strategies/shared/state.d.ts.map +1 -0
- package/dist/strategies/shared/timing.d.ts +53 -0
- package/dist/strategies/shared/timing.d.ts.map +1 -0
- package/dist/strategies/shared/watcher.d.ts +37 -0
- package/dist/strategies/shared/watcher.d.ts.map +1 -0
- package/dist/strategies/use-auto-request.d.ts +77 -0
- package/dist/strategies/use-auto-request.d.ts.map +1 -0
- package/dist/strategies/use-download.d.ts +103 -0
- package/dist/strategies/use-download.d.ts.map +1 -0
- package/dist/strategies/use-fetcher.d.ts +52 -0
- package/dist/strategies/use-fetcher.d.ts.map +1 -0
- package/dist/strategies/use-pagination.d.ts +101 -0
- package/dist/strategies/use-pagination.d.ts.map +1 -0
- package/dist/strategies/use-request.d.ts +50 -0
- package/dist/strategies/use-request.d.ts.map +1 -0
- package/dist/strategies/use-retriable-request.d.ts +46 -0
- package/dist/strategies/use-retriable-request.d.ts.map +1 -0
- package/dist/strategies/use-sse.d.ts +103 -0
- package/dist/strategies/use-sse.d.ts.map +1 -0
- package/dist/strategies/use-token-auth.d.ts +88 -0
- package/dist/strategies/use-token-auth.d.ts.map +1 -0
- package/dist/strategies/use-uploader.d.ts +88 -0
- package/dist/strategies/use-uploader.d.ts.map +1 -0
- package/dist/strategies/use-watcher.d.ts +69 -0
- package/dist/strategies/use-watcher.d.ts.map +1 -0
- package/dist/typings/adapter.d.ts +61 -0
- package/dist/typings/adapter.d.ts.map +1 -0
- package/dist/typings/api.d.ts +122 -0
- package/dist/typings/api.d.ts.map +1 -0
- package/dist/typings/args.d.ts +51 -0
- package/dist/typings/args.d.ts.map +1 -0
- package/dist/typings/index.d.ts +8 -12
- package/dist/typings/index.d.ts.map +1 -0
- package/dist/typings/meta.d.ts +44 -0
- package/dist/typings/meta.d.ts.map +1 -0
- package/dist/typings/plugin.d.ts +114 -0
- package/dist/typings/plugin.d.ts.map +1 -0
- package/dist/typings/response.d.ts +118 -0
- package/dist/typings/response.d.ts.map +1 -0
- package/dist/typings/server.d.ts +83 -0
- package/dist/typings/server.d.ts.map +1 -0
- package/dist/typings/stream.d.ts +150 -0
- package/dist/typings/stream.d.ts.map +1 -0
- package/dist/utils/download.d.ts +97 -0
- package/dist/utils/download.d.ts.map +1 -0
- package/dist/utils/emitter.d.ts +36 -0
- package/dist/utils/emitter.d.ts.map +1 -0
- package/dist/utils/index.d.ts +6 -1
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/is.d.ts +22 -0
- package/dist/utils/is.d.ts.map +1 -0
- package/dist/utils/object.d.ts +44 -0
- package/dist/utils/object.d.ts.map +1 -0
- package/dist/utils/url.d.ts +44 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/package.json +90 -27
- package/README_EN.md +0 -607
- package/dist/cache/index.d.ts +0 -9
- package/dist/cache/indexDBCache.d.ts +0 -13
- package/dist/cache/localstorageCache.d.ts +0 -10
- package/dist/cache/memoryCache.d.ts +0 -11
- package/dist/core/index.d.ts +0 -4
- package/dist/core/snailApi.d.ts +0 -22
- package/dist/core/snailMethod.d.ts +0 -49
- package/dist/core/snailServer.d.ts +0 -35
- package/dist/core/snailSse.d.ts +0 -20
- package/dist/decorators/cache.d.ts +0 -15
- package/dist/decorators/method.d.ts +0 -38
- package/dist/decorators/sse.d.ts +0 -30
- package/dist/decorators/strategy.d.ts +0 -10
- package/dist/decorators/versioning.d.ts +0 -16
- package/dist/eventEmmit/index.d.ts +0 -1
- package/dist/eventEmmit/snail.event.d.ts +0 -10
- package/dist/snail-api.js +0 -4871
- package/dist/snail-api.umd.cjs +0 -4875
- package/dist/strategies/jwtStrategy.d.ts +0 -4
- package/dist/typings/api.option.d.ts +0 -10
- package/dist/typings/apiProxy.d.ts +0 -8
- package/dist/typings/cache.management.option.d.ts +0 -25
- package/dist/typings/cache.type.d.ts +0 -23
- package/dist/typings/content.type.d.ts +0 -5
- package/dist/typings/request.body.d.ts +0 -3
- package/dist/typings/response.data.d.ts +0 -13
- package/dist/typings/snail.event.d.ts +0 -6
- package/dist/typings/snail.method.d.ts +0 -14
- package/dist/typings/snail.option.d.ts +0 -16
- package/dist/typings/sse.d.ts +0 -15
- package/dist/typings/strategy.d.ts +0 -5
- package/dist/typings/versioning.option.d.ts +0 -30
- package/dist/utils/function.d.ts +0 -31
- package/dist/versioning/index.d.ts +0 -1
- package/dist/versioning/versioning.d.ts +0 -12
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
//#region src/utils/emitter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Minimal typed event emitter.
|
|
4
|
+
*
|
|
5
|
+
* Used for the `SnailMethod` event surface (`onSuccess`, `onError`, …). It is
|
|
6
|
+
* deliberately tiny: no wildcard events, no `once`, no async scheduling.
|
|
7
|
+
*/
|
|
8
|
+
var Emitter = class {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Register a listener.
|
|
14
|
+
*
|
|
15
|
+
* @returns an unsubscribe function — the ergonomic alternative to keeping a
|
|
16
|
+
* reference around just to call {@link off}.
|
|
17
|
+
*/
|
|
18
|
+
on(type, listener) {
|
|
19
|
+
let set = this.listeners.get(type);
|
|
20
|
+
if (!set) {
|
|
21
|
+
set = /* @__PURE__ */ new Set();
|
|
22
|
+
this.listeners.set(type, set);
|
|
23
|
+
}
|
|
24
|
+
set.add(listener);
|
|
25
|
+
return () => this.off(type, listener);
|
|
26
|
+
}
|
|
27
|
+
/** Remove a previously registered listener. */
|
|
28
|
+
off(type, listener) {
|
|
29
|
+
this.listeners.get(type)?.delete(listener);
|
|
30
|
+
}
|
|
31
|
+
/** Number of listeners registered for `type`. */
|
|
32
|
+
count(type) {
|
|
33
|
+
return this.listeners.get(type)?.size ?? 0;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Invoke every listener for `type`.
|
|
37
|
+
*
|
|
38
|
+
* A throwing listener must not derail the request lifecycle: the promise from
|
|
39
|
+
* `send()` has already settled correctly, and one broken UI callback has no
|
|
40
|
+
* business turning a successful request into a failure. The other listeners for
|
|
41
|
+
* the same event still run.
|
|
42
|
+
*
|
|
43
|
+
* The error is therefore *reported*, not rethrown. Rethrowing from a microtask
|
|
44
|
+
* was the obvious alternative and is wrong: in Node it becomes an uncaught
|
|
45
|
+
* exception, so a throwing toast handler could take the process down.
|
|
46
|
+
*/
|
|
47
|
+
emit(type, payload) {
|
|
48
|
+
const set = this.listeners.get(type);
|
|
49
|
+
if (!set || set.size === 0) return;
|
|
50
|
+
for (const listener of [...set]) try {
|
|
51
|
+
listener(payload);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
reportListenerError(type, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Drop every listener, optionally only for one event type. */
|
|
57
|
+
clear(type) {
|
|
58
|
+
if (type === void 0) {
|
|
59
|
+
this.listeners.clear();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.listeners.delete(type);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Surface a listener's exception without letting it escape.
|
|
67
|
+
*
|
|
68
|
+
* `globalThis.reportError` is the HTML standard for exactly this situation —
|
|
69
|
+
* asynchronous callback failure — and exists in every modern browser, where it
|
|
70
|
+
* reaches `window.onerror` and devtools without unwinding anything. Node and
|
|
71
|
+
* older runtimes get `console.error`.
|
|
72
|
+
*
|
|
73
|
+
* Swallowing it silently is deliberately not an option: hiding a developer's bug
|
|
74
|
+
* is worse than a log line.
|
|
75
|
+
*/
|
|
76
|
+
function reportListenerError(type, error) {
|
|
77
|
+
const reporter = globalThis.reportError;
|
|
78
|
+
if (typeof reporter === "function") {
|
|
79
|
+
reporter(error);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
console.error(`[snail] a listener for "${String(type)}" threw`, error);
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/utils/download.ts
|
|
86
|
+
/**
|
|
87
|
+
* Navigate the browser to `url` as a download.
|
|
88
|
+
*
|
|
89
|
+
* Works for a same-origin path, a cross-origin absolute URL and a `blob:` object
|
|
90
|
+
* URL alike. Throws when there is no DOM, because silently doing nothing is the
|
|
91
|
+
* worst possible outcome for a function whose entire job is a side effect.
|
|
92
|
+
*/
|
|
93
|
+
function triggerDownload(url, options = {}) {
|
|
94
|
+
if (typeof document === "undefined") throw new ReferenceError("[snail] triggerDownload() needs a DOM. On a server, return the url to the client and let the browser fetch it, or write the bytes with node:fs.");
|
|
95
|
+
const anchor = document.createElement("a");
|
|
96
|
+
if (options.openInNewTab) {
|
|
97
|
+
anchor.target = "_blank";
|
|
98
|
+
anchor.rel = "noopener noreferrer";
|
|
99
|
+
} else if (options.filename) anchor.download = options.filename;
|
|
100
|
+
if (options.referrerPolicy) anchor.referrerPolicy = options.referrerPolicy;
|
|
101
|
+
anchor.href = url;
|
|
102
|
+
anchor.style.display = "none";
|
|
103
|
+
(options.container ?? document.body).appendChild(anchor);
|
|
104
|
+
try {
|
|
105
|
+
anchor.click();
|
|
106
|
+
} finally {
|
|
107
|
+
anchor.remove();
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
url,
|
|
111
|
+
filename: options.filename
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Download an in-memory `Blob` by handing the browser an object URL.
|
|
116
|
+
*
|
|
117
|
+
* Use this only when the bytes are already in hand. The object URL is revoked on
|
|
118
|
+
* the next macrotask rather than immediately: revoking it in the same tick races
|
|
119
|
+
* the navigation in Safari and Firefox, and the download silently never starts.
|
|
120
|
+
* The cost is a short-lived duplicate in memory, which is why {@link triggerDownload}
|
|
121
|
+
* remains the recommended path.
|
|
122
|
+
*/
|
|
123
|
+
function triggerBlobDownload(blob, options = {}) {
|
|
124
|
+
if (typeof URL === "undefined" || typeof URL.createObjectURL !== "function") throw new ReferenceError("[snail] triggerBlobDownload() needs URL.createObjectURL, which this runtime does not provide");
|
|
125
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
126
|
+
try {
|
|
127
|
+
return triggerDownload(objectUrl, options);
|
|
128
|
+
} finally {
|
|
129
|
+
setTimeout(() => URL.revokeObjectURL(objectUrl), 0);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Build a filename from a `Content-Disposition` header.
|
|
134
|
+
*
|
|
135
|
+
* Servers send the header, not a JSON field, and parsing it is fiddlier than it
|
|
136
|
+
* looks: `filename*` (RFC 5987, percent-encoded UTF-8) wins over `filename`, which
|
|
137
|
+
* may itself be quoted. Returns `undefined` when the header is absent or names
|
|
138
|
+
* nothing, so a caller can fall back to its own default instead of writing a
|
|
139
|
+
* literal `"undefined"` to disk.
|
|
140
|
+
*/
|
|
141
|
+
function filenameFromDisposition(header) {
|
|
142
|
+
if (!header) return void 0;
|
|
143
|
+
const extended = /filename\*\s*=\s*([^;]+)/i.exec(header);
|
|
144
|
+
if (extended) {
|
|
145
|
+
const value = extended[1].trim();
|
|
146
|
+
const encoded = value.includes("''") ? value.slice(value.indexOf("''") + 2) : value;
|
|
147
|
+
try {
|
|
148
|
+
return decodeURIComponent(encoded.replace(/^["']|["']$/g, ""));
|
|
149
|
+
} catch {}
|
|
150
|
+
}
|
|
151
|
+
const plain = /filename\s*=\s*("([^"]*)"|([^;]+))/i.exec(header);
|
|
152
|
+
if (plain) {
|
|
153
|
+
const value = (plain[2] ?? plain[3] ?? "").trim();
|
|
154
|
+
if (value.length > 0) return value;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { Emitter as i, triggerBlobDownload as n, triggerDownload as r, filenameFromDisposition as t };
|
|
159
|
+
|
|
160
|
+
//# sourceMappingURL=download-lBC7oOTT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-lBC7oOTT.js","names":[],"sources":["../../src/utils/emitter.ts","../../src/utils/download.ts"],"sourcesContent":["/**\n * Minimal typed event emitter.\n *\n * Used for the `SnailMethod` event surface (`onSuccess`, `onError`, …). It is\n * deliberately tiny: no wildcard events, no `once`, no async scheduling.\n */\nexport class Emitter<Events extends Record<string, unknown>> {\n private readonly listeners = new Map<keyof Events, Set<(payload: any) => void>>();\n\n /**\n * Register a listener.\n *\n * @returns an unsubscribe function — the ergonomic alternative to keeping a\n * reference around just to call {@link off}.\n */\n on<K extends keyof Events>(\n type: K,\n listener: (payload: Events[K]) => void\n ): () => void {\n let set = this.listeners.get(type);\n if (!set) {\n set = new Set();\n this.listeners.set(type, set);\n }\n set.add(listener);\n return () => this.off(type, listener);\n }\n\n /** Remove a previously registered listener. */\n off<K extends keyof Events>(type: K, listener: (payload: Events[K]) => void): void {\n this.listeners.get(type)?.delete(listener);\n }\n\n /** Number of listeners registered for `type`. */\n count<K extends keyof Events>(type: K): number {\n return this.listeners.get(type)?.size ?? 0;\n }\n\n /**\n * Invoke every listener for `type`.\n *\n * A throwing listener must not derail the request lifecycle: the promise from\n * `send()` has already settled correctly, and one broken UI callback has no\n * business turning a successful request into a failure. The other listeners for\n * the same event still run.\n *\n * The error is therefore *reported*, not rethrown. Rethrowing from a microtask\n * was the obvious alternative and is wrong: in Node it becomes an uncaught\n * exception, so a throwing toast handler could take the process down.\n */\n emit<K extends keyof Events>(type: K, payload: Events[K]): void {\n const set = this.listeners.get(type);\n if (!set || set.size === 0) return;\n\n for (const listener of [...set]) {\n try {\n listener(payload);\n } catch (error) {\n reportListenerError(type, error);\n }\n }\n }\n\n /** Drop every listener, optionally only for one event type. */\n clear<K extends keyof Events>(type?: K): void {\n if (type === undefined) {\n this.listeners.clear();\n return;\n }\n this.listeners.delete(type);\n }\n}\n\n/**\n * Surface a listener's exception without letting it escape.\n *\n * `globalThis.reportError` is the HTML standard for exactly this situation —\n * asynchronous callback failure — and exists in every modern browser, where it\n * reaches `window.onerror` and devtools without unwinding anything. Node and\n * older runtimes get `console.error`.\n *\n * Swallowing it silently is deliberately not an option: hiding a developer's bug\n * is worse than a log line.\n */\nfunction reportListenerError(type: PropertyKey, error: unknown): void {\n const reporter = (globalThis as { reportError?: (error: unknown) => void }).reportError;\n if (typeof reporter === \"function\") {\n reporter(error);\n return;\n }\n\n console.error(`[snail] a listener for \"${String(type)}\" threw`, error);\n}\n","/**\n * Trigger a browser download from a URL, without ever holding the bytes.\n *\n * ## Why the library does not download for you\n *\n * The obvious design — `responseType: \"blob\"`, `await`, then an object URL — is\n * wrong for anything but a small file. It forces the whole payload through\n * JavaScript memory, so a 200 MB export becomes a 200 MB `Blob` plus a second copy\n * when the object URL is created, with no progress reporting and no way to resume.\n * On a slow connection the tab simply runs out of memory, and the user has no idea\n * whether anything is happening.\n *\n * The design that scales is the one every large site already uses: the server\n * mints a short-lived download URL, and the browser fetches it natively. That gives\n * you a real progress bar in the browser's own download manager, resume support,\n * streaming to disk instead of RAM, and a download that survives navigation. All\n * this library does is ask for the URL and then click a link.\n *\n * ```ts\n * @Api(\"/report\")\n * class ReportApi {\n * /** Ask the server to prepare the export; it answers with a temp URL. *\\/\n * @Post(\"/export\")\n * create(@Data() query: ReportQuery): Promise<{ url: string; filename: string }> {\n * return null!;\n * }\n * }\n *\n * const { url, filename } = (await reportApi.create(query).send()).data;\n * triggerDownload(url, { filename });\n * ```\n *\n * ## When you genuinely need the blob\n *\n * If the response must be transformed, or the backend cannot issue a URL, request\n * `responseType: \"blob\"` and use {@link triggerBlobDownload} instead — it accepts\n * an already-materialised `Blob` and takes care of revoking the object URL.\n */\n\n/** Options accepted by {@link triggerDownload}. */\nexport interface TriggerDownloadOptions {\n /**\n * Filename to suggest to the browser.\n *\n * A cross-origin `href` ignores this — the browser honours the server's\n * `Content-Disposition` instead, because letting a page rename a cross-origin\n * download would be a security problem. For a cross-origin file, make the server\n * send the name in that header.\n */\n filename?: string;\n\n /** Open in a new tab instead of downloading. Defaults to `false`. */\n openInNewTab?: boolean;\n\n /**\n * Where to attach the temporary anchor.\n *\n * Needed only for the old Firefox behaviour where an anchor that was never in the\n * document ignores `click()`. Defaults to `document.body`.\n */\n container?: HTMLElement;\n\n /** `referrerpolicy` for the navigation. */\n referrerPolicy?: string;\n}\n\n/** Result of a successful {@link triggerDownload}. */\nexport interface TriggerDownloadResult {\n /** The URL that was navigated to. */\n url: string;\n\n /** The filename the browser was asked to use, when one was supplied. */\n filename: string | undefined;\n}\n\n/**\n * Navigate the browser to `url` as a download.\n *\n * Works for a same-origin path, a cross-origin absolute URL and a `blob:` object\n * URL alike. Throws when there is no DOM, because silently doing nothing is the\n * worst possible outcome for a function whose entire job is a side effect.\n */\nexport function triggerDownload(\n url: string,\n options: TriggerDownloadOptions = {}\n): TriggerDownloadResult {\n if (typeof document === \"undefined\") {\n throw new ReferenceError(\n \"[snail] triggerDownload() needs a DOM. On a server, return the url to the \" +\n \"client and let the browser fetch it, or write the bytes with node:fs.\"\n );\n }\n\n const anchor = document.createElement(\"a\");\n\n // `target=\"_blank\"` without `rel=\"noopener\"` hands the opened page a handle on\n // this one through `window.opener`, which is a well known tabnabbing vector.\n if (options.openInNewTab) {\n anchor.target = \"_blank\";\n anchor.rel = \"noopener noreferrer\";\n } else if (options.filename) {\n // `download` is what turns a navigation into a download. Setting it on a\n // cross-origin URL is ignored by the browser (see the filename note above),\n // which is why the server must send `Content-Disposition` in that case.\n anchor.download = options.filename;\n }\n\n if (options.referrerPolicy) anchor.referrerPolicy = options.referrerPolicy;\n\n anchor.href = url;\n anchor.style.display = \"none\";\n\n const container = options.container ?? document.body;\n container.appendChild(anchor);\n\n try {\n anchor.click();\n } finally {\n // Always detached: a hidden anchor left in the DOM leaks for the lifetime of\n // the page, and in a single-page app that is unbounded.\n anchor.remove();\n }\n\n return { url, filename: options.filename };\n}\n\n/**\n * Download an in-memory `Blob` by handing the browser an object URL.\n *\n * Use this only when the bytes are already in hand. The object URL is revoked on\n * the next macrotask rather than immediately: revoking it in the same tick races\n * the navigation in Safari and Firefox, and the download silently never starts.\n * The cost is a short-lived duplicate in memory, which is why {@link triggerDownload}\n * remains the recommended path.\n */\nexport function triggerBlobDownload(\n blob: Blob,\n options: TriggerDownloadOptions = {}\n): TriggerDownloadResult {\n if (typeof URL === \"undefined\" || typeof URL.createObjectURL !== \"function\") {\n throw new ReferenceError(\n \"[snail] triggerBlobDownload() needs URL.createObjectURL, which this runtime does not provide\"\n );\n }\n\n const objectUrl = URL.createObjectURL(blob);\n\n try {\n return triggerDownload(objectUrl, options);\n } finally {\n setTimeout(() => URL.revokeObjectURL(objectUrl), 0);\n }\n}\n\n/**\n * Build a filename from a `Content-Disposition` header.\n *\n * Servers send the header, not a JSON field, and parsing it is fiddlier than it\n * looks: `filename*` (RFC 5987, percent-encoded UTF-8) wins over `filename`, which\n * may itself be quoted. Returns `undefined` when the header is absent or names\n * nothing, so a caller can fall back to its own default instead of writing a\n * literal `\"undefined\"` to disk.\n */\nexport function filenameFromDisposition(header: string | undefined): string | undefined {\n if (!header) return undefined;\n\n const extended = /filename\\*\\s*=\\s*([^;]+)/i.exec(header);\n if (extended) {\n const value = extended[1]!.trim();\n const encoded = value.includes(\"''\") ? value.slice(value.indexOf(\"''\") + 2) : value;\n try {\n return decodeURIComponent(encoded.replace(/^[\"']|[\"']$/g, \"\"));\n } catch {\n // A malformed escape is not worth failing a download over.\n }\n }\n\n const plain = /filename\\s*=\\s*(\"([^\"]*)\"|([^;]+))/i.exec(header);\n if (plain) {\n const value = (plain[2] ?? plain[3] ?? \"\").trim();\n if (value.length > 0) return value;\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { L as isPlainObject } from "./plugin-D3RDffDG.js";
|
|
2
|
+
//#region src/utils/object.ts
|
|
3
|
+
/** Return a copy of `source` without the listed keys. */
|
|
4
|
+
function omit(source, keys) {
|
|
5
|
+
const result = { ...source };
|
|
6
|
+
for (const key of keys) delete result[key];
|
|
7
|
+
return result;
|
|
8
|
+
}
|
|
9
|
+
/** Return a copy of `source` containing only the listed keys. */
|
|
10
|
+
function pick(source, keys) {
|
|
11
|
+
const result = {};
|
|
12
|
+
for (const key of keys) if (key in source) result[key] = source[key];
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
/** Drop keys whose value is `undefined`. `null` is preserved deliberately. */
|
|
16
|
+
function omitUndefined(source) {
|
|
17
|
+
const result = {};
|
|
18
|
+
for (const [key, value] of Object.entries(source)) if (value !== void 0) result[key] = value;
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Recursively merge plain objects.
|
|
23
|
+
*
|
|
24
|
+
* Accepts **deeply partial** sources, so
|
|
25
|
+
* `deepMerge({ a: { b: 1, c: 2 } }, { a: { c: 3 } })` type-checks without a cast —
|
|
26
|
+
* which is the whole point of overriding one nested default.
|
|
27
|
+
*
|
|
28
|
+
* Arrays are replaced, not concatenated: concatenating them would make it
|
|
29
|
+
* impossible for a method-level option to override a server-level list.
|
|
30
|
+
*/
|
|
31
|
+
function deepMerge(...sources) {
|
|
32
|
+
const result = {};
|
|
33
|
+
for (const source of sources) {
|
|
34
|
+
if (!isPlainObject(source)) continue;
|
|
35
|
+
for (const [key, value] of Object.entries(source)) {
|
|
36
|
+
const current = result[key];
|
|
37
|
+
if (isPlainObject(current) && isPlainObject(value)) result[key] = deepMerge(current, value);
|
|
38
|
+
else if (value !== void 0) result[key] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
/** Run `fn`, returning `fallback` if it throws. */
|
|
44
|
+
function tryCatch(fn, fallback) {
|
|
45
|
+
try {
|
|
46
|
+
return fn();
|
|
47
|
+
} catch {
|
|
48
|
+
return fallback;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a promise together with its resolve/reject handles.
|
|
53
|
+
*
|
|
54
|
+
* Used by strategies to hand a "ready" promise out before the underlying
|
|
55
|
+
* request is actually started.
|
|
56
|
+
*/
|
|
57
|
+
function deferred() {
|
|
58
|
+
let resolve;
|
|
59
|
+
let reject;
|
|
60
|
+
return {
|
|
61
|
+
promise: new Promise((res, rej) => {
|
|
62
|
+
resolve = res;
|
|
63
|
+
reject = rej;
|
|
64
|
+
}),
|
|
65
|
+
resolve,
|
|
66
|
+
reject
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** A function that does nothing — used as a default callback. */
|
|
70
|
+
function noop() {}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { omitUndefined as a, omit as i, deferred as n, pick as o, noop as r, tryCatch as s, deepMerge as t };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=object-Ct0w-h4i.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-Ct0w-h4i.js","names":[],"sources":["../../src/utils/object.ts"],"sourcesContent":["import { isFunction, isPlainObject } from \"./is\";\n\n/** Return a copy of `source` without the listed keys. */\nexport function omit<T extends Record<string, any>, K extends keyof T>(\n source: T,\n keys: readonly K[]\n): Omit<T, K> {\n const result = { ...source } as Record<string, any>;\n for (const key of keys) delete result[key as string];\n return result as Omit<T, K>;\n}\n\n/** Return a copy of `source` containing only the listed keys. */\nexport function pick<T extends Record<string, any>, K extends keyof T>(\n source: T,\n keys: readonly K[]\n): Pick<T, K> {\n const result = {} as Record<string, any>;\n for (const key of keys) {\n if (key in source) result[key as string] = source[key];\n }\n return result as Pick<T, K>;\n}\n\n/** Drop keys whose value is `undefined`. `null` is preserved deliberately. */\nexport function omitUndefined<T extends Record<string, any>>(source: T): T {\n const result = {} as Record<string, any>;\n for (const [key, value] of Object.entries(source)) {\n if (value !== undefined) result[key] = value;\n }\n return result as T;\n}\n\n/** A deeply optional version of `T`, for merge inputs. */\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends readonly unknown[]\n ? T[K]\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n\n/**\n * Recursively merge plain objects.\n *\n * Accepts **deeply partial** sources, so\n * `deepMerge({ a: { b: 1, c: 2 } }, { a: { c: 3 } })` type-checks without a cast —\n * which is the whole point of overriding one nested default.\n *\n * Arrays are replaced, not concatenated: concatenating them would make it\n * impossible for a method-level option to override a server-level list.\n */\nexport function deepMerge<T extends Record<string, any>>(\n ...sources: Array<DeepPartial<T> | undefined | null>\n): T {\n const result: Record<string, any> = {};\n\n for (const source of sources) {\n if (!isPlainObject(source)) continue;\n for (const [key, value] of Object.entries(source)) {\n const current = result[key];\n if (isPlainObject(current) && isPlainObject(value)) {\n result[key] = deepMerge(current, value);\n } else if (value !== undefined) {\n result[key] = value;\n }\n }\n }\n\n return result as T;\n}\n\n/**\n * Resolve a possibly-functional option value.\n *\n * Options such as `@Header(...)` often need values computed per request, so most\n * option fields accept `T | ((ctx) => T)`.\n */\nexport function resolveValue<T, A>(value: T | ((arg: A) => T), arg: A): T {\n return isFunction(value) ? (value as (arg: A) => T)(arg) : value;\n}\n\n/** Run `fn`, returning `fallback` if it throws. */\nexport function tryCatch<T>(fn: () => T, fallback: T): T {\n try {\n return fn();\n } catch {\n return fallback;\n }\n}\n\n/**\n * Create a promise together with its resolve/reject handles.\n *\n * Used by strategies to hand a \"ready\" promise out before the underlying\n * request is actually started.\n */\nexport function deferred<T = void>(): {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n} {\n let resolve!: (value: T | PromiseLike<T>) => void;\n let reject!: (reason?: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\n\n/** A function that does nothing — used as a default callback. */\nexport function noop(): void {\n /* intentionally empty */\n}\n"],"mappings":";;;AAGA,SAAgB,KACd,QACA,MACY;CACZ,MAAM,SAAS,EAAE,GAAG,OAAO;CAC3B,KAAK,MAAM,OAAO,MAAM,OAAO,OAAO;CACtC,OAAO;AACT;;AAGA,SAAgB,KACd,QACA,MACY;CACZ,MAAM,SAAS,CAAC;CAChB,KAAK,MAAM,OAAO,MAChB,IAAI,OAAO,QAAQ,OAAO,OAAiB,OAAO;CAEpD,OAAO;AACT;;AAGA,SAAgB,cAA6C,QAAc;CACzE,MAAM,SAAS,CAAC;CAChB,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,UAAU,KAAA,GAAW,OAAO,OAAO;CAEzC,OAAO;AACT;;;;;;;;;;;AAqBA,SAAgB,UACd,GAAG,SACA;CACH,MAAM,SAA8B,CAAC;CAErC,KAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,CAAC,cAAc,MAAM,GAAG;EAC5B,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAAG;GACjD,MAAM,UAAU,OAAO;GACvB,IAAI,cAAc,OAAO,KAAK,cAAc,KAAK,GAC/C,OAAO,OAAO,UAAU,SAAS,KAAK;QACjC,IAAI,UAAU,KAAA,GACnB,OAAO,OAAO;EAElB;CACF;CAEA,OAAO;AACT;;AAaA,SAAgB,SAAY,IAAa,UAAgB;CACvD,IAAI;EACF,OAAO,GAAG;CACZ,QAAQ;EACN,OAAO;CACT;AACF;;;;;;;AAQA,SAAgB,WAId;CACA,IAAI;CACJ,IAAI;CAKJ,OAAO;EAAE,SAAA,IAJW,SAAY,KAAK,QAAQ;GAC3C,UAAU;GACV,SAAS;EACX,CACS;EAAS;EAAS;CAAO;AACpC;;AAGA,SAAgB,OAAa,CAE7B"}
|