@quadrokit/client 0.3.11 → 0.3.13
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 +3 -2
- package/dist/generate/codegen.d.ts +18 -0
- package/dist/generate/codegen.d.ts.map +1 -1
- package/dist/generate/codegen.mjs +84 -202
- package/dist/runtime/catalog-builder.d.ts +25 -0
- package/dist/runtime/catalog-builder.d.ts.map +1 -0
- package/dist/runtime/catalog-builder.mjs +99 -0
- package/dist/runtime/class-function.d.ts +0 -4
- package/dist/runtime/class-function.d.ts.map +1 -1
- package/dist/runtime/class-function.mjs +28 -6
- package/dist/runtime/client-types.d.ts +17 -0
- package/dist/runtime/client-types.d.ts.map +1 -0
- package/dist/runtime/client-types.mjs +1 -0
- package/dist/runtime/collection.d.ts.map +1 -1
- package/dist/runtime/collection.mjs +56 -41
- package/dist/runtime/data-class.d.ts.map +1 -1
- package/dist/runtime/data-class.mjs +10 -2
- package/dist/runtime/datastore.d.ts +2 -1
- package/dist/runtime/datastore.d.ts.map +1 -1
- package/dist/runtime/datastore.mjs +8 -3
- package/dist/runtime/events.d.ts +65 -0
- package/dist/runtime/events.d.ts.map +1 -0
- package/dist/runtime/events.mjs +86 -0
- package/dist/runtime/http.d.ts +24 -3
- package/dist/runtime/http.d.ts.map +1 -1
- package/dist/runtime/http.mjs +65 -14
- package/dist/runtime/index.d.ts +4 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.mjs +2 -0
- package/dist/runtime/paths.d.ts +17 -1
- package/dist/runtime/paths.d.ts.map +1 -1
- package/dist/runtime/rxjs.d.ts +20 -0
- package/dist/runtime/rxjs.d.ts.map +1 -0
- package/dist/runtime/rxjs.mjs +27 -0
- package/package.json +13 -2
|
@@ -93,29 +93,59 @@ export function createCollection(ctx, initialOptions, mapRow) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
const listContext = {
|
|
97
|
+
operation: 'collection.list',
|
|
98
|
+
className: ctx.className,
|
|
99
|
+
attributes: {
|
|
100
|
+
page,
|
|
101
|
+
useEntitySet,
|
|
102
|
+
...(initialOptions.filter !== undefined ? { filter: initialOptions.filter } : {}),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
return ctx.http.runWithEvents(listContext, ctx.path, 'GET', async () => {
|
|
106
|
+
if (useEntitySet && !entitySetUrl) {
|
|
107
|
+
const qsCreate = buildEntitySetCreationParams(initialOptions);
|
|
108
|
+
const createPath = `${ctx.path}${qsCreate}`;
|
|
109
|
+
const resCreate = await ctx.http.rawRequest(createPath, {
|
|
110
|
+
signal: initialOptions.signal,
|
|
111
|
+
});
|
|
112
|
+
const textCreate = await resCreate.text();
|
|
113
|
+
if (!resCreate.ok) {
|
|
114
|
+
throw new Error(`Entity set creation failed ${resCreate.status}: ${textCreate.slice(0, 200)}`);
|
|
115
|
+
}
|
|
116
|
+
const jsonCreate = textCreate ? JSON.parse(textCreate) : [];
|
|
117
|
+
await parseEntitySetFromResponse(jsonCreate, resCreate);
|
|
118
|
+
if (!entitySetUrl) {
|
|
119
|
+
return unwrapEntityList(ctx.className, jsonCreate);
|
|
120
|
+
}
|
|
121
|
+
const qsPage = buildEntitySetPageParams(skip, pageSize, initialOptions.select);
|
|
122
|
+
const base = entitySetUrl;
|
|
123
|
+
const pagePath = qsPage
|
|
124
|
+
? base.includes('?')
|
|
125
|
+
? `${base}&${qsPage.slice(1)}`
|
|
126
|
+
: `${base}${qsPage}`
|
|
127
|
+
: base;
|
|
128
|
+
const res = await ctx.http.rawRequest(pagePath, {
|
|
129
|
+
signal: initialOptions.signal,
|
|
130
|
+
});
|
|
131
|
+
const text = await res.text();
|
|
132
|
+
if (!res.ok) {
|
|
133
|
+
throw new Error(`List failed ${res.status}: ${text.slice(0, 200)}`);
|
|
134
|
+
}
|
|
135
|
+
const json = text ? JSON.parse(text) : [];
|
|
136
|
+
return unwrapEntityList(ctx.className, json);
|
|
105
137
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
138
|
+
let requestPath;
|
|
139
|
+
if (entitySetUrl && useEntitySet) {
|
|
140
|
+
const qs = buildEntitySetPageParams(skip, pageSize, initialOptions.select);
|
|
141
|
+
const base = entitySetUrl;
|
|
142
|
+
requestPath = qs ? (base.includes('?') ? `${base}&${qs.slice(1)}` : `${base}${qs}`) : base;
|
|
110
143
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
: `${base}${qsPage}`
|
|
117
|
-
: base;
|
|
118
|
-
const res = await ctx.http.request(pagePath, {
|
|
144
|
+
else {
|
|
145
|
+
const qs = buildListSearchParams(ctx.className, { ...initialOptions, page }, ctx.relationMap);
|
|
146
|
+
requestPath = `${ctx.path}${qs}`;
|
|
147
|
+
}
|
|
148
|
+
const res = await ctx.http.rawRequest(requestPath, {
|
|
119
149
|
signal: initialOptions.signal,
|
|
120
150
|
});
|
|
121
151
|
const text = await res.text();
|
|
@@ -124,26 +154,7 @@ export function createCollection(ctx, initialOptions, mapRow) {
|
|
|
124
154
|
}
|
|
125
155
|
const json = text ? JSON.parse(text) : [];
|
|
126
156
|
return unwrapEntityList(ctx.className, json);
|
|
127
|
-
}
|
|
128
|
-
let requestPath;
|
|
129
|
-
if (entitySetUrl && useEntitySet) {
|
|
130
|
-
const qs = buildEntitySetPageParams(skip, pageSize, initialOptions.select);
|
|
131
|
-
const base = entitySetUrl;
|
|
132
|
-
requestPath = qs ? (base.includes('?') ? `${base}&${qs.slice(1)}` : `${base}${qs}`) : base;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
const qs = buildListSearchParams(ctx.className, { ...initialOptions, page }, ctx.relationMap);
|
|
136
|
-
requestPath = `${ctx.path}${qs}`;
|
|
137
|
-
}
|
|
138
|
-
const res = await ctx.http.request(requestPath, {
|
|
139
|
-
signal: initialOptions.signal,
|
|
140
157
|
});
|
|
141
|
-
const text = await res.text();
|
|
142
|
-
if (!res.ok) {
|
|
143
|
-
throw new Error(`List failed ${res.status}: ${text.slice(0, 200)}`);
|
|
144
|
-
}
|
|
145
|
-
const json = text ? JSON.parse(text) : [];
|
|
146
|
-
return unwrapEntityList(ctx.className, json);
|
|
147
158
|
}
|
|
148
159
|
async function* iteratePages() {
|
|
149
160
|
let page = initialOptions.page ?? 1;
|
|
@@ -190,6 +201,10 @@ export function createCollection(ctx, initialOptions, mapRow) {
|
|
|
190
201
|
}
|
|
191
202
|
await Promise.all(ids.map((id) => ctx.http.void(`${ctx.className}(${encodeURIComponent(String(id))})`, {
|
|
192
203
|
method: 'DELETE',
|
|
204
|
+
}, {
|
|
205
|
+
operation: 'dataclass.delete',
|
|
206
|
+
className: ctx.className,
|
|
207
|
+
entityKey: id,
|
|
193
208
|
})));
|
|
194
209
|
seenIds.clear();
|
|
195
210
|
},
|
|
@@ -201,7 +216,7 @@ export function createCollection(ctx, initialOptions, mapRow) {
|
|
|
201
216
|
entitySetUrl = undefined;
|
|
202
217
|
try {
|
|
203
218
|
const path = appendReleaseQuery(toRelease);
|
|
204
|
-
const res = await ctx.http.request(path, { method: 'GET' });
|
|
219
|
+
const res = await ctx.http.request(path, { method: 'GET' }, { operation: 'collection.release', className: ctx.className });
|
|
205
220
|
await res.text();
|
|
206
221
|
}
|
|
207
222
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-class.d.ts","sourceRoot":"","sources":["../../src/runtime/data-class.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAoB,MAAM,iBAAiB,CAAA;AACjG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAgB,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,wGAAwG;IACxG,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,sBAAsB;QAIjE,CAAC,SAAS,SAAS,MAAM,EAAE,0BACnB,iBAAiB,GAAG;QAAE,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,GAC3C,gBAAgB,CAAC,CAAC,SAAS,SAAS,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAc7C,CAAC,SAAS,SAAS,MAAM,EAAE,oBAC/B,MAAM,GAAG,MAAM,YACT;QAAE,MAAM,CAAC,EAAE,CAAC,CAAA;KAAE,GACvB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"data-class.d.ts","sourceRoot":"","sources":["../../src/runtime/data-class.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,13 +19,21 @@ export function makeDataClassApi(cfg) {
|
|
|
19
19
|
? buildEntityParams(cfg.className, options.select, cfg.relationMap)
|
|
20
20
|
: '';
|
|
21
21
|
const key = encodeURIComponent(String(id));
|
|
22
|
-
const body = await cfg.http.json(`${cfg.className}(${key})${qs}
|
|
22
|
+
const body = await cfg.http.json(`${cfg.className}(${key})${qs}`, {}, {
|
|
23
|
+
operation: 'dataclass.get',
|
|
24
|
+
className: cfg.className,
|
|
25
|
+
entityKey: id,
|
|
26
|
+
});
|
|
23
27
|
return unwrapEntity(cfg.className, body);
|
|
24
28
|
},
|
|
25
29
|
async delete(id) {
|
|
26
30
|
const key = encodeURIComponent(String(id));
|
|
27
31
|
try {
|
|
28
|
-
await cfg.http.void(`${cfg.className}(${key})`, { method: 'DELETE' }
|
|
32
|
+
await cfg.http.void(`${cfg.className}(${key})`, { method: 'DELETE' }, {
|
|
33
|
+
operation: 'dataclass.delete',
|
|
34
|
+
className: cfg.className,
|
|
35
|
+
entityKey: id,
|
|
36
|
+
});
|
|
29
37
|
return true;
|
|
30
38
|
}
|
|
31
39
|
catch {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { QuadroRequestContext } from './events.js';
|
|
1
2
|
import type { QuadroHttp } from './http.js';
|
|
2
3
|
/** Call nested datastore paths like `authentify/login` (POST by default). */
|
|
3
4
|
export declare function callDatastorePath(http: QuadroHttp, segments: readonly string[], init?: {
|
|
4
5
|
method?: 'GET' | 'POST';
|
|
5
6
|
body?: unknown;
|
|
6
|
-
}): Promise<unknown>;
|
|
7
|
+
}, context?: QuadroRequestContext): Promise<unknown>;
|
|
7
8
|
export declare function createDatastoreNamespace(_http: QuadroHttp, tree: Record<string, unknown>): Record<string, unknown>;
|
|
8
9
|
//# sourceMappingURL=datastore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datastore.d.ts","sourceRoot":"","sources":["../../src/runtime/datastore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,6EAA6E;AAC7E,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"datastore.d.ts","sourceRoot":"","sources":["../../src/runtime/datastore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,6EAA6E;AAC7E,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,EAClD,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB"}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/** Call nested datastore paths like `authentify/login` (POST by default). */
|
|
2
|
-
export async function callDatastorePath(http, segments, init) {
|
|
2
|
+
export async function callDatastorePath(http, segments, init, context) {
|
|
3
3
|
const path = `/${segments.join('/')}`;
|
|
4
4
|
const method = init?.method ?? 'POST';
|
|
5
|
+
const ctx = context ??
|
|
6
|
+
{
|
|
7
|
+
operation: 'datastore',
|
|
8
|
+
methodName: segments.join('/'),
|
|
9
|
+
};
|
|
5
10
|
if (method === 'GET') {
|
|
6
|
-
return http.json(path, { method: 'GET' });
|
|
11
|
+
return http.json(path, { method: 'GET' }, ctx);
|
|
7
12
|
}
|
|
8
13
|
return http.json(path, {
|
|
9
14
|
method: 'POST',
|
|
10
15
|
body: init?.body !== undefined ? JSON.stringify(init.body) : undefined,
|
|
11
|
-
});
|
|
16
|
+
}, ctx);
|
|
12
17
|
}
|
|
13
18
|
export function createDatastoreNamespace(_http, tree) {
|
|
14
19
|
return tree;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured lifecycle events for all Quadro HTTP-backed operations.
|
|
3
|
+
* Use {@link QuadroEventBus} with {@link QuadroHttp} options, or bridge to RxJS via `@quadrokit/client/rx`.
|
|
4
|
+
*/
|
|
5
|
+
/** What the client is doing (for filtering and UI). */
|
|
6
|
+
export type QuadroOperation = 'http.json' | 'http.void' | 'http.request' | 'collection.list' | 'collection.release' | 'dataclass.get' | 'dataclass.delete' | 'function.dataclass' | 'function.entity' | 'function.entityCollection' | 'datastore' | 'auth.login';
|
|
7
|
+
/** Optional metadata for an operation (class, method, entity key, arbitrary tags). */
|
|
8
|
+
export type QuadroRequestContext = {
|
|
9
|
+
operation: QuadroOperation;
|
|
10
|
+
/** Dataclass name when applicable. */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** 4D method / function name for `function.*` operations. */
|
|
13
|
+
methodName?: string;
|
|
14
|
+
/** Primary key for entity-scoped calls. */
|
|
15
|
+
entityKey?: string | number;
|
|
16
|
+
/** Extra structured data (page, filter summary, datastore path, …). */
|
|
17
|
+
attributes?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
export type QuadroLoadingEvent = {
|
|
20
|
+
type: 'loading';
|
|
21
|
+
operationId: string;
|
|
22
|
+
context: QuadroRequestContext;
|
|
23
|
+
path: string;
|
|
24
|
+
method: string;
|
|
25
|
+
startedAt: number;
|
|
26
|
+
};
|
|
27
|
+
export type QuadroSuccessEvent = {
|
|
28
|
+
type: 'success';
|
|
29
|
+
operationId: string;
|
|
30
|
+
context: QuadroRequestContext;
|
|
31
|
+
path: string;
|
|
32
|
+
durationMs: number;
|
|
33
|
+
/** HTTP status when applicable. */
|
|
34
|
+
status?: number;
|
|
35
|
+
/** Result payload: parsed JSON, rows, void, or a summary for raw `Response`. */
|
|
36
|
+
body?: unknown;
|
|
37
|
+
};
|
|
38
|
+
export type QuadroErrorEvent = {
|
|
39
|
+
type: 'error';
|
|
40
|
+
operationId: string;
|
|
41
|
+
context: QuadroRequestContext;
|
|
42
|
+
path: string;
|
|
43
|
+
durationMs: number;
|
|
44
|
+
message: string;
|
|
45
|
+
error: unknown;
|
|
46
|
+
/** HTTP status when the failure came from the transport. */
|
|
47
|
+
status?: number;
|
|
48
|
+
};
|
|
49
|
+
export type QuadroClientEvent = QuadroLoadingEvent | QuadroSuccessEvent | QuadroErrorEvent;
|
|
50
|
+
/**
|
|
51
|
+
* Subscribe to {@link QuadroClientEvent} from a {@link QuadroHttp} client.
|
|
52
|
+
* Pass `new QuadroEventBus()` as `events` in {@link QuadroFetchOptions}.
|
|
53
|
+
*/
|
|
54
|
+
export declare class QuadroEventBus {
|
|
55
|
+
private readonly listeners;
|
|
56
|
+
subscribe(listener: (e: QuadroClientEvent) => void): () => void;
|
|
57
|
+
/** @internal */
|
|
58
|
+
emit(event: QuadroClientEvent): void;
|
|
59
|
+
/**
|
|
60
|
+
* Run an async operation with loading → success | error events.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
runWithEvents<T>(context: QuadroRequestContext, path: string, method: string, fn: () => Promise<T>): Promise<T>;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/runtime/events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,uDAAuD;AACvD,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,WAAW,GACX,cAAc,GACd,iBAAiB,GACjB,oBAAoB,GACpB,eAAe,GACf,kBAAkB,GAClB,oBAAoB,GACpB,iBAAiB,GACjB,2BAA2B,GAC3B,WAAW,GACX,YAAY,CAAA;AAEhB,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,eAAe,CAAA;IAC1B,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,SAAS,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,oBAAoB,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,SAAS,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,oBAAoB,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gFAAgF;IAChF,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,oBAAoB,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,OAAO,CAAA;IACd,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,GAAG,kBAAkB,GAAG,gBAAgB,CAAA;AAM1F;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4C;IAEtE,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI;IAO/D,gBAAgB;IAChB,IAAI,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAUpC;;;OAGG;IACH,aAAa,CAAC,CAAC,EACb,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC;CAmDd"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured lifecycle events for all Quadro HTTP-backed operations.
|
|
3
|
+
* Use {@link QuadroEventBus} with {@link QuadroHttp} options, or bridge to RxJS via `@quadrokit/client/rx`.
|
|
4
|
+
*/
|
|
5
|
+
function newOperationId() {
|
|
6
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Subscribe to {@link QuadroClientEvent} from a {@link QuadroHttp} client.
|
|
10
|
+
* Pass `new QuadroEventBus()` as `events` in {@link QuadroFetchOptions}.
|
|
11
|
+
*/
|
|
12
|
+
export class QuadroEventBus {
|
|
13
|
+
listeners = new Set();
|
|
14
|
+
subscribe(listener) {
|
|
15
|
+
this.listeners.add(listener);
|
|
16
|
+
return () => {
|
|
17
|
+
this.listeners.delete(listener);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** @internal */
|
|
21
|
+
emit(event) {
|
|
22
|
+
for (const fn of this.listeners) {
|
|
23
|
+
try {
|
|
24
|
+
fn(event);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
/* listener errors must not break the client */
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run an async operation with loading → success | error events.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
runWithEvents(context, path, method, fn) {
|
|
36
|
+
const operationId = newOperationId();
|
|
37
|
+
const startedAt = Date.now();
|
|
38
|
+
this.emit({ type: 'loading', operationId, context, path, method, startedAt });
|
|
39
|
+
return (async () => {
|
|
40
|
+
try {
|
|
41
|
+
const result = await fn();
|
|
42
|
+
const durationMs = Date.now() - startedAt;
|
|
43
|
+
let body = result;
|
|
44
|
+
if (result instanceof Response) {
|
|
45
|
+
body = {
|
|
46
|
+
kind: 'response',
|
|
47
|
+
status: result.status,
|
|
48
|
+
ok: result.ok,
|
|
49
|
+
url: result.url,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
this.emit({
|
|
53
|
+
type: 'success',
|
|
54
|
+
operationId,
|
|
55
|
+
context,
|
|
56
|
+
path,
|
|
57
|
+
durationMs,
|
|
58
|
+
status: result instanceof Response ? result.status : undefined,
|
|
59
|
+
body,
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const durationMs = Date.now() - startedAt;
|
|
65
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
66
|
+
const status = error &&
|
|
67
|
+
typeof error === 'object' &&
|
|
68
|
+
'status' in error &&
|
|
69
|
+
typeof error.status === 'number'
|
|
70
|
+
? error.status
|
|
71
|
+
: undefined;
|
|
72
|
+
this.emit({
|
|
73
|
+
type: 'error',
|
|
74
|
+
operationId,
|
|
75
|
+
context,
|
|
76
|
+
path,
|
|
77
|
+
durationMs,
|
|
78
|
+
message,
|
|
79
|
+
error,
|
|
80
|
+
status,
|
|
81
|
+
});
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
})();
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/runtime/http.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import type { QuadroClientEvent, QuadroEventBus, QuadroRequestContext } from './events.js';
|
|
1
2
|
export interface QuadroFetchOptions {
|
|
2
3
|
baseURL: string;
|
|
3
4
|
fetchImpl?: typeof fetch;
|
|
4
5
|
/** Extra headers on every request (e.g. Authorization for generate). */
|
|
5
6
|
defaultHeaders?: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Optional bus for {@link QuadroClientEvent}: loading, success, error per logical operation.
|
|
9
|
+
* Create with `new QuadroEventBus()` and pass here; subscribe before calling the client.
|
|
10
|
+
*/
|
|
11
|
+
events?: QuadroEventBus;
|
|
6
12
|
}
|
|
7
13
|
export declare function normalizeBaseURL(baseURL: string): string;
|
|
8
14
|
/**
|
|
@@ -14,8 +20,23 @@ export declare class QuadroHttp {
|
|
|
14
20
|
private readonly opts;
|
|
15
21
|
constructor(opts: QuadroFetchOptions);
|
|
16
22
|
get baseURL(): string;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
/** Optional event bus from constructor options. */
|
|
24
|
+
get events(): QuadroEventBus | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Run a logical operation with loading / success / error events (when `events` is set).
|
|
27
|
+
* Use from collection code and other multi-step flows that do not use {@link json}.
|
|
28
|
+
*/
|
|
29
|
+
runWithEvents<T>(context: QuadroRequestContext, path: string, method: string, fn: () => Promise<T>): Promise<T>;
|
|
30
|
+
/** Subscribe without reaching into options: `quadro._http.subscribe(cb)`. */
|
|
31
|
+
subscribe(listener: (e: QuadroClientEvent) => void): () => void;
|
|
32
|
+
/** @internal Raw fetch without events (used inside {@link runWithEvents}). */
|
|
33
|
+
rawRequest(path: string, init?: RequestInit): Promise<Response>;
|
|
34
|
+
/**
|
|
35
|
+
* Low-level request. When `events` is configured, emits loading/success/error unless
|
|
36
|
+
* you pass `context: undefined` and use {@link rawRequest} for manual control.
|
|
37
|
+
*/
|
|
38
|
+
request(path: string, init?: RequestInit, context?: QuadroRequestContext): Promise<Response>;
|
|
39
|
+
json<T>(path: string, init?: RequestInit, context?: QuadroRequestContext): Promise<T>;
|
|
40
|
+
void(path: string, init?: RequestInit, context?: QuadroRequestContext): Promise<void>;
|
|
20
41
|
}
|
|
21
42
|
//# sourceMappingURL=http.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAE1F,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAa5D;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,kBAAkB;IAErD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,mDAAmD;IACnD,IAAI,MAAM,IAAI,cAAc,GAAG,SAAS,CAEvC;IAED;;;OAGG;IACH,aAAa,CAAC,CAAC,EACb,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC;IAQb,6EAA6E;IAC7E,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI;IAI/D,8EAA8E;IACxE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;IAwBzE;;;OAGG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,WAAgB,EACtB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,QAAQ,CAAC;IAUd,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,CAAC,CAAC;IAqBzF,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBhG"}
|
package/dist/runtime/http.mjs
CHANGED
|
@@ -29,7 +29,27 @@ export class QuadroHttp {
|
|
|
29
29
|
get baseURL() {
|
|
30
30
|
return normalizeBaseURL(this.opts.baseURL);
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
/** Optional event bus from constructor options. */
|
|
33
|
+
get events() {
|
|
34
|
+
return this.opts.events;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Run a logical operation with loading / success / error events (when `events` is set).
|
|
38
|
+
* Use from collection code and other multi-step flows that do not use {@link json}.
|
|
39
|
+
*/
|
|
40
|
+
runWithEvents(context, path, method, fn) {
|
|
41
|
+
const bus = this.opts.events;
|
|
42
|
+
if (!bus) {
|
|
43
|
+
return fn();
|
|
44
|
+
}
|
|
45
|
+
return bus.runWithEvents(context, path, method, fn);
|
|
46
|
+
}
|
|
47
|
+
/** Subscribe without reaching into options: `quadro._http.subscribe(cb)`. */
|
|
48
|
+
subscribe(listener) {
|
|
49
|
+
return this.opts.events?.subscribe(listener) ?? (() => { });
|
|
50
|
+
}
|
|
51
|
+
/** @internal Raw fetch without events (used inside {@link runWithEvents}). */
|
|
52
|
+
async rawRequest(path, init = {}) {
|
|
33
53
|
const url = path.startsWith('http')
|
|
34
54
|
? path
|
|
35
55
|
: `${this.baseURL}${path.startsWith('/') ? '' : '/'}${path}`;
|
|
@@ -52,22 +72,53 @@ export class QuadroHttp {
|
|
|
52
72
|
headers,
|
|
53
73
|
});
|
|
54
74
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Low-level request. When `events` is configured, emits loading/success/error unless
|
|
77
|
+
* you pass `context: undefined` and use {@link rawRequest} for manual control.
|
|
78
|
+
*/
|
|
79
|
+
async request(path, init = {}, context) {
|
|
80
|
+
const ctx = context ?? { operation: 'http.request' };
|
|
81
|
+
const method = (init.method ?? 'GET').toUpperCase();
|
|
82
|
+
const bus = this.opts.events;
|
|
83
|
+
if (!bus) {
|
|
84
|
+
return this.rawRequest(path, init);
|
|
63
85
|
}
|
|
64
|
-
return
|
|
86
|
+
return bus.runWithEvents(ctx, path, method, () => this.rawRequest(path, init));
|
|
65
87
|
}
|
|
66
|
-
async
|
|
67
|
-
const
|
|
68
|
-
|
|
88
|
+
async json(path, init = {}, context) {
|
|
89
|
+
const ctx = context ?? { operation: 'http.json' };
|
|
90
|
+
const method = (init.method ?? 'GET').toUpperCase();
|
|
91
|
+
const bus = this.opts.events;
|
|
92
|
+
const exec = async () => {
|
|
93
|
+
const res = await this.rawRequest(path, init);
|
|
69
94
|
const text = await res.text();
|
|
70
|
-
|
|
95
|
+
if (!res.ok) {
|
|
96
|
+
throw new QuadroHttpError(res.status, text);
|
|
97
|
+
}
|
|
98
|
+
if (!text) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return JSON.parse(text);
|
|
102
|
+
};
|
|
103
|
+
if (!bus) {
|
|
104
|
+
return exec();
|
|
105
|
+
}
|
|
106
|
+
return bus.runWithEvents(ctx, path, method, exec);
|
|
107
|
+
}
|
|
108
|
+
async void(path, init = {}, context) {
|
|
109
|
+
const ctx = context ?? { operation: 'http.void' };
|
|
110
|
+
const method = (init.method ?? 'GET').toUpperCase();
|
|
111
|
+
const bus = this.opts.events;
|
|
112
|
+
const exec = async () => {
|
|
113
|
+
const res = await this.rawRequest(path, init);
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
const text = await res.text();
|
|
116
|
+
throw new QuadroHttpError(res.status, text);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
if (!bus) {
|
|
120
|
+
return exec();
|
|
71
121
|
}
|
|
122
|
+
return bus.runWithEvents(ctx, path, method, exec);
|
|
72
123
|
}
|
|
73
124
|
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
export { buildQuadroClientFromCatalogSpec, type CatalogClassRuntimeSpec, type CatalogRuntimeSpec, } from './catalog-builder.js';
|
|
1
2
|
export { type ClassFunctionHttpOptions, callDataClassFunction, callEntityCollectionFunction, callEntityFunction, type EntityCollectionMethodOptions, unwrapClassFunctionResult, } from './class-function.js';
|
|
3
|
+
export type { BaseDataClassApi } from './client-types.js';
|
|
2
4
|
export { type CollectionContext, type CollectionHandle, type CollectionOptions, createCollection, } from './collection.js';
|
|
3
5
|
export { attachEntityClassMethods, attachRelatedApis, bindEntityCollectionMethods, type DataClassRuntimeConfig, type EntityNavigationConfig, makeDataClassApi, makeRelatedCollectionApi, type RelatedNavigationSpec, } from './data-class.js';
|
|
4
6
|
export { callDatastorePath, createDatastoreNamespace } from './datastore.js';
|
|
5
7
|
export { QuadroHttpError } from './errors.js';
|
|
8
|
+
export { type QuadroClientEvent, type QuadroErrorEvent, QuadroEventBus, type QuadroLoadingEvent, type QuadroOperation, type QuadroRequestContext, type QuadroSuccessEvent, } from './events.js';
|
|
6
9
|
export { mountPathFromBaseURL, normalizeBaseURL, type QuadroFetchOptions, QuadroHttp, } from './http.js';
|
|
7
|
-
export type { Paths1, SelectedEntity } from './paths.js';
|
|
10
|
+
export type { Paths1, QuadroAttributePaths, SelectedEntity } from './paths.js';
|
|
8
11
|
export { buildEntitySetCreationParams, buildEntitySetPageParams, buildListSearchParams, buildMethodSelectionQuery, type ListQueryParams, type MethodSelectionQuery, } from './query.js';
|
|
9
12
|
export { unwrapEntity, unwrapEntityList } from './unwrap.js';
|
|
10
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,wBAAwB,EAC7B,qBAAqB,EACrB,4BAA4B,EAC5B,kBAAkB,EAClB,KAAK,6BAA6B,EAClC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,KAAK,wBAAwB,EAC7B,qBAAqB,EACrB,4BAA4B,EAC5B,kBAAkB,EAClB,KAAK,6BAA6B,EAClC,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,gBAAgB,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,2BAA2B,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,KAAK,qBAAqB,GAC3B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,MAAM,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAC9E,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA"}
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export { buildQuadroClientFromCatalogSpec, } from './catalog-builder.mjs';
|
|
1
2
|
export { callDataClassFunction, callEntityCollectionFunction, callEntityFunction, unwrapClassFunctionResult, } from './class-function.mjs';
|
|
2
3
|
export { createCollection, } from './collection.mjs';
|
|
3
4
|
export { attachEntityClassMethods, attachRelatedApis, bindEntityCollectionMethods, makeDataClassApi, makeRelatedCollectionApi, } from './data-class.mjs';
|
|
4
5
|
export { callDatastorePath, createDatastoreNamespace } from './datastore.mjs';
|
|
5
6
|
export { QuadroHttpError } from './errors.mjs';
|
|
7
|
+
export { QuadroEventBus, } from './events.mjs';
|
|
6
8
|
export { mountPathFromBaseURL, normalizeBaseURL, QuadroHttp, } from './http.mjs';
|
|
7
9
|
export { buildEntitySetCreationParams, buildEntitySetPageParams, buildListSearchParams, buildMethodSelectionQuery, } from './query.mjs';
|
|
8
10
|
export { unwrapEntity, unwrapEntityList } from './unwrap.mjs';
|
package/dist/runtime/paths.d.ts
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
/** Type-level helpers for `$attributes` dot paths (compile-time only). */
|
|
2
|
+
/** Decrements depth for {@link QuadroAttributePaths} (index = current max depth). */
|
|
3
|
+
type QuadroPathDepthPrev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
|
|
4
|
+
type QuadroPathNextDepth<D extends number> = D extends keyof QuadroPathDepthPrev ? QuadroPathDepthPrev[D] : 0;
|
|
5
|
+
/**
|
|
6
|
+
* Valid `$attributes` dot paths for entity `T` (e.g. `ceo.manager.manager.employer.name`),
|
|
7
|
+
* including arbitrary nesting along related-entity fields. Bounded by `MaxDepth` so circular
|
|
8
|
+
* graphs (e.g. `Employee.manager: Employee`) stay instantiable in TypeScript.
|
|
9
|
+
*
|
|
10
|
+
* Index-signature objects (`Record<string, unknown>`) are treated as leaves (single segment only).
|
|
11
|
+
*/
|
|
12
|
+
export type QuadroAttributePaths<T, MaxDepth extends number = 8> = [MaxDepth] extends [0] ? never : T extends object ? T extends readonly unknown[] ? never : {
|
|
13
|
+
[K in keyof T & string]: NonNullable<T[K]> extends infer U ? U extends string | number | boolean | bigint | symbol ? K : U extends (...args: never) => unknown ? K : U extends readonly unknown[] ? K : [U] extends [never] ? K : U extends Date ? K : U extends object ? string extends keyof U ? K : K | `${K}.${QuadroAttributePaths<U, QuadroPathNextDepth<MaxDepth>>}` : K : K;
|
|
14
|
+
}[keyof T & string] : never;
|
|
2
15
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
3
16
|
type PickOne<T, H extends string> = H extends keyof T & string ? Pick<T, H> : H extends `${infer K}.${infer R}` ? K extends keyof T & string ? NonNullable<T[K]> extends infer U ? U extends object ? {
|
|
4
17
|
[P in K]: PickOne<U, R>;
|
|
@@ -8,7 +21,10 @@ declare const selectBrand: unique symbol;
|
|
|
8
21
|
export type SelectedEntity<T, S extends readonly string[]> = UnionToIntersection<S[number] extends infer H ? (H extends string ? PickOne<T, H> : never) : never> extends infer O ? O extends object ? O & {
|
|
9
22
|
readonly [selectBrand]: S;
|
|
10
23
|
} : never : never;
|
|
11
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Recursive dot paths (can hit "excessively deep" on circular entity types).
|
|
26
|
+
* Prefer {@link QuadroAttributePaths} for catalog-generated entities.
|
|
27
|
+
*/
|
|
12
28
|
export type Paths1<T> = T extends object ? {
|
|
13
29
|
[K in keyof T & string]: NonNullable<T[K]> extends infer U ? U extends object ? K | `${K}.${Paths1<U>}` : K : K;
|
|
14
30
|
}[keyof T & string] : never;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/runtime/paths.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,SAAS,CACjF,CAAC,EAAE,MAAM,CAAC,KACP,IAAI,GACL,CAAC,GACD,KAAK,CAAA;AAET,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,GAC1D,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACV,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,EAAE,GAC/B,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,GACxB,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,GAC/B,CAAC,SAAS,MAAM,GACd;KAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;CAAE,GAC3B,KAAK,GACP,KAAK,GACP,KAAK,GACP,KAAK,CAAA;AAEX,OAAO,CAAC,MAAM,WAAW,EAAE,OAAO,MAAM,CAAA;AAExC,2EAA2E;AAC3E,MAAM,MAAM,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,SAAS,MAAM,EAAE,IACvD,mBAAmB,CACjB,CAAC,CAAC,MAAM,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAC/E,SAAS,MAAM,CAAC,GACb,CAAC,SAAS,MAAM,GACd,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;CAAE,GACjC,KAAK,GACP,KAAK,CAAA;AAEX
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/runtime/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RxJS bridge for {@link QuadroEventBus}. Install `rxjs` as a dependency in your app.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { QuadroEventBus } from '@quadrokit/client/runtime'
|
|
7
|
+
* import { quadroEventsObservable } from '@quadrokit/client/rx'
|
|
8
|
+
* import { filter } from 'rxjs/operators'
|
|
9
|
+
*
|
|
10
|
+
* const bus = new QuadroEventBus()
|
|
11
|
+
* const quadro = createClient({ baseURL: '/rest', events: bus })
|
|
12
|
+
* quadroEventsObservable(bus)
|
|
13
|
+
* .pipe(filter((e) => e.type === 'error'))
|
|
14
|
+
* .subscribe(console.warn)
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { Observable } from 'rxjs';
|
|
18
|
+
import type { QuadroClientEvent, QuadroEventBus } from './events.js';
|
|
19
|
+
export declare function quadroEventsObservable(bus: QuadroEventBus): Observable<QuadroClientEvent>;
|
|
20
|
+
//# sourceMappingURL=rxjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rxjs.d.ts","sourceRoot":"","sources":["../../src/runtime/rxjs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AACjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEpE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,UAAU,CAAC,iBAAiB,CAAC,CASzF"}
|