@toa.io/origin 1.12.0 → 1.14.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/dist/index.cjs +19 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +19 -8
- package/dist/index.js.map +1 -1
- package/package.json +16 -16
- package/source/Agent.ts +4 -2
- package/source/Events.ts +5 -1
- package/source/Resource.ts +25 -10
package/dist/index.cjs
CHANGED
|
@@ -58,9 +58,10 @@ var Agent = class {
|
|
|
58
58
|
const options = this.setup(init);
|
|
59
59
|
const response = await this.request(path, options);
|
|
60
60
|
const body = response.headers.get("content-type") === "application/json" ? await response.json() : await response.text();
|
|
61
|
-
if (response.ok)
|
|
61
|
+
if (response.ok) {
|
|
62
|
+
this.events.emit("response", { status: response.status, headers: response.headers });
|
|
62
63
|
return body;
|
|
63
|
-
else {
|
|
64
|
+
} else {
|
|
64
65
|
this.events.emit("error", { code: response.status, body });
|
|
65
66
|
return new import_error_value.Err(response.status, body);
|
|
66
67
|
}
|
|
@@ -148,18 +149,28 @@ var Resource = class {
|
|
|
148
149
|
this.init = options.init;
|
|
149
150
|
}
|
|
150
151
|
async json(relOrInit, init) {
|
|
151
|
-
|
|
152
|
-
init = typeof relOrInit === "string" ? init : relOrInit;
|
|
153
|
-
const abs = this.abs(rel);
|
|
154
|
-
const options = Object.assign({}, this.init, init);
|
|
155
|
-
return await this.agent.json(abs, options);
|
|
152
|
+
return await this.request("json", relOrInit, init);
|
|
156
153
|
}
|
|
157
154
|
async octets(relOrInit, init) {
|
|
155
|
+
return await this.request("octets", relOrInit, init);
|
|
156
|
+
}
|
|
157
|
+
async multipart(relOrInit, init) {
|
|
158
|
+
return await this.request("multipart", relOrInit, init);
|
|
159
|
+
}
|
|
160
|
+
async request(method, relOrInit, init) {
|
|
158
161
|
const rel = typeof relOrInit === "string" ? relOrInit : "";
|
|
159
162
|
init = typeof relOrInit === "string" ? init : relOrInit;
|
|
160
163
|
const abs = this.abs(rel);
|
|
161
164
|
const options = Object.assign({}, this.init, init);
|
|
162
|
-
|
|
165
|
+
if (options.body !== void 0 && options.method === void 0)
|
|
166
|
+
options.method = "POST";
|
|
167
|
+
if (method === "json")
|
|
168
|
+
return await this.agent.json(abs, options);
|
|
169
|
+
else if (method === "octets")
|
|
170
|
+
return await this.agent.octets(abs, options);
|
|
171
|
+
else if (method === "multipart")
|
|
172
|
+
return await this.agent.multipart(abs, options);
|
|
173
|
+
else throw new Error(`Invalid method: ${method}`);
|
|
163
174
|
}
|
|
164
175
|
abs(rel) {
|
|
165
176
|
const base = new URL(this.path, "uri://void");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../source/index.ts","../source/Origin.ts","../source/Agent.ts","../source/Resource.ts","../source/criteria/range.ts","../source/criteria/index.ts","../source/query.ts"],"sourcesContent":["export { connect, type Origin } from './Origin'\nexport { query } from './query'\nexport type { GenericError } from './Error'\nexport type { OctetsEntry, WorkflowStep } from './Octets'\nexport type { Resource } from './Resource'\nexport type { RequestOptions } from './Agent'\n","import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\nimport type { RequestOptions } from './Agent'\nimport type { Events } from './Events'\nimport type { Emitter } from 'mitt'\n\n/** Resoruce factory */\nclass Origin {\n public readonly events: Emitter<Events>\n private readonly agent: Agent\n\n constructor(options: Options) {\n this.events = mitt<Events>()\n\n this.agent = new Agent({\n origin: options.origin,\n events: this.events,\n sleep: options.sleep,\n })\n }\n\n public resource<T = unknown>(path: string, init?: Partial<RequestOptions>) {\n return new Resource<T>({\n agent: this.agent,\n path,\n init,\n })\n }\n\n public authenticate(challenge: string | null) {\n this.agent.authenticate(challenge)\n }\n\n public use(fetch: Fetch) {\n this.agent.use(fetch)\n }\n}\n\nfunction connect(options: Options | string) {\n if (typeof options === 'string')\n options = { origin: options }\n\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n sleep?: [number, number]\n}\n\ntype Fetch = typeof fetch\n\nexport { connect, type Origin }\n","import { Err } from 'error-value'\nimport { meros } from 'meros/browser'\nimport mitt from 'mitt'\nimport type { GenericError } from './Error'\nimport type { Events } from './Events'\nimport type { Faulty, OctetsEntry, WorkflowStep } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Agent {\n private readonly origin: string\n private readonly events: Emitter<Events>\n private sleep?: string\n private fetch: Fetch = fetch\n\n private challenge: string | null = null\n\n constructor(options: Options) {\n this.origin = options.origin\n this.events = options.events\n\n if (options.sleep !== undefined)\n this.sleep = JSON.stringify(options.sleep)\n }\n\n public async json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n const body = response.headers.get('content-type') === 'application/json'\n ? await response.json()\n : await response.text()\n\n if (response.ok)\n return body as T\n else {\n this.events.emit('error', { code: response.status, body })\n\n return new Err(response.status, body) as E\n }\n }\n\n public async multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n if (!response.ok)\n return new Err(response.status, await response.json())\n\n const generator = await meros(response) as AsyncGenerator<{ body: string }>\n const ack = await generator.next()\n\n if (JSON.parse(ack.value.body) !== 'ACK') throw new Error('No ACK')\n\n return (async function * () {\n for await (const chunk of generator) {\n const value = JSON.parse(chunk.body)\n\n if (value === 'FIN') return\n\n yield value\n }\n })()\n }\n\n public async octets<\n T extends Record<string, unknown> = Record<string, unknown>,\n E extends GenericError = GenericError\n >(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {\n const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)\n\n if (generator instanceof Error) return generator as E\n\n const chunk = await generator.next()\n const entry = chunk.value as OctetsEntry\n const emitter = mitt<Faulty<T>>()\n\n void (async () => {\n for await (const part of (generator as AsyncGenerator<WorkflowStep>)) {\n const payload =\n part.status === 'completed'\n ? part.error\n ? new Err(part.error.code ?? 'UNKNOWN', part.error.message)\n : part.output\n : new Err('EXCEPTION')\n\n emitter.emit(part.step, payload as T[typeof part.step])\n }\n\n emitter.off('*')\n })()\n\n return [entry, emitter]\n }\n\n public authenticate(challenge: string | null) {\n this.challenge = challenge\n }\n\n public use(fetch: Fetch) {\n this.fetch = fetch\n }\n\n private setup(init?: RequestOptions): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\n\n if (this.sleep !== undefined)\n init.headers['sleep'] = this.sleep\n\n if (init.credentials === 'include' && init.headers['authorization'] === undefined) {\n if (this.challenge === null)\n throw new Error('Credentials must be set before sending authenticated request')\n\n init.headers['authorization'] = this.challenge\n delete init.credentials // no cookies\n }\n\n if (init.body !== undefined)\n if (init.body instanceof File || init.body instanceof ReadableStream) {\n init.method ??= 'POST'\n init.duplex = 'half'\n init.headers['content-type'] ??= (init.body as File).type ?? 'application/octet-stream'\n } else {\n init.body = JSON.stringify(init.body)\n init.headers['content-type'] ??= 'application/json'\n }\n\n return init as InitWithHeaders\n }\n\n private async request(path: string, init: RequestOptions): Promise<Response> {\n const url = new URL(path, this.origin)\n const response = await this.fetch(url.href, init)\n\n const challenge = response.headers.get('authorization')\n\n if (challenge !== null) {\n this.challenge = challenge\n this.events.emit('challenge', challenge)\n }\n\n return response\n }\n}\n\ninterface Options {\n origin: string\n events: Emitter<Events>\n sleep?: [number, number]\n}\n\ninterface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends RequestOptions {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { RequestOptions }\n","import type { Agent, RequestOptions } from './Agent'\nimport type { GenericError } from './Error'\nimport type { Faulty, OctetsEntry } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Resource<T = unknown, E extends GenericError = GenericError> {\n private readonly agent: Agent\n private readonly path: string\n private readonly init?: Partial<RequestOptions>\n\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n this.init = options.init\n }\n\n public async json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F> {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n return await this.agent.json<R, F>(abs, options)\n }\n\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n return await this.agent.octets<T, F>(abs, options)\n }\n\n private abs(rel: string): string {\n const base = new URL(this.path, 'uri://void')\n const url = new URL(rel, base)\n\n // Allows to use resource.json(id) instead of resource.json(id + '/')\n if (!url.pathname.endsWith('/'))\n url.pathname += '/'\n\n return url.pathname + url.search\n }\n}\n\ninterface Options {\n agent: Agent\n path: string\n init?: Partial<RequestOptions>\n}\n\nexport { Resource }\n","/**\n *\n * @example\n * [10..20]\n * [10..20)\n * (10..20]\n * (10..20)\n */\nexport function test(value: string): boolean {\n return /^[[(]\\d+\\.\\.\\d+[\\])]{1}$/.test(value)\n}\n\nexport function format(name: string, value: string): string[] {\n const [min, max] = value.slice(1, -1).split('..')\n\n return [\n `${name}${value.startsWith('(') ? '>' : '>='}${min}`,\n `${name}${value.endsWith(')') ? '<' : '<='}${max}`,\n ]\n}\n","import * as range from './range'\nimport type { Format } from './Format'\n\nconst formats: Format[] = [range]\n\nexport { formats }\n","import { formats } from './criteria'\n\nfunction query(params?: URLSearchParams, options?: Options): string {\n if (params === undefined) return ''\n\n const parts: string[] = []\n const criteria: string[] = []\n\n for (const [key, value] of params.entries()) {\n const name = options?.map?.[key] ?? key\n\n if (SEPARATE.includes(name) || options?.separate?.includes(name) === true)\n parts.push(`${name}=${value}`)\n else {\n const format = formats.find((format) => format.test(value))\n\n if (format === undefined)\n criteria.push(`${name}==${value}`)\n else\n criteria.push(...format.format(name, value))\n }\n }\n\n if (criteria.length > 0)\n parts.unshift(`criteria=${criteria.join(';')}`)\n\n return parts.length === 0\n ? ''\n : '?' + parts.join('&')\n}\n\nconst SEPARATE: string[] = ['omit', 'limit', 'search'] as const\n\ninterface Options {\n separate?: string[]\n map?: Record<string, string>\n}\n\nexport { query }\n"],"mappings":"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","names":["import_mitt","mitt","fetch","mitt","fetch","format"]}
|
|
1
|
+
{"version":3,"sources":["../source/index.ts","../source/Origin.ts","../source/Agent.ts","../source/Resource.ts","../source/criteria/range.ts","../source/criteria/index.ts","../source/query.ts"],"sourcesContent":["export { connect, type Origin } from './Origin'\nexport { query } from './query'\nexport type { GenericError } from './Error'\nexport type { OctetsEntry, WorkflowStep } from './Octets'\nexport type { Resource } from './Resource'\nexport type { RequestOptions } from './Agent'\n","import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\nimport type { RequestOptions } from './Agent'\nimport type { Events } from './Events'\nimport type { Emitter } from 'mitt'\n\n/** Resoruce factory */\nclass Origin {\n public readonly events: Emitter<Events>\n private readonly agent: Agent\n\n constructor(options: Options) {\n this.events = mitt<Events>()\n\n this.agent = new Agent({\n origin: options.origin,\n events: this.events,\n sleep: options.sleep,\n })\n }\n\n public resource<T = unknown>(path: string, init?: Partial<RequestOptions>) {\n return new Resource<T>({\n agent: this.agent,\n path,\n init,\n })\n }\n\n public authenticate(challenge: string | null) {\n this.agent.authenticate(challenge)\n }\n\n public use(fetch: Fetch) {\n this.agent.use(fetch)\n }\n}\n\nfunction connect(options: Options | string) {\n if (typeof options === 'string')\n options = { origin: options }\n\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n sleep?: [number, number]\n}\n\ntype Fetch = typeof fetch\n\nexport { connect, type Origin }\n","import { Err } from 'error-value'\nimport { meros } from 'meros/browser'\nimport mitt from 'mitt'\nimport type { GenericError } from './Error'\nimport type { Events } from './Events'\nimport type { Faulty, OctetsEntry, WorkflowStep } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Agent {\n private readonly origin: string\n private readonly events: Emitter<Events>\n private sleep?: string\n private fetch: Fetch = fetch\n\n private challenge: string | null = null\n\n constructor(options: Options) {\n this.origin = options.origin\n this.events = options.events\n\n if (options.sleep !== undefined)\n this.sleep = JSON.stringify(options.sleep)\n }\n\n public async json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n const body = response.headers.get('content-type') === 'application/json'\n ? await response.json()\n : await response.text()\n\n if (response.ok) {\n this.events.emit('response', { status: response.status, headers: response.headers })\n\n return body as T\n } else {\n this.events.emit('error', { code: response.status, body })\n\n return new Err(response.status, body) as E\n }\n }\n\n public async multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n if (!response.ok)\n return new Err(response.status, await response.json())\n\n const generator = await meros(response) as AsyncGenerator<{ body: string }>\n const ack = await generator.next()\n\n if (JSON.parse(ack.value.body) !== 'ACK') throw new Error('No ACK')\n\n return (async function * () {\n for await (const chunk of generator) {\n const value = JSON.parse(chunk.body)\n\n if (value === 'FIN') return\n\n yield value\n }\n })()\n }\n\n public async octets<\n T extends Record<string, unknown> = Record<string, unknown>,\n E extends GenericError = GenericError\n >(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {\n const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)\n\n if (generator instanceof Error) return generator as E\n\n const chunk = await generator.next()\n const entry = chunk.value as OctetsEntry\n const emitter = mitt<Faulty<T>>()\n\n void (async () => {\n for await (const part of (generator as AsyncGenerator<WorkflowStep>)) {\n const payload =\n part.status === 'completed'\n ? part.error\n ? new Err(part.error.code ?? 'UNKNOWN', part.error.message)\n : part.output\n : new Err('EXCEPTION')\n\n emitter.emit(part.step, payload as T[typeof part.step])\n }\n\n emitter.off('*')\n })()\n\n return [entry, emitter]\n }\n\n public authenticate(challenge: string | null) {\n this.challenge = challenge\n }\n\n public use(fetch: Fetch) {\n this.fetch = fetch\n }\n\n private setup(init?: RequestOptions): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\n\n if (this.sleep !== undefined)\n init.headers['sleep'] = this.sleep\n\n if (init.credentials === 'include' && init.headers['authorization'] === undefined) {\n if (this.challenge === null)\n throw new Error('Credentials must be set before sending authenticated request')\n\n init.headers['authorization'] = this.challenge\n delete init.credentials // no cookies\n }\n\n if (init.body !== undefined)\n if (init.body instanceof File || init.body instanceof ReadableStream) {\n init.method ??= 'POST'\n init.duplex = 'half'\n init.headers['content-type'] ??= (init.body as File).type ?? 'application/octet-stream'\n } else {\n init.body = JSON.stringify(init.body)\n init.headers['content-type'] ??= 'application/json'\n }\n\n return init as InitWithHeaders\n }\n\n private async request(path: string, init: RequestOptions): Promise<Response> {\n const url = new URL(path, this.origin)\n const response = await this.fetch(url.href, init)\n\n const challenge = response.headers.get('authorization')\n\n if (challenge !== null) {\n this.challenge = challenge\n this.events.emit('challenge', challenge)\n }\n\n return response\n }\n}\n\ninterface Options {\n origin: string\n events: Emitter<Events>\n sleep?: [number, number]\n}\n\ninterface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends RequestOptions {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { RequestOptions }\n","import type { Agent, RequestOptions } from './Agent'\nimport type { GenericError } from './Error'\nimport type { Faulty, OctetsEntry } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Resource<T = unknown, E extends GenericError = GenericError> {\n private readonly agent: Agent\n private readonly path: string\n private readonly init?: Partial<RequestOptions>\n\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n this.init = options.init\n }\n\n public async json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F> {\n return await this.request<R, F>('json', relOrInit, init)\n }\n\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F> {\n return await this.request<R, F>('octets', relOrInit, init)\n }\n\n public async multipart<R = unknown, F extends E = E>(init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n public async multipart<R = unknown, F extends E = E>(rel: string, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n public async multipart<R = unknown, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F> {\n return await this.request<R, F>('multipart', relOrInit, init)\n }\n\n private async request<R, F extends E>(method: 'json', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F>\n private async request<R extends Record<string, unknown>, F extends E = E>(method: 'octets', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n private async request<R, F extends E = E>(method: 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n private async request<R extends T, F extends E = E>(method: 'json' | 'octets' | 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions) {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n if (options.body !== undefined && options.method === undefined)\n options.method = 'POST'\n\n if (method === 'json')\n return await this.agent.json<R, F>(abs, options)\n else if (method === 'octets')\n return await this.agent.octets<Record<string, unknown>, F>(abs, options)\n else if (method === 'multipart')\n return await this.agent.multipart<R>(abs, options)\n else throw new Error(`Invalid method: ${method}`)\n }\n\n private abs(rel: string): string {\n const base = new URL(this.path, 'uri://void')\n const url = new URL(rel, base)\n\n // Allows to use resource.json(id) instead of resource.json(id + '/')\n if (!url.pathname.endsWith('/'))\n url.pathname += '/'\n\n return url.pathname + url.search\n }\n}\n\ninterface Options {\n agent: Agent\n path: string\n init?: Partial<RequestOptions>\n}\n\nexport { Resource }\n","/**\n *\n * @example\n * [10..20]\n * [10..20)\n * (10..20]\n * (10..20)\n */\nexport function test(value: string): boolean {\n return /^[[(]\\d+\\.\\.\\d+[\\])]{1}$/.test(value)\n}\n\nexport function format(name: string, value: string): string[] {\n const [min, max] = value.slice(1, -1).split('..')\n\n return [\n `${name}${value.startsWith('(') ? '>' : '>='}${min}`,\n `${name}${value.endsWith(')') ? '<' : '<='}${max}`,\n ]\n}\n","import * as range from './range'\nimport type { Format } from './Format'\n\nconst formats: Format[] = [range]\n\nexport { formats }\n","import { formats } from './criteria'\n\nfunction query(params?: URLSearchParams, options?: Options): string {\n if (params === undefined) return ''\n\n const parts: string[] = []\n const criteria: string[] = []\n\n for (const [key, value] of params.entries()) {\n const name = options?.map?.[key] ?? key\n\n if (SEPARATE.includes(name) || options?.separate?.includes(name) === true)\n parts.push(`${name}=${value}`)\n else {\n const format = formats.find((format) => format.test(value))\n\n if (format === undefined)\n criteria.push(`${name}==${value}`)\n else\n criteria.push(...format.format(name, value))\n }\n }\n\n if (criteria.length > 0)\n parts.unshift(`criteria=${criteria.join(';')}`)\n\n return parts.length === 0\n ? ''\n : '?' + parts.join('&')\n}\n\nconst SEPARATE: string[] = ['omit', 'limit', 'search'] as const\n\ninterface Options {\n separate?: string[]\n map?: Record<string, string>\n}\n\nexport { query }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,eAAiB;;;ACAjB,yBAAoB;AACpB,qBAAsB;AACtB,kBAAiB;AAMjB,IAAM,QAAN,MAAY;AAAA,EACO;AAAA,EACA;AAAA,EACT;AAAA,EACA,QAAe;AAAA,EAEf,YAA2B;AAAA,EAEnC,YAAY,SAAkB;AAC5B,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,QAAQ;AAEtB,QAAI,QAAQ,UAAU;AACpB,WAAK,QAAQ,KAAK,UAAU,QAAQ,KAAK;AAAA,EAC7C;AAAA,EAEA,MAAa,KAA+C,MAAc,MAAuC;AAC/G,UAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAM,OAAO;AAEjD,UAAM,OAAO,SAAS,QAAQ,IAAI,cAAc,MAAM,qBAClD,MAAM,SAAS,KAAK,IACpB,MAAM,SAAS,KAAK;AAExB,QAAI,SAAS,IAAI;AACf,WAAK,OAAO,KAAK,YAAY,EAAE,QAAQ,SAAS,QAAQ,SAAS,SAAS,QAAQ,CAAC;AAEnF,aAAO;AAAA,IACT,OAAO;AACL,WAAK,OAAO,KAAK,SAAS,EAAE,MAAM,SAAS,QAAQ,KAAK,CAAC;AAEzD,aAAO,IAAI,uBAAI,SAAS,QAAQ,IAAI;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAa,UAAuB,MAAc,MAAmF;AACnI,UAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAM,OAAO;AAEjD,QAAI,CAAC,SAAS;AACZ,aAAO,IAAI,uBAAI,SAAS,QAAQ,MAAM,SAAS,KAAK,CAAC;AAEvD,UAAM,YAAY,UAAM,sBAAM,QAAQ;AACtC,UAAM,MAAM,MAAM,UAAU,KAAK;AAEjC,QAAI,KAAK,MAAM,IAAI,MAAM,IAAI,MAAM,MAAO,OAAM,IAAI,MAAM,QAAQ;AAElE,YAAQ,mBAAoB;AAC1B,uBAAiB,SAAS,WAAW;AACnC,cAAM,QAAQ,KAAK,MAAM,MAAM,IAAI;AAEnC,YAAI,UAAU,MAAO;AAErB,cAAM;AAAA,MACR;AAAA,IACF,GAAG;AAAA,EACL;AAAA,EAEA,MAAa,OAGX,MAAc,MAAuE;AACrF,UAAM,YAAY,MAAM,KAAK,UAAsC,MAAM,IAAI;AAE7E,QAAI,qBAAqB,MAAO,QAAO;AAEvC,UAAM,QAAQ,MAAM,UAAU,KAAK;AACnC,UAAM,QAAQ,MAAM;AACpB,UAAM,cAAU,YAAAC,SAAgB;AAEhC,UAAM,YAAY;AAChB,uBAAiB,QAAS,WAA4C;AACpE,cAAM,UACJ,KAAK,WAAW,cACZ,KAAK,QACH,IAAI,uBAAI,KAAK,MAAM,QAAQ,WAAW,KAAK,MAAM,OAAO,IACxD,KAAK,SACP,IAAI,uBAAI,WAAW;AAEzB,gBAAQ,KAAK,KAAK,MAAM,OAA8B;AAAA,MACxD;AAEA,cAAQ,IAAI,GAAG;AAAA,IACjB,GAAG;AAEH,WAAO,CAAC,OAAO,OAAO;AAAA,EACxB;AAAA,EAEO,aAAa,WAA0B;AAC5C,SAAK,YAAY;AAAA,EACnB;AAAA,EAEO,IAAIC,QAAc;AACvB,SAAK,QAAQA;AAAA,EACf;AAAA,EAEQ,MAAM,MAAwC;AACpD,aAAS,CAAC;AACV,SAAK,YAAY,CAAC;AAClB,SAAK,QAAQ,QAAQ,MAAM;AAE3B,QAAI,KAAK,UAAU;AACjB,WAAK,QAAQ,OAAO,IAAI,KAAK;AAE/B,QAAI,KAAK,gBAAgB,aAAa,KAAK,QAAQ,eAAe,MAAM,QAAW;AACjF,UAAI,KAAK,cAAc;AACrB,cAAM,IAAI,MAAM,8DAA8D;AAEhF,WAAK,QAAQ,eAAe,IAAI,KAAK;AACrC,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,gBAAgB;AACpE,aAAK,WAAW;AAChB,aAAK,SAAS;AACd,aAAK,QAAQ,cAAc,MAAO,KAAK,KAAc,QAAQ;AAAA,MAC/D,OAAO;AACL,aAAK,OAAO,KAAK,UAAU,KAAK,IAAI;AACpC,aAAK,QAAQ,cAAc,MAAM;AAAA,MACnC;AAEF,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,QAAQ,MAAc,MAAyC;AAC3E,UAAM,MAAM,IAAI,IAAI,MAAM,KAAK,MAAM;AACrC,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,MAAM,IAAI;AAEhD,UAAM,YAAY,SAAS,QAAQ,IAAI,eAAe;AAEtD,QAAI,cAAc,MAAM;AACtB,WAAK,YAAY;AACjB,WAAK,OAAO,KAAK,aAAa,SAAS;AAAA,IACzC;AAEA,WAAO;AAAA,EACT;AACF;;;AC7IA,IAAM,WAAN,MAAmE;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EAEV,YAAY,SAAkB;AACnC,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ;AACpB,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAIA,MAAa,KAA6B,WAAqC,MAAuC;AACpH,WAAO,MAAM,KAAK,QAAc,QAAQ,WAAW,IAAI;AAAA,EACzD;AAAA,EAIA,MAAa,OAAqF,WAAqC,MAAuE;AAC5M,WAAO,MAAM,KAAK,QAAc,UAAU,WAAW,IAAI;AAAA,EAC3D;AAAA,EAIA,MAAa,UAAwC,WAAqC,MAAwE;AAChK,WAAO,MAAM,KAAK,QAAc,aAAa,WAAW,IAAI;AAAA,EAC9D;AAAA,EAKA,MAAc,QAAsC,QAAyC,WAAqC,MAAuB;AACvJ,UAAM,MAAM,OAAO,cAAc,WAAW,YAAY;AAExD,WAAO,OAAO,cAAc,WAAW,OAAO;AAE9C,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,UAAU,OAAO,OAAO,CAAC,GAAG,KAAK,MAAM,IAAI;AAEjD,QAAI,QAAQ,SAAS,UAAa,QAAQ,WAAW;AACnD,cAAQ,SAAS;AAEnB,QAAI,WAAW;AACb,aAAO,MAAM,KAAK,MAAM,KAAW,KAAK,OAAO;AAAA,aACxC,WAAW;AAClB,aAAO,MAAM,KAAK,MAAM,OAAmC,KAAK,OAAO;AAAA,aAChE,WAAW;AAClB,aAAO,MAAM,KAAK,MAAM,UAAa,KAAK,OAAO;AAAA,QAC9C,OAAM,IAAI,MAAM,mBAAmB,MAAM,EAAE;AAAA,EAClD;AAAA,EAEQ,IAAI,KAAqB;AAC/B,UAAM,OAAO,IAAI,IAAI,KAAK,MAAM,YAAY;AAC5C,UAAM,MAAM,IAAI,IAAI,KAAK,IAAI;AAG7B,QAAI,CAAC,IAAI,SAAS,SAAS,GAAG;AAC5B,UAAI,YAAY;AAElB,WAAO,IAAI,WAAW,IAAI;AAAA,EAC5B;AACF;;;AF3DA,IAAM,SAAN,MAAa;AAAA,EACK;AAAA,EACC;AAAA,EAEjB,YAAY,SAAkB;AAC5B,SAAK,aAAS,aAAAC,SAAa;AAE3B,SAAK,QAAQ,IAAI,MAAM;AAAA,MACrB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEO,SAAsB,MAAc,MAAgC;AACzE,WAAO,IAAI,SAAY;AAAA,MACrB,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEO,aAAa,WAA0B;AAC5C,SAAK,MAAM,aAAa,SAAS;AAAA,EACnC;AAAA,EAEO,IAAIC,QAAc;AACvB,SAAK,MAAM,IAAIA,MAAK;AAAA,EACtB;AACF;AAEA,SAAS,QAAQ,SAA2B;AAC1C,MAAI,OAAO,YAAY;AACrB,cAAU,EAAE,QAAQ,QAAQ;AAE9B,SAAO,IAAI,OAAO,OAAO;AAC3B;;;AG5CA;AAAA;AAAA;AAAA;AAAA;AAQO,SAAS,KAAK,OAAwB;AAC3C,SAAO,2BAA2B,KAAK,KAAK;AAC9C;AAEO,SAAS,OAAO,MAAc,OAAyB;AAC5D,QAAM,CAAC,KAAK,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,EAAE,MAAM,IAAI;AAEhD,SAAO;AAAA,IACL,GAAG,IAAI,GAAG,MAAM,WAAW,GAAG,IAAI,MAAM,IAAI,GAAG,GAAG;AAAA,IAClD,GAAG,IAAI,GAAG,MAAM,SAAS,GAAG,IAAI,MAAM,IAAI,GAAG,GAAG;AAAA,EAClD;AACF;;;AChBA,IAAM,UAAoB,CAAC,aAAK;;;ACDhC,SAAS,MAAM,QAA0B,SAA2B;AAClE,MAAI,WAAW,OAAW,QAAO;AAEjC,QAAM,QAAkB,CAAC;AACzB,QAAM,WAAqB,CAAC;AAE5B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG;AAC3C,UAAM,OAAO,SAAS,MAAM,GAAG,KAAK;AAEpC,QAAI,SAAS,SAAS,IAAI,KAAK,SAAS,UAAU,SAAS,IAAI,MAAM;AACnE,YAAM,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE;AAAA,SAC1B;AACH,YAAMC,UAAS,QAAQ,KAAK,CAACA,YAAWA,QAAO,KAAK,KAAK,CAAC;AAE1D,UAAIA,YAAW;AACb,iBAAS,KAAK,GAAG,IAAI,KAAK,KAAK,EAAE;AAAA;AAEjC,iBAAS,KAAK,GAAGA,QAAO,OAAO,MAAM,KAAK,CAAC;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI,SAAS,SAAS;AACpB,UAAM,QAAQ,YAAY,SAAS,KAAK,GAAG,CAAC,EAAE;AAEhD,SAAO,MAAM,WAAW,IACpB,KACA,MAAM,MAAM,KAAK,GAAG;AAC1B;AAEA,IAAM,WAAqB,CAAC,QAAQ,SAAS,QAAQ;","names":["import_mitt","mitt","fetch","mitt","fetch","format"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,10 @@ type Events = {
|
|
|
9
9
|
code: number;
|
|
10
10
|
body: unknown;
|
|
11
11
|
};
|
|
12
|
+
response: {
|
|
13
|
+
status: number;
|
|
14
|
+
headers: Headers;
|
|
15
|
+
};
|
|
12
16
|
};
|
|
13
17
|
|
|
14
18
|
interface OctetsEntry {
|
|
@@ -56,8 +60,11 @@ declare class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
|
56
60
|
constructor(options: Options$2);
|
|
57
61
|
json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>;
|
|
58
62
|
json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>;
|
|
59
|
-
octets<
|
|
60
|
-
octets<
|
|
63
|
+
octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>;
|
|
64
|
+
octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>;
|
|
65
|
+
multipart<R = unknown, F extends E = E>(init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>;
|
|
66
|
+
multipart<R = unknown, F extends E = E>(rel: string, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>;
|
|
67
|
+
private request;
|
|
61
68
|
private abs;
|
|
62
69
|
}
|
|
63
70
|
interface Options$2 {
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ type Events = {
|
|
|
9
9
|
code: number;
|
|
10
10
|
body: unknown;
|
|
11
11
|
};
|
|
12
|
+
response: {
|
|
13
|
+
status: number;
|
|
14
|
+
headers: Headers;
|
|
15
|
+
};
|
|
12
16
|
};
|
|
13
17
|
|
|
14
18
|
interface OctetsEntry {
|
|
@@ -56,8 +60,11 @@ declare class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
|
56
60
|
constructor(options: Options$2);
|
|
57
61
|
json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>;
|
|
58
62
|
json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>;
|
|
59
|
-
octets<
|
|
60
|
-
octets<
|
|
63
|
+
octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>;
|
|
64
|
+
octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>;
|
|
65
|
+
multipart<R = unknown, F extends E = E>(init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>;
|
|
66
|
+
multipart<R = unknown, F extends E = E>(rel: string, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>;
|
|
67
|
+
private request;
|
|
61
68
|
private abs;
|
|
62
69
|
}
|
|
63
70
|
interface Options$2 {
|
package/dist/index.js
CHANGED
|
@@ -27,9 +27,10 @@ var Agent = class {
|
|
|
27
27
|
const options = this.setup(init);
|
|
28
28
|
const response = await this.request(path, options);
|
|
29
29
|
const body = response.headers.get("content-type") === "application/json" ? await response.json() : await response.text();
|
|
30
|
-
if (response.ok)
|
|
30
|
+
if (response.ok) {
|
|
31
|
+
this.events.emit("response", { status: response.status, headers: response.headers });
|
|
31
32
|
return body;
|
|
32
|
-
else {
|
|
33
|
+
} else {
|
|
33
34
|
this.events.emit("error", { code: response.status, body });
|
|
34
35
|
return new Err(response.status, body);
|
|
35
36
|
}
|
|
@@ -117,18 +118,28 @@ var Resource = class {
|
|
|
117
118
|
this.init = options.init;
|
|
118
119
|
}
|
|
119
120
|
async json(relOrInit, init) {
|
|
120
|
-
|
|
121
|
-
init = typeof relOrInit === "string" ? init : relOrInit;
|
|
122
|
-
const abs = this.abs(rel);
|
|
123
|
-
const options = Object.assign({}, this.init, init);
|
|
124
|
-
return await this.agent.json(abs, options);
|
|
121
|
+
return await this.request("json", relOrInit, init);
|
|
125
122
|
}
|
|
126
123
|
async octets(relOrInit, init) {
|
|
124
|
+
return await this.request("octets", relOrInit, init);
|
|
125
|
+
}
|
|
126
|
+
async multipart(relOrInit, init) {
|
|
127
|
+
return await this.request("multipart", relOrInit, init);
|
|
128
|
+
}
|
|
129
|
+
async request(method, relOrInit, init) {
|
|
127
130
|
const rel = typeof relOrInit === "string" ? relOrInit : "";
|
|
128
131
|
init = typeof relOrInit === "string" ? init : relOrInit;
|
|
129
132
|
const abs = this.abs(rel);
|
|
130
133
|
const options = Object.assign({}, this.init, init);
|
|
131
|
-
|
|
134
|
+
if (options.body !== void 0 && options.method === void 0)
|
|
135
|
+
options.method = "POST";
|
|
136
|
+
if (method === "json")
|
|
137
|
+
return await this.agent.json(abs, options);
|
|
138
|
+
else if (method === "octets")
|
|
139
|
+
return await this.agent.octets(abs, options);
|
|
140
|
+
else if (method === "multipart")
|
|
141
|
+
return await this.agent.multipart(abs, options);
|
|
142
|
+
else throw new Error(`Invalid method: ${method}`);
|
|
132
143
|
}
|
|
133
144
|
abs(rel) {
|
|
134
145
|
const base = new URL(this.path, "uri://void");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../source/Origin.ts","../source/Agent.ts","../source/Resource.ts","../source/criteria/range.ts","../source/criteria/index.ts","../source/query.ts"],"sourcesContent":["import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\nimport type { RequestOptions } from './Agent'\nimport type { Events } from './Events'\nimport type { Emitter } from 'mitt'\n\n/** Resoruce factory */\nclass Origin {\n public readonly events: Emitter<Events>\n private readonly agent: Agent\n\n constructor(options: Options) {\n this.events = mitt<Events>()\n\n this.agent = new Agent({\n origin: options.origin,\n events: this.events,\n sleep: options.sleep,\n })\n }\n\n public resource<T = unknown>(path: string, init?: Partial<RequestOptions>) {\n return new Resource<T>({\n agent: this.agent,\n path,\n init,\n })\n }\n\n public authenticate(challenge: string | null) {\n this.agent.authenticate(challenge)\n }\n\n public use(fetch: Fetch) {\n this.agent.use(fetch)\n }\n}\n\nfunction connect(options: Options | string) {\n if (typeof options === 'string')\n options = { origin: options }\n\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n sleep?: [number, number]\n}\n\ntype Fetch = typeof fetch\n\nexport { connect, type Origin }\n","import { Err } from 'error-value'\nimport { meros } from 'meros/browser'\nimport mitt from 'mitt'\nimport type { GenericError } from './Error'\nimport type { Events } from './Events'\nimport type { Faulty, OctetsEntry, WorkflowStep } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Agent {\n private readonly origin: string\n private readonly events: Emitter<Events>\n private sleep?: string\n private fetch: Fetch = fetch\n\n private challenge: string | null = null\n\n constructor(options: Options) {\n this.origin = options.origin\n this.events = options.events\n\n if (options.sleep !== undefined)\n this.sleep = JSON.stringify(options.sleep)\n }\n\n public async json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n const body = response.headers.get('content-type') === 'application/json'\n ? await response.json()\n : await response.text()\n\n if (response.ok)\n return body as T\n else {\n this.events.emit('error', { code: response.status, body })\n\n return new Err(response.status, body) as E\n }\n }\n\n public async multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n if (!response.ok)\n return new Err(response.status, await response.json())\n\n const generator = await meros(response) as AsyncGenerator<{ body: string }>\n const ack = await generator.next()\n\n if (JSON.parse(ack.value.body) !== 'ACK') throw new Error('No ACK')\n\n return (async function * () {\n for await (const chunk of generator) {\n const value = JSON.parse(chunk.body)\n\n if (value === 'FIN') return\n\n yield value\n }\n })()\n }\n\n public async octets<\n T extends Record<string, unknown> = Record<string, unknown>,\n E extends GenericError = GenericError\n >(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {\n const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)\n\n if (generator instanceof Error) return generator as E\n\n const chunk = await generator.next()\n const entry = chunk.value as OctetsEntry\n const emitter = mitt<Faulty<T>>()\n\n void (async () => {\n for await (const part of (generator as AsyncGenerator<WorkflowStep>)) {\n const payload =\n part.status === 'completed'\n ? part.error\n ? new Err(part.error.code ?? 'UNKNOWN', part.error.message)\n : part.output\n : new Err('EXCEPTION')\n\n emitter.emit(part.step, payload as T[typeof part.step])\n }\n\n emitter.off('*')\n })()\n\n return [entry, emitter]\n }\n\n public authenticate(challenge: string | null) {\n this.challenge = challenge\n }\n\n public use(fetch: Fetch) {\n this.fetch = fetch\n }\n\n private setup(init?: RequestOptions): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\n\n if (this.sleep !== undefined)\n init.headers['sleep'] = this.sleep\n\n if (init.credentials === 'include' && init.headers['authorization'] === undefined) {\n if (this.challenge === null)\n throw new Error('Credentials must be set before sending authenticated request')\n\n init.headers['authorization'] = this.challenge\n delete init.credentials // no cookies\n }\n\n if (init.body !== undefined)\n if (init.body instanceof File || init.body instanceof ReadableStream) {\n init.method ??= 'POST'\n init.duplex = 'half'\n init.headers['content-type'] ??= (init.body as File).type ?? 'application/octet-stream'\n } else {\n init.body = JSON.stringify(init.body)\n init.headers['content-type'] ??= 'application/json'\n }\n\n return init as InitWithHeaders\n }\n\n private async request(path: string, init: RequestOptions): Promise<Response> {\n const url = new URL(path, this.origin)\n const response = await this.fetch(url.href, init)\n\n const challenge = response.headers.get('authorization')\n\n if (challenge !== null) {\n this.challenge = challenge\n this.events.emit('challenge', challenge)\n }\n\n return response\n }\n}\n\ninterface Options {\n origin: string\n events: Emitter<Events>\n sleep?: [number, number]\n}\n\ninterface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends RequestOptions {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { RequestOptions }\n","import type { Agent, RequestOptions } from './Agent'\nimport type { GenericError } from './Error'\nimport type { Faulty, OctetsEntry } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Resource<T = unknown, E extends GenericError = GenericError> {\n private readonly agent: Agent\n private readonly path: string\n private readonly init?: Partial<RequestOptions>\n\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n this.init = options.init\n }\n\n public async json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F> {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n return await this.agent.json<R, F>(abs, options)\n }\n\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n return await this.agent.octets<T, F>(abs, options)\n }\n\n private abs(rel: string): string {\n const base = new URL(this.path, 'uri://void')\n const url = new URL(rel, base)\n\n // Allows to use resource.json(id) instead of resource.json(id + '/')\n if (!url.pathname.endsWith('/'))\n url.pathname += '/'\n\n return url.pathname + url.search\n }\n}\n\ninterface Options {\n agent: Agent\n path: string\n init?: Partial<RequestOptions>\n}\n\nexport { Resource }\n","/**\n *\n * @example\n * [10..20]\n * [10..20)\n * (10..20]\n * (10..20)\n */\nexport function test(value: string): boolean {\n return /^[[(]\\d+\\.\\.\\d+[\\])]{1}$/.test(value)\n}\n\nexport function format(name: string, value: string): string[] {\n const [min, max] = value.slice(1, -1).split('..')\n\n return [\n `${name}${value.startsWith('(') ? '>' : '>='}${min}`,\n `${name}${value.endsWith(')') ? '<' : '<='}${max}`,\n ]\n}\n","import * as range from './range'\nimport type { Format } from './Format'\n\nconst formats: Format[] = [range]\n\nexport { formats }\n","import { formats } from './criteria'\n\nfunction query(params?: URLSearchParams, options?: Options): string {\n if (params === undefined) return ''\n\n const parts: string[] = []\n const criteria: string[] = []\n\n for (const [key, value] of params.entries()) {\n const name = options?.map?.[key] ?? key\n\n if (SEPARATE.includes(name) || options?.separate?.includes(name) === true)\n parts.push(`${name}=${value}`)\n else {\n const format = formats.find((format) => format.test(value))\n\n if (format === undefined)\n criteria.push(`${name}==${value}`)\n else\n criteria.push(...format.format(name, value))\n }\n }\n\n if (criteria.length > 0)\n parts.unshift(`criteria=${criteria.join(';')}`)\n\n return parts.length === 0\n ? ''\n : '?' + parts.join('&')\n}\n\nconst SEPARATE: string[] = ['omit', 'limit', 'search'] as const\n\ninterface Options {\n separate?: string[]\n map?: Record<string, string>\n}\n\nexport { query }\n"],"mappings":"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","names":["mitt","fetch","mitt","fetch","format"]}
|
|
1
|
+
{"version":3,"sources":["../source/Origin.ts","../source/Agent.ts","../source/Resource.ts","../source/criteria/range.ts","../source/criteria/index.ts","../source/query.ts"],"sourcesContent":["import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\nimport type { RequestOptions } from './Agent'\nimport type { Events } from './Events'\nimport type { Emitter } from 'mitt'\n\n/** Resoruce factory */\nclass Origin {\n public readonly events: Emitter<Events>\n private readonly agent: Agent\n\n constructor(options: Options) {\n this.events = mitt<Events>()\n\n this.agent = new Agent({\n origin: options.origin,\n events: this.events,\n sleep: options.sleep,\n })\n }\n\n public resource<T = unknown>(path: string, init?: Partial<RequestOptions>) {\n return new Resource<T>({\n agent: this.agent,\n path,\n init,\n })\n }\n\n public authenticate(challenge: string | null) {\n this.agent.authenticate(challenge)\n }\n\n public use(fetch: Fetch) {\n this.agent.use(fetch)\n }\n}\n\nfunction connect(options: Options | string) {\n if (typeof options === 'string')\n options = { origin: options }\n\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n sleep?: [number, number]\n}\n\ntype Fetch = typeof fetch\n\nexport { connect, type Origin }\n","import { Err } from 'error-value'\nimport { meros } from 'meros/browser'\nimport mitt from 'mitt'\nimport type { GenericError } from './Error'\nimport type { Events } from './Events'\nimport type { Faulty, OctetsEntry, WorkflowStep } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Agent {\n private readonly origin: string\n private readonly events: Emitter<Events>\n private sleep?: string\n private fetch: Fetch = fetch\n\n private challenge: string | null = null\n\n constructor(options: Options) {\n this.origin = options.origin\n this.events = options.events\n\n if (options.sleep !== undefined)\n this.sleep = JSON.stringify(options.sleep)\n }\n\n public async json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n const body = response.headers.get('content-type') === 'application/json'\n ? await response.json()\n : await response.text()\n\n if (response.ok) {\n this.events.emit('response', { status: response.status, headers: response.headers })\n\n return body as T\n } else {\n this.events.emit('error', { code: response.status, body })\n\n return new Err(response.status, body) as E\n }\n }\n\n public async multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError> {\n const options = this.setup(init)\n const response = await this.request(path, options)\n\n if (!response.ok)\n return new Err(response.status, await response.json())\n\n const generator = await meros(response) as AsyncGenerator<{ body: string }>\n const ack = await generator.next()\n\n if (JSON.parse(ack.value.body) !== 'ACK') throw new Error('No ACK')\n\n return (async function * () {\n for await (const chunk of generator) {\n const value = JSON.parse(chunk.body)\n\n if (value === 'FIN') return\n\n yield value\n }\n })()\n }\n\n public async octets<\n T extends Record<string, unknown> = Record<string, unknown>,\n E extends GenericError = GenericError\n >(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {\n const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)\n\n if (generator instanceof Error) return generator as E\n\n const chunk = await generator.next()\n const entry = chunk.value as OctetsEntry\n const emitter = mitt<Faulty<T>>()\n\n void (async () => {\n for await (const part of (generator as AsyncGenerator<WorkflowStep>)) {\n const payload =\n part.status === 'completed'\n ? part.error\n ? new Err(part.error.code ?? 'UNKNOWN', part.error.message)\n : part.output\n : new Err('EXCEPTION')\n\n emitter.emit(part.step, payload as T[typeof part.step])\n }\n\n emitter.off('*')\n })()\n\n return [entry, emitter]\n }\n\n public authenticate(challenge: string | null) {\n this.challenge = challenge\n }\n\n public use(fetch: Fetch) {\n this.fetch = fetch\n }\n\n private setup(init?: RequestOptions): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\n\n if (this.sleep !== undefined)\n init.headers['sleep'] = this.sleep\n\n if (init.credentials === 'include' && init.headers['authorization'] === undefined) {\n if (this.challenge === null)\n throw new Error('Credentials must be set before sending authenticated request')\n\n init.headers['authorization'] = this.challenge\n delete init.credentials // no cookies\n }\n\n if (init.body !== undefined)\n if (init.body instanceof File || init.body instanceof ReadableStream) {\n init.method ??= 'POST'\n init.duplex = 'half'\n init.headers['content-type'] ??= (init.body as File).type ?? 'application/octet-stream'\n } else {\n init.body = JSON.stringify(init.body)\n init.headers['content-type'] ??= 'application/json'\n }\n\n return init as InitWithHeaders\n }\n\n private async request(path: string, init: RequestOptions): Promise<Response> {\n const url = new URL(path, this.origin)\n const response = await this.fetch(url.href, init)\n\n const challenge = response.headers.get('authorization')\n\n if (challenge !== null) {\n this.challenge = challenge\n this.events.emit('challenge', challenge)\n }\n\n return response\n }\n}\n\ninterface Options {\n origin: string\n events: Emitter<Events>\n sleep?: [number, number]\n}\n\ninterface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends RequestOptions {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { RequestOptions }\n","import type { Agent, RequestOptions } from './Agent'\nimport type { GenericError } from './Error'\nimport type { Faulty, OctetsEntry } from './Octets'\nimport type { Emitter } from 'mitt'\n\nclass Resource<T = unknown, E extends GenericError = GenericError> {\n private readonly agent: Agent\n private readonly path: string\n private readonly init?: Partial<RequestOptions>\n\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n this.init = options.init\n }\n\n public async json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>\n public async json<R = T, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F> {\n return await this.request<R, F>('json', relOrInit, init)\n }\n\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F> {\n return await this.request<R, F>('octets', relOrInit, init)\n }\n\n public async multipart<R = unknown, F extends E = E>(init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n public async multipart<R = unknown, F extends E = E>(rel: string, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n public async multipart<R = unknown, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F> {\n return await this.request<R, F>('multipart', relOrInit, init)\n }\n\n private async request<R, F extends E>(method: 'json', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F>\n private async request<R extends Record<string, unknown>, F extends E = E>(method: 'octets', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>\n private async request<R, F extends E = E>(method: 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>\n private async request<R extends T, F extends E = E>(method: 'json' | 'octets' | 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions) {\n const rel = typeof relOrInit === 'string' ? relOrInit : ''\n\n init = typeof relOrInit === 'string' ? init : relOrInit\n\n const abs = this.abs(rel)\n const options = Object.assign({}, this.init, init)\n\n if (options.body !== undefined && options.method === undefined)\n options.method = 'POST'\n\n if (method === 'json')\n return await this.agent.json<R, F>(abs, options)\n else if (method === 'octets')\n return await this.agent.octets<Record<string, unknown>, F>(abs, options)\n else if (method === 'multipart')\n return await this.agent.multipart<R>(abs, options)\n else throw new Error(`Invalid method: ${method}`)\n }\n\n private abs(rel: string): string {\n const base = new URL(this.path, 'uri://void')\n const url = new URL(rel, base)\n\n // Allows to use resource.json(id) instead of resource.json(id + '/')\n if (!url.pathname.endsWith('/'))\n url.pathname += '/'\n\n return url.pathname + url.search\n }\n}\n\ninterface Options {\n agent: Agent\n path: string\n init?: Partial<RequestOptions>\n}\n\nexport { Resource }\n","/**\n *\n * @example\n * [10..20]\n * [10..20)\n * (10..20]\n * (10..20)\n */\nexport function test(value: string): boolean {\n return /^[[(]\\d+\\.\\.\\d+[\\])]{1}$/.test(value)\n}\n\nexport function format(name: string, value: string): string[] {\n const [min, max] = value.slice(1, -1).split('..')\n\n return [\n `${name}${value.startsWith('(') ? '>' : '>='}${min}`,\n `${name}${value.endsWith(')') ? '<' : '<='}${max}`,\n ]\n}\n","import * as range from './range'\nimport type { Format } from './Format'\n\nconst formats: Format[] = [range]\n\nexport { formats }\n","import { formats } from './criteria'\n\nfunction query(params?: URLSearchParams, options?: Options): string {\n if (params === undefined) return ''\n\n const parts: string[] = []\n const criteria: string[] = []\n\n for (const [key, value] of params.entries()) {\n const name = options?.map?.[key] ?? key\n\n if (SEPARATE.includes(name) || options?.separate?.includes(name) === true)\n parts.push(`${name}=${value}`)\n else {\n const format = formats.find((format) => format.test(value))\n\n if (format === undefined)\n criteria.push(`${name}==${value}`)\n else\n criteria.push(...format.format(name, value))\n }\n }\n\n if (criteria.length > 0)\n parts.unshift(`criteria=${criteria.join(';')}`)\n\n return parts.length === 0\n ? ''\n : '?' + parts.join('&')\n}\n\nconst SEPARATE: string[] = ['omit', 'limit', 'search'] as const\n\ninterface Options {\n separate?: string[]\n map?: Record<string, string>\n}\n\nexport { query }\n"],"mappings":"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","names":["mitt","fetch","mitt","fetch","format"]}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/origin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"description": "Toa Origin",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "
|
|
10
|
+
"url": "https://github.com/toa-io/origin.git"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://github.com/toa-io/origin#readme",
|
|
13
13
|
"type": "module",
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
"README.md"
|
|
28
28
|
],
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"typescript": "^5.
|
|
30
|
+
"typescript": "^5.9.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@semantic-release/changelog": "
|
|
34
|
-
"@semantic-release/commit-analyzer": "
|
|
35
|
-
"@semantic-release/git": "
|
|
36
|
-
"@semantic-release/github": "
|
|
37
|
-
"@semantic-release/npm": "
|
|
38
|
-
"@semantic-release/release-notes-generator": "
|
|
39
|
-
"@types/node": "
|
|
40
|
-
"eslint": "
|
|
41
|
-
"eslint-plugin-import": "
|
|
42
|
-
"husky": "
|
|
43
|
-
"neostandard": "
|
|
44
|
-
"semantic-release": "
|
|
33
|
+
"@semantic-release/changelog": "6.0.3",
|
|
34
|
+
"@semantic-release/commit-analyzer": "13.0.1",
|
|
35
|
+
"@semantic-release/git": "10.0.1",
|
|
36
|
+
"@semantic-release/github": "12.0.2",
|
|
37
|
+
"@semantic-release/npm": "13.1.3",
|
|
38
|
+
"@semantic-release/release-notes-generator": "14.1.0",
|
|
39
|
+
"@types/node": "24",
|
|
40
|
+
"eslint": "9.39.2",
|
|
41
|
+
"eslint-plugin-import": "2.32.0",
|
|
42
|
+
"husky": "9.1.7",
|
|
43
|
+
"neostandard": "0.12.2",
|
|
44
|
+
"semantic-release": "25.0.2",
|
|
45
45
|
"ts-node": "^10.9.2",
|
|
46
|
-
"tsup": "
|
|
46
|
+
"tsup": "8.5.1"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"prepare": "husky",
|
package/source/Agent.ts
CHANGED
|
@@ -30,9 +30,11 @@ class Agent {
|
|
|
30
30
|
? await response.json()
|
|
31
31
|
: await response.text()
|
|
32
32
|
|
|
33
|
-
if (response.ok)
|
|
33
|
+
if (response.ok) {
|
|
34
|
+
this.events.emit('response', { status: response.status, headers: response.headers })
|
|
35
|
+
|
|
34
36
|
return body as T
|
|
35
|
-
else {
|
|
37
|
+
} else {
|
|
36
38
|
this.events.emit('error', { code: response.status, body })
|
|
37
39
|
|
|
38
40
|
return new Err(response.status, body) as E
|
package/source/Events.ts
CHANGED
package/source/Resource.ts
CHANGED
|
@@ -17,19 +17,25 @@ class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
|
17
17
|
public async json<R = T, F extends E = E>(init?: RequestOptions): Promise<R | F>
|
|
18
18
|
public async json<R = T, F extends E = E>(rel: string, init?: RequestOptions): Promise<R | F>
|
|
19
19
|
public async json<R = T, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F> {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
init = typeof relOrInit === 'string' ? init : relOrInit
|
|
20
|
+
return await this.request<R, F>('json', relOrInit, init)
|
|
21
|
+
}
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>
|
|
24
|
+
public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>
|
|
25
|
+
public async octets<R extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F> {
|
|
26
|
+
return await this.request<R, F>('octets', relOrInit, init)
|
|
27
|
+
}
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
public async multipart<R = unknown, F extends E = E>(init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>
|
|
30
|
+
public async multipart<R = unknown, F extends E = E>(rel: string, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>
|
|
31
|
+
public async multipart<R = unknown, F extends E = E>(relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F> {
|
|
32
|
+
return await this.request<R, F>('multipart', relOrInit, init)
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
private async request<R, F extends E>(method: 'json', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<R | F>
|
|
36
|
+
private async request<R extends Record<string, unknown>, F extends E = E>(method: 'octets', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<R>>] | F>
|
|
37
|
+
private async request<R, F extends E = E>(method: 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions): Promise<AsyncGenerator<R, void, undefined> | F>
|
|
38
|
+
private async request<R extends T, F extends E = E>(method: 'json' | 'octets' | 'multipart', relOrInit?: string | RequestOptions, init?: RequestOptions) {
|
|
33
39
|
const rel = typeof relOrInit === 'string' ? relOrInit : ''
|
|
34
40
|
|
|
35
41
|
init = typeof relOrInit === 'string' ? init : relOrInit
|
|
@@ -37,7 +43,16 @@ class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
|
37
43
|
const abs = this.abs(rel)
|
|
38
44
|
const options = Object.assign({}, this.init, init)
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
if (options.body !== undefined && options.method === undefined)
|
|
47
|
+
options.method = 'POST'
|
|
48
|
+
|
|
49
|
+
if (method === 'json')
|
|
50
|
+
return await this.agent.json<R, F>(abs, options)
|
|
51
|
+
else if (method === 'octets')
|
|
52
|
+
return await this.agent.octets<Record<string, unknown>, F>(abs, options)
|
|
53
|
+
else if (method === 'multipart')
|
|
54
|
+
return await this.agent.multipart<R>(abs, options)
|
|
55
|
+
else throw new Error(`Invalid method: ${method}`)
|
|
41
56
|
}
|
|
42
57
|
|
|
43
58
|
private abs(rel: string): string {
|