@svadmin/supabase 0.13.9 → 0.15.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/package.json +7 -7
- package/src/audit-handler.ts +59 -10
- package/src/auth-contract.ts +169 -0
- package/src/auth-provider.ts +262 -123
- package/src/data-provider.ts +112 -178
- package/src/index.ts +16 -11
- package/src/live-provider.ts +193 -75
- package/src/permission-adapter.ts +28 -0
- package/src/rpc.ts +11 -29
- package/src/sdk-boundary.ts +79 -0
- package/src/supacloud.ts +220 -594
package/src/supacloud.ts
CHANGED
|
@@ -1,660 +1,286 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
status:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
[
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export type
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
reconcileIntervalMs?: number;
|
|
42
|
-
onUpdate: (task: TTask) => void;
|
|
43
|
-
onStateChange?: (state: SupaCloudTaskSubscribeState, details?: { error?: unknown }) => void;
|
|
44
|
-
onError?: (error: unknown) => void;
|
|
45
|
-
stopOnTerminal?: boolean;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface SupaCloudSdkTaskWaitOptions {
|
|
49
|
-
intervalMs?: number;
|
|
50
|
-
signal?: AbortSignal;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface SupaCloudSdkTaskSubmitOptions {
|
|
54
|
-
body?: string
|
|
55
|
-
| Blob
|
|
56
|
-
| ArrayBuffer
|
|
57
|
-
| FormData
|
|
58
|
-
| File
|
|
59
|
-
| ReadableStream<Uint8Array>
|
|
60
|
-
| Record<string, unknown>;
|
|
1
|
+
import { Type, type Static, type TSchema } from '@sinclair/typebox';
|
|
2
|
+
import type { LiveEvent, LiveProvider, TaskHandle, TaskProvider, TaskRecord, SubmitTaskOptions } from '@svadmin/core';
|
|
3
|
+
import { definedOptions } from '@svadmin/core/options';
|
|
4
|
+
import { checkExact, decodeTaskRecord, decodeTaskSubmitOptions, snapshotPlainData, TaskError, validatedTaskSubscription, taskClientField, requiredTaskClientMethod } from '@svadmin/core/schema';
|
|
5
|
+
|
|
6
|
+
const text = Type.String({ minLength: 1 });
|
|
7
|
+
const idSchema = Type.String({ pattern: '^[A-Za-z0-9][A-Za-z0-9_.:-]*$' });
|
|
8
|
+
const nameSchema = Type.String({ pattern: '^[A-Za-z0-9][A-Za-z0-9_.-]*(/[A-Za-z0-9][A-Za-z0-9_.-]*)*$' });
|
|
9
|
+
const statusSchema = Type.Union([
|
|
10
|
+
Type.Literal('pending'), Type.Literal('leased'), Type.Literal('running'),
|
|
11
|
+
Type.Literal('retry_scheduled'), Type.Literal('succeeded'), Type.Literal('failed'),
|
|
12
|
+
Type.Literal('dead_lettered'), Type.Literal('cancelled'), Type.Literal('queued'),
|
|
13
|
+
Type.Literal('processing'), Type.Literal('completed'), Type.Literal('enqueued'),
|
|
14
|
+
]);
|
|
15
|
+
const filterValue = Type.Union([text, Type.Array(text, { minItems: 1 })]);
|
|
16
|
+
const limitSchema = Type.Integer({ minimum: 1, maximum: Number.MAX_SAFE_INTEGER });
|
|
17
|
+
const listSchema = Type.Object({
|
|
18
|
+
status: Type.Optional(filterValue), taskType: Type.Optional(filterValue),
|
|
19
|
+
functionSlug: Type.Optional(text), dlq: Type.Optional(Type.Boolean()), limit: Type.Optional(limitSchema),
|
|
20
|
+
}, { additionalProperties: false });
|
|
21
|
+
const dlqSchema = Type.Object({ limit: Type.Optional(limitSchema) }, { additionalProperties: false });
|
|
22
|
+
const snapshotSchema = Type.Object({
|
|
23
|
+
id: idSchema, status: statusSchema, raw: Type.Unknown(),
|
|
24
|
+
progress: Type.Optional(Type.Union([Type.Number({ minimum: 0, maximum: 100 }), Type.Null()])),
|
|
25
|
+
error: Type.Optional(Type.Union([Type.String(), Type.Null()])),
|
|
26
|
+
updatedAt: Type.Optional(Type.Union([text, Type.Null()])),
|
|
27
|
+
}, { additionalProperties: false });
|
|
28
|
+
const liveParamsSchema = Type.Object({ taskId: idSchema }, { additionalProperties: false });
|
|
29
|
+
const eventSchema = Type.Object({
|
|
30
|
+
type: Type.Union([Type.Literal('INSERT'), Type.Literal('UPDATE'), Type.Literal('DELETE')]),
|
|
31
|
+
resource: text, payload: Type.Record(Type.String(), Type.Unknown()),
|
|
32
|
+
}, { additionalProperties: false });
|
|
33
|
+
const terminal = new Set<string>(['succeeded', 'failed', 'dead_lettered', 'cancelled', 'completed']);
|
|
34
|
+
|
|
35
|
+
export type SupaCloudTaskRecord = TaskRecord & { status: Static<typeof statusSchema> };
|
|
36
|
+
export type SupaCloudTaskListParams = Static<typeof listSchema>;
|
|
37
|
+
export type SupaCloudTaskDlqParams = Static<typeof dlqSchema>;
|
|
38
|
+
|
|
39
|
+
export interface SupaCloudTaskSdkSubmitOptions {
|
|
40
|
+
body?: Record<string, unknown>;
|
|
61
41
|
headers?: Record<string, string>;
|
|
62
|
-
retries?: number;
|
|
63
|
-
timeoutSec?: number;
|
|
64
42
|
idempotencyKey?: string;
|
|
65
|
-
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
66
|
-
correlationId?: string;
|
|
67
|
-
businessTaskId?: string;
|
|
68
43
|
metadata?: Record<string, unknown>;
|
|
69
44
|
}
|
|
70
45
|
|
|
71
|
-
export interface
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
TWaitOptions = unknown,
|
|
75
|
-
> {
|
|
76
|
-
id?: string;
|
|
77
|
-
taskId?: string;
|
|
78
|
-
status?: string;
|
|
79
|
-
wait(options?: TWaitOptions): Promise<TTask>;
|
|
80
|
-
get?(): Promise<TTask>;
|
|
81
|
-
cancel?(): Promise<unknown>;
|
|
82
|
-
retry?(): Promise<unknown>;
|
|
83
|
-
subscribe?(
|
|
84
|
-
options: Omit<SupaCloudTaskSubscribeOptions<TUpdate>, 'onUpdate'> & {
|
|
85
|
-
onUpdate: (task: TUpdate) => void;
|
|
86
|
-
},
|
|
87
|
-
): TaskSubscription | (() => void);
|
|
46
|
+
export interface SupaCloudTaskSubscribeOptions {
|
|
47
|
+
onUpdate: (snapshot: unknown) => void;
|
|
48
|
+
onError: (error: unknown) => void;
|
|
88
49
|
}
|
|
89
50
|
|
|
90
|
-
/**
|
|
91
|
-
export interface
|
|
92
|
-
TTask = SupaCloudSdkTaskRecord,
|
|
93
|
-
TUpdate = SupaCloudTaskSnapshot,
|
|
94
|
-
> {
|
|
95
|
-
submit(
|
|
96
|
-
taskName: string,
|
|
97
|
-
options?: SupaCloudSdkTaskSubmitOptions,
|
|
98
|
-
): Promise<SupaCloudTaskReceipt<TTask, TUpdate, SupaCloudSdkTaskWaitOptions>>;
|
|
99
|
-
get(taskId: string): Promise<TTask>;
|
|
100
|
-
list?(params?: {
|
|
101
|
-
status?: string | string[];
|
|
102
|
-
taskType?: string | string[];
|
|
103
|
-
functionSlug?: string;
|
|
104
|
-
dlq?: boolean;
|
|
105
|
-
limit?: number;
|
|
106
|
-
}): Promise<TTask[]>;
|
|
107
|
-
listDlq?(limit?: number): Promise<TTask[]>;
|
|
108
|
-
cancel?(taskId: string): Promise<unknown>;
|
|
109
|
-
retry?(taskId: string): Promise<unknown>;
|
|
110
|
-
subscribe?(
|
|
111
|
-
taskId: string,
|
|
112
|
-
options: Omit<SupaCloudTaskSubscribeOptions<TUpdate>, 'onUpdate'> & {
|
|
113
|
-
onUpdate: (task: TUpdate) => void;
|
|
114
|
-
},
|
|
115
|
-
): TaskSubscription | (() => void);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** Structural shape of a root `createSupaCloudClient()` task result. */
|
|
119
|
-
export interface SupaCloudTaskSdkClient<
|
|
120
|
-
TTask = SupaCloudTaskRecord,
|
|
121
|
-
TUpdate = TTask,
|
|
122
|
-
TWaitOptions = unknown,
|
|
123
|
-
> {
|
|
51
|
+
/** SDK values stay unknown until their matching request/receipt is validated. */
|
|
52
|
+
export interface SupaCloudTaskClient {
|
|
124
53
|
tasks: {
|
|
125
|
-
submit(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
): Promise<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
cancel?(taskId: string): Promise<unknown>;
|
|
133
|
-
retry?(taskId: string): Promise<unknown>;
|
|
134
|
-
subscribe?(
|
|
135
|
-
taskId: string,
|
|
136
|
-
options: Omit<SupaCloudTaskSubscribeOptions<TUpdate>, 'onUpdate'> & {
|
|
137
|
-
onUpdate: (task: TUpdate) => void;
|
|
138
|
-
},
|
|
139
|
-
): TaskSubscription | (() => void);
|
|
54
|
+
submit(name: string, options?: SupaCloudTaskSdkSubmitOptions): Promise<unknown>;
|
|
55
|
+
get(id: string): Promise<unknown>;
|
|
56
|
+
list(params?: SupaCloudTaskListParams): Promise<unknown>;
|
|
57
|
+
listDlq(limit?: number): Promise<unknown>;
|
|
58
|
+
cancel(id: string): Promise<unknown>;
|
|
59
|
+
retry(id: string): Promise<unknown>;
|
|
60
|
+
subscribe(id: string, options: SupaCloudTaskSubscribeOptions): unknown;
|
|
140
61
|
};
|
|
141
62
|
}
|
|
142
63
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
export interface SupaCloudTaskLegacyClient<TTask extends SupaCloudTaskRecord = SupaCloudTaskRecord> {
|
|
150
|
-
submit(taskName: string, options?: SubmitTaskOptions): Promise<TaskHandle<TTask>>;
|
|
151
|
-
get(taskId: string): Promise<TTask>;
|
|
152
|
-
list?(params?: Record<string, unknown>): Promise<TTask[] | { data?: TTask[] }>;
|
|
153
|
-
listDlq?(params?: Record<string, unknown>): Promise<TTask[] | { data?: TTask[] }>;
|
|
154
|
-
cancel?(taskId: string): Promise<unknown>;
|
|
155
|
-
retry?(taskId: string): Promise<unknown>;
|
|
156
|
-
subscribe?(
|
|
157
|
-
taskId: string,
|
|
158
|
-
callback: (task: TTask) => void
|
|
159
|
-
): TaskSubscription | (() => void) | undefined;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** Supported task-client shapes: the legacy root methods or a root SDK client. */
|
|
163
|
-
export type SupaCloudTaskClient<TTask extends SupaCloudTaskRecord = SupaCloudTaskRecord> =
|
|
164
|
-
| SupaCloudTaskLegacyClient<TTask>
|
|
165
|
-
| SupaCloudTaskSdkClient<TTask>
|
|
166
|
-
| CurrentSupaCloudSdkRootClient;
|
|
167
|
-
|
|
168
|
-
interface LegacyTaskProviderOptions<TTask extends SupaCloudTaskRecord> {
|
|
169
|
-
supacloud: SupaCloudTaskLegacyClient<TTask>;
|
|
170
|
-
clientKind?: 'legacy';
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
interface SdkTaskProviderOptions<TTask extends SupaCloudTaskRecord> {
|
|
174
|
-
supacloud:
|
|
175
|
-
| SupaCloudSdkTaskClient
|
|
176
|
-
| SupaCloudTaskSdkClient<TTask>
|
|
177
|
-
| CurrentSupaCloudSdkRootClient;
|
|
178
|
-
clientKind: 'sdk';
|
|
64
|
+
export interface SupaCloudTaskHandle extends TaskHandle<SupaCloudTaskRecord> {
|
|
65
|
+
id: string;
|
|
66
|
+
cancel(): Promise<SupaCloudTaskRecord>;
|
|
67
|
+
retry(): Promise<SupaCloudTaskRecord>;
|
|
68
|
+
subscribe(callback: (task: SupaCloudTaskRecord) => void, onError?: (error: TaskError) => void): () => void;
|
|
179
69
|
}
|
|
180
70
|
|
|
181
|
-
interface
|
|
182
|
-
|
|
183
|
-
|
|
71
|
+
export interface SupaCloudTaskProvider extends TaskProvider<SupaCloudTaskRecord> {
|
|
72
|
+
submit(name: string, options?: SubmitTaskOptions): Promise<SupaCloudTaskHandle>;
|
|
73
|
+
list(params?: SupaCloudTaskListParams): Promise<{ data: SupaCloudTaskRecord[]; total: number }>;
|
|
74
|
+
listDlq(params?: SupaCloudTaskDlqParams): Promise<{ data: SupaCloudTaskRecord[]; total: number }>;
|
|
75
|
+
cancel(id: string): Promise<SupaCloudTaskRecord>;
|
|
76
|
+
retry(id: string): Promise<SupaCloudTaskRecord>;
|
|
77
|
+
subscribe(id: string, callback: (task: SupaCloudTaskRecord) => void, onError?: (error: TaskError) => void): () => void;
|
|
184
78
|
}
|
|
185
79
|
|
|
186
|
-
export
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
| SdkTaskProviderOptions<TTask>
|
|
190
|
-
| AutoSdkTaskProviderOptions<TTask>;
|
|
191
|
-
|
|
192
|
-
interface LegacyTaskLiveProviderOptions<TTask extends SupaCloudTaskRecord> {
|
|
193
|
-
supacloud: Pick<SupaCloudTaskLegacyClient<TTask>, 'subscribe'>;
|
|
194
|
-
clientKind?: 'legacy';
|
|
195
|
-
resource?: string;
|
|
196
|
-
mapTaskToEvent?: (task: TTask, resource: string) => LiveEvent;
|
|
80
|
+
export interface CreateSupaCloudTaskProviderOptions {
|
|
81
|
+
supacloud: SupaCloudTaskClient;
|
|
82
|
+
onError?: (error: TaskError) => void;
|
|
197
83
|
}
|
|
198
84
|
|
|
199
|
-
interface
|
|
200
|
-
supacloud:
|
|
201
|
-
| Pick<SupaCloudSdkTaskClient, 'subscribe'>
|
|
202
|
-
| SupaCloudTaskSdkClient<TTask>
|
|
203
|
-
| CurrentSupaCloudSdkRootClient;
|
|
204
|
-
clientKind: 'sdk';
|
|
85
|
+
export interface CreateSupaCloudTaskLiveProviderOptions {
|
|
86
|
+
supacloud: { tasks: Pick<SupaCloudTaskClient['tasks'], 'subscribe'> };
|
|
205
87
|
resource?: string;
|
|
206
|
-
mapTaskToEvent?: (task:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
interface AutoSdkTaskLiveProviderOptions<TTask extends SupaCloudTaskRecord> {
|
|
210
|
-
supacloud: SupaCloudTaskSdkClient<TTask> | CurrentSupaCloudSdkRootClient;
|
|
211
|
-
clientKind?: undefined;
|
|
212
|
-
resource?: string;
|
|
213
|
-
mapTaskToEvent?: (task: TTask, resource: string) => LiveEvent;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export type CreateSupaCloudTaskLiveProviderOptions<
|
|
217
|
-
TTask extends SupaCloudTaskRecord = SupaCloudTaskRecord,
|
|
218
|
-
> = LegacyTaskLiveProviderOptions<TTask>
|
|
219
|
-
| SdkTaskLiveProviderOptions<TTask>
|
|
220
|
-
| AutoSdkTaskLiveProviderOptions<TTask>;
|
|
221
|
-
|
|
222
|
-
function normalizeTaskSubscription(subscription: unknown): (() => void) | undefined {
|
|
223
|
-
if (!subscription) return undefined;
|
|
224
|
-
if (typeof subscription === 'function') return subscription as () => void;
|
|
225
|
-
if (
|
|
226
|
-
typeof subscription === 'object'
|
|
227
|
-
&& subscription !== null
|
|
228
|
-
&& 'unsubscribe' in subscription
|
|
229
|
-
&& typeof subscription.unsubscribe === 'function'
|
|
230
|
-
) {
|
|
231
|
-
const unsubscribe = (subscription as { unsubscribe: () => void }).unsubscribe;
|
|
232
|
-
return () => unsubscribe.call(subscription);
|
|
233
|
-
}
|
|
234
|
-
return undefined;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function readSdkTaskSubscription(subscription: unknown, operation: string): () => void {
|
|
238
|
-
const unsubscribe = normalizeTaskSubscription(subscription);
|
|
239
|
-
if (!unsubscribe) {
|
|
240
|
-
throw invalidSdkResponse(operation, 'an invalid task subscription');
|
|
241
|
-
}
|
|
242
|
-
return unsubscribe;
|
|
88
|
+
mapTaskToEvent?: (task: SupaCloudTaskRecord, resource: string) => unknown;
|
|
89
|
+
onError?: (error: TaskError) => void;
|
|
243
90
|
}
|
|
244
91
|
|
|
245
|
-
function
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
249
|
-
|
|
250
|
-
|
|
92
|
+
function decode<S extends TSchema>(schema: S, value: unknown, input = false, write = false): Static<S> {
|
|
93
|
+
try {
|
|
94
|
+
const candidate = snapshotPlainData(value);
|
|
95
|
+
if (checkExact(schema, candidate)) return candidate;
|
|
96
|
+
} catch {
|
|
97
|
+
// Reflection and raw SDK errors must not escape this boundary.
|
|
251
98
|
}
|
|
252
|
-
|
|
253
|
-
return { data: payload.data as TTask[], total: payload.data.length };
|
|
254
|
-
}
|
|
255
|
-
throw new Error(`[svadmin/supabase] ${context} returned an invalid task list response`);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function invalidSdkResponse(operation: string, reason: string): TypeError {
|
|
259
|
-
return new TypeError(`[svadmin/supabase] SupaCloud SDK ${operation} returned ${reason}`);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function isObjectRecord(payload: unknown): payload is Record<string, unknown> {
|
|
263
|
-
return typeof payload === 'object' && payload !== null && !Array.isArray(payload);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function isSdkRootClient(
|
|
267
|
-
payload: unknown,
|
|
268
|
-
): payload is SupaCloudTaskSdkClient {
|
|
269
|
-
return isObjectRecord(payload) && isObjectRecord(payload.tasks);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
interface ResolvedSdkTaskClient {
|
|
273
|
-
submit(taskName: string, options?: SupaCloudSdkTaskSubmitOptions): Promise<unknown>;
|
|
274
|
-
get(taskId: string): Promise<unknown>;
|
|
275
|
-
list?(params?: Record<string, unknown>): Promise<unknown>;
|
|
276
|
-
listDlq?(limit?: number): Promise<unknown>;
|
|
277
|
-
cancel?(taskId: string): Promise<unknown>;
|
|
278
|
-
retry?(taskId: string): Promise<unknown>;
|
|
279
|
-
subscribe?(
|
|
280
|
-
taskId: string,
|
|
281
|
-
options: Omit<SupaCloudTaskSubscribeOptions<unknown>, 'onUpdate'> & {
|
|
282
|
-
onUpdate: (task: unknown) => void;
|
|
283
|
-
},
|
|
284
|
-
): unknown;
|
|
99
|
+
throw new TaskError(input ? 'INVALID_TASK_INPUT' : 'INVALID_TASK_RESPONSE', write);
|
|
285
100
|
}
|
|
286
101
|
|
|
287
|
-
function
|
|
288
|
-
const
|
|
289
|
-
|
|
102
|
+
function taskRecord(value: unknown, id?: string, write = false): SupaCloudTaskRecord {
|
|
103
|
+
const task = decodeTaskRecord(value, id, write);
|
|
104
|
+
decode(idSchema, task.id, false, write);
|
|
105
|
+
return { ...task, status: decode(statusSchema, task.status, false, write) };
|
|
290
106
|
}
|
|
291
107
|
|
|
292
|
-
function
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
if (!taskId) throw invalidSdkResponse(operation, 'a task without a non-empty id');
|
|
303
|
-
return taskId;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function readSdkTaskStatus(
|
|
307
|
-
taskPayload: Record<string, unknown>,
|
|
308
|
-
rawTask: Record<string, unknown>,
|
|
309
|
-
operation: string,
|
|
310
|
-
): string {
|
|
311
|
-
const taskStatus = nonEmptyString(taskPayload.status) ?? nonEmptyString(rawTask.status);
|
|
312
|
-
if (!taskStatus) throw invalidSdkResponse(operation, 'a task without a non-empty status');
|
|
313
|
-
return taskStatus;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function validateSdkProgress(
|
|
317
|
-
taskPayload: Record<string, unknown>,
|
|
318
|
-
operation: string,
|
|
319
|
-
): void {
|
|
320
|
-
if (
|
|
321
|
-
taskPayload.progress !== undefined
|
|
322
|
-
&& taskPayload.progress !== null
|
|
323
|
-
&& (typeof taskPayload.progress !== 'number' || !Number.isFinite(taskPayload.progress))
|
|
324
|
-
) {
|
|
325
|
-
throw invalidSdkResponse(operation, 'a task with invalid progress');
|
|
108
|
+
function taskSnapshot(value: unknown, id: string): SupaCloudTaskRecord {
|
|
109
|
+
const snapshot = decode(snapshotSchema, value);
|
|
110
|
+
const task = taskRecord(snapshot.raw, id);
|
|
111
|
+
const expectedError = typeof task.error === 'string' ? task.error : task.error_message ?? null;
|
|
112
|
+
const expectedDate = task.updated_at ?? task.updatedAt ?? null;
|
|
113
|
+
if (snapshot.id !== task.id || snapshot.status !== task.status
|
|
114
|
+
|| snapshot.progress !== undefined && snapshot.progress !== (task.progress ?? null)
|
|
115
|
+
|| snapshot.error !== undefined && snapshot.error !== expectedError
|
|
116
|
+
|| snapshot.updatedAt !== undefined && snapshot.updatedAt !== expectedDate) {
|
|
117
|
+
throw new TaskError('INVALID_TASK_RESPONSE');
|
|
326
118
|
}
|
|
119
|
+
return task;
|
|
327
120
|
}
|
|
328
121
|
|
|
329
|
-
function
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
taskPayload: Record<string, unknown>,
|
|
341
|
-
operation: string,
|
|
342
|
-
): void {
|
|
343
|
-
const updatedAtPayload = taskPayload.updatedAt ?? taskPayload.updated_at;
|
|
344
|
-
if (updatedAtPayload !== undefined && updatedAtPayload !== null && typeof updatedAtPayload !== 'string') {
|
|
345
|
-
throw invalidSdkResponse(operation, 'a task with invalid updatedAt');
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function validateOptionalSdkTaskFields(
|
|
350
|
-
taskPayload: Record<string, unknown>,
|
|
351
|
-
operation: string,
|
|
352
|
-
): void {
|
|
353
|
-
validateSdkProgress(taskPayload, operation);
|
|
354
|
-
validateSdkError(taskPayload, operation);
|
|
355
|
-
validateSdkUpdatedAt(taskPayload, operation);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
function readSdkTask<TTask extends SupaCloudTaskRecord>(
|
|
359
|
-
taskPayload: unknown,
|
|
360
|
-
operation: string,
|
|
361
|
-
): TTask {
|
|
362
|
-
if (!isObjectRecord(taskPayload)) {
|
|
363
|
-
throw invalidSdkResponse(operation, 'a non-object task payload');
|
|
364
|
-
}
|
|
365
|
-
validateOptionalSdkTaskFields(taskPayload, operation);
|
|
366
|
-
|
|
367
|
-
const rawTask = isObjectRecord(taskPayload.raw) ? taskPayload.raw : taskPayload;
|
|
368
|
-
if (rawTask !== taskPayload) validateOptionalSdkTaskFields(rawTask, operation);
|
|
369
|
-
const taskId = readSdkTaskId(taskPayload, rawTask, operation);
|
|
370
|
-
const taskStatus = readSdkTaskStatus(taskPayload, rawTask, operation);
|
|
371
|
-
|
|
372
|
-
const normalizedTask: Record<string, unknown> = { ...rawTask, id: taskId, status: taskStatus };
|
|
373
|
-
const taskProgress = taskPayload.progress ?? rawTask.progress;
|
|
374
|
-
if (typeof taskProgress === 'number') normalizedTask.progress = taskProgress;
|
|
375
|
-
else delete normalizedTask.progress;
|
|
376
|
-
if (taskPayload.error === null || typeof taskPayload.error === 'string') {
|
|
377
|
-
normalizedTask.error = taskPayload.error;
|
|
378
|
-
}
|
|
379
|
-
if (taskPayload.updatedAt === null || typeof taskPayload.updatedAt === 'string') {
|
|
380
|
-
normalizedTask.updatedAt = taskPayload.updatedAt;
|
|
381
|
-
}
|
|
382
|
-
return normalizedTask as TTask;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function readSdkTaskList<TTask extends SupaCloudTaskRecord>(
|
|
386
|
-
taskListPayload: unknown,
|
|
387
|
-
operation: string,
|
|
388
|
-
): TaskListResult<TTask> {
|
|
389
|
-
if (!Array.isArray(taskListPayload)) {
|
|
390
|
-
throw invalidSdkResponse(operation, 'a non-array task list');
|
|
391
|
-
}
|
|
392
|
-
const tasks = taskListPayload.map((task) => readSdkTask<TTask>(task, operation));
|
|
393
|
-
return { data: tasks, total: tasks.length };
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
function assertOptionalReceiptMethod(
|
|
397
|
-
receipt: Record<string, unknown>,
|
|
398
|
-
method: 'cancel' | 'retry' | 'subscribe',
|
|
399
|
-
): void {
|
|
400
|
-
if (receipt[method] !== undefined && typeof receipt[method] !== 'function') {
|
|
401
|
-
throw invalidSdkResponse('submit', `a receipt with invalid ${method}`);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function readSdkReceipt(receiptPayload: unknown): SupaCloudTaskReceipt {
|
|
406
|
-
if (!isObjectRecord(receiptPayload)) {
|
|
407
|
-
throw invalidSdkResponse('submit', 'a non-object receipt');
|
|
408
|
-
}
|
|
409
|
-
if (!nonEmptyString(receiptPayload.taskId) || typeof receiptPayload.wait !== 'function') {
|
|
410
|
-
throw invalidSdkResponse('submit', 'a receipt without a non-empty taskId and wait method');
|
|
122
|
+
function ownField(value: unknown, key: string, write = false): unknown {
|
|
123
|
+
try {
|
|
124
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
125
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
126
|
+
if (descriptor && 'value' in descriptor) {
|
|
127
|
+
const field: unknown = descriptor.value;
|
|
128
|
+
return field;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} catch {
|
|
132
|
+
// Never invoke receipt or subscription accessors.
|
|
411
133
|
}
|
|
412
|
-
|
|
413
|
-
assertOptionalReceiptMethod(receiptPayload, 'retry');
|
|
414
|
-
assertOptionalReceiptMethod(receiptPayload, 'subscribe');
|
|
415
|
-
return receiptPayload as unknown as SupaCloudTaskReceipt;
|
|
134
|
+
throw new TaskError('INVALID_TASK_RESPONSE', write);
|
|
416
135
|
}
|
|
417
136
|
|
|
418
|
-
function
|
|
419
|
-
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
wait: async () => readSdkTask<TTask>(
|
|
425
|
-
await wait.call(receipt),
|
|
426
|
-
'receipt.wait',
|
|
427
|
-
),
|
|
137
|
+
function method(value: unknown, key: string, write = false): (...args: unknown[]) => unknown {
|
|
138
|
+
const callable = ownField(value, key, write);
|
|
139
|
+
if (typeof callable !== 'function') throw new TaskError('INVALID_TASK_RESPONSE', write);
|
|
140
|
+
return (...args) => {
|
|
141
|
+
const result: unknown = Reflect.apply(callable, value, args);
|
|
142
|
+
return result;
|
|
428
143
|
};
|
|
429
|
-
|
|
430
|
-
const cancel = receipt.cancel;
|
|
431
|
-
if (cancel) taskHandle.cancel = () => cancel.call(receipt);
|
|
432
|
-
const retry = receipt.retry;
|
|
433
|
-
if (retry) taskHandle.retry = () => retry.call(receipt);
|
|
434
|
-
const subscribe = receipt.subscribe;
|
|
435
|
-
if (subscribe) {
|
|
436
|
-
taskHandle.subscribe = (callback) => readSdkTaskSubscription(
|
|
437
|
-
subscribe.call(receipt, {
|
|
438
|
-
onUpdate: (task) => callback(readSdkTask<TTask>(task, 'receipt.subscribe')),
|
|
439
|
-
}),
|
|
440
|
-
'receipt.subscribe',
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
return taskHandle;
|
|
444
144
|
}
|
|
445
145
|
|
|
446
|
-
function
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
if (!submitOptions) return undefined;
|
|
450
|
-
const { meta, ...sharedOptions } = submitOptions;
|
|
451
|
-
return {
|
|
452
|
-
...sharedOptions,
|
|
453
|
-
...(meta === undefined ? {} : { metadata: meta }),
|
|
454
|
-
};
|
|
146
|
+
async function request(invoke: () => unknown, write = false): Promise<unknown> {
|
|
147
|
+
try { return await invoke(); }
|
|
148
|
+
catch { throw new TaskError('TASK_PROVIDER_FAILED', write); }
|
|
455
149
|
}
|
|
456
150
|
|
|
457
|
-
function
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
return
|
|
151
|
+
function listen(
|
|
152
|
+
start: (options: SupaCloudTaskSubscribeOptions) => unknown,
|
|
153
|
+
id: string,
|
|
154
|
+
callback: (task: SupaCloudTaskRecord) => void,
|
|
155
|
+
onError?: (error: TaskError) => void,
|
|
156
|
+
): () => void {
|
|
157
|
+
return validatedTaskSubscription(
|
|
158
|
+
(onUpdate, onFailure) => start({ onUpdate, onError: onFailure }),
|
|
159
|
+
value => taskSnapshot(value, id), callback, onError,
|
|
160
|
+
);
|
|
464
161
|
}
|
|
465
162
|
|
|
466
|
-
function
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
if (!supacloud.list) {
|
|
474
|
-
throw new Error('[svadmin/supabase] SupaCloud client does not implement tasks.list');
|
|
475
|
-
}
|
|
476
|
-
return normalizeLegacyTaskList(await supacloud.list(params), 'tasks.list');
|
|
477
|
-
},
|
|
478
|
-
async listDlq(params) {
|
|
479
|
-
if (!supacloud.listDlq) {
|
|
480
|
-
throw new Error('[svadmin/supabase] SupaCloud client does not implement tasks.listDlq');
|
|
163
|
+
function submitOptions(value: SubmitTaskOptions | undefined): SupaCloudTaskSdkSubmitOptions {
|
|
164
|
+
const input = decodeTaskSubmitOptions(value === undefined ? {} : value);
|
|
165
|
+
try {
|
|
166
|
+
if (input.headers) {
|
|
167
|
+
const headers = new Headers(input.headers);
|
|
168
|
+
if (headers.has('x-supacloud-task-metadata') || headers.has('x-supacloud-idempotency-key')) {
|
|
169
|
+
throw new TaskError('INVALID_TASK_INPUT');
|
|
481
170
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
171
|
+
}
|
|
172
|
+
if (input.idempotencyKey !== undefined) {
|
|
173
|
+
if (!input.idempotencyKey.trim()) throw new TaskError('INVALID_TASK_INPUT');
|
|
174
|
+
new Headers({ 'x-supacloud-idempotency-key': input.idempotencyKey });
|
|
175
|
+
}
|
|
176
|
+
} catch { throw new TaskError('INVALID_TASK_INPUT'); }
|
|
177
|
+
return definedOptions({
|
|
178
|
+
body: input.body, headers: input.headers, idempotencyKey: input.idempotencyKey, metadata: input.meta,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function receipt(value: unknown, onError?: (error: TaskError) => void): SupaCloudTaskHandle {
|
|
183
|
+
const id = decode(idSchema, ownField(value, 'taskId', true), false, true);
|
|
184
|
+
decode(statusSchema, ownField(value, 'status', true), false, true);
|
|
185
|
+
const wait = method(value, 'wait', true);
|
|
186
|
+
const cancel = method(value, 'cancel', true);
|
|
187
|
+
const retry = method(value, 'retry', true);
|
|
188
|
+
const subscribe = method(value, 'subscribe', true);
|
|
189
|
+
return {
|
|
190
|
+
id,
|
|
191
|
+
async wait() {
|
|
192
|
+
const task = taskRecord(await request(() => wait()), id);
|
|
193
|
+
if (!terminal.has(task.status)) throw new TaskError('INVALID_TASK_RESPONSE');
|
|
194
|
+
return task;
|
|
495
195
|
},
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
return supacloud.subscribe(taskId, callback);
|
|
196
|
+
async cancel() { return taskRecord(await request(() => cancel(), true), id, true); },
|
|
197
|
+
async retry() { return taskRecord(await request(() => retry(), true), id, true); },
|
|
198
|
+
subscribe(callback, subscriptionError) {
|
|
199
|
+
return listen(options => subscribe(options), id, callback, subscriptionError ?? onError);
|
|
501
200
|
},
|
|
502
201
|
};
|
|
503
202
|
}
|
|
504
203
|
|
|
505
|
-
function
|
|
506
|
-
supacloud
|
|
507
|
-
|
|
508
|
-
const
|
|
204
|
+
export function createSupaCloudTaskProvider(options: CreateSupaCloudTaskProviderOptions): SupaCloudTaskProvider {
|
|
205
|
+
const sdk = taskClientField(taskClientField(options, 'supacloud'), 'tasks');
|
|
206
|
+
const submit = requiredTaskClientMethod(sdk, 'submit');
|
|
207
|
+
const get = requiredTaskClientMethod(sdk, 'get');
|
|
208
|
+
const list = requiredTaskClientMethod(sdk, 'list');
|
|
209
|
+
const listDlq = requiredTaskClientMethod(sdk, 'listDlq');
|
|
210
|
+
const cancel = requiredTaskClientMethod(sdk, 'cancel');
|
|
211
|
+
const retry = requiredTaskClientMethod(sdk, 'retry');
|
|
212
|
+
const subscribe = requiredTaskClientMethod(sdk, 'subscribe');
|
|
213
|
+
const onError = errorCallback(taskClientField(options, 'onError'));
|
|
214
|
+
const listResult = (value: unknown) => {
|
|
215
|
+
const values = decode(Type.Array(Type.Unknown()), value);
|
|
216
|
+
const data = values.map(value => taskRecord(value));
|
|
217
|
+
return { data, total: data.length };
|
|
218
|
+
};
|
|
509
219
|
return {
|
|
510
|
-
async submit(
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
));
|
|
515
|
-
return adaptSdkReceipt<TTask>(receipt);
|
|
220
|
+
async submit(name, options) {
|
|
221
|
+
const taskName = decode(nameSchema, name, true);
|
|
222
|
+
const params = submitOptions(options);
|
|
223
|
+
return receipt(await request(() => submit(taskName, params), true), onError);
|
|
516
224
|
},
|
|
517
225
|
async get(taskId) {
|
|
518
|
-
|
|
226
|
+
const id = decode(idSchema, taskId, true);
|
|
227
|
+
return taskRecord(await request(() => get(id)), id);
|
|
519
228
|
},
|
|
520
229
|
async list(params) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
524
|
-
return readSdkTaskList<TTask>(await sdk.list(params), 'tasks.list');
|
|
230
|
+
const input = decode(listSchema, params === undefined ? {} : params, true);
|
|
231
|
+
return listResult(await request(() => list(input)));
|
|
525
232
|
},
|
|
526
233
|
async listDlq(params) {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
return readSdkTaskList<TTask>(
|
|
531
|
-
await sdk.listDlq(readSdkDlqLimit(params)),
|
|
532
|
-
'tasks.listDlq',
|
|
533
|
-
);
|
|
234
|
+
const input = decode(dlqSchema, params === undefined ? {} : params, true);
|
|
235
|
+
return listResult(await request(() => listDlq(input.limit)));
|
|
534
236
|
},
|
|
535
|
-
cancel(taskId) {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
return sdk.cancel(taskId);
|
|
237
|
+
async cancel(taskId) {
|
|
238
|
+
const id = decode(idSchema, taskId, true);
|
|
239
|
+
return taskRecord(await request(() => cancel(id), true), id, true);
|
|
540
240
|
},
|
|
541
|
-
retry(taskId) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
}
|
|
545
|
-
return sdk.retry(taskId);
|
|
241
|
+
async retry(taskId) {
|
|
242
|
+
const id = decode(idSchema, taskId, true);
|
|
243
|
+
return taskRecord(await request(() => retry(id), true), id, true);
|
|
546
244
|
},
|
|
547
|
-
subscribe(taskId, callback) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
return readSdkTaskSubscription(
|
|
552
|
-
sdk.subscribe(taskId, {
|
|
553
|
-
onUpdate: (task) => callback(readSdkTask<TTask>(task, 'tasks.subscribe')),
|
|
554
|
-
}),
|
|
555
|
-
'tasks.subscribe',
|
|
556
|
-
);
|
|
245
|
+
subscribe(taskId, callback, subscriptionError) {
|
|
246
|
+
const id = decode(idSchema, taskId, true);
|
|
247
|
+
return listen(options => subscribe(id, options), id, callback, subscriptionError ?? onError);
|
|
557
248
|
},
|
|
558
249
|
};
|
|
559
250
|
}
|
|
560
251
|
|
|
561
|
-
function
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return {
|
|
566
|
-
type: 'UPDATE',
|
|
567
|
-
resource,
|
|
568
|
-
payload: task as Record<string, unknown>,
|
|
569
|
-
};
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
function requiredLiveTaskId(liveParams?: Record<string, unknown>): string {
|
|
573
|
-
const taskId = nonEmptyString(liveParams?.taskId);
|
|
574
|
-
if (!taskId) {
|
|
575
|
-
throw new Error('[svadmin/supabase] createSupaCloudTaskLiveProvider requires liveParams.taskId');
|
|
576
|
-
}
|
|
577
|
-
return taskId;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
function createLegacyTaskLiveProvider<TTask extends SupaCloudTaskRecord>(
|
|
581
|
-
options: LegacyTaskLiveProviderOptions<TTask>,
|
|
582
|
-
): LiveProvider {
|
|
583
|
-
const resourceName = options.resource ?? 'tasks';
|
|
584
|
-
const mapTaskToEvent = options.mapTaskToEvent ?? defaultMapTaskToEvent<TTask>;
|
|
585
|
-
return {
|
|
586
|
-
subscribe({ resource, liveParams, callback }) {
|
|
587
|
-
if (!options.supacloud.subscribe) {
|
|
588
|
-
throw new Error('[svadmin/supabase] SupaCloud client does not implement tasks.subscribe');
|
|
589
|
-
}
|
|
590
|
-
const taskId = requiredLiveTaskId(liveParams);
|
|
591
|
-
const subscription = options.supacloud.subscribe(taskId, (task) => {
|
|
592
|
-
callback(mapTaskToEvent(task, resource || resourceName));
|
|
593
|
-
});
|
|
594
|
-
return normalizeTaskSubscription(subscription) ?? (() => {});
|
|
595
|
-
},
|
|
596
|
-
};
|
|
252
|
+
function errorCallback(value: unknown): ((error: TaskError) => unknown) | undefined {
|
|
253
|
+
if (value === undefined) return undefined;
|
|
254
|
+
if (typeof value !== 'function') throw new TaskError('INVALID_TASK_INPUT');
|
|
255
|
+
return error => { const result: unknown = Reflect.apply(value, undefined, [error]); return result; };
|
|
597
256
|
}
|
|
598
257
|
|
|
599
|
-
function
|
|
600
|
-
options
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
)
|
|
606
|
-
const
|
|
607
|
-
const resourceName = options.resource ?? 'tasks';
|
|
608
|
-
const mapTaskToEvent = options.mapTaskToEvent ?? defaultMapTaskToEvent<TTask>;
|
|
258
|
+
export function createSupaCloudTaskLiveProvider(options: CreateSupaCloudTaskLiveProviderOptions): LiveProvider {
|
|
259
|
+
const sdk = taskClientField(taskClientField(options, 'supacloud'), 'tasks');
|
|
260
|
+
const subscribe = requiredTaskClientMethod(sdk, 'subscribe');
|
|
261
|
+
const resource = taskClientField(options, 'resource');
|
|
262
|
+
const resourceName = decode(text, resource === undefined ? 'tasks' : resource, true);
|
|
263
|
+
const map = taskClientField(options, 'mapTaskToEvent');
|
|
264
|
+
if (map !== undefined && typeof map !== 'function') throw new TaskError('INVALID_TASK_INPUT');
|
|
265
|
+
const onError = errorCallback(taskClientField(options, 'onError'));
|
|
609
266
|
return {
|
|
610
267
|
subscribe({ resource, liveParams, callback }) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
resource
|
|
620
|
-
)
|
|
621
|
-
|
|
622
|
-
|
|
268
|
+
const resourceId = decode(text, resource === undefined ? resourceName : resource, true);
|
|
269
|
+
const { taskId } = decode(liveParamsSchema, liveParams, true);
|
|
270
|
+
return validatedTaskSubscription(
|
|
271
|
+
(onUpdate, onError) => subscribe(taskId, { onUpdate, onError }),
|
|
272
|
+
value => {
|
|
273
|
+
const task = taskSnapshot(value, taskId);
|
|
274
|
+
let mapped: unknown;
|
|
275
|
+
try {
|
|
276
|
+
mapped = map ? Reflect.apply(map, undefined, [task, resourceId]) : { type: 'UPDATE', resource: resourceId, payload: task };
|
|
277
|
+
} catch { throw new TaskError('TASK_CALLBACK_FAILED'); }
|
|
278
|
+
const event: LiveEvent = decode(eventSchema, mapped);
|
|
279
|
+
if (event.resource !== resourceId) throw new TaskError('INVALID_TASK_RESPONSE');
|
|
280
|
+
return event;
|
|
281
|
+
},
|
|
282
|
+
callback, onError,
|
|
623
283
|
);
|
|
624
284
|
},
|
|
625
285
|
};
|
|
626
286
|
}
|
|
627
|
-
|
|
628
|
-
export function createSupaCloudTaskProvider<
|
|
629
|
-
TTask extends SupaCloudTaskRecord = SupaCloudTaskRecord,
|
|
630
|
-
>(options: CreateSupaCloudTaskProviderOptions<TTask>): TaskProvider<TTask> {
|
|
631
|
-
if (options.clientKind === 'legacy') {
|
|
632
|
-
return createLegacyTaskProvider(options.supacloud);
|
|
633
|
-
}
|
|
634
|
-
if (options.clientKind === 'sdk') {
|
|
635
|
-
return createSdkTaskProvider<TTask>(options.supacloud);
|
|
636
|
-
}
|
|
637
|
-
if (isSdkRootClient(options.supacloud)) {
|
|
638
|
-
return createSdkTaskProvider<TTask>(options.supacloud);
|
|
639
|
-
}
|
|
640
|
-
return createLegacyTaskProvider(options.supacloud as SupaCloudTaskLegacyClient<TTask>);
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
export function createSupaCloudTaskLiveProvider<
|
|
644
|
-
TTask extends SupaCloudTaskRecord = SupaCloudTaskRecord,
|
|
645
|
-
>(options: CreateSupaCloudTaskLiveProviderOptions<TTask>): LiveProvider {
|
|
646
|
-
if (options.clientKind === 'legacy') {
|
|
647
|
-
return createLegacyTaskLiveProvider(options);
|
|
648
|
-
}
|
|
649
|
-
if (options.clientKind === 'sdk') {
|
|
650
|
-
return createSdkTaskLiveProvider(options);
|
|
651
|
-
}
|
|
652
|
-
if (isSdkRootClient(options.supacloud)) {
|
|
653
|
-
return createSdkTaskLiveProvider({
|
|
654
|
-
supacloud: options.supacloud,
|
|
655
|
-
resource: options.resource,
|
|
656
|
-
mapTaskToEvent: options.mapTaskToEvent,
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
return createLegacyTaskLiveProvider(options as LegacyTaskLiveProviderOptions<TTask>);
|
|
660
|
-
}
|