@liase/core 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 +9 -0
- package/README.md +62 -0
- package/dist/ActionContext.d.ts +603 -0
- package/dist/ActionContext.d.ts.map +1 -0
- package/dist/ActionContext.js +227 -0
- package/dist/DomSelection.d.ts +30 -0
- package/dist/DomSelection.d.ts.map +1 -0
- package/dist/DomSelection.js +60 -0
- package/dist/Liase.d.ts +40 -0
- package/dist/Liase.d.ts.map +1 -0
- package/dist/Liase.js +105 -0
- package/dist/LiaseQuery.d.ts +593 -0
- package/dist/LiaseQuery.d.ts.map +1 -0
- package/dist/LiaseQuery.js +145 -0
- package/dist/actionHelpers.d.ts +30 -0
- package/dist/actionHelpers.d.ts.map +1 -0
- package/dist/actionHelpers.js +73 -0
- package/dist/constructorExecution.d.ts +7 -0
- package/dist/constructorExecution.d.ts.map +1 -0
- package/dist/constructorExecution.js +149 -0
- package/dist/generateResponse.d.ts +14 -0
- package/dist/generateResponse.d.ts.map +1 -0
- package/dist/generateResponse.js +88 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/lib/fetch.d.ts +10 -0
- package/dist/lib/fetch.d.ts.map +1 -0
- package/dist/lib/fetch.js +68 -0
- package/dist/lib/hooks.d.ts +7 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +13 -0
- package/dist/lib/networkRequestsCache.d.ts +23 -0
- package/dist/lib/networkRequestsCache.d.ts.map +1 -0
- package/dist/lib/networkRequestsCache.js +81 -0
- package/dist/lib/networkRequestsHistory.d.ts +21 -0
- package/dist/lib/networkRequestsHistory.d.ts.map +1 -0
- package/dist/lib/networkRequestsHistory.js +119 -0
- package/dist/lib/time.d.ts +2 -0
- package/dist/lib/time.d.ts.map +1 -0
- package/dist/lib/time.js +31 -0
- package/dist/lib/utils.d.ts +46 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +208 -0
- package/dist/lib/zod.d.ts +35 -0
- package/dist/lib/zod.d.ts.map +1 -0
- package/dist/lib/zod.js +290 -0
- package/dist/loadUrl.d.ts +45 -0
- package/dist/loadUrl.d.ts.map +1 -0
- package/dist/loadUrl.js +111 -0
- package/dist/plugins/built-in-sources/bluesky/client.d.ts +11 -0
- package/dist/plugins/built-in-sources/bluesky/client.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/client.js +17 -0
- package/dist/plugins/built-in-sources/bluesky/index.d.ts +1115 -0
- package/dist/plugins/built-in-sources/bluesky/index.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/index.js +14 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/feed.d.ts +378 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/feed.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/feed.js +77 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/mediaSearch.d.ts +390 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/mediaSearch.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/mediaSearch.js +87 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/singleMedia.d.ts +351 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/singleMedia.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/requestHandlers/singleMedia.js +56 -0
- package/dist/plugins/built-in-sources/bluesky/shared.d.ts +53 -0
- package/dist/plugins/built-in-sources/bluesky/shared.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/shared.js +127 -0
- package/dist/plugins/built-in-sources/bluesky/types.d.ts +488 -0
- package/dist/plugins/built-in-sources/bluesky/types.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/bluesky/types.js +48 -0
- package/dist/plugins/built-in-sources/giphy/index.d.ts +584 -0
- package/dist/plugins/built-in-sources/giphy/index.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/giphy/index.js +9 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/mediaSearch.d.ts +310 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/mediaSearch.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/mediaSearch.js +71 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/singleMedia.d.ts +274 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/singleMedia.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/giphy/requestHandlers/singleMedia.js +43 -0
- package/dist/plugins/built-in-sources/giphy/shared.d.ts +24 -0
- package/dist/plugins/built-in-sources/giphy/shared.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/giphy/shared.js +30 -0
- package/dist/plugins/built-in-sources/giphy/types.d.ts +398 -0
- package/dist/plugins/built-in-sources/giphy/types.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/giphy/types.js +46 -0
- package/dist/plugins/built-in-sources/index.d.ts +1698 -0
- package/dist/plugins/built-in-sources/index.d.ts.map +1 -0
- package/dist/plugins/built-in-sources/index.js +5 -0
- package/dist/schemas/constructor.d.ts +14 -0
- package/dist/schemas/constructor.d.ts.map +1 -0
- package/dist/schemas/constructor.js +33 -0
- package/dist/schemas/file.d.ts +124 -0
- package/dist/schemas/file.d.ts.map +1 -0
- package/dist/schemas/file.js +28 -0
- package/dist/schemas/finderOptions.d.ts +389 -0
- package/dist/schemas/finderOptions.d.ts.map +1 -0
- package/dist/schemas/finderOptions.js +7 -0
- package/dist/schemas/media.d.ts +433 -0
- package/dist/schemas/media.d.ts.map +1 -0
- package/dist/schemas/media.js +81 -0
- package/dist/schemas/plugin.d.ts +298 -0
- package/dist/schemas/plugin.d.ts.map +1 -0
- package/dist/schemas/plugin.js +19 -0
- package/dist/schemas/primitives.d.ts +4 -0
- package/dist/schemas/primitives.d.ts.map +1 -0
- package/dist/schemas/primitives.js +11 -0
- package/dist/schemas/queryOptions.d.ts +19 -0
- package/dist/schemas/queryOptions.d.ts.map +1 -0
- package/dist/schemas/queryOptions.js +9 -0
- package/dist/schemas/request.d.ts +77 -0
- package/dist/schemas/request.d.ts.map +1 -0
- package/dist/schemas/request.js +21 -0
- package/dist/schemas/requestHandler.d.ts +126 -0
- package/dist/schemas/requestHandler.d.ts.map +1 -0
- package/dist/schemas/requestHandler.js +26 -0
- package/dist/schemas/response.d.ts +4673 -0
- package/dist/schemas/response.d.ts.map +1 -0
- package/dist/schemas/response.js +51 -0
- package/dist/schemas/secrets.d.ts +4 -0
- package/dist/schemas/secrets.d.ts.map +1 -0
- package/dist/schemas/secrets.js +2 -0
- package/dist/schemas/source.d.ts +202 -0
- package/dist/schemas/source.d.ts.map +1 -0
- package/dist/schemas/source.js +10 -0
- package/dist/test/fixtures/currentTimeSource.d.ts +53 -0
- package/dist/test/fixtures/currentTimeSource.d.ts.map +1 -0
- package/dist/test/fixtures/currentTimeSource.js +76 -0
- package/dist/test/fixtures/examplePlugin.d.ts +266 -0
- package/dist/test/fixtures/examplePlugin.d.ts.map +1 -0
- package/dist/test/fixtures/examplePlugin.js +4 -0
- package/dist/test/fixtures/exampleSource.d.ts +265 -0
- package/dist/test/fixtures/exampleSource.d.ts.map +1 -0
- package/dist/test/fixtures/exampleSource.js +107 -0
- package/dist/test/testFiles/internal/caching.test.d.ts +2 -0
- package/dist/test/testFiles/internal/caching.test.d.ts.map +1 -0
- package/dist/test/testFiles/internal/caching.test.js +116 -0
- package/dist/test/testFiles/internal/mediaTypeGuessing.test.d.ts +2 -0
- package/dist/test/testFiles/internal/mediaTypeGuessing.test.d.ts.map +1 -0
- package/dist/test/testFiles/internal/mediaTypeGuessing.test.js +86 -0
- package/dist/test/testFiles/sources/bluesky.test.d.ts +2 -0
- package/dist/test/testFiles/sources/bluesky.test.d.ts.map +1 -0
- package/dist/test/testFiles/sources/bluesky.test.js +40 -0
- package/dist/test/testFiles/sources/exampleSource.test.d.ts +2 -0
- package/dist/test/testFiles/sources/exampleSource.test.d.ts.map +1 -0
- package/dist/test/testFiles/sources/exampleSource.test.js +27 -0
- package/dist/test/testFiles/sources/giphy.test.d.ts +2 -0
- package/dist/test/testFiles/sources/giphy.test.d.ts.map +1 -0
- package/dist/test/testFiles/sources/giphy.test.js +17 -0
- package/dist/test/utils/general.d.ts +3 -0
- package/dist/test/utils/general.d.ts.map +1 -0
- package/dist/test/utils/general.js +24 -0
- package/dist/test/utils/globalSetup.d.ts +3 -0
- package/dist/test/utils/globalSetup.d.ts.map +1 -0
- package/dist/test/utils/globalSetup.js +12 -0
- package/dist/test/utils/vitest.d.ts +551 -0
- package/dist/test/utils/vitest.d.ts.map +1 -0
- package/dist/test/utils/vitest.js +166 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { ZodError, z } from "zod";
|
|
2
|
+
import { finderOptionsSchema } from "./schemas/finderOptions.js";
|
|
3
|
+
import { queryOptionsSchema, } from "./schemas/queryOptions.js";
|
|
4
|
+
import { genericRequestSchema, } from "./schemas/request.js";
|
|
5
|
+
import Liase from "./Liase.js";
|
|
6
|
+
import { generateResponse, getResponseDetailsBasedOnRequest, requestWithDefaults, } from "./generateResponse.js";
|
|
7
|
+
import { exportNetworkRequestsHistoryIfRelevantError } from "./lib/networkRequestsHistory.js";
|
|
8
|
+
import { FriendlyZodError } from "./lib/zod.js";
|
|
9
|
+
const propsSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
request: genericRequestSchema,
|
|
12
|
+
queryOptions: queryOptionsSchema.default({}),
|
|
13
|
+
finderOptions: finderOptionsSchema.default({}),
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
16
|
+
export default class LiaseQuery extends Liase {
|
|
17
|
+
#request;
|
|
18
|
+
#queryOptions;
|
|
19
|
+
#iterator;
|
|
20
|
+
constructor(props) {
|
|
21
|
+
let parsedProps;
|
|
22
|
+
try {
|
|
23
|
+
parsedProps = propsSchema.parse(props);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (err instanceof ZodError) {
|
|
27
|
+
const error = new FriendlyZodError(err, {
|
|
28
|
+
message: "Liase argument invalid",
|
|
29
|
+
inputData: props,
|
|
30
|
+
});
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
super(parsedProps.finderOptions);
|
|
36
|
+
this.#request = parsedProps.request;
|
|
37
|
+
this.#queryOptions = parsedProps.queryOptions;
|
|
38
|
+
this.#iterator = this.getIterator();
|
|
39
|
+
}
|
|
40
|
+
get request() {
|
|
41
|
+
return { ...this.#request };
|
|
42
|
+
}
|
|
43
|
+
get requestWithDefaults() {
|
|
44
|
+
const requestSchema = this.getRequestSchema();
|
|
45
|
+
return requestWithDefaults(this.#request, requestSchema);
|
|
46
|
+
}
|
|
47
|
+
set request(request) {
|
|
48
|
+
this.changeRequest(request);
|
|
49
|
+
}
|
|
50
|
+
changeRequest(request) {
|
|
51
|
+
this.rewind();
|
|
52
|
+
this.#request = genericRequestSchema.parse(request);
|
|
53
|
+
}
|
|
54
|
+
async getNext() {
|
|
55
|
+
const next = await this.#iterator.next();
|
|
56
|
+
if (next.done) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return next.value;
|
|
60
|
+
}
|
|
61
|
+
rewind() {
|
|
62
|
+
this.#iterator = this.getIterator();
|
|
63
|
+
}
|
|
64
|
+
[Symbol.asyncIterator] = this.getIterator;
|
|
65
|
+
async *getIterator() {
|
|
66
|
+
const handler = this.getRequestHandler();
|
|
67
|
+
const handlerSecretsSchema = handler.secretsSchema;
|
|
68
|
+
try {
|
|
69
|
+
if (handlerSecretsSchema) {
|
|
70
|
+
handlerSecretsSchema.parse(this.#queryOptions.secrets);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err instanceof ZodError) {
|
|
75
|
+
const error = new FriendlyZodError(err, {
|
|
76
|
+
message: "Secrets are invalid",
|
|
77
|
+
inputData: this.#queryOptions.secrets,
|
|
78
|
+
});
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
let pageFetchedCount = 0;
|
|
84
|
+
const maxPagesToFetch = this.#queryOptions.fetchCountLimit;
|
|
85
|
+
while (pageFetchedCount < maxPagesToFetch) {
|
|
86
|
+
pageFetchedCount++;
|
|
87
|
+
const parsedRequest = this.requestWithDefaults;
|
|
88
|
+
const parsedSecrets = handler.secretsSchema?.parse(this.#queryOptions.secrets) ?? {};
|
|
89
|
+
const pageFetchLimitReached = handler.paginationType === "none"
|
|
90
|
+
? undefined
|
|
91
|
+
: pageFetchedCount === maxPagesToFetch;
|
|
92
|
+
try {
|
|
93
|
+
const response = await generateResponse({
|
|
94
|
+
requestHandler: handler,
|
|
95
|
+
request: parsedRequest,
|
|
96
|
+
secrets: parsedSecrets,
|
|
97
|
+
responseDetails: this.getResponseDetails(),
|
|
98
|
+
pageFetchLimitReached,
|
|
99
|
+
cacheNetworkRequests: this.#queryOptions.cacheNetworkRequests,
|
|
100
|
+
sourceId: this.getSource(parsedRequest.source).id,
|
|
101
|
+
hooks: this._hooks,
|
|
102
|
+
});
|
|
103
|
+
if (handler.paginationType === "offset") {
|
|
104
|
+
// if paginationType is "offset" then pageNumber must exist due to a check in validateResponse
|
|
105
|
+
// in generateResponse.ts but hard to prove that to typescript so we just add an if statement here
|
|
106
|
+
// to stop typescript complaining
|
|
107
|
+
if (response.page && "pageNumber" in response.page) {
|
|
108
|
+
this.#request.pageNumber = response.page.pageNumber + 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (handler.paginationType === "cursor") {
|
|
112
|
+
// Same situation as in earlier if statement
|
|
113
|
+
if (response.page && "nextCursor" in response.page) {
|
|
114
|
+
this.#request.cursor = response.page.nextCursor;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
yield response;
|
|
118
|
+
if (handler.paginationType === "none") {
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (response.page?.isLastPage) {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
await exportNetworkRequestsHistoryIfRelevantError(error);
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
getRequestHandler() {
|
|
132
|
+
return super.getRequestHandler(this.#request.source, this.#request.queryType);
|
|
133
|
+
}
|
|
134
|
+
getRequestSchema() {
|
|
135
|
+
return super.getRequestSchema(this.#request.source, this.#request.queryType);
|
|
136
|
+
}
|
|
137
|
+
getResponseSchema() {
|
|
138
|
+
return this.getResponseDetails().schema;
|
|
139
|
+
}
|
|
140
|
+
getResponseDetails() {
|
|
141
|
+
const request = this.requestWithDefaults;
|
|
142
|
+
const responses = this.getRequestHandler().responses;
|
|
143
|
+
return getResponseDetailsBasedOnRequest(responses, request);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare function guessMediaInfoFromUrl<AdditionalValues extends {
|
|
2
|
+
[key: string]: unknown;
|
|
3
|
+
mimeType?: string;
|
|
4
|
+
ext?: string;
|
|
5
|
+
video?: boolean;
|
|
6
|
+
image?: boolean;
|
|
7
|
+
audio?: boolean;
|
|
8
|
+
}>(url: string, additionalValues?: AdditionalValues): {
|
|
9
|
+
url: string;
|
|
10
|
+
mimeType: string;
|
|
11
|
+
ext: string;
|
|
12
|
+
video: boolean;
|
|
13
|
+
image: boolean;
|
|
14
|
+
audio?: boolean;
|
|
15
|
+
} & AdditionalValues;
|
|
16
|
+
export declare function guessMediaInfoFromMimeType<AdditionalValues extends {
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
url?: string;
|
|
19
|
+
ext?: string;
|
|
20
|
+
video?: boolean;
|
|
21
|
+
image?: boolean;
|
|
22
|
+
audio?: boolean;
|
|
23
|
+
}>(mimeType: string, additionalValues?: AdditionalValues): {
|
|
24
|
+
mimeType: string;
|
|
25
|
+
ext: string;
|
|
26
|
+
video: boolean;
|
|
27
|
+
image: boolean;
|
|
28
|
+
audio?: boolean;
|
|
29
|
+
} & AdditionalValues;
|
|
30
|
+
//# sourceMappingURL=actionHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionHelpers.d.ts","sourceRoot":"","sources":["../src/actionHelpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,qBAAqB,CACnC,gBAAgB,SAAS;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,EAED,GAAG,EAAE,MAAM,EACX,gBAAgB,GAAE,gBAAyC,GAC1D;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,gBAAgB,CAsBnB;AAED,wBAAgB,0BAA0B,CACxC,gBAAgB,SAAS;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,EAED,QAAQ,EAAE,MAAM,EAChB,gBAAgB,GAAE,gBAAyC,GAC1D;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,gBAAgB,CAWnB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import mimeTypes from "mime-types";
|
|
2
|
+
export function guessMediaInfoFromUrl(url, additionalValues = {}) {
|
|
3
|
+
let ext = additionalValues?.ext || url.match(/\.(\w+)(?:\?[^?]*)?$/)?.[1];
|
|
4
|
+
let mimeType = additionalValues?.mimeType;
|
|
5
|
+
if (!mimeType && ext && typeof ext === "string") {
|
|
6
|
+
mimeType = mimeTypes.lookup(ext) || "";
|
|
7
|
+
}
|
|
8
|
+
else if (!ext && mimeType && typeof mimeType === "string") {
|
|
9
|
+
ext = mimeTypes.extension(mimeType) || "";
|
|
10
|
+
}
|
|
11
|
+
if (!ext || !mimeType) {
|
|
12
|
+
console.info(`url: ${url}\next: ${ext}\nmimeType: ${mimeType}`);
|
|
13
|
+
throw new Error("Couldn't derive file type");
|
|
14
|
+
}
|
|
15
|
+
const { video, image, audio } = guessBasicMediaType({ mimeType, ext });
|
|
16
|
+
return {
|
|
17
|
+
url,
|
|
18
|
+
ext,
|
|
19
|
+
mimeType,
|
|
20
|
+
video,
|
|
21
|
+
image,
|
|
22
|
+
audio,
|
|
23
|
+
...(additionalValues || {}),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function guessMediaInfoFromMimeType(mimeType, additionalValues = {}) {
|
|
27
|
+
const ext = mimeTypes.extension(mimeType) || "";
|
|
28
|
+
const { video, image, audio } = guessBasicMediaType({ mimeType, ext });
|
|
29
|
+
return {
|
|
30
|
+
ext,
|
|
31
|
+
mimeType,
|
|
32
|
+
video,
|
|
33
|
+
image,
|
|
34
|
+
audio,
|
|
35
|
+
...additionalValues,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function guessBasicMediaType({ mimeType, ext, }) {
|
|
39
|
+
const coreMimeType = mimeType?.split(";")[0].trim().toLowerCase() || "";
|
|
40
|
+
const coreExt = ext?.trim().toLowerCase() || "";
|
|
41
|
+
if (coreMimeType.startsWith("video/") ||
|
|
42
|
+
[
|
|
43
|
+
"application/x-mpegurl",
|
|
44
|
+
"application/vnd.apple.mpegurl",
|
|
45
|
+
"application/mp4",
|
|
46
|
+
"application/mpeg4-generic",
|
|
47
|
+
"application/dash+xml",
|
|
48
|
+
"application/dash-patch+xml",
|
|
49
|
+
].includes(coreMimeType) ||
|
|
50
|
+
coreExt === "gif") {
|
|
51
|
+
return {
|
|
52
|
+
video: true,
|
|
53
|
+
image: false,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (coreMimeType.startsWith("image/")) {
|
|
57
|
+
return {
|
|
58
|
+
video: false,
|
|
59
|
+
image: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (coreMimeType.startsWith("audio/")) {
|
|
63
|
+
return {
|
|
64
|
+
video: false,
|
|
65
|
+
image: false,
|
|
66
|
+
audio: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (["application/ogg"].includes(coreMimeType)) {
|
|
70
|
+
throw new Error(`Unable to determine type of media: ${mimeType || ext}`);
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`Resource does not appear to be media: ${mimeType || ext}`);
|
|
73
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ActionContext } from "./ActionContext.js";
|
|
2
|
+
import type { Action, Constructor, ConstructorObject } from "./schemas/constructor.js";
|
|
3
|
+
export declare function executeConstructor(constructorDef: Constructor, context: ActionContext): Promise<unknown>;
|
|
4
|
+
export declare function executeConstructorObject(constructorDef: ConstructorObject, context: ActionContext): Promise<unknown>;
|
|
5
|
+
export declare function executeConstructorArray(constructorDef: Array<Constructor>, context: ActionContext): Promise<Array<unknown>>;
|
|
6
|
+
export declare function executeActions(actions: Action[], context: ActionContext): Promise<ActionContext>;
|
|
7
|
+
//# sourceMappingURL=constructorExecution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constructorExecution.d.ts","sourceRoot":"","sources":["../src/constructorExecution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsB,MAAM,oBAAoB,CAAC;AAQvE,OAAO,KAAK,EACV,MAAM,EACN,WAAW,EACX,iBAAiB,EAClB,MAAM,0BAA0B,CAAC;AAIlC,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,WAAW,EAC3B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,iBAAiB,EACjC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,OAAO,CAAC,CA6ElB;AAED,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,EAClC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAiDzB;AA6BD,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,aAAa,CAAC,CAaxB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { ActionContext, excludeFieldSymbol } from "./ActionContext.js";
|
|
2
|
+
import { DomSelection } from "./DomSelection.js";
|
|
3
|
+
import { ConstructorExecutionError, formatObjectPath, getType, waitForAllPropertiesToResolve, } from "./lib/utils.js";
|
|
4
|
+
const log = [];
|
|
5
|
+
export async function executeConstructor(constructorDef, context) {
|
|
6
|
+
try {
|
|
7
|
+
if (!Array.isArray(constructorDef) &&
|
|
8
|
+
typeof constructorDef === "object" &&
|
|
9
|
+
!(constructorDef instanceof Date) &&
|
|
10
|
+
constructorDef !== null) {
|
|
11
|
+
return executeConstructorObject(constructorDef, context);
|
|
12
|
+
}
|
|
13
|
+
if (Array.isArray(constructorDef)) {
|
|
14
|
+
return executeConstructorArray(constructorDef, context);
|
|
15
|
+
}
|
|
16
|
+
if (typeof constructorDef === "function") {
|
|
17
|
+
return executeAction(constructorDef, context)
|
|
18
|
+
.then((context) => context.lastResult())
|
|
19
|
+
.then((result) => result instanceof DomSelection ? result.text : result);
|
|
20
|
+
}
|
|
21
|
+
return constructorDef;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
handleExecutionError(error, context);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function executeConstructorObject(constructorDef, context) {
|
|
28
|
+
let currentContext = context;
|
|
29
|
+
const topLevelPath = currentContext.path;
|
|
30
|
+
if (constructorDef._arrayMap) {
|
|
31
|
+
handleExecutionError(new Error(`Constructor with "_arrayMap" used outside of an array context`), currentContext.clone({ appendToPath: ["_arrayMap"] }));
|
|
32
|
+
}
|
|
33
|
+
if (constructorDef._setup) {
|
|
34
|
+
currentContext = await executeAction(constructorDef._setup, currentContext.clone({ path: [...topLevelPath, "_setup"] }));
|
|
35
|
+
}
|
|
36
|
+
const returnObject = {};
|
|
37
|
+
if (constructorDef._include) {
|
|
38
|
+
const resultContext = await executeAction(constructorDef._include, currentContext.clone({ path: [...topLevelPath, "_include"] }));
|
|
39
|
+
const resultValue = resultContext.get("");
|
|
40
|
+
if (resultValue.constructor !== Object) {
|
|
41
|
+
throw handleExecutionError(Error(`_include must return a plain object but instead received: ${getType(resultValue)}`), resultContext);
|
|
42
|
+
}
|
|
43
|
+
Object.assign(returnObject, resultValue);
|
|
44
|
+
// We don't want _include to override any value _setup has written to $.get('') but we do
|
|
45
|
+
// want to keep any values it has written to other non-'' keys.
|
|
46
|
+
currentContext = currentContext.clone({
|
|
47
|
+
data: { ...resultContext.getAll(), "": currentContext.get("") },
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const constructorReturnKeys = Object.fromEntries(Object.entries(constructorDef).filter(
|
|
51
|
+
// Filter out constructor instruction keys
|
|
52
|
+
([key]) => !key.match(/^_[^_]/)));
|
|
53
|
+
for (const key of Object.keys(constructorReturnKeys)) {
|
|
54
|
+
const value = constructorReturnKeys[key];
|
|
55
|
+
const newKey = key.replace(/^__/, "_"); // Unescape _ if starts with escaped _
|
|
56
|
+
returnObject[newKey] = executeConstructor(value, currentContext.clone({ path: [...topLevelPath, key] }));
|
|
57
|
+
}
|
|
58
|
+
const awaitedReturnObject = await waitForAllPropertiesToResolve(returnObject);
|
|
59
|
+
// Remove any fields/array elements who's value is the ExcludeField symbol
|
|
60
|
+
for (const key of Object.keys(awaitedReturnObject)) {
|
|
61
|
+
const value = awaitedReturnObject[key];
|
|
62
|
+
if (value === excludeFieldSymbol) {
|
|
63
|
+
delete awaitedReturnObject[key];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return awaitedReturnObject;
|
|
67
|
+
}
|
|
68
|
+
export async function executeConstructorArray(constructorDef, context) {
|
|
69
|
+
const resultArray = [];
|
|
70
|
+
for (const [i, element] of constructorDef.entries()) {
|
|
71
|
+
const elementContext = context.clone({ appendToPath: [i] });
|
|
72
|
+
// If valueElement is a constructor with a _arrayMap property, get the array returned by _arrayMap and
|
|
73
|
+
// loop over each element
|
|
74
|
+
if (!Array.isArray(element) &&
|
|
75
|
+
typeof element === "object" &&
|
|
76
|
+
!(element instanceof Date) &&
|
|
77
|
+
element !== null &&
|
|
78
|
+
element._arrayMap) {
|
|
79
|
+
const { _arrayMap, ...constructorWithoutArrayMap } = element;
|
|
80
|
+
const arrayMapContext = await executeAction(_arrayMap, elementContext.clone({ appendToPath: ["_arrayMap"] }));
|
|
81
|
+
let elementsToMap;
|
|
82
|
+
const data = arrayMapContext.get();
|
|
83
|
+
if (Array.isArray(data)) {
|
|
84
|
+
elementsToMap = data;
|
|
85
|
+
}
|
|
86
|
+
else if (data instanceof DomSelection) {
|
|
87
|
+
elementsToMap = data.selectedNodes;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
throw handleExecutionError(new Error(`_arrayMap must return either an array or a DomSelection but instead returned:\n${data}`), arrayMapContext);
|
|
91
|
+
}
|
|
92
|
+
for (const elementToMap of elementsToMap) {
|
|
93
|
+
resultArray.push(executeConstructorObject(constructorWithoutArrayMap, elementContext.clone().set("", elementToMap)));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
resultArray.push(executeConstructor(element, elementContext));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const awaitedReturnArray = await Promise.all(resultArray);
|
|
101
|
+
// Remove any array elements who's value is the ExcludeField symbol
|
|
102
|
+
return awaitedReturnArray.filter((element) => element !== excludeFieldSymbol);
|
|
103
|
+
}
|
|
104
|
+
async function executeAction(action, context) {
|
|
105
|
+
log.push(`Executing action for ${formatObjectPath(context.path)}`);
|
|
106
|
+
// Actions can be run in parallel and we don't want the execution of one action to modify the context
|
|
107
|
+
// object and non-deterministically effect the execution of a different action
|
|
108
|
+
let currentContext = context.clone();
|
|
109
|
+
try {
|
|
110
|
+
const result = await action(currentContext);
|
|
111
|
+
if (result instanceof ActionContext) {
|
|
112
|
+
// Needed for .chain() to be able to update context by returning cloned context
|
|
113
|
+
currentContext = result;
|
|
114
|
+
currentContext.recordResult(undefined);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
currentContext.recordResult(result);
|
|
118
|
+
}
|
|
119
|
+
if (typeof currentContext.lastResult() !== "undefined") {
|
|
120
|
+
currentContext.set("", currentContext.lastResult());
|
|
121
|
+
}
|
|
122
|
+
await currentContext.waitForAllPromisesToResolve();
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
handleExecutionError(error, currentContext);
|
|
126
|
+
}
|
|
127
|
+
return currentContext;
|
|
128
|
+
}
|
|
129
|
+
export async function executeActions(actions, context) {
|
|
130
|
+
const parentPath = context.path.slice(0, -1);
|
|
131
|
+
const lastPathSegment = context.path[context.path.length - 1];
|
|
132
|
+
let currentContext = context;
|
|
133
|
+
for (const [i, action] of actions.entries()) {
|
|
134
|
+
currentContext = await executeAction(action, currentContext.clone({
|
|
135
|
+
path: [...parentPath, `${lastPathSegment} (chain step ${i + 1})`],
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
return currentContext;
|
|
139
|
+
}
|
|
140
|
+
function handleExecutionError(error, actionContext) {
|
|
141
|
+
if (error instanceof ConstructorExecutionError) {
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
throw new ConstructorExecutionError({
|
|
145
|
+
cause: error instanceof Error ? error : undefined,
|
|
146
|
+
actionContext,
|
|
147
|
+
log,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { GenericRequest } from "./schemas/request.js";
|
|
3
|
+
import type { RequestHandler, requestHandlerSchema } from "./schemas/requestHandler.js";
|
|
4
|
+
import { type GenericResponse } from "./schemas/response.js";
|
|
5
|
+
import type { ConstructorExecutionContext } from "./types.js";
|
|
6
|
+
export declare function generateResponse(constructorContext: ConstructorExecutionContext): Promise<GenericResponse>;
|
|
7
|
+
export declare function getResponseDetailsBasedOnRequest(responses: RequestHandler["responses"], request: GenericRequest): {
|
|
8
|
+
schema: z.AnyZodObject;
|
|
9
|
+
description?: string | undefined;
|
|
10
|
+
requestMatcher?: z.AnyZodObject | undefined;
|
|
11
|
+
constructor?: import("./index.js").Constructor;
|
|
12
|
+
};
|
|
13
|
+
export declare function requestWithDefaults(request: GenericRequest, requestSchema: z.infer<typeof requestHandlerSchema.shape.requestSchema>): GenericRequest;
|
|
14
|
+
//# sourceMappingURL=generateResponse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateResponse.d.ts","sourceRoot":"","sources":["../src/generateResponse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D,wBAAsB,gBAAgB,CACpC,kBAAkB,EAAE,2BAA2B,GAC9C,OAAO,CAAC,eAAe,CAAC,CAoB1B;AA0DD,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,cAAc,CAAC,WAAW,CAAC,EACtC,OAAO,EAAE,cAAc;;;;;EAgBxB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,KAAK,CAAC,aAAa,CAAC,GACtE,cAAc,CAahB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { ActionContext } from "./ActionContext.js";
|
|
4
|
+
import { executeActions, executeConstructor } from "./constructorExecution.js";
|
|
5
|
+
import { FriendlyZodError, zodParseOrThrow } from "./lib/zod.js";
|
|
6
|
+
import { genericResponseSchema, } from "./schemas/response.js";
|
|
7
|
+
export async function generateResponse(constructorContext) {
|
|
8
|
+
// If the requestHandler's requestSchema sets any defaults add them to the request
|
|
9
|
+
const resolvedContext = {
|
|
10
|
+
...constructorContext,
|
|
11
|
+
request: requestWithDefaults(constructorContext.request, constructorContext.requestHandler.requestSchema),
|
|
12
|
+
};
|
|
13
|
+
Error.stackTraceLimit = 50;
|
|
14
|
+
const rootActionContext = new ActionContext({
|
|
15
|
+
constructorContext: resolvedContext,
|
|
16
|
+
executeActions,
|
|
17
|
+
path: [],
|
|
18
|
+
});
|
|
19
|
+
const res = await executeConstructor(resolvedContext.responseDetails.constructor, rootActionContext);
|
|
20
|
+
return await validateResponse(res, resolvedContext, rootActionContext);
|
|
21
|
+
}
|
|
22
|
+
async function validateResponse(
|
|
23
|
+
// biome-ignore lint/suspicious/noExplicitAny: dynamic response object validated by zod
|
|
24
|
+
response, constructorContext, rootActionContext) {
|
|
25
|
+
const errorMessage = `The response returned from the request handler "${constructorContext.requestHandler.id}" of the source "${constructorContext.sourceId}" is invalid`;
|
|
26
|
+
const parsedResponse = zodParseOrThrow(genericResponseSchema, response, {
|
|
27
|
+
errorMessage,
|
|
28
|
+
context: rootActionContext,
|
|
29
|
+
});
|
|
30
|
+
zodParseOrThrow(constructorContext.responseDetails.schema, response, {
|
|
31
|
+
errorMessage,
|
|
32
|
+
context: rootActionContext,
|
|
33
|
+
});
|
|
34
|
+
assert.deepEqual(constructorContext.request, parsedResponse.request);
|
|
35
|
+
for (const [index, media] of Object.entries(parsedResponse.media)) {
|
|
36
|
+
if (media.mediaFinderSource !== constructorContext.sourceId) {
|
|
37
|
+
throw Error(`Request was for source ${constructorContext.sourceId} but media number ${index} ` +
|
|
38
|
+
`has source set to ${media.mediaFinderSource}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (constructorContext.requestHandler.paginationType !== "none") {
|
|
42
|
+
if (!parsedResponse.page) {
|
|
43
|
+
throw Error(`Request was for a ${constructorContext.requestHandler.paginationType} page but response has no page`);
|
|
44
|
+
}
|
|
45
|
+
if (constructorContext.requestHandler.paginationType !==
|
|
46
|
+
parsedResponse.page?.paginationType) {
|
|
47
|
+
throw Error(`Request was for a ${constructorContext.requestHandler.paginationType} page but response page type was ${parsedResponse.page.paginationType}`);
|
|
48
|
+
}
|
|
49
|
+
assert.equal(constructorContext.pageFetchLimitReached, parsedResponse.page.pageFetchLimitReached);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
if (parsedResponse.page) {
|
|
53
|
+
throw Error("has page");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return parsedResponse;
|
|
57
|
+
}
|
|
58
|
+
export function getResponseDetailsBasedOnRequest(responses, request) {
|
|
59
|
+
const response = responses.find((response) => {
|
|
60
|
+
if (response.requestMatcher) {
|
|
61
|
+
const { success } = response.requestMatcher.safeParse(request);
|
|
62
|
+
if (success) {
|
|
63
|
+
return response;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
return response;
|
|
68
|
+
});
|
|
69
|
+
if (!response) {
|
|
70
|
+
throw Error("Could not find matching response details");
|
|
71
|
+
}
|
|
72
|
+
return response;
|
|
73
|
+
}
|
|
74
|
+
export function requestWithDefaults(request, requestSchema) {
|
|
75
|
+
try {
|
|
76
|
+
return requestSchema.parse(request);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (err instanceof z.ZodError) {
|
|
80
|
+
const error = new FriendlyZodError(err, {
|
|
81
|
+
message: "Request is invalid",
|
|
82
|
+
inputData: request,
|
|
83
|
+
});
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import LiaseQuery, { type LiaseQueryProps } from "./LiaseQuery.js";
|
|
2
|
+
export { default as Liase } from "./Liase.js";
|
|
3
|
+
export { default as LiaseQuery } from "./LiaseQuery.js";
|
|
4
|
+
export declare function createLiaseQuery(props: LiaseQueryProps): LiaseQuery;
|
|
5
|
+
export type { GenericMedia } from "./schemas/media.js";
|
|
6
|
+
export type { GenericRequest } from "./schemas/request.js";
|
|
7
|
+
export type { GenericResponse } from "./schemas/response.js";
|
|
8
|
+
export type { GenericFile } from "./schemas/file.js";
|
|
9
|
+
export type { Source } from "./schemas/source.js";
|
|
10
|
+
export type { Plugin } from "./schemas/plugin.js";
|
|
11
|
+
export type { RequestHandler } from "./schemas/requestHandler.js";
|
|
12
|
+
export type { Constructor } from "./schemas/constructor.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAExD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,UAAU,CAEnE;AAED,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,YAAY,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type ParsedFetchArgs = {
|
|
2
|
+
url: URL;
|
|
3
|
+
method: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
body: string | Promise<string>;
|
|
6
|
+
};
|
|
7
|
+
export declare function parseFetchArgs(input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): ParsedFetchArgs;
|
|
8
|
+
export declare function headersToNormalisedBasicObject(headers: globalThis.Headers | string[][] | Record<string, string | string[] | readonly string[] | undefined>): Record<string, string>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/lib/fetch.ts"],"names":[],"mappings":"AAAA,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,cAAc,CAC5B,KAAK,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAClC,IAAI,CAAC,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GACjC,eAAe,CA8CjB;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EACH,UAAU,CAAC,OAAO,GAClB,MAAM,EAAE,EAAE,GACV,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,GAchE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAC5B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function parseFetchArgs(input, init) {
|
|
2
|
+
let url;
|
|
3
|
+
let body;
|
|
4
|
+
let headers;
|
|
5
|
+
let method;
|
|
6
|
+
if (typeof input === "string" || input instanceof URL) {
|
|
7
|
+
url = input instanceof URL ? input : new URL(input);
|
|
8
|
+
if (!init || !init.body) {
|
|
9
|
+
body = "";
|
|
10
|
+
}
|
|
11
|
+
else if (init.body instanceof URLSearchParams) {
|
|
12
|
+
body = init.body.toString();
|
|
13
|
+
}
|
|
14
|
+
else if (init.body instanceof FormData) {
|
|
15
|
+
body = init.body.toString();
|
|
16
|
+
}
|
|
17
|
+
else if (init.body instanceof ArrayBuffer) {
|
|
18
|
+
body = new TextDecoder().decode(init.body);
|
|
19
|
+
}
|
|
20
|
+
else if (ArrayBuffer.isView(init.body)) {
|
|
21
|
+
body = new TextDecoder().decode(init.body);
|
|
22
|
+
}
|
|
23
|
+
else if (init.body instanceof Blob) {
|
|
24
|
+
body = init.body.text();
|
|
25
|
+
}
|
|
26
|
+
else if (init.body instanceof ReadableStream) {
|
|
27
|
+
body = new Response(init.body).text();
|
|
28
|
+
}
|
|
29
|
+
else if (typeof init.body === "object") {
|
|
30
|
+
throw Error("Only string, URLSearchParams, FormData, ArrayBuffer, ArrayBufferView, Blob, and ReadableStream type bodies are currently supported. Sorry!");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
body = init.body;
|
|
34
|
+
}
|
|
35
|
+
headers = headersToNormalisedBasicObject(init?.headers ?? {});
|
|
36
|
+
method = init?.method ?? "";
|
|
37
|
+
}
|
|
38
|
+
else if (input instanceof Request) {
|
|
39
|
+
const clonedRequest = input.clone();
|
|
40
|
+
url = new URL(clonedRequest.url);
|
|
41
|
+
body = clonedRequest.text();
|
|
42
|
+
headers = headersToNormalisedBasicObject(clonedRequest.headers);
|
|
43
|
+
method = clonedRequest.method;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
input;
|
|
47
|
+
throw Error("Input is invalid");
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
url,
|
|
51
|
+
body,
|
|
52
|
+
headers,
|
|
53
|
+
method,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function headersToNormalisedBasicObject(headers) {
|
|
57
|
+
let entries;
|
|
58
|
+
if (Array.isArray(headers)) {
|
|
59
|
+
entries = headers;
|
|
60
|
+
}
|
|
61
|
+
else if (headers instanceof global.Headers) {
|
|
62
|
+
entries = [...headers.entries()];
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
entries = Object.entries(headers);
|
|
66
|
+
}
|
|
67
|
+
return Object.fromEntries(entries.map((entry) => [entry[0].toLocaleLowerCase(), entry[1]]));
|
|
68
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type Hook = (input: any, next: (output: any) => any) => any;
|
|
2
|
+
export type LiaseHooks = {
|
|
3
|
+
loadUrl: Array<Hook>;
|
|
4
|
+
getFetchClient: Array<Hook>;
|
|
5
|
+
};
|
|
6
|
+
export declare function executeHooks(input: any, hooks: Array<Hook>): Promise<any>;
|
|
7
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/lib/hooks.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,CAAC;AAEnE,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACrB,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;CAC7B,CAAC;AAGF,wBAAsB,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,gBAWhE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// biome-ignore lint/suspicious/noExplicitAny: hooks pipeline passes arbitrary data between middleware
|
|
2
|
+
export async function executeHooks(input, hooks) {
|
|
3
|
+
const hooksIterator = hooks.values();
|
|
4
|
+
// biome-ignore lint/suspicious/noExplicitAny: hooks pipeline passes arbitrary data between middleware
|
|
5
|
+
async function runNextHook(input) {
|
|
6
|
+
const nextHook = hooksIterator.next().value;
|
|
7
|
+
if (!nextHook) {
|
|
8
|
+
return input;
|
|
9
|
+
}
|
|
10
|
+
return nextHook(await input, runNextHook);
|
|
11
|
+
}
|
|
12
|
+
return await runNextHook(await input);
|
|
13
|
+
}
|