@toa.io/origin 1.3.4 → 1.5.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 +9 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/source/Agent.ts +8 -8
- package/source/Origin.ts +3 -1
- package/source/Resource.ts +10 -5
- package/source/index.ts +1 -0
package/dist/index.cjs
CHANGED
|
@@ -135,17 +135,21 @@ var Agent = class {
|
|
|
135
135
|
var Resource = class {
|
|
136
136
|
agent;
|
|
137
137
|
path;
|
|
138
|
+
init;
|
|
138
139
|
constructor(options) {
|
|
139
140
|
this.agent = options.agent;
|
|
140
141
|
this.path = options.path;
|
|
142
|
+
this.init = options.init;
|
|
141
143
|
}
|
|
142
144
|
async json(rel = "", init) {
|
|
143
145
|
const abs = this.abs(rel);
|
|
144
|
-
|
|
146
|
+
const options = Object.assign({}, this.init, init);
|
|
147
|
+
return await this.agent.json(abs, options);
|
|
145
148
|
}
|
|
146
149
|
async octets(rel = "", init) {
|
|
147
150
|
const abs = this.abs(rel);
|
|
148
|
-
|
|
151
|
+
const options = Object.assign({}, this.init, init);
|
|
152
|
+
return await this.agent.octets(abs, options);
|
|
149
153
|
}
|
|
150
154
|
abs(rel) {
|
|
151
155
|
const base = new URL(this.path, "uri://void");
|
|
@@ -167,10 +171,11 @@ var Origin = class {
|
|
|
167
171
|
events: this.events
|
|
168
172
|
});
|
|
169
173
|
}
|
|
170
|
-
resource(path) {
|
|
174
|
+
resource(path, init) {
|
|
171
175
|
return new Resource({
|
|
172
176
|
agent: this.agent,
|
|
173
|
-
path
|
|
177
|
+
path,
|
|
178
|
+
init
|
|
174
179
|
});
|
|
175
180
|
}
|
|
176
181
|
authenticate(challenge) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../source/index.ts","../source/Origin.ts","../source/Agent.ts","../source/Resource.ts"],"sourcesContent":["export { connect } from './Origin'\nexport type { GenericError } from './Error'\nexport type { OctetsEntry, WorkflowStep } from './Octets'\n","import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\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 })\n }\n\n public resource<T = unknown>(path: string) {\n return new Resource<T>({\n agent: this.agent,\n path,\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) {\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n}\n\ntype Fetch = typeof fetch\n\nexport { connect }\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 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\n public async json<T, E extends GenericError = GenericError>(path: string, init?: Init): 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?: Init): 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?: Init): 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.output\n : new Err(part.error?.code ?? 'UNKNOWN', part.error?.message)\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?: Init): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\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: Init): 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}\n\ninterface Init extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends Init {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { Init }\n","import type { Agent, Init } 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\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n }\n\n public async json<R = T, F extends E = E>(rel: string = '', init?: Init): Promise<R | F> {\n const abs = this.abs(rel)\n\n return await this.agent.json<R, F>(abs, init)\n }\n\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string = '', init?: Init): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\n const abs = this.abs(rel)\n\n return await this.agent.octets<T, F>(abs, init)\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 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}\n\nexport { Resource }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,eAAiB;;;ACAjB,yBAAoB;AACpB,qBAAsB;AACtB,kBAAiB;AAMjB,IAAM,QAAN,MAAY;AAAA,EACO;AAAA,EACA;AAAA,EACT,QAAe;AAAA,EAEf,YAA2B;AAAA,EAEnC,YAAY,SAAkB;AAC5B,SAAK,SAAS,QAAQ;AACtB,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEA,MAAa,KAA+C,MAAc,MAA6B;AACrG,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;AACX,aAAO;AAAA,SACJ;AACH,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,MAAyE;AACzH,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,MAA6D;AAC3E,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,SACL,IAAI,uBAAI,KAAK,OAAO,QAAQ,WAAW,KAAK,OAAO,OAAO;AAEhE,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,MAA8B;AAC1C,aAAS,CAAC;AACV,SAAK,YAAY,CAAC;AAClB,SAAK,QAAQ,QAAQ,MAAM;AAE3B,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,MAA+B;AACjE,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;;;AClIA,IAAM,WAAN,MAAmE;AAAA,EAChD;AAAA,EACA;AAAA,EAEV,YAAY,SAAkB;AACnC,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAa,KAA6B,MAAc,IAAI,MAA6B;AACvF,UAAM,MAAM,KAAK,IAAI,GAAG;AAExB,WAAO,MAAM,KAAK,MAAM,KAAW,KAAK,IAAI;AAAA,EAC9C;AAAA,EAEA,MAAa,OAAqF,MAAc,IAAI,MAA6D;AAC/K,UAAM,MAAM,KAAK,IAAI,GAAG;AAExB,WAAO,MAAM,KAAK,MAAM,OAAa,KAAK,IAAI;AAAA,EAChD;AAAA,EAEQ,IAAI,KAAqB;AAC/B,UAAM,OAAO,IAAI,IAAI,KAAK,MAAM,YAAY;AAC5C,UAAM,MAAM,IAAI,IAAI,KAAK,IAAI;AAE7B,QAAI,CAAC,IAAI,SAAS,SAAS,GAAG;AAC5B,UAAI,YAAY;AAElB,WAAO,IAAI,WAAW,IAAI;AAAA,EAC5B;AACF;;;AF5BA,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,IACf,CAAC;AAAA,EACH;AAAA,EAEO,SAAsB,MAAc;AACzC,WAAO,IAAI,SAAY;AAAA,MACrB,OAAO,KAAK;AAAA,MACZ;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,SAAkB;AACjC,SAAO,IAAI,OAAO,OAAO;AAC3B;","names":["import_mitt","mitt","fetch","mitt","fetch"]}
|
|
1
|
+
{"version":3,"sources":["../source/index.ts","../source/Origin.ts","../source/Agent.ts","../source/Resource.ts"],"sourcesContent":["export { connect } from './Origin'\nexport type { GenericError } from './Error'\nexport type { OctetsEntry, WorkflowStep } from './Octets'\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 })\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) {\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n}\n\ntype Fetch = typeof fetch\n\nexport { connect }\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 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\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.output\n : new Err(part.error?.code ?? 'UNKNOWN', part.error?.message)\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 (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}\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>(rel: string = '', init?: RequestOptions): Promise<R | F> {\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>(rel: string = '', init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\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 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"],"mappings":"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","names":["import_mitt","mitt","fetch","mitt","fetch"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -28,9 +28,9 @@ declare class Agent {
|
|
|
28
28
|
private fetch;
|
|
29
29
|
private challenge;
|
|
30
30
|
constructor(options: Options$2);
|
|
31
|
-
json<T, E extends GenericError = GenericError>(path: string, init?:
|
|
32
|
-
multipart<T = unknown>(path: string, init?:
|
|
33
|
-
octets<T extends Record<string, unknown> = Record<string, unknown>, E extends GenericError = GenericError>(path: string, init?:
|
|
31
|
+
json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E>;
|
|
32
|
+
multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError>;
|
|
33
|
+
octets<T extends Record<string, unknown> = Record<string, unknown>, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E>;
|
|
34
34
|
authenticate(challenge: string | null): void;
|
|
35
35
|
use(fetch: Fetch$1): void;
|
|
36
36
|
private setup;
|
|
@@ -40,7 +40,7 @@ interface Options$2 {
|
|
|
40
40
|
origin: string;
|
|
41
41
|
events: Emitter<Events>;
|
|
42
42
|
}
|
|
43
|
-
interface
|
|
43
|
+
interface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {
|
|
44
44
|
duplex?: 'half';
|
|
45
45
|
body?: any;
|
|
46
46
|
headers?: Record<string, string>;
|
|
@@ -50,14 +50,16 @@ type Fetch$1 = typeof fetch;
|
|
|
50
50
|
declare class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
51
51
|
private readonly agent;
|
|
52
52
|
private readonly path;
|
|
53
|
+
private readonly init?;
|
|
53
54
|
constructor(options: Options$1);
|
|
54
|
-
json<R = T, F extends E = E>(rel?: string, init?:
|
|
55
|
-
octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel?: string, init?:
|
|
55
|
+
json<R = T, F extends E = E>(rel?: string, init?: RequestOptions): Promise<R | F>;
|
|
56
|
+
octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel?: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>;
|
|
56
57
|
private abs;
|
|
57
58
|
}
|
|
58
59
|
interface Options$1 {
|
|
59
60
|
agent: Agent;
|
|
60
61
|
path: string;
|
|
62
|
+
init?: Partial<RequestOptions>;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/** Resoruce factory */
|
|
@@ -65,7 +67,7 @@ declare class Origin {
|
|
|
65
67
|
readonly events: Emitter<Events>;
|
|
66
68
|
private readonly agent;
|
|
67
69
|
constructor(options: Options);
|
|
68
|
-
resource<T = unknown>(path: string): Resource<T, GenericError>;
|
|
70
|
+
resource<T = unknown>(path: string, init?: Partial<RequestOptions>): Resource<T, GenericError>;
|
|
69
71
|
authenticate(challenge: string | null): void;
|
|
70
72
|
use(fetch: Fetch): void;
|
|
71
73
|
}
|
|
@@ -75,4 +77,4 @@ interface Options {
|
|
|
75
77
|
}
|
|
76
78
|
type Fetch = typeof fetch;
|
|
77
79
|
|
|
78
|
-
export { type GenericError, type OctetsEntry, type WorkflowStep, connect };
|
|
80
|
+
export { type GenericError, type OctetsEntry, type RequestOptions, type WorkflowStep, connect };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,9 +28,9 @@ declare class Agent {
|
|
|
28
28
|
private fetch;
|
|
29
29
|
private challenge;
|
|
30
30
|
constructor(options: Options$2);
|
|
31
|
-
json<T, E extends GenericError = GenericError>(path: string, init?:
|
|
32
|
-
multipart<T = unknown>(path: string, init?:
|
|
33
|
-
octets<T extends Record<string, unknown> = Record<string, unknown>, E extends GenericError = GenericError>(path: string, init?:
|
|
31
|
+
json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E>;
|
|
32
|
+
multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError>;
|
|
33
|
+
octets<T extends Record<string, unknown> = Record<string, unknown>, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E>;
|
|
34
34
|
authenticate(challenge: string | null): void;
|
|
35
35
|
use(fetch: Fetch$1): void;
|
|
36
36
|
private setup;
|
|
@@ -40,7 +40,7 @@ interface Options$2 {
|
|
|
40
40
|
origin: string;
|
|
41
41
|
events: Emitter<Events>;
|
|
42
42
|
}
|
|
43
|
-
interface
|
|
43
|
+
interface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {
|
|
44
44
|
duplex?: 'half';
|
|
45
45
|
body?: any;
|
|
46
46
|
headers?: Record<string, string>;
|
|
@@ -50,14 +50,16 @@ type Fetch$1 = typeof fetch;
|
|
|
50
50
|
declare class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
51
51
|
private readonly agent;
|
|
52
52
|
private readonly path;
|
|
53
|
+
private readonly init?;
|
|
53
54
|
constructor(options: Options$1);
|
|
54
|
-
json<R = T, F extends E = E>(rel?: string, init?:
|
|
55
|
-
octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel?: string, init?:
|
|
55
|
+
json<R = T, F extends E = E>(rel?: string, init?: RequestOptions): Promise<R | F>;
|
|
56
|
+
octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel?: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F>;
|
|
56
57
|
private abs;
|
|
57
58
|
}
|
|
58
59
|
interface Options$1 {
|
|
59
60
|
agent: Agent;
|
|
60
61
|
path: string;
|
|
62
|
+
init?: Partial<RequestOptions>;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
/** Resoruce factory */
|
|
@@ -65,7 +67,7 @@ declare class Origin {
|
|
|
65
67
|
readonly events: Emitter<Events>;
|
|
66
68
|
private readonly agent;
|
|
67
69
|
constructor(options: Options);
|
|
68
|
-
resource<T = unknown>(path: string): Resource<T, GenericError>;
|
|
70
|
+
resource<T = unknown>(path: string, init?: Partial<RequestOptions>): Resource<T, GenericError>;
|
|
69
71
|
authenticate(challenge: string | null): void;
|
|
70
72
|
use(fetch: Fetch): void;
|
|
71
73
|
}
|
|
@@ -75,4 +77,4 @@ interface Options {
|
|
|
75
77
|
}
|
|
76
78
|
type Fetch = typeof fetch;
|
|
77
79
|
|
|
78
|
-
export { type GenericError, type OctetsEntry, type WorkflowStep, connect };
|
|
80
|
+
export { type GenericError, type OctetsEntry, type RequestOptions, type WorkflowStep, connect };
|
package/dist/index.js
CHANGED
|
@@ -99,17 +99,21 @@ var Agent = class {
|
|
|
99
99
|
var Resource = class {
|
|
100
100
|
agent;
|
|
101
101
|
path;
|
|
102
|
+
init;
|
|
102
103
|
constructor(options) {
|
|
103
104
|
this.agent = options.agent;
|
|
104
105
|
this.path = options.path;
|
|
106
|
+
this.init = options.init;
|
|
105
107
|
}
|
|
106
108
|
async json(rel = "", init) {
|
|
107
109
|
const abs = this.abs(rel);
|
|
108
|
-
|
|
110
|
+
const options = Object.assign({}, this.init, init);
|
|
111
|
+
return await this.agent.json(abs, options);
|
|
109
112
|
}
|
|
110
113
|
async octets(rel = "", init) {
|
|
111
114
|
const abs = this.abs(rel);
|
|
112
|
-
|
|
115
|
+
const options = Object.assign({}, this.init, init);
|
|
116
|
+
return await this.agent.octets(abs, options);
|
|
113
117
|
}
|
|
114
118
|
abs(rel) {
|
|
115
119
|
const base = new URL(this.path, "uri://void");
|
|
@@ -131,10 +135,11 @@ var Origin = class {
|
|
|
131
135
|
events: this.events
|
|
132
136
|
});
|
|
133
137
|
}
|
|
134
|
-
resource(path) {
|
|
138
|
+
resource(path, init) {
|
|
135
139
|
return new Resource({
|
|
136
140
|
agent: this.agent,
|
|
137
|
-
path
|
|
141
|
+
path,
|
|
142
|
+
init
|
|
138
143
|
});
|
|
139
144
|
}
|
|
140
145
|
authenticate(challenge) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../source/Origin.ts","../source/Agent.ts","../source/Resource.ts"],"sourcesContent":["import mitt from 'mitt'\nimport { Agent } from './Agent'\nimport { Resource } from './Resource'\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 })\n }\n\n public resource<T = unknown>(path: string) {\n return new Resource<T>({\n agent: this.agent,\n path,\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) {\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n}\n\ntype Fetch = typeof fetch\n\nexport { connect }\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 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\n public async json<T, E extends GenericError = GenericError>(path: string, init?: Init): 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?: Init): 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?: Init): 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.output\n : new Err(part.error?.code ?? 'UNKNOWN', part.error?.message)\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?: Init): InitWithHeaders {\n init ??= {}\n init.headers ??= {}\n init.headers['accept'] ??= 'application/json'\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: Init): 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}\n\ninterface Init extends Omit<RequestInit, 'path' | 'headers'> {\n duplex?: 'half'\n body?: any\n headers?: Record<string, string>\n}\n\ninterface InitWithHeaders extends Init {\n headers: Record<string, string>\n}\n\ntype Fetch = typeof fetch\n\nexport { Agent }\nexport type { Init }\n","import type { Agent, Init } 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\n public constructor(options: Options) {\n this.agent = options.agent\n this.path = options.path\n }\n\n public async json<R = T, F extends E = E>(rel: string = '', init?: Init): Promise<R | F> {\n const abs = this.abs(rel)\n\n return await this.agent.json<R, F>(abs, init)\n }\n\n public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string = '', init?: Init): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\n const abs = this.abs(rel)\n\n return await this.agent.octets<T, F>(abs, init)\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 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}\n\nexport { Resource }\n"],"mappings":"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","names":["mitt","fetch","mitt","fetch"]}
|
|
1
|
+
{"version":3,"sources":["../source/Origin.ts","../source/Agent.ts","../source/Resource.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 })\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) {\n return new Origin(options)\n}\n\ninterface Options {\n origin: string\n}\n\ntype Fetch = typeof fetch\n\nexport { connect }\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 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\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.output\n : new Err(part.error?.code ?? 'UNKNOWN', part.error?.message)\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 (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}\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>(rel: string = '', init?: RequestOptions): Promise<R | F> {\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>(rel: string = '', init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | F> {\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 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"],"mappings":"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","names":["mitt","fetch","mitt","fetch"]}
|
package/package.json
CHANGED
package/source/Agent.ts
CHANGED
|
@@ -18,7 +18,7 @@ class Agent {
|
|
|
18
18
|
this.events = options.events
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
public async json<T, E extends GenericError = GenericError>(path: string, init?:
|
|
21
|
+
public async json<T, E extends GenericError = GenericError>(path: string, init?: RequestOptions): Promise<T | E> {
|
|
22
22
|
const options = this.setup(init)
|
|
23
23
|
const response = await this.request(path, options)
|
|
24
24
|
|
|
@@ -35,7 +35,7 @@ class Agent {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
public async multipart<T = unknown>(path: string, init?:
|
|
38
|
+
public async multipart<T = unknown>(path: string, init?: RequestOptions): Promise<AsyncGenerator<T, void, undefined> | GenericError> {
|
|
39
39
|
const options = this.setup(init)
|
|
40
40
|
const response = await this.request(path, options)
|
|
41
41
|
|
|
@@ -61,7 +61,7 @@ class Agent {
|
|
|
61
61
|
public async octets<
|
|
62
62
|
T extends Record<string, unknown> = Record<string, unknown>,
|
|
63
63
|
E extends GenericError = GenericError
|
|
64
|
-
>(path: string, init?:
|
|
64
|
+
>(path: string, init?: RequestOptions): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {
|
|
65
65
|
const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)
|
|
66
66
|
|
|
67
67
|
if (generator instanceof Error) return generator as E
|
|
@@ -94,7 +94,7 @@ class Agent {
|
|
|
94
94
|
this.fetch = fetch
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
private setup(init?:
|
|
97
|
+
private setup(init?: RequestOptions): InitWithHeaders {
|
|
98
98
|
init ??= {}
|
|
99
99
|
init.headers ??= {}
|
|
100
100
|
init.headers['accept'] ??= 'application/json'
|
|
@@ -120,7 +120,7 @@ class Agent {
|
|
|
120
120
|
return init as InitWithHeaders
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
private async request(path: string, init:
|
|
123
|
+
private async request(path: string, init: RequestOptions): Promise<Response> {
|
|
124
124
|
const url = new URL(path, this.origin)
|
|
125
125
|
const response = await this.fetch(url.href, init)
|
|
126
126
|
|
|
@@ -140,17 +140,17 @@ interface Options {
|
|
|
140
140
|
events: Emitter<Events>
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
interface
|
|
143
|
+
interface RequestOptions extends Omit<RequestInit, 'path' | 'headers'> {
|
|
144
144
|
duplex?: 'half'
|
|
145
145
|
body?: any
|
|
146
146
|
headers?: Record<string, string>
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
interface InitWithHeaders extends
|
|
149
|
+
interface InitWithHeaders extends RequestOptions {
|
|
150
150
|
headers: Record<string, string>
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
type Fetch = typeof fetch
|
|
154
154
|
|
|
155
155
|
export { Agent }
|
|
156
|
-
export type {
|
|
156
|
+
export type { RequestOptions }
|
package/source/Origin.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import mitt from 'mitt'
|
|
2
2
|
import { Agent } from './Agent'
|
|
3
3
|
import { Resource } from './Resource'
|
|
4
|
+
import type { RequestOptions } from './Agent'
|
|
4
5
|
import type { Events } from './Events'
|
|
5
6
|
import type { Emitter } from 'mitt'
|
|
6
7
|
|
|
@@ -18,10 +19,11 @@ class Origin {
|
|
|
18
19
|
})
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
public resource<T = unknown>(path: string) {
|
|
22
|
+
public resource<T = unknown>(path: string, init?: Partial<RequestOptions>) {
|
|
22
23
|
return new Resource<T>({
|
|
23
24
|
agent: this.agent,
|
|
24
25
|
path,
|
|
26
|
+
init,
|
|
25
27
|
})
|
|
26
28
|
}
|
|
27
29
|
|
package/source/Resource.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Agent,
|
|
1
|
+
import type { Agent, RequestOptions } from './Agent'
|
|
2
2
|
import type { GenericError } from './Error'
|
|
3
3
|
import type { Faulty, OctetsEntry } from './Octets'
|
|
4
4
|
import type { Emitter } from 'mitt'
|
|
@@ -6,22 +6,26 @@ import type { Emitter } from 'mitt'
|
|
|
6
6
|
class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
7
7
|
private readonly agent: Agent
|
|
8
8
|
private readonly path: string
|
|
9
|
+
private readonly init?: Partial<RequestOptions>
|
|
9
10
|
|
|
10
11
|
public constructor(options: Options) {
|
|
11
12
|
this.agent = options.agent
|
|
12
13
|
this.path = options.path
|
|
14
|
+
this.init = options.init
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
public async json<R = T, F extends E = E>(rel: string = '', init?:
|
|
17
|
+
public async json<R = T, F extends E = E>(rel: string = '', init?: RequestOptions): Promise<R | F> {
|
|
16
18
|
const abs = this.abs(rel)
|
|
19
|
+
const options = Object.assign({}, this.init, init)
|
|
17
20
|
|
|
18
|
-
return await this.agent.json<R, F>(abs,
|
|
21
|
+
return await this.agent.json<R, F>(abs, options)
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
public async octets<T extends Record<string, unknown> = Record<string, unknown>, F extends E = E>(rel: string = '', init?:
|
|
24
|
+
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> {
|
|
22
25
|
const abs = this.abs(rel)
|
|
26
|
+
const options = Object.assign({}, this.init, init)
|
|
23
27
|
|
|
24
|
-
return await this.agent.octets<T, F>(abs,
|
|
28
|
+
return await this.agent.octets<T, F>(abs, options)
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
private abs(rel: string): string {
|
|
@@ -38,6 +42,7 @@ class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
|
38
42
|
interface Options {
|
|
39
43
|
agent: Agent
|
|
40
44
|
path: string
|
|
45
|
+
init?: Partial<RequestOptions>
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
export { Resource }
|
package/source/index.ts
CHANGED