@syncular/transport-http 0.0.6-185 → 0.0.6-201
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/README.md +1 -1
- package/dist/api-client.d.ts +11 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +30 -0
- package/dist/api-client.js.map +1 -0
- package/dist/blob.d.ts +6 -0
- package/dist/blob.d.ts.map +1 -0
- package/dist/blob.js +46 -0
- package/dist/blob.js.map +1 -0
- package/dist/generated/api.d.ts +42 -33
- package/dist/generated/api.d.ts.map +1 -1
- package/dist/index.d.ts +10 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -238
- package/dist/index.js.map +1 -1
- package/dist/shared.d.ts +36 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +74 -0
- package/dist/shared.js.map +1 -0
- package/dist/transport-client.d.ts +31 -0
- package/dist/transport-client.d.ts.map +1 -0
- package/dist/transport-client.js +189 -0
- package/dist/transport-client.js.map +1 -0
- package/package.json +10 -2
- package/src/api-client.ts +39 -0
- package/src/blob.ts +95 -0
- package/src/generated/api.ts +42 -33
- package/src/index.ts +46 -367
- package/src/shared.ts +146 -0
- package/src/transport-client.ts +307 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { encodeSnapshotScopes, resolveRequestUrl, SNAPSHOT_SCOPES_HEADER, } from './shared.js';
|
|
2
|
+
export const HTTP_TRANSPORT_SOURCE = Symbol.for('@syncular/transport-http/source');
|
|
3
|
+
function isApiClientLike(value) {
|
|
4
|
+
return (typeof value === 'object' &&
|
|
5
|
+
value !== null &&
|
|
6
|
+
typeof value.GET === 'function' &&
|
|
7
|
+
typeof value.POST === 'function');
|
|
8
|
+
}
|
|
9
|
+
function isJsonContentType(contentType) {
|
|
10
|
+
return contentType?.includes('application/json') === true;
|
|
11
|
+
}
|
|
12
|
+
async function parseErrorBody(response) {
|
|
13
|
+
if (!isJsonContentType(response.headers.get('content-type'))) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
return (await response.json());
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function parseJsonBody(response) {
|
|
24
|
+
if (!isJsonContentType(response.headers.get('content-type'))) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return (await response.json());
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function createAuthRetryResolver(defaultAuthLifecycle) {
|
|
35
|
+
let refreshInFlight = null;
|
|
36
|
+
const runRefreshSingleFlight = async (lifecycle, context) => {
|
|
37
|
+
if (!lifecycle.refreshToken)
|
|
38
|
+
return false;
|
|
39
|
+
if (!refreshInFlight) {
|
|
40
|
+
refreshInFlight = Promise.resolve(lifecycle.refreshToken(context))
|
|
41
|
+
.then((result) => Boolean(result))
|
|
42
|
+
.finally(() => {
|
|
43
|
+
refreshInFlight = null;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return refreshInFlight;
|
|
47
|
+
};
|
|
48
|
+
return async (context, options) => {
|
|
49
|
+
if (options?.onAuthError) {
|
|
50
|
+
return Boolean(await options.onAuthError());
|
|
51
|
+
}
|
|
52
|
+
const lifecycle = options?.authLifecycle ?? defaultAuthLifecycle;
|
|
53
|
+
if (!lifecycle)
|
|
54
|
+
return false;
|
|
55
|
+
await lifecycle.onAuthExpired?.(context);
|
|
56
|
+
const refreshResult = await runRefreshSingleFlight(lifecycle, context);
|
|
57
|
+
if (lifecycle.retryWithFreshToken) {
|
|
58
|
+
return Boolean(await lifecycle.retryWithFreshToken({ ...context, refreshResult }));
|
|
59
|
+
}
|
|
60
|
+
return refreshResult;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function createRequestHeaders(baseOptions, extraHeaders) {
|
|
64
|
+
return Promise.resolve(baseOptions.getHeaders?.()).then((dynamicHeaders) => {
|
|
65
|
+
const headers = new Headers(extraHeaders);
|
|
66
|
+
if (dynamicHeaders) {
|
|
67
|
+
for (const [key, value] of Object.entries(dynamicHeaders)) {
|
|
68
|
+
headers.set(key, value);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (!headers.has('x-syncular-transport-path')) {
|
|
72
|
+
headers.set('x-syncular-transport-path', baseOptions.transportPath ?? 'direct');
|
|
73
|
+
}
|
|
74
|
+
return headers;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function createFetchApiClient(baseOptions) {
|
|
78
|
+
const fetchImpl = baseOptions.fetch ?? globalThis.fetch;
|
|
79
|
+
const request = async (args) => {
|
|
80
|
+
const headers = await createRequestHeaders(baseOptions, args.headers);
|
|
81
|
+
let body;
|
|
82
|
+
if (args.body !== undefined) {
|
|
83
|
+
headers.set('content-type', 'application/json');
|
|
84
|
+
body = JSON.stringify(args.body);
|
|
85
|
+
}
|
|
86
|
+
const response = await fetchImpl(resolveRequestUrl(baseOptions.baseUrl, args.path), {
|
|
87
|
+
method: args.method,
|
|
88
|
+
headers,
|
|
89
|
+
body,
|
|
90
|
+
...(args.signal ? { signal: args.signal } : {}),
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
return {
|
|
94
|
+
response,
|
|
95
|
+
error: await parseErrorBody(response),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (args.parseAs === 'blob') {
|
|
99
|
+
return {
|
|
100
|
+
response,
|
|
101
|
+
data: (await response.blob()),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
response,
|
|
106
|
+
data: await parseJsonBody(response),
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
sync: (requestBody, signal) => request({
|
|
111
|
+
method: 'POST',
|
|
112
|
+
path: '/sync',
|
|
113
|
+
body: requestBody,
|
|
114
|
+
signal,
|
|
115
|
+
}),
|
|
116
|
+
initiateUpload: (args, signal) => request({
|
|
117
|
+
method: 'POST',
|
|
118
|
+
path: '/sync/blobs/upload',
|
|
119
|
+
body: args,
|
|
120
|
+
signal,
|
|
121
|
+
}),
|
|
122
|
+
completeUpload: (hash, signal) => request({
|
|
123
|
+
method: 'POST',
|
|
124
|
+
path: `/sync/blobs/${encodeURIComponent(hash)}/complete`,
|
|
125
|
+
signal,
|
|
126
|
+
}),
|
|
127
|
+
getDownloadUrl: (hash, signal) => request({
|
|
128
|
+
method: 'GET',
|
|
129
|
+
path: `/sync/blobs/${encodeURIComponent(hash)}/url`,
|
|
130
|
+
signal,
|
|
131
|
+
}),
|
|
132
|
+
getSnapshotChunk: (chunkId, scopeValues, signal) => request({
|
|
133
|
+
method: 'GET',
|
|
134
|
+
path: `/sync/snapshot-chunks/${encodeURIComponent(chunkId)}`,
|
|
135
|
+
headers: (() => {
|
|
136
|
+
const encodedScopes = encodeSnapshotScopes(scopeValues);
|
|
137
|
+
return encodedScopes
|
|
138
|
+
? {
|
|
139
|
+
[SNAPSHOT_SCOPES_HEADER]: encodedScopes,
|
|
140
|
+
}
|
|
141
|
+
: undefined;
|
|
142
|
+
})(),
|
|
143
|
+
signal,
|
|
144
|
+
parseAs: 'blob',
|
|
145
|
+
}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function createTypedTransportClient(client) {
|
|
149
|
+
return {
|
|
150
|
+
sync: (request, signal) => client.POST('/sync', {
|
|
151
|
+
body: request,
|
|
152
|
+
...(signal ? { signal } : {}),
|
|
153
|
+
}),
|
|
154
|
+
initiateUpload: (args, signal) => client.POST('/sync/blobs/upload', {
|
|
155
|
+
body: args,
|
|
156
|
+
...(signal ? { signal } : {}),
|
|
157
|
+
}),
|
|
158
|
+
completeUpload: (hash, signal) => client.POST('/sync/blobs/{hash}/complete', {
|
|
159
|
+
params: { path: { hash } },
|
|
160
|
+
...(signal ? { signal } : {}),
|
|
161
|
+
}),
|
|
162
|
+
getDownloadUrl: (hash, signal) => client.GET('/sync/blobs/{hash}/url', {
|
|
163
|
+
params: { path: { hash } },
|
|
164
|
+
...(signal ? { signal } : {}),
|
|
165
|
+
}),
|
|
166
|
+
getSnapshotChunk: (chunkId, scopeValues, signal) => client.GET('/sync/snapshot-chunks/{chunkId}', {
|
|
167
|
+
params: { path: { chunkId } },
|
|
168
|
+
parseAs: 'blob',
|
|
169
|
+
headers: (() => {
|
|
170
|
+
const encodedScopes = encodeSnapshotScopes(scopeValues);
|
|
171
|
+
return encodedScopes
|
|
172
|
+
? {
|
|
173
|
+
[SNAPSHOT_SCOPES_HEADER]: encodedScopes,
|
|
174
|
+
}
|
|
175
|
+
: undefined;
|
|
176
|
+
})(),
|
|
177
|
+
...(signal ? { signal } : {}),
|
|
178
|
+
}),
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
export function createTransportApiClient(source) {
|
|
182
|
+
return isApiClientLike(source)
|
|
183
|
+
? createTypedTransportClient(source)
|
|
184
|
+
: createFetchApiClient(source);
|
|
185
|
+
}
|
|
186
|
+
export function createTransportAuthRetryResolver(source) {
|
|
187
|
+
return createAuthRetryResolver(isApiClientLike(source) ? undefined : source.authLifecycle);
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=transport-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport-client.js","sourceRoot":"","sources":["../src/transport-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/transport-http",
|
|
3
|
-
"version": "0.0.6-
|
|
3
|
+
"version": "0.0.6-201",
|
|
4
4
|
"description": "HTTP transport for Syncular client-server communication",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"fetch"
|
|
24
24
|
],
|
|
25
25
|
"private": false,
|
|
26
|
+
"sideEffects": false,
|
|
26
27
|
"publishConfig": {
|
|
27
28
|
"access": "public"
|
|
28
29
|
},
|
|
@@ -34,6 +35,13 @@
|
|
|
34
35
|
"types": "./dist/index.d.ts",
|
|
35
36
|
"default": "./dist/index.js"
|
|
36
37
|
}
|
|
38
|
+
},
|
|
39
|
+
"./blob": {
|
|
40
|
+
"bun": "./src/blob.ts",
|
|
41
|
+
"import": {
|
|
42
|
+
"types": "./dist/blob.d.ts",
|
|
43
|
+
"default": "./dist/blob.js"
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
},
|
|
39
47
|
"scripts": {
|
|
@@ -43,7 +51,7 @@
|
|
|
43
51
|
"release": "bunx syncular-publish"
|
|
44
52
|
},
|
|
45
53
|
"dependencies": {
|
|
46
|
-
"@syncular/core": "0.0.6-
|
|
54
|
+
"@syncular/core": "0.0.6-201",
|
|
47
55
|
"openapi-fetch": "^0.17.0"
|
|
48
56
|
},
|
|
49
57
|
"devDependencies": {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import createClient from 'openapi-fetch';
|
|
2
|
+
import type { paths } from './generated/api';
|
|
3
|
+
import type { ClientOptions } from './shared';
|
|
4
|
+
|
|
5
|
+
export type SyncClient = ReturnType<typeof createClient<paths>>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Create a typed API client for the full Syncular API.
|
|
9
|
+
*
|
|
10
|
+
* Returns an openapi-fetch client with full type safety for all endpoints.
|
|
11
|
+
*/
|
|
12
|
+
export function createApiClient(options: ClientOptions): SyncClient {
|
|
13
|
+
const client = createClient<paths>({
|
|
14
|
+
baseUrl: options.baseUrl,
|
|
15
|
+
...(options.fetch && { fetch: options.fetch }),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const getHeaders = options.getHeaders;
|
|
19
|
+
const transportPath = options.transportPath ?? 'direct';
|
|
20
|
+
|
|
21
|
+
client.use({
|
|
22
|
+
async onRequest({ request }) {
|
|
23
|
+
if (getHeaders) {
|
|
24
|
+
const headers = await getHeaders();
|
|
25
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
26
|
+
request.headers.set(key, value);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (!request.headers.has('x-syncular-transport-path')) {
|
|
31
|
+
request.headers.set('x-syncular-transport-path', transportPath);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return request;
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return client;
|
|
39
|
+
}
|
package/src/blob.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { SyncTransport, SyncTransportBlobs } from '@syncular/core';
|
|
2
|
+
import { SyncTransportError } from '@syncular/core';
|
|
3
|
+
import { executeWithAuthRetry, getErrorMessage } from './shared';
|
|
4
|
+
import {
|
|
5
|
+
createTransportApiClient,
|
|
6
|
+
createTransportAuthRetryResolver,
|
|
7
|
+
HTTP_TRANSPORT_SOURCE,
|
|
8
|
+
type HttpTransportSource,
|
|
9
|
+
} from './transport-client';
|
|
10
|
+
|
|
11
|
+
type HttpTransportWithSource = SyncTransport & {
|
|
12
|
+
[HTTP_TRANSPORT_SOURCE]?: HttpTransportSource;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function createHttpTransportBlobs(
|
|
16
|
+
source: HttpTransportSource
|
|
17
|
+
): SyncTransportBlobs {
|
|
18
|
+
const client = createTransportApiClient(source);
|
|
19
|
+
const resolveAuthRetry = createTransportAuthRetryResolver(source);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
async initiateUpload(args) {
|
|
23
|
+
const { data, error, response } = await executeWithAuthRetry(
|
|
24
|
+
(signal) => client.initiateUpload(args, signal),
|
|
25
|
+
undefined,
|
|
26
|
+
'blobInitiateUpload',
|
|
27
|
+
resolveAuthRetry
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (error || !data) {
|
|
31
|
+
throw new SyncTransportError(
|
|
32
|
+
`Blob upload init failed: ${getErrorMessage(error) || response.statusText}`,
|
|
33
|
+
response.status
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return data;
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
async completeUpload(hash) {
|
|
41
|
+
const { data, error } = await executeWithAuthRetry(
|
|
42
|
+
(signal) => client.completeUpload(hash, signal),
|
|
43
|
+
undefined,
|
|
44
|
+
'blobCompleteUpload',
|
|
45
|
+
resolveAuthRetry
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (error || !data) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
error: getErrorMessage(error) || 'Complete upload failed',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return data;
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
async getDownloadUrl(hash) {
|
|
59
|
+
const { data, error, response } = await executeWithAuthRetry(
|
|
60
|
+
(signal) => client.getDownloadUrl(hash, signal),
|
|
61
|
+
undefined,
|
|
62
|
+
'blobGetDownloadUrl',
|
|
63
|
+
resolveAuthRetry
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
if (error || !data) {
|
|
67
|
+
throw new SyncTransportError(
|
|
68
|
+
`Get download URL failed: ${getErrorMessage(error) || response.statusText}`,
|
|
69
|
+
response.status
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return data;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function ensureHttpTransportBlobs(
|
|
79
|
+
transport: SyncTransport
|
|
80
|
+
): SyncTransportBlobs | null {
|
|
81
|
+
if (transport.blobs) {
|
|
82
|
+
return transport.blobs;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const source = (transport as HttpTransportWithSource)[HTTP_TRANSPORT_SOURCE];
|
|
86
|
+
if (!source) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const blobs = createHttpTransportBlobs(source);
|
|
91
|
+
transport.blobs = blobs;
|
|
92
|
+
return blobs;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type { SyncClient } from './api-client';
|
package/src/generated/api.ts
CHANGED
|
@@ -739,18 +739,20 @@ export interface operations {
|
|
|
739
739
|
"application/json": {
|
|
740
740
|
clientId: string;
|
|
741
741
|
push?: {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
742
|
+
commits: {
|
|
743
|
+
clientCommitId: string;
|
|
744
|
+
operations: {
|
|
745
|
+
table: string;
|
|
746
|
+
row_id: string;
|
|
747
|
+
/** @enum {string} */
|
|
748
|
+
op: "upsert" | "delete";
|
|
749
|
+
payload: {
|
|
750
|
+
[key: string]: unknown;
|
|
751
|
+
} | null;
|
|
752
|
+
base_version?: number | null;
|
|
753
|
+
}[];
|
|
754
|
+
schemaVersion: number;
|
|
752
755
|
}[];
|
|
753
|
-
schemaVersion: number;
|
|
754
756
|
};
|
|
755
757
|
pull?: {
|
|
756
758
|
limitCommits: number;
|
|
@@ -791,28 +793,33 @@ export interface operations {
|
|
|
791
793
|
push?: {
|
|
792
794
|
/** @constant */
|
|
793
795
|
ok: true;
|
|
794
|
-
|
|
795
|
-
status: "applied" | "cached" | "rejected";
|
|
796
|
-
commitSeq?: number;
|
|
797
|
-
results: ({
|
|
798
|
-
opIndex: number;
|
|
799
|
-
/** @constant */
|
|
800
|
-
status: "applied";
|
|
801
|
-
} | {
|
|
802
|
-
opIndex: number;
|
|
796
|
+
commits: {
|
|
803
797
|
/** @constant */
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
798
|
+
ok: true;
|
|
799
|
+
/** @enum {string} */
|
|
800
|
+
status: "applied" | "cached" | "rejected";
|
|
801
|
+
commitSeq?: number;
|
|
802
|
+
results: ({
|
|
803
|
+
opIndex: number;
|
|
804
|
+
/** @constant */
|
|
805
|
+
status: "applied";
|
|
806
|
+
} | {
|
|
807
|
+
opIndex: number;
|
|
808
|
+
/** @constant */
|
|
809
|
+
status: "conflict";
|
|
810
|
+
message: string;
|
|
811
|
+
server_version: number;
|
|
812
|
+
server_row: unknown;
|
|
813
|
+
} | {
|
|
814
|
+
opIndex: number;
|
|
815
|
+
/** @constant */
|
|
816
|
+
status: "error";
|
|
817
|
+
error: string;
|
|
818
|
+
code?: string;
|
|
819
|
+
retriable?: boolean;
|
|
820
|
+
})[];
|
|
821
|
+
clientCommitId: string;
|
|
822
|
+
}[];
|
|
816
823
|
};
|
|
817
824
|
pull?: {
|
|
818
825
|
/** @constant */
|
|
@@ -898,7 +905,9 @@ export interface operations {
|
|
|
898
905
|
};
|
|
899
906
|
getSyncSnapshotChunksByChunkId: {
|
|
900
907
|
parameters: {
|
|
901
|
-
query?:
|
|
908
|
+
query?: {
|
|
909
|
+
scopes?: string;
|
|
910
|
+
};
|
|
902
911
|
header?: never;
|
|
903
912
|
path: {
|
|
904
913
|
chunkId: string;
|