@toa.io/origin 1.0.0 → 1.2.2
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/.vscode/settings.json +8 -1
- package/CHANGELOG.md +28 -0
- package/README.md +8 -30
- package/eslint.config.js +3 -5
- package/package.json +1 -1
- package/source/Agent.ts +156 -0
- package/source/Error.ts +3 -0
- package/source/Evt.ts +3 -0
- package/source/Octets.ts +5 -6
- package/source/Origin.ts +47 -0
- package/source/Resource.ts +41 -16
- package/source/index.ts +3 -6
- package/transpiled/Agent.d.ts +30 -0
- package/transpiled/Agent.js +102 -0
- package/transpiled/Agent.js.map +1 -0
- package/transpiled/Error.d.ts +2 -0
- package/transpiled/Error.js +2 -0
- package/transpiled/Error.js.map +1 -0
- package/transpiled/Evt.d.ts +8 -0
- package/transpiled/Evt.js +2 -0
- package/transpiled/Evt.js.map +1 -0
- package/transpiled/Octets.d.ts +4 -7
- package/transpiled/Origin.d.ts +18 -0
- package/transpiled/Origin.js +32 -0
- package/transpiled/Origin.js.map +1 -0
- package/transpiled/Resource.d.ts +16 -9
- package/transpiled/Resource.js +22 -13
- package/transpiled/Resource.js.map +1 -1
- package/transpiled/index.d.ts +3 -6
- package/transpiled/index.js +1 -5
- package/transpiled/index.js.map +1 -1
- package/tsconfig.json +3 -5
- package/source/Failure.ts +0 -3
- package/source/Method.ts +0 -99
- package/source/events.ts +0 -20
- package/source/fail.ts +0 -13
- package/source/ok.ts +0 -15
- package/source/request.ts +0 -84
- package/transpiled/Failure.d.ts +0 -3
- package/transpiled/Failure.js +0 -4
- package/transpiled/Failure.js.map +0 -1
- package/transpiled/Method.d.ts +0 -15
- package/transpiled/Method.js +0 -71
- package/transpiled/Method.js.map +0 -1
- package/transpiled/events.d.ts +0 -15
- package/transpiled/events.js +0 -3
- package/transpiled/events.js.map +0 -1
- package/transpiled/fail.d.ts +0 -2
- package/transpiled/fail.js +0 -10
- package/transpiled/fail.js.map +0 -1
- package/transpiled/ok.d.ts +0 -1
- package/transpiled/ok.js +0 -17
- package/transpiled/ok.js.map +0 -1
- package/transpiled/request.d.ts +0 -15
- package/transpiled/request.js +0 -52
- package/transpiled/request.js.map +0 -1
package/.vscode/settings.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [1.2.2](https://github.com/toa-io/origin/compare/v1.2.1...v1.2.2) (2025-10-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* rename file ([de63ef8](https://github.com/toa-io/origin/commit/de63ef889d9ca247f36ddbb52453d46f0f7655ab))
|
|
7
|
+
|
|
8
|
+
## [1.2.1](https://github.com/toa-io/origin/compare/v1.2.0...v1.2.1) (2025-10-06)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* update tsconfig ([3a69b4a](https://github.com/toa-io/origin/commit/3a69b4a873675a1214d01b1c119df624a6978fd5))
|
|
14
|
+
|
|
15
|
+
# [1.2.0](https://github.com/toa-io/origin/compare/v1.1.0...v1.2.0) (2025-10-06)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* change type to `module` ([5b70fd5](https://github.com/toa-io/origin/commit/5b70fd5cb7cfacefcb05ea4d0b8fa7f0c5b58d9e))
|
|
21
|
+
|
|
22
|
+
# [1.1.0](https://github.com/toa-io/origin/compare/v1.0.0...v1.1.0) (2025-10-06)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* remove singleton ([df8e18a](https://github.com/toa-io/origin/commit/df8e18a4e9a5c065e9ea33e20e6437374c3bebb3))
|
|
28
|
+
|
|
1
29
|
# 1.0.0 (2025-10-05)
|
|
2
30
|
|
|
3
31
|
|
package/README.md
CHANGED
|
@@ -2,50 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
[Exposition](https://github.com/toa-io/toa/tree/dev/extensions/exposition) Client
|
|
4
4
|
|
|
5
|
-
## `new Resource<T>(path: string, options?: RequestInit)`
|
|
6
|
-
|
|
7
|
-
### Parameters
|
|
8
|
-
|
|
9
|
-
- `path` — Base API path (e.g. '/favorites/').
|
|
10
|
-
- `options` — Options passed to `fetch`.
|
|
11
|
-
- `T` — Type of the resource representation.
|
|
12
|
-
|
|
13
|
-
Each HTTP verb (get, post, patch, put, delete) provides the following response handling modes:
|
|
14
|
-
|
|
15
|
-
- `.value()`: Expects a single JSON object response `T`.
|
|
16
|
-
- `.array()`: Expects a JSON array response `T[]`.
|
|
17
|
-
- `.none()`: Expects no response body `void`.
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
(resource.<method>).<mode>(
|
|
21
|
-
segments?: string[], // Optional URL path segments, relative to the base path
|
|
22
|
-
options?: RequestInit // fetch-compatible request options
|
|
23
|
-
): Promise<...>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
5
|
## Usage
|
|
27
6
|
|
|
28
7
|
```typescript
|
|
29
|
-
import {
|
|
30
|
-
import type {
|
|
8
|
+
import { connect } from '@toa.io/origin'
|
|
9
|
+
import type { MyEntity } from './MyEntity'
|
|
31
10
|
|
|
32
|
-
|
|
33
|
-
const favorites =
|
|
11
|
+
const origin = connect({ origin: 'https://my-origin.com' })
|
|
12
|
+
const favorites = origin.resource<Favorite>('/favorites/')
|
|
34
13
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return favorites.get.array([identity])
|
|
14
|
+
export async function get(): Promise<Favorite[] | Error> {
|
|
15
|
+
return favorites.json<Favorite[]>('', { method: 'GET' })
|
|
38
16
|
}
|
|
39
17
|
|
|
40
18
|
// POST /favorites/:identity/ with typed body
|
|
41
19
|
type Post = Omit<Favorite, 'id'>
|
|
42
20
|
|
|
43
21
|
export async function post(identity: string, body: Post): Promise<Favorite | Error> {
|
|
44
|
-
return favorites.
|
|
22
|
+
return favorites.json(identity, { method: 'POST', body, credentials: 'include' })
|
|
45
23
|
}
|
|
46
24
|
|
|
47
25
|
// DELETE /favorites/:identity/:id/
|
|
48
26
|
export async function del(identity: string, id: string): Promise<Favorite | Error> {
|
|
49
|
-
return favorites.
|
|
27
|
+
return favorites.json(`${identity}/${id}`, { method: 'DELETE', credentials: 'include' })
|
|
50
28
|
}
|
|
51
29
|
```
|
package/eslint.config.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import importPlugin from 'eslint-plugin-import'
|
|
2
|
+
import neostandard from 'neostandard'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const neostandard = require('neostandard')
|
|
5
|
-
|
|
6
|
-
module.exports = [
|
|
4
|
+
export default [
|
|
7
5
|
...neostandard({
|
|
8
6
|
ts: true,
|
|
9
7
|
ignores: neostandard.resolveIgnoresFromGitignore(),
|
package/package.json
CHANGED
package/source/Agent.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Err } from 'error-value'
|
|
2
|
+
import { meros } from 'meros/browser'
|
|
3
|
+
import mitt from 'mitt'
|
|
4
|
+
import type { GenericError } from './Error'
|
|
5
|
+
import type { Events } from './Evt'
|
|
6
|
+
import type { Faulty, OctetsEntry, WorkflowStep } from './Octets'
|
|
7
|
+
import type { Emitter } from 'mitt'
|
|
8
|
+
|
|
9
|
+
class Agent {
|
|
10
|
+
private readonly origin: string
|
|
11
|
+
private readonly events: Emitter<Events>
|
|
12
|
+
private fetch: Fetch = fetch
|
|
13
|
+
|
|
14
|
+
private challenge: string | null = null
|
|
15
|
+
|
|
16
|
+
constructor(options: Options) {
|
|
17
|
+
this.origin = options.origin
|
|
18
|
+
this.events = options.events
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public async json<T, E extends GenericError = GenericError>(path: string, init?: Init): Promise<T | E> {
|
|
22
|
+
const options = this.setup(init)
|
|
23
|
+
const response = await this.request(path, options)
|
|
24
|
+
|
|
25
|
+
const body = response.headers.get('content-type') === 'application/json'
|
|
26
|
+
? await response.json()
|
|
27
|
+
: await response.text()
|
|
28
|
+
|
|
29
|
+
if (response.ok)
|
|
30
|
+
return body as T
|
|
31
|
+
else {
|
|
32
|
+
this.events.emit('error', { code: response.status, body })
|
|
33
|
+
|
|
34
|
+
return new Err(response.status, body) as E
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async multipart<T = unknown>(path: string, init?: Init): Promise<AsyncGenerator<T, void, undefined> | GenericError> {
|
|
39
|
+
const options = this.setup(init)
|
|
40
|
+
const response = await this.request(path, options)
|
|
41
|
+
|
|
42
|
+
if (!response.ok)
|
|
43
|
+
return new Err(response.status, await response.json())
|
|
44
|
+
|
|
45
|
+
const generator = await meros(response) as AsyncGenerator<{ body: string }>
|
|
46
|
+
const ack = await generator.next()
|
|
47
|
+
|
|
48
|
+
if (JSON.parse(ack.value.body) !== 'ACK') throw new Error('No ACK')
|
|
49
|
+
|
|
50
|
+
return (async function * () {
|
|
51
|
+
for await (const chunk of generator) {
|
|
52
|
+
const value = JSON.parse(chunk.body)
|
|
53
|
+
|
|
54
|
+
if (value === 'FIN') return
|
|
55
|
+
|
|
56
|
+
yield value
|
|
57
|
+
}
|
|
58
|
+
})()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async octets<
|
|
62
|
+
T extends Record<string, unknown> = Record<string, unknown>,
|
|
63
|
+
E extends GenericError = GenericError
|
|
64
|
+
>(path: string, init?: Init): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E> {
|
|
65
|
+
const generator = await this.multipart<OctetsEntry | WorkflowStep>(path, init)
|
|
66
|
+
|
|
67
|
+
if (generator instanceof Error) return generator as E
|
|
68
|
+
|
|
69
|
+
const chunk = await generator.next()
|
|
70
|
+
const entry = chunk.value as OctetsEntry
|
|
71
|
+
const emitter = mitt<Faulty<T>>()
|
|
72
|
+
|
|
73
|
+
void (async () => {
|
|
74
|
+
for await (const part of (generator as AsyncGenerator<WorkflowStep>)) {
|
|
75
|
+
const payload =
|
|
76
|
+
part.status === 'completed'
|
|
77
|
+
? part.output
|
|
78
|
+
: new Err(part.error?.code ?? 'UNKNOWN', part.error?.message)
|
|
79
|
+
|
|
80
|
+
emitter.emit(part.step, payload as T[typeof part.step])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
emitter.off('*')
|
|
84
|
+
})()
|
|
85
|
+
|
|
86
|
+
return [entry, emitter]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public authenticate(challenge: string | null) {
|
|
90
|
+
this.challenge = challenge
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public use(fetch: Fetch) {
|
|
94
|
+
this.fetch = fetch
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private setup(init?: Init): InitWithHeaders {
|
|
98
|
+
init ??= {}
|
|
99
|
+
init.headers ??= {}
|
|
100
|
+
init.headers['accept'] ??= 'application/json'
|
|
101
|
+
|
|
102
|
+
if (init.credentials === 'include' && init.headers['authorization'] === undefined) {
|
|
103
|
+
if (this.challenge === null)
|
|
104
|
+
throw new Error('Credentials must be set before sending authenticated request')
|
|
105
|
+
|
|
106
|
+
init.headers['authorization'] = this.challenge
|
|
107
|
+
delete init.credentials // no cookies
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (init.body !== undefined)
|
|
111
|
+
if (init.body instanceof File || init.body instanceof ReadableStream) {
|
|
112
|
+
init.method ??= 'POST'
|
|
113
|
+
init.duplex = 'half'
|
|
114
|
+
init.headers['content-type'] ??= (init.body as File).type ?? 'application/octet-stream'
|
|
115
|
+
} else {
|
|
116
|
+
init.body = JSON.stringify(init.body)
|
|
117
|
+
init.headers['content-type'] ??= 'application/json'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return init as InitWithHeaders
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private async request(path: string, init: Init): Promise<Response> {
|
|
124
|
+
const url = new URL(path, this.origin)
|
|
125
|
+
const response = await this.fetch(url.href, init)
|
|
126
|
+
|
|
127
|
+
const challenge = response.headers.get('authorization')
|
|
128
|
+
|
|
129
|
+
if (challenge !== null) {
|
|
130
|
+
this.challenge = challenge
|
|
131
|
+
this.events.emit('challenge', challenge)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return response
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
interface Options {
|
|
139
|
+
origin: string
|
|
140
|
+
events: Emitter<Events>
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface Init extends Omit<RequestInit, 'path' | 'headers'> {
|
|
144
|
+
duplex?: 'half'
|
|
145
|
+
body?: any
|
|
146
|
+
headers?: Record<string, string>
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface InitWithHeaders extends Init {
|
|
150
|
+
headers: Record<string, string>
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
type Fetch = typeof fetch
|
|
154
|
+
|
|
155
|
+
export { Agent }
|
|
156
|
+
export type { Init }
|
package/source/Error.ts
ADDED
package/source/Evt.ts
ADDED
package/source/Octets.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
+
import type { Err } from 'error-value'
|
|
2
|
+
|
|
1
3
|
export interface OctetsEntry {
|
|
2
4
|
id: string
|
|
3
5
|
}
|
|
4
6
|
|
|
5
|
-
export interface WorkflowStep<K = string, T = unknown> {
|
|
7
|
+
export interface WorkflowStep<K extends string = string, T = unknown, E extends Err = Err> {
|
|
6
8
|
step: K
|
|
7
9
|
status: 'completed' | 'exception'
|
|
8
10
|
output?: T
|
|
9
|
-
error:
|
|
11
|
+
error: E
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
code: string
|
|
14
|
-
message?: string
|
|
15
|
-
}
|
|
14
|
+
export type Faulty<T extends Record<string, unknown>> = Record<keyof T, T[keyof T] | Err>
|
package/source/Origin.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import mitt from 'mitt'
|
|
2
|
+
import { Agent } from './Agent'
|
|
3
|
+
import { Resource } from './Resource'
|
|
4
|
+
import type { Events } from './Evt'
|
|
5
|
+
import type { Emitter } from 'mitt'
|
|
6
|
+
|
|
7
|
+
/** Resoruce factory */
|
|
8
|
+
class Origin {
|
|
9
|
+
public readonly events: Emitter<Events>
|
|
10
|
+
private readonly agent: Agent
|
|
11
|
+
|
|
12
|
+
constructor(options: Options) {
|
|
13
|
+
this.events = mitt<Events>()
|
|
14
|
+
|
|
15
|
+
this.agent = new Agent({
|
|
16
|
+
origin: options.origin,
|
|
17
|
+
events: this.events,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public resource<T = unknown>(path: string) {
|
|
22
|
+
return new Resource<T>({
|
|
23
|
+
agent: this.agent,
|
|
24
|
+
path,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public authenticate(challenge: string | null) {
|
|
29
|
+
this.agent.authenticate(challenge)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public use(fetch: Fetch) {
|
|
33
|
+
this.agent.use(fetch)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function connect(options: Options) {
|
|
38
|
+
return new Origin(options)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface Options {
|
|
42
|
+
origin: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type Fetch = typeof fetch
|
|
46
|
+
|
|
47
|
+
export { connect }
|
package/source/Resource.ts
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import type { Agent, Init } from './Agent'
|
|
2
|
+
import type { GenericError } from './Error'
|
|
3
|
+
import type { Faulty, OctetsEntry } from './Octets'
|
|
4
|
+
import type { Emitter } from 'mitt'
|
|
5
|
+
|
|
6
|
+
class Resource<T = unknown, E extends GenericError = GenericError> {
|
|
7
|
+
private readonly agent: Agent
|
|
8
|
+
private readonly path: string
|
|
9
|
+
|
|
10
|
+
public constructor(options: Options) {
|
|
11
|
+
this.agent = options.agent
|
|
12
|
+
this.path = options.path
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async json<R = T, F extends E = E>(rel: string = '', init?: Init): Promise<R | F> {
|
|
16
|
+
const abs = this.abs(rel)
|
|
17
|
+
|
|
18
|
+
return await this.agent.json<R, F>(abs, init)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
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> {
|
|
22
|
+
const abs = this.abs(rel)
|
|
23
|
+
|
|
24
|
+
return await this.agent.octets<T, F>(abs, init)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private abs(rel: string): string {
|
|
28
|
+
const base = new URL(this.path, 'uri://void')
|
|
29
|
+
const url = new URL(rel, base)
|
|
30
|
+
|
|
31
|
+
if (!url.pathname.endsWith('/'))
|
|
32
|
+
url.pathname += '/'
|
|
33
|
+
|
|
34
|
+
return url.pathname + url.search
|
|
17
35
|
}
|
|
18
36
|
}
|
|
37
|
+
|
|
38
|
+
interface Options {
|
|
39
|
+
agent: Agent
|
|
40
|
+
path: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { Resource }
|
package/source/index.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export { authenticate, request, use, connect, type Options } from './request'
|
|
5
|
-
export { events } from './events'
|
|
6
|
-
export type * from './Octets'
|
|
1
|
+
export { connect } from './Origin'
|
|
2
|
+
export type { GenericError } from './Error'
|
|
3
|
+
export type { OctetsEntry, WorkflowStep } from './Octets'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { GenericError } from './Error';
|
|
2
|
+
import type { Events } from './Evt';
|
|
3
|
+
import type { Faulty, OctetsEntry } from './Octets';
|
|
4
|
+
import type { Emitter } from 'mitt';
|
|
5
|
+
declare class Agent {
|
|
6
|
+
private readonly origin;
|
|
7
|
+
private readonly events;
|
|
8
|
+
private fetch;
|
|
9
|
+
private challenge;
|
|
10
|
+
constructor(options: Options);
|
|
11
|
+
json<T, E extends GenericError = GenericError>(path: string, init?: Init): Promise<T | E>;
|
|
12
|
+
multipart<T = unknown>(path: string, init?: Init): Promise<AsyncGenerator<T, void, undefined> | GenericError>;
|
|
13
|
+
octets<T extends Record<string, unknown> = Record<string, unknown>, E extends GenericError = GenericError>(path: string, init?: Init): Promise<[OctetsEntry, Emitter<Faulty<T>>] | E>;
|
|
14
|
+
authenticate(challenge: string | null): void;
|
|
15
|
+
use(fetch: Fetch): void;
|
|
16
|
+
private setup;
|
|
17
|
+
private request;
|
|
18
|
+
}
|
|
19
|
+
interface Options {
|
|
20
|
+
origin: string;
|
|
21
|
+
events: Emitter<Events>;
|
|
22
|
+
}
|
|
23
|
+
interface Init extends Omit<RequestInit, 'path' | 'headers'> {
|
|
24
|
+
duplex?: 'half';
|
|
25
|
+
body?: any;
|
|
26
|
+
headers?: Record<string, string>;
|
|
27
|
+
}
|
|
28
|
+
type Fetch = typeof fetch;
|
|
29
|
+
export { Agent };
|
|
30
|
+
export type { Init };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Err } from 'error-value';
|
|
2
|
+
import { meros } from 'meros/browser';
|
|
3
|
+
import mitt from 'mitt';
|
|
4
|
+
class Agent {
|
|
5
|
+
origin;
|
|
6
|
+
events;
|
|
7
|
+
fetch = fetch;
|
|
8
|
+
challenge = null;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.origin = options.origin;
|
|
11
|
+
this.events = options.events;
|
|
12
|
+
}
|
|
13
|
+
async json(path, init) {
|
|
14
|
+
const options = this.setup(init);
|
|
15
|
+
const response = await this.request(path, options);
|
|
16
|
+
const body = response.headers.get('content-type') === 'application/json'
|
|
17
|
+
? await response.json()
|
|
18
|
+
: await response.text();
|
|
19
|
+
if (response.ok)
|
|
20
|
+
return body;
|
|
21
|
+
else {
|
|
22
|
+
this.events.emit('error', { code: response.status, body });
|
|
23
|
+
return new Err(response.status, body);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async multipart(path, init) {
|
|
27
|
+
const options = this.setup(init);
|
|
28
|
+
const response = await this.request(path, options);
|
|
29
|
+
if (!response.ok)
|
|
30
|
+
return new Err(response.status, await response.json());
|
|
31
|
+
const generator = await meros(response);
|
|
32
|
+
const ack = await generator.next();
|
|
33
|
+
if (JSON.parse(ack.value.body) !== 'ACK')
|
|
34
|
+
throw new Error('No ACK');
|
|
35
|
+
return (async function* () {
|
|
36
|
+
for await (const chunk of generator) {
|
|
37
|
+
const value = JSON.parse(chunk.body);
|
|
38
|
+
if (value === 'FIN')
|
|
39
|
+
return;
|
|
40
|
+
yield value;
|
|
41
|
+
}
|
|
42
|
+
})();
|
|
43
|
+
}
|
|
44
|
+
async octets(path, init) {
|
|
45
|
+
const generator = await this.multipart(path, init);
|
|
46
|
+
if (generator instanceof Error)
|
|
47
|
+
return generator;
|
|
48
|
+
const chunk = await generator.next();
|
|
49
|
+
const entry = chunk.value;
|
|
50
|
+
const emitter = mitt();
|
|
51
|
+
void (async () => {
|
|
52
|
+
for await (const part of generator) {
|
|
53
|
+
const payload = part.status === 'completed'
|
|
54
|
+
? part.output
|
|
55
|
+
: new Err(part.error?.code ?? 'UNKNOWN', part.error?.message);
|
|
56
|
+
emitter.emit(part.step, payload);
|
|
57
|
+
}
|
|
58
|
+
emitter.off('*');
|
|
59
|
+
})();
|
|
60
|
+
return [entry, emitter];
|
|
61
|
+
}
|
|
62
|
+
authenticate(challenge) {
|
|
63
|
+
this.challenge = challenge;
|
|
64
|
+
}
|
|
65
|
+
use(fetch) {
|
|
66
|
+
this.fetch = fetch;
|
|
67
|
+
}
|
|
68
|
+
setup(init) {
|
|
69
|
+
init ??= {};
|
|
70
|
+
init.headers ??= {};
|
|
71
|
+
init.headers['accept'] ??= 'application/json';
|
|
72
|
+
if (init.credentials === 'include' && init.headers['authorization'] === undefined) {
|
|
73
|
+
if (this.challenge === null)
|
|
74
|
+
throw new Error('Credentials must be set before sending authenticated request');
|
|
75
|
+
init.headers['authorization'] = this.challenge;
|
|
76
|
+
delete init.credentials; // no cookies
|
|
77
|
+
}
|
|
78
|
+
if (init.body !== undefined)
|
|
79
|
+
if (init.body instanceof File || init.body instanceof ReadableStream) {
|
|
80
|
+
init.method ??= 'POST';
|
|
81
|
+
init.duplex = 'half';
|
|
82
|
+
init.headers['content-type'] ??= init.body.type ?? 'application/octet-stream';
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
init.body = JSON.stringify(init.body);
|
|
86
|
+
init.headers['content-type'] ??= 'application/json';
|
|
87
|
+
}
|
|
88
|
+
return init;
|
|
89
|
+
}
|
|
90
|
+
async request(path, init) {
|
|
91
|
+
const url = new URL(path, this.origin);
|
|
92
|
+
const response = await this.fetch(url.href, init);
|
|
93
|
+
const challenge = response.headers.get('authorization');
|
|
94
|
+
if (challenge !== null) {
|
|
95
|
+
this.challenge = challenge;
|
|
96
|
+
this.events.emit('challenge', challenge);
|
|
97
|
+
}
|
|
98
|
+
return response;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export { Agent };
|
|
102
|
+
//# sourceMappingURL=Agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Agent.js","sourceRoot":"","sources":["../source/Agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Error.js","sourceRoot":"","sources":["../source/Error.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Evt.js","sourceRoot":"","sources":["../source/Evt.ts"],"names":[],"mappings":""}
|
package/transpiled/Octets.d.ts
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
|
+
import type { Err } from 'error-value';
|
|
1
2
|
export interface OctetsEntry {
|
|
2
3
|
id: string;
|
|
3
4
|
}
|
|
4
|
-
export interface WorkflowStep<K = string, T = unknown> {
|
|
5
|
+
export interface WorkflowStep<K extends string = string, T = unknown, E extends Err = Err> {
|
|
5
6
|
step: K;
|
|
6
7
|
status: 'completed' | 'exception';
|
|
7
8
|
output?: T;
|
|
8
|
-
error:
|
|
9
|
+
error: E;
|
|
9
10
|
}
|
|
10
|
-
|
|
11
|
-
code: string;
|
|
12
|
-
message?: string;
|
|
13
|
-
}
|
|
14
|
-
export {};
|
|
11
|
+
export type Faulty<T extends Record<string, unknown>> = Record<keyof T, T[keyof T] | Err>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Resource } from './Resource';
|
|
2
|
+
import type { Events } from './Evt';
|
|
3
|
+
import type { Emitter } from 'mitt';
|
|
4
|
+
/** Resoruce factory */
|
|
5
|
+
declare class Origin {
|
|
6
|
+
readonly events: Emitter<Events>;
|
|
7
|
+
private readonly agent;
|
|
8
|
+
constructor(options: Options);
|
|
9
|
+
resource<T = unknown>(path: string): Resource<T, import("./Error").GenericError>;
|
|
10
|
+
authenticate(challenge: string | null): void;
|
|
11
|
+
use(fetch: Fetch): void;
|
|
12
|
+
}
|
|
13
|
+
declare function connect(options: Options): Origin;
|
|
14
|
+
interface Options {
|
|
15
|
+
origin: string;
|
|
16
|
+
}
|
|
17
|
+
type Fetch = typeof fetch;
|
|
18
|
+
export { connect };
|