@jskit-ai/users-web 0.1.106 → 0.1.107
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.descriptor.mjs +7 -7
- package/package.json +7 -7
- package/src/client/composables/records/useAddEdit.js +2 -0
- package/src/client/composables/records/useList.js +2 -0
- package/src/client/composables/records/useView.js +2 -0
- package/src/client/composables/runtime/useEndpointResource.js +6 -5
- package/src/client/composables/runtime/useListCore.js +5 -4
- package/src/client/composables/useCommand.js +2 -0
- package/src/client/lib/httpClient.js +45 -8
- package/test/requestTransportOptions.test.js +116 -0
package/package.descriptor.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import { HOME_COG_OUTLET } from "./src/shared/toolsOutletContracts.js";
|
|
|
3
3
|
export default Object.freeze({
|
|
4
4
|
packageVersion: 1,
|
|
5
5
|
packageId: "@jskit-ai/users-web",
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.107",
|
|
7
7
|
kind: "runtime",
|
|
8
8
|
description: "Users web module: account/profile UI plus shared users web widgets.",
|
|
9
9
|
dependsOn: [
|
|
@@ -278,12 +278,12 @@ export default Object.freeze({
|
|
|
278
278
|
dependencies: {
|
|
279
279
|
runtime: {
|
|
280
280
|
"@mdi/js": "^7.4.47",
|
|
281
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
282
|
-
"@jskit-ai/realtime": "0.1.
|
|
283
|
-
"@jskit-ai/kernel": "0.1.
|
|
284
|
-
"@jskit-ai/shell-web": "0.1.
|
|
285
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
286
|
-
"@jskit-ai/users-core": "0.1.
|
|
281
|
+
"@jskit-ai/http-runtime": "0.1.91",
|
|
282
|
+
"@jskit-ai/realtime": "0.1.91",
|
|
283
|
+
"@jskit-ai/kernel": "0.1.92",
|
|
284
|
+
"@jskit-ai/shell-web": "0.1.91",
|
|
285
|
+
"@jskit-ai/uploads-image-web": "0.1.70",
|
|
286
|
+
"@jskit-ai/users-core": "0.1.102"
|
|
287
287
|
},
|
|
288
288
|
dev: {}
|
|
289
289
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/users-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@mdi/js": "^7.4.47",
|
|
47
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
48
|
-
"@jskit-ai/kernel": "0.1.
|
|
49
|
-
"@jskit-ai/realtime": "0.1.
|
|
50
|
-
"@jskit-ai/shell-web": "0.1.
|
|
51
|
-
"@jskit-ai/uploads-image-web": "0.1.
|
|
52
|
-
"@jskit-ai/users-core": "0.1.
|
|
47
|
+
"@jskit-ai/http-runtime": "0.1.91",
|
|
48
|
+
"@jskit-ai/kernel": "0.1.92",
|
|
49
|
+
"@jskit-ai/realtime": "0.1.91",
|
|
50
|
+
"@jskit-ai/shell-web": "0.1.91",
|
|
51
|
+
"@jskit-ai/uploads-image-web": "0.1.70",
|
|
52
|
+
"@jskit-ai/users-core": "0.1.102"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@tanstack/vue-query": "^5.90.5",
|
|
@@ -29,6 +29,7 @@ function useAddEdit({
|
|
|
29
29
|
readMethod = "GET",
|
|
30
30
|
readEnabled = true,
|
|
31
31
|
writeMethod = "PATCH",
|
|
32
|
+
client = null,
|
|
32
33
|
transport = null,
|
|
33
34
|
requestRecovery = null,
|
|
34
35
|
requestRecoveryLabel = "Resource",
|
|
@@ -119,6 +120,7 @@ function useAddEdit({
|
|
|
119
120
|
queryKey: requestQueryRuntime.queryKey,
|
|
120
121
|
path: operationScope.apiPath,
|
|
121
122
|
enabled: queryCanRun,
|
|
123
|
+
client,
|
|
122
124
|
readMethod,
|
|
123
125
|
writeMethod,
|
|
124
126
|
readQuery: requestQueryRuntime.requestQuery,
|
|
@@ -43,6 +43,7 @@ function useList({
|
|
|
43
43
|
initialPageParam = null,
|
|
44
44
|
getNextPageParam,
|
|
45
45
|
selectItems,
|
|
46
|
+
client = null,
|
|
46
47
|
transport = null,
|
|
47
48
|
requestOptions,
|
|
48
49
|
queryOptions,
|
|
@@ -224,6 +225,7 @@ function useList({
|
|
|
224
225
|
queryKey: listQueryKey,
|
|
225
226
|
path: listPath,
|
|
226
227
|
enabled: operationScope.queryCanRun(canView),
|
|
228
|
+
client,
|
|
227
229
|
transport,
|
|
228
230
|
initialPageParam,
|
|
229
231
|
getNextPageParam,
|
|
@@ -20,6 +20,7 @@ function useView({
|
|
|
20
20
|
viewPermissions = [],
|
|
21
21
|
readMethod = "GET",
|
|
22
22
|
readEnabled = true,
|
|
23
|
+
client = null,
|
|
23
24
|
transport = null,
|
|
24
25
|
requestRecovery = null,
|
|
25
26
|
requestRecoveryLabel = "Resource",
|
|
@@ -103,6 +104,7 @@ function useView({
|
|
|
103
104
|
queryKey: requestQueryRuntime.queryKey,
|
|
104
105
|
path: operationScope.apiPath,
|
|
105
106
|
enabled: operationScope.queryCanRun(canView),
|
|
107
|
+
client,
|
|
106
108
|
readMethod,
|
|
107
109
|
readQuery: requestQueryRuntime.requestQuery,
|
|
108
110
|
transport,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, unref } from "vue";
|
|
2
2
|
import { useMutation, useQuery } from "@tanstack/vue-query";
|
|
3
|
-
import {
|
|
3
|
+
import { getUsersWebHttpClient } from "../../lib/httpClient.js";
|
|
4
4
|
import { asPlainObject } from "../support/scopeHelpers.js";
|
|
5
5
|
import { resolveEnabledRef, resolveTextRef } from "../support/refValueHelpers.js";
|
|
6
6
|
import { toQueryErrorMessage } from "../support/errorMessageHelpers.js";
|
|
@@ -67,7 +67,7 @@ function useEndpointResource({
|
|
|
67
67
|
queryKey,
|
|
68
68
|
path = "",
|
|
69
69
|
enabled = true,
|
|
70
|
-
client =
|
|
70
|
+
client = null,
|
|
71
71
|
readMethod = "GET",
|
|
72
72
|
writeMethod = "PATCH",
|
|
73
73
|
readQuery = null,
|
|
@@ -81,7 +81,8 @@ function useEndpointResource({
|
|
|
81
81
|
fallbackLoadError = "Unable to load resource.",
|
|
82
82
|
fallbackSaveError = "Unable to save resource."
|
|
83
83
|
} = {}) {
|
|
84
|
-
|
|
84
|
+
const activeClient = client || getUsersWebHttpClient();
|
|
85
|
+
if (!activeClient || typeof activeClient.request !== "function") {
|
|
85
86
|
throw new TypeError("useEndpointResource requires a client with request().");
|
|
86
87
|
}
|
|
87
88
|
|
|
@@ -96,7 +97,7 @@ function useEndpointResource({
|
|
|
96
97
|
throw new Error("Resource path is required.");
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
return
|
|
100
|
+
return activeClient.request(requestPath, {
|
|
100
101
|
...buildEndpointReadRequestOptions({
|
|
101
102
|
method: readMethod,
|
|
102
103
|
query: readQuery,
|
|
@@ -137,7 +138,7 @@ function useEndpointResource({
|
|
|
137
138
|
const method = String(options.method || writeMethod || "PATCH").toUpperCase();
|
|
138
139
|
const hasBody = Object.hasOwn(options, "body");
|
|
139
140
|
const body = hasBody ? options.body : options.payload;
|
|
140
|
-
return
|
|
141
|
+
return activeClient.request(
|
|
141
142
|
requestPath,
|
|
142
143
|
buildEndpointWriteRequestOptions({
|
|
143
144
|
method,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { computed, unref } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { getUsersWebHttpClient } from "../../lib/httpClient.js";
|
|
3
3
|
import { asPlainObject } from "../support/scopeHelpers.js";
|
|
4
4
|
import { resolveEnabledRef, resolveTextRef } from "../support/refValueHelpers.js";
|
|
5
5
|
import { usePagedCollection } from "../usePagedCollection.js";
|
|
@@ -56,7 +56,7 @@ function useListCore({
|
|
|
56
56
|
queryKey,
|
|
57
57
|
path = "",
|
|
58
58
|
enabled = true,
|
|
59
|
-
client =
|
|
59
|
+
client = null,
|
|
60
60
|
transport = null,
|
|
61
61
|
initialPageParam = null,
|
|
62
62
|
getNextPageParam,
|
|
@@ -67,7 +67,8 @@ function useListCore({
|
|
|
67
67
|
requestRecoveryLabel = "List",
|
|
68
68
|
fallbackLoadError = "Unable to load list."
|
|
69
69
|
} = {}) {
|
|
70
|
-
|
|
70
|
+
const activeClient = client || getUsersWebHttpClient();
|
|
71
|
+
if (!activeClient || typeof activeClient.request !== "function") {
|
|
71
72
|
throw new TypeError("useListCore requires a client with request().");
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -84,7 +85,7 @@ function useListCore({
|
|
|
84
85
|
throw new Error("List path is required.");
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
return
|
|
88
|
+
return activeClient.request(
|
|
88
89
|
requestPath,
|
|
89
90
|
buildListRequestOptions({
|
|
90
91
|
requestOptions,
|
|
@@ -17,6 +17,7 @@ function useCommand({
|
|
|
17
17
|
apiSuffix = "",
|
|
18
18
|
runPermissions = [],
|
|
19
19
|
writeMethod = "POST",
|
|
20
|
+
client = null,
|
|
20
21
|
transport = null,
|
|
21
22
|
placementSource = "users-web.command",
|
|
22
23
|
fallbackRunError = "Unable to complete action.",
|
|
@@ -52,6 +53,7 @@ function useCommand({
|
|
|
52
53
|
const resource = useEndpointResource({
|
|
53
54
|
path: operationScope.apiPath,
|
|
54
55
|
enabled: false,
|
|
56
|
+
client,
|
|
55
57
|
writeMethod,
|
|
56
58
|
transport,
|
|
57
59
|
fallbackSaveError: fallbackRunError
|
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { createTransientRetryHttpClient } from "@jskit-ai/http-runtime/client";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
function normalizeOptions(value = null) {
|
|
4
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function createUsersWebHttpClient(options = {}) {
|
|
8
|
+
const source = normalizeOptions(options);
|
|
9
|
+
const sourceCsrf = normalizeOptions(source.csrf);
|
|
10
|
+
|
|
11
|
+
return createTransientRetryHttpClient({
|
|
12
|
+
...source,
|
|
13
|
+
credentials: source.credentials ?? "include",
|
|
14
|
+
csrf: {
|
|
15
|
+
sessionPath: "/api/session",
|
|
16
|
+
...sourceCsrf
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let usersWebHttpClient = createUsersWebHttpClient();
|
|
22
|
+
|
|
23
|
+
function configureUsersWebHttpClient(optionsOrClient = {}) {
|
|
24
|
+
const source = normalizeOptions(optionsOrClient);
|
|
25
|
+
usersWebHttpClient =
|
|
26
|
+
typeof source.request === "function"
|
|
27
|
+
? source
|
|
28
|
+
: createUsersWebHttpClient(source);
|
|
29
|
+
return usersWebHttpClient;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getUsersWebHttpClient() {
|
|
33
|
+
return usersWebHttpClient;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resetUsersWebHttpClientForTests() {
|
|
37
|
+
usersWebHttpClient = createUsersWebHttpClient();
|
|
38
|
+
return usersWebHttpClient;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
configureUsersWebHttpClient,
|
|
43
|
+
createUsersWebHttpClient,
|
|
44
|
+
getUsersWebHttpClient,
|
|
45
|
+
resetUsersWebHttpClientForTests,
|
|
46
|
+
usersWebHttpClient
|
|
47
|
+
};
|
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
buildEndpointWriteRequestOptions,
|
|
10
10
|
useEndpointResource
|
|
11
11
|
} from "../src/client/composables/runtime/useEndpointResource.js";
|
|
12
|
+
import { useCommand } from "../src/client/composables/useCommand.js";
|
|
13
|
+
import {
|
|
14
|
+
configureUsersWebHttpClient,
|
|
15
|
+
resetUsersWebHttpClientForTests
|
|
16
|
+
} from "../src/client/lib/httpClient.js";
|
|
12
17
|
import { buildListRequestOptions } from "../src/client/composables/runtime/useListCore.js";
|
|
13
18
|
import {
|
|
14
19
|
resolveOperationRealtimeOptions
|
|
@@ -287,3 +292,114 @@ test("endpoint resource reads attach request recovery metadata to query options"
|
|
|
287
292
|
requestRecoveryMethod: "GET"
|
|
288
293
|
});
|
|
289
294
|
});
|
|
295
|
+
|
|
296
|
+
test("endpoint resources use the configured users-web HTTP client by default", async () => {
|
|
297
|
+
const queryClient = new QueryClient();
|
|
298
|
+
const calls = [];
|
|
299
|
+
let resource = null;
|
|
300
|
+
configureUsersWebHttpClient({
|
|
301
|
+
csrf: {
|
|
302
|
+
enabled: false
|
|
303
|
+
},
|
|
304
|
+
resolveRequestUrl(url) {
|
|
305
|
+
return url.replace(/^\/api\//u, "/api/app/beepollen/");
|
|
306
|
+
},
|
|
307
|
+
fetchImpl: async (url, options) => {
|
|
308
|
+
calls.push([url, options]);
|
|
309
|
+
return {
|
|
310
|
+
ok: true,
|
|
311
|
+
status: 200,
|
|
312
|
+
headers: {
|
|
313
|
+
get(name) {
|
|
314
|
+
return String(name || "").toLowerCase() === "content-type"
|
|
315
|
+
? "application/json; charset=utf-8"
|
|
316
|
+
: "";
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
async json() {
|
|
320
|
+
return {
|
|
321
|
+
ok: true
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
try {
|
|
329
|
+
const app = createSSRApp({
|
|
330
|
+
setup() {
|
|
331
|
+
resource = useEndpointResource({
|
|
332
|
+
queryKey: ["vibe64-sessions"],
|
|
333
|
+
path: "/api/vibe64/sessions"
|
|
334
|
+
});
|
|
335
|
+
return () => h("div");
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
app.use(VueQueryPlugin, {
|
|
339
|
+
queryClient
|
|
340
|
+
});
|
|
341
|
+
await renderToString(app);
|
|
342
|
+
|
|
343
|
+
await resource.reload();
|
|
344
|
+
|
|
345
|
+
assert.equal(calls.at(-1)?.[0], "/api/app/beepollen/vibe64/sessions");
|
|
346
|
+
} finally {
|
|
347
|
+
resetUsersWebHttpClientForTests();
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("commands use the configured users-web HTTP client by default", async () => {
|
|
352
|
+
const queryClient = new QueryClient();
|
|
353
|
+
const calls = [];
|
|
354
|
+
let command = null;
|
|
355
|
+
configureUsersWebHttpClient({
|
|
356
|
+
csrf: {
|
|
357
|
+
enabled: false
|
|
358
|
+
},
|
|
359
|
+
resolveRequestUrl(url) {
|
|
360
|
+
return url.replace(/^\/api\//u, "/api/app/beepollen/");
|
|
361
|
+
},
|
|
362
|
+
fetchImpl: async (url, options) => {
|
|
363
|
+
calls.push([url, options]);
|
|
364
|
+
return {
|
|
365
|
+
ok: true,
|
|
366
|
+
status: 200,
|
|
367
|
+
headers: {
|
|
368
|
+
get(name) {
|
|
369
|
+
return String(name || "").toLowerCase() === "content-type"
|
|
370
|
+
? "application/json; charset=utf-8"
|
|
371
|
+
: "";
|
|
372
|
+
}
|
|
373
|
+
},
|
|
374
|
+
async json() {
|
|
375
|
+
return {
|
|
376
|
+
ok: true
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const app = createSSRApp({
|
|
385
|
+
setup() {
|
|
386
|
+
command = useCommand({
|
|
387
|
+
access: "always",
|
|
388
|
+
apiSuffix: "/vibe64/sessions"
|
|
389
|
+
});
|
|
390
|
+
return () => h("div");
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
app.use(VueQueryPlugin, {
|
|
394
|
+
queryClient
|
|
395
|
+
});
|
|
396
|
+
await renderToString(app);
|
|
397
|
+
|
|
398
|
+
await command.run();
|
|
399
|
+
|
|
400
|
+
assert.equal(calls.at(-1)?.[0], "/api/app/beepollen/vibe64/sessions");
|
|
401
|
+
assert.equal(calls.at(-1)?.[1]?.method, "POST");
|
|
402
|
+
} finally {
|
|
403
|
+
resetUsersWebHttpClientForTests();
|
|
404
|
+
}
|
|
405
|
+
});
|