@wssto2/vue-core 0.4.25 → 0.4.26
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/CHANGELOG.md +16 -0
- package/dist/{AccessGate.vue_vue_type_script_setup_true_lang-DcbZBINh.js → AccessGate.vue_vue_type_script_setup_true_lang-J5HoyGNJ.js} +1 -1
- package/dist/{Activity-CI-l_OFl.js → Activity-B6R8Jghz.js} +2 -2
- package/dist/{Changes-BdR0R20V.js → Changes-BQG7IV49.js} +2 -2
- package/dist/{CollectionPage.vue_vue_type_script_setup_true_lang-BNM_cbXa.js → CollectionPage.vue_vue_type_script_setup_true_lang-BrbQ0Y5d.js} +1 -1
- package/dist/{DeadLetters-CRTeoZS1.js → DeadLetters-CJZSWjsn.js} +4 -4
- package/dist/{General-hdmVP72B.js → General-tsRC866T.js} +2 -2
- package/dist/{NewRolePage-BPeKasOp.js → NewRolePage-L57Zg1Mg.js} +2 -2
- package/dist/{ProfilePage-Dq9lcO5O.js → ProfilePage-B9WUrImn.js} +2 -2
- package/dist/{RoleEditor.vue_vue_type_script_setup_true_lang-B6g2760V.js → RoleEditor.vue_vue_type_script_setup_true_lang-Hr0WgL1K.js} +2 -2
- package/dist/{RolePage-BYH-0fVI.js → RolePage-uezn-Og1.js} +3 -3
- package/dist/{RolesPage-BRm5xDw7.js → RolesPage-DkMAJZR6.js} +2 -2
- package/dist/{SectionNavigator.vue_vue_type_script_setup_true_lang-BltrQnrQ.js → SectionNavigator.vue_vue_type_script_setup_true_lang-BYRc0-qh.js} +1 -1
- package/dist/{Sessions-B1eKG_I2.js → Sessions-BDu3nMmz.js} +2 -2
- package/dist/{SettingsPage-0P38Ty4w.js → SettingsPage-CA7YCy6K.js} +2 -2
- package/dist/{SignIn-Dp8Ji0_r.js → SignIn-DQzS20kM.js} +2 -2
- package/dist/{SignInPage-CiStJboK.js → SignInPage-ft3unWwX.js} +2 -2
- package/dist/{SignIns-Bo7R2Coi.js → SignIns-C3h_YIkc.js} +2 -2
- package/dist/{UserRecord-DGq_PPy1.js → UserRecord-BO5-wsYt.js} +5 -5
- package/dist/{UsersList-BulNu4aE.js → UsersList-D3b3DGN5.js} +4 -4
- package/dist/access/index.js +1 -1
- package/dist/app/index.js +5 -5
- package/dist/collection/index.js +3 -3
- package/dist/{contributions-DsfmDoRD.js → contributions-BVBZP5Jb.js} +1 -1
- package/dist/{guards-Dve61KjR.js → guards-BJZjc3FZ.js} +1 -1
- package/dist/{http-D_D9YbLH.js → http-BFfkA7gN.js} +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/{index-BmowiT1y.js → index-BVU76sBO.js} +12 -12
- package/dist/{index-tnSTp0cM.js → index-C3CzOub7.js} +2 -2
- package/dist/{index-Yy28omu6.js → index-CvJSAsfk.js} +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{navigation-Cm3iChlR.js → navigation-DpcDF0rX.js} +1 -1
- package/dist/{neighbors-DVN_cADL.js → neighbors-RVQ4O3Qv.js} +1 -1
- package/dist/notifications/index.js +1 -1
- package/dist/page/index.js +1 -1
- package/dist/platform/index.d.ts +25 -1
- package/dist/platform/index.js +59 -49
- package/dist/platform/platform.d.ts +9 -5
- package/dist/platform/session.d.ts +10 -0
- package/dist/platform/sessionUser.d.ts +8 -0
- package/dist/platform-PZpUkkMS.js +268 -0
- package/dist/router/index.js +3 -3
- package/dist/{sections-D-kD98vu.js → sections-CeZl-Jxg.js} +1 -1
- package/dist/shell/index.js +3 -3
- package/dist/{status-Bh3-Cg7o.js → status-8KH7PITT.js} +2 -2
- package/dist/testing/index.js +1 -1
- package/dist/testing/platform.d.ts +10 -7
- package/package.json +3 -2
- package/dist/platform-q3cjODLx.js +0 -255
package/dist/platform/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
var N = Object.defineProperty;
|
|
2
|
-
var
|
|
2
|
+
var S = (s) => {
|
|
3
3
|
throw TypeError(s);
|
|
4
4
|
};
|
|
5
|
-
var
|
|
6
|
-
var $ = (s, t, e) =>
|
|
7
|
-
var o = (s, t, e) => (w(s, t, "read from private field"), e ? e.call(s) : t.get(s)),
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
5
|
+
var v = (s, t, e) => t in s ? N(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e;
|
|
6
|
+
var $ = (s, t, e) => v(s, typeof t != "symbol" ? t + "" : t, e), w = (s, t, e) => t.has(s) || S("Cannot " + e);
|
|
7
|
+
var o = (s, t, e) => (w(s, t, "read from private field"), e ? e.call(s) : t.get(s)), l = (s, t, e) => t.has(s) ? S("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(s) : t.set(s, e), f = (s, t, e, r) => (w(s, t, "write to private field"), r ? r.call(s, e) : t.set(s, e), e), h = (s, t, e) => (w(s, t, "access private method"), e);
|
|
8
|
+
import { u as E } from "../platform-PZpUkkMS.js";
|
|
9
|
+
import { b as F, c as G, a as K, d as U, h as _, e as z, i as D, p as H, f as Q, g as R } from "../platform-PZpUkkMS.js";
|
|
10
|
+
import { M as W, d as X } from "../context-Ch1r4fdN.js";
|
|
11
|
+
import { computed as O } from "vue";
|
|
12
|
+
import { _ as Z } from "../AccessGate.vue_vue_type_script_setup_true_lang-J5HoyGNJ.js";
|
|
13
|
+
class m extends Error {
|
|
12
14
|
constructor(e, r = [], n) {
|
|
13
15
|
super(r.length > 0 ? `${e}: ${r.join("; ")}` : e);
|
|
14
16
|
$(this, "issues");
|
|
@@ -16,52 +18,52 @@ class d extends Error {
|
|
|
16
18
|
this.name = "BootstrapError", this.issues = r, this.cause = n?.cause;
|
|
17
19
|
}
|
|
18
20
|
}
|
|
19
|
-
const x = (s) => s === null ? "null" : Array.isArray(s) ? "array" : typeof s,
|
|
20
|
-
var a, c, p,
|
|
21
|
+
const x = (s) => s === null ? "null" : Array.isArray(s) ? "array" : typeof s, B = (s) => typeof s == "object" && s !== null && !Array.isArray(s);
|
|
22
|
+
var a, c, p, d, u, g;
|
|
21
23
|
const b = class b {
|
|
22
24
|
/** @internal use the `fields` passed to `extend`. */
|
|
23
25
|
constructor(t, e, r, n = !1) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
f(this, a, t), f(this, c, e), f(this, p, r), f(this,
|
|
26
|
+
l(this, u);
|
|
27
|
+
l(this, a);
|
|
28
|
+
l(this, c);
|
|
29
|
+
l(this, p);
|
|
30
|
+
l(this, d);
|
|
31
|
+
f(this, a, t), f(this, c, e), f(this, p, r), f(this, d, n);
|
|
30
32
|
}
|
|
31
33
|
/** Records a problem with `key`; for values `raw` returns that the application validates itself. */
|
|
32
34
|
fail(t, e) {
|
|
33
|
-
o(this,
|
|
35
|
+
o(this, d) || o(this, p).push(`${o(this, c)}${t}: ${e}`);
|
|
34
36
|
}
|
|
35
37
|
/** The value as sent, unchecked. Validate it and report with `fail`. */
|
|
36
38
|
raw(t) {
|
|
37
39
|
return o(this, a)[t];
|
|
38
40
|
}
|
|
39
41
|
string(t, ...e) {
|
|
40
|
-
return
|
|
42
|
+
return h(this, u, g).call(this, t, "string", (r) => typeof r == "string", e);
|
|
41
43
|
}
|
|
42
44
|
number(t, ...e) {
|
|
43
|
-
return
|
|
45
|
+
return h(this, u, g).call(this, t, "number", (r) => typeof r == "number" && Number.isFinite(r), e);
|
|
44
46
|
}
|
|
45
47
|
boolean(t, ...e) {
|
|
46
|
-
return
|
|
48
|
+
return h(this, u, g).call(this, t, "boolean", (r) => typeof r == "boolean", e);
|
|
47
49
|
}
|
|
48
50
|
stringList(t, ...e) {
|
|
49
|
-
return
|
|
51
|
+
return h(this, u, g).call(this, t, "array of strings", (r) => Array.isArray(r) && r.every((n) => typeof n == "string"), e);
|
|
50
52
|
}
|
|
51
53
|
/** A nested object, read with the same checks; issues are reported as `parent.child`. */
|
|
52
54
|
section(t) {
|
|
53
55
|
const e = o(this, a)[t];
|
|
54
|
-
return
|
|
56
|
+
return B(e) ? new b(e, `${o(this, c)}${t}.`, o(this, p)) : (this.fail(t, `expected object, got ${x(e)}`), new b({}, `${o(this, c)}${t}.`, o(this, p), !0));
|
|
55
57
|
}
|
|
56
58
|
};
|
|
57
|
-
a = new WeakMap(), c = new WeakMap(), p = new WeakMap(),
|
|
59
|
+
a = new WeakMap(), c = new WeakMap(), p = new WeakMap(), d = new WeakMap(), u = new WeakSet(), g = function(t, e, r, n) {
|
|
58
60
|
const i = o(this, a)[t];
|
|
59
61
|
return i === void 0 && n.length > 0 ? n[0] : r(i) ? i : (this.fail(t, `expected ${e}, got ${i === void 0 ? "nothing (missing)" : x(i)}`), null);
|
|
60
62
|
};
|
|
61
63
|
let A = b;
|
|
62
|
-
function
|
|
63
|
-
if (!
|
|
64
|
-
throw new
|
|
64
|
+
function C(s, t) {
|
|
65
|
+
if (!B(s))
|
|
66
|
+
throw new m("Invalid bootstrap config", [`expected a JSON object, got ${x(s)}`]);
|
|
65
67
|
const e = [], r = new A(s, "", e), n = r.string("locale");
|
|
66
68
|
n === "" && r.fail("locale", "must not be empty");
|
|
67
69
|
const i = {
|
|
@@ -70,42 +72,50 @@ function O(s, t) {
|
|
|
70
72
|
appName: r.string("app_name", null),
|
|
71
73
|
capabilities: r.stringList("capabilities", [])
|
|
72
74
|
}, y = t?.(r) ?? {};
|
|
73
|
-
if (e.length > 0) throw new
|
|
75
|
+
if (e.length > 0) throw new m("Invalid bootstrap config", e);
|
|
74
76
|
return { ...y, ...i };
|
|
75
77
|
}
|
|
76
|
-
function
|
|
78
|
+
function L(s = {}) {
|
|
77
79
|
const { element: t = "app-state", extend: e } = s, r = typeof t == "string" ? document.getElementById(t) : t, n = typeof t == "string" ? `#${t}` : "the given element";
|
|
78
80
|
if (!r)
|
|
79
|
-
throw new
|
|
81
|
+
throw new m(
|
|
80
82
|
`Bootstrap config not found: the page has no ${n} element (expected <script id="app-state" type="application/json">)`
|
|
81
83
|
);
|
|
82
84
|
const i = r.textContent?.trim() ?? "";
|
|
83
|
-
if (i === "") throw new
|
|
85
|
+
if (i === "") throw new m(`Bootstrap config is empty: ${n} has no content`);
|
|
84
86
|
let y;
|
|
85
87
|
try {
|
|
86
88
|
y = JSON.parse(i);
|
|
87
89
|
} catch (j) {
|
|
88
|
-
throw new
|
|
90
|
+
throw new m(`Bootstrap config in ${n} is not valid JSON`, [], { cause: j });
|
|
89
91
|
}
|
|
90
|
-
return
|
|
92
|
+
return C(y, e);
|
|
93
|
+
}
|
|
94
|
+
function M() {
|
|
95
|
+
const { session: s } = E();
|
|
96
|
+
return O(() => {
|
|
97
|
+
const t = s.state.value;
|
|
98
|
+
return t.status === "authenticated" ? t.user : null;
|
|
99
|
+
});
|
|
91
100
|
}
|
|
92
101
|
export {
|
|
93
|
-
|
|
94
|
-
|
|
102
|
+
Z as AccessGate,
|
|
103
|
+
m as BootstrapError,
|
|
95
104
|
A as BootstrapFields,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
W as MissingContextError,
|
|
106
|
+
F as beforeSignOutTimeout,
|
|
107
|
+
G as createAccessClient,
|
|
108
|
+
K as createPlatform,
|
|
109
|
+
U as createSession,
|
|
110
|
+
X as defineFeatureContext,
|
|
111
|
+
_ as heldSession,
|
|
112
|
+
z as httpSessionAdapter,
|
|
113
|
+
D as installPlatform,
|
|
114
|
+
C as parseBootstrap,
|
|
115
|
+
H as parseNavigation,
|
|
116
|
+
Q as parseSessionPayload,
|
|
117
|
+
R as platformKey,
|
|
118
|
+
L as readBootstrap,
|
|
119
|
+
E as usePlatform,
|
|
120
|
+
M as useSessionUser
|
|
111
121
|
};
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import type { App } from "vue";
|
|
1
|
+
import type { App, InjectionKey } from "vue";
|
|
2
2
|
import { type HttpClient, type HttpClientOptions, type Transport } from "../client";
|
|
3
3
|
import { type AccessClient, type AccessClientOptions } from "./access";
|
|
4
4
|
import type { BootstrapConfig } from "./bootstrap";
|
|
5
|
+
import type { RegisteredConfig, RegisteredUser } from "./index";
|
|
5
6
|
import { type BeforeSignOutHook, type Session, type SessionAdapter, type SessionUser } from "./session";
|
|
6
|
-
/**
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* One application's shared services. Everything in it belongs to this instance alone. Bare `Platform` is the
|
|
9
|
+
* application's own: its user and config as declared in `PlatformRegistry`.
|
|
10
|
+
*/
|
|
11
|
+
export interface Platform<U extends SessionUser = RegisteredUser, C extends BootstrapConfig = RegisteredConfig> {
|
|
8
12
|
readonly config: C;
|
|
9
13
|
readonly http: HttpClient;
|
|
10
14
|
readonly session: Session<U>;
|
|
@@ -54,6 +58,6 @@ export declare function createPlatform<C extends BootstrapConfig>(options: Platf
|
|
|
54
58
|
export declare function createPlatform<U extends SessionUser, C extends BootstrapConfig>(options: PlatformOptions<U, C> & {
|
|
55
59
|
session: NonNullable<PlatformOptions<U, C>["session"]>;
|
|
56
60
|
}): Platform<U, C>;
|
|
57
|
-
|
|
58
|
-
export declare const
|
|
61
|
+
export declare const platformKey: InjectionKey<Platform>;
|
|
62
|
+
export declare const usePlatform: () => Platform;
|
|
59
63
|
export declare function installPlatform(app: App, platform: Platform): void;
|
|
@@ -51,6 +51,8 @@ export type SessionState<U extends SessionUser = SessionUser> =
|
|
|
51
51
|
* expired (its user, access and menu stay on screen while the person signs in again); null otherwise.
|
|
52
52
|
*/
|
|
53
53
|
export declare function heldSession<U extends SessionUser>(state: SessionState<U>): SessionSnapshot<U> | null;
|
|
54
|
+
/** The parts of a signed-in session `Session.update` may replace. */
|
|
55
|
+
export type SessionPatch<U extends SessionUser = SessionUser> = Partial<Pick<SessionSnapshot<U>, "user" | "access" | "navigation">>;
|
|
54
56
|
/** The seam to a backend: how to ask who is signed in and how to end the session. */
|
|
55
57
|
export interface SessionAdapter<U extends SessionUser = SessionUser> {
|
|
56
58
|
/** The current session, or null when there is none (not signed in). Reject for failures; honour `signal`. */
|
|
@@ -77,6 +79,14 @@ export interface Session<U extends SessionUser = SessionUser> {
|
|
|
77
79
|
refresh(): Promise<SessionState<U>>;
|
|
78
80
|
/** A sign-in succeeded: the application's login call produced this snapshot. */
|
|
79
81
|
establish(snapshot: SessionSnapshot<U>): void;
|
|
82
|
+
/**
|
|
83
|
+
* The same person, changed in place: a profile or language saved, a menu or access re-read by the application. Replaces
|
|
84
|
+
* only the parts in the patch; the status, `expiresAt` and the impersonator stay, and nothing in flight is cancelled
|
|
85
|
+
* (this is not "a change of who is signed in", which is `establish`). A no-op unless authenticated. A `user.id` other than
|
|
86
|
+
* the signed-in one is a programming error and throws: a different person is `establish`. A refresh already asked
|
|
87
|
+
* still lands when it is answered, with the server's version.
|
|
88
|
+
*/
|
|
89
|
+
update(patch: SessionPatch<U>): void;
|
|
80
90
|
/** The server rejected the session (401): signed in becomes anonymous with reason `expired`. No-op when nobody is signed in. */
|
|
81
91
|
expire(): void;
|
|
82
92
|
/**
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ComputedRef } from "vue";
|
|
2
|
+
import type { RegisteredUser } from "./index";
|
|
3
|
+
/**
|
|
4
|
+
* The signed-in user, typed from `PlatformRegistry`, or `null` while nobody is signed in (also while a session
|
|
5
|
+
* that expired is held on screen: it is not a signed-in user). Follows the session, so a user changed in place
|
|
6
|
+
* (`session.update({ user })`) reaches the reader. The impersonator stays on `session.state`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useSessionUser(): Readonly<ComputedRef<RegisteredUser | null>>;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { c as k } from "./client-k9euDWF4.js";
|
|
2
|
+
import { d as q } from "./context-Ch1r4fdN.js";
|
|
3
|
+
import { a as x, A as U } from "./error-CD7x0Jrz.js";
|
|
4
|
+
import { shallowRef as _ } from "vue";
|
|
5
|
+
const z = (e, n) => e.level === n.level && e.id === n.id, C = (e, n) => Object.prototype.hasOwnProperty.call(e, n);
|
|
6
|
+
function I(e, n = {}) {
|
|
7
|
+
const t = n.covers ?? z;
|
|
8
|
+
function o(s) {
|
|
9
|
+
const r = e();
|
|
10
|
+
return !r || !C(r.permissions, s) || r.unavailable.includes(s) ? null : r.permissions[s] ?? null;
|
|
11
|
+
}
|
|
12
|
+
function u(s, r) {
|
|
13
|
+
const i = o(s);
|
|
14
|
+
return i ? r ? (i.clauses.length > 0 ? i.clauses.map((f) => f.scope) : [i.scope]).some((f) => t(f, r)) : !0 : !1;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
get root() {
|
|
18
|
+
return e()?.root ?? !1;
|
|
19
|
+
},
|
|
20
|
+
can: u,
|
|
21
|
+
canAny: (s) => s.some((r) => u(r)),
|
|
22
|
+
canAll: (s) => s.every((r) => u(r)),
|
|
23
|
+
held: o
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const A = ["own", "own_location", "all"], m = (e) => typeof e == "object" && e !== null && !Array.isArray(e);
|
|
27
|
+
function $(e, n, t) {
|
|
28
|
+
return !m(e) || typeof e.level != "string" ? (t.push(`${n}: expected { level: string, id?: number }`), { level: "" }) : (e.id !== void 0 && typeof e.id != "number" && t.push(`${n}.id: expected number`), typeof e.id == "number" ? { level: e.level, id: e.id } : { level: e.level });
|
|
29
|
+
}
|
|
30
|
+
function S(e, n, t) {
|
|
31
|
+
return typeof e == "string" && A.includes(e) ? e : (t.push(`${n}: expected one of ${A.join(", ")}`), "own");
|
|
32
|
+
}
|
|
33
|
+
function T(e) {
|
|
34
|
+
const n = [], t = {}, o = { root: !1, permissions: {}, unavailable: [] };
|
|
35
|
+
if (!m(e)) return { snapshot: o, issues: ["access: expected an object"] };
|
|
36
|
+
if (!m(e.permissions)) n.push("access.permissions: expected an object");
|
|
37
|
+
else
|
|
38
|
+
for (const [s, r] of Object.entries(e.permissions)) {
|
|
39
|
+
const i = `access.permissions.${s}`;
|
|
40
|
+
if (!m(r)) {
|
|
41
|
+
n.push(`${i}: expected an object`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const c = (Array.isArray(r.clauses) ? r.clauses : []).map((f, g) => {
|
|
45
|
+
const a = `${i}.clauses[${g}]`;
|
|
46
|
+
if (!m(f))
|
|
47
|
+
return n.push(`${a}: expected an object`), { scope: { level: "" }, qualifier: "own" };
|
|
48
|
+
const l = { scope: $(f.scope, `${a}.scope`, n), qualifier: S(f.qualifier, `${a}.qualifier`, n) };
|
|
49
|
+
return typeof f.role == "string" ? { ...l, role: f.role } : l;
|
|
50
|
+
});
|
|
51
|
+
t[s] = {
|
|
52
|
+
scope: $(r.scope, `${i}.scope`, n),
|
|
53
|
+
qualifier: S(r.qualifier, `${i}.qualifier`, n),
|
|
54
|
+
clauses: c
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const u = e.unavailable ?? [];
|
|
58
|
+
return (!Array.isArray(u) || !u.every((s) => typeof s == "string")) && n.push("access.unavailable: expected an array of strings"), {
|
|
59
|
+
snapshot: {
|
|
60
|
+
root: e.root === !0,
|
|
61
|
+
permissions: t,
|
|
62
|
+
unavailable: Array.isArray(u) ? u.filter((s) => typeof s == "string") : []
|
|
63
|
+
},
|
|
64
|
+
issues: n
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const N = (e) => typeof e == "object" && e !== null && !Array.isArray(e);
|
|
68
|
+
function j(e, n, t = "navigation") {
|
|
69
|
+
return Array.isArray(e) ? e.flatMap((o, u) => {
|
|
70
|
+
const s = `${t}[${u}]`;
|
|
71
|
+
if (!N(o) || typeof o.i18n != "string")
|
|
72
|
+
return n.push(`${s}: expected an object with an i18n key`), [];
|
|
73
|
+
for (const i of ["icon", "route"])
|
|
74
|
+
o[i] != null && typeof o[i] != "string" && n.push(`${s}.${i}: expected a string`);
|
|
75
|
+
const r = o.children == null ? void 0 : j(o.children, n, `${s}.children`);
|
|
76
|
+
return [
|
|
77
|
+
{
|
|
78
|
+
i18n: o.i18n,
|
|
79
|
+
...typeof o.icon == "string" && { icon: o.icon },
|
|
80
|
+
...typeof o.route == "string" && { route: o.route },
|
|
81
|
+
...r && { children: r }
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
}) : (n.push(`${t}: expected an array`), []);
|
|
85
|
+
}
|
|
86
|
+
const b = (e) => typeof e == "object" && e !== null && !Array.isArray(e), B = (e) => {
|
|
87
|
+
if (b(e) && (typeof e.id == "number" || typeof e.id == "string")) return { id: e.id };
|
|
88
|
+
throw new TypeError("expected an object with a numeric or string id");
|
|
89
|
+
};
|
|
90
|
+
function F(e, n = B) {
|
|
91
|
+
const t = [];
|
|
92
|
+
if (!b(e)) throw w(["expected an object"]);
|
|
93
|
+
let o = null;
|
|
94
|
+
try {
|
|
95
|
+
o = n(e.user);
|
|
96
|
+
} catch (c) {
|
|
97
|
+
t.push(`user: ${c instanceof Error ? c.message : "invalid"}`);
|
|
98
|
+
}
|
|
99
|
+
let u = null;
|
|
100
|
+
if (e.expires_at !== void 0 && e.expires_at !== null) {
|
|
101
|
+
const c = typeof e.expires_at == "string" ? new Date(e.expires_at) : null;
|
|
102
|
+
c === null || Number.isNaN(c.getTime()) ? t.push("expires_at: expected an ISO date-time string") : u = c;
|
|
103
|
+
}
|
|
104
|
+
let s;
|
|
105
|
+
if (e.impersonator !== void 0 && e.impersonator !== null) {
|
|
106
|
+
const c = e.impersonator;
|
|
107
|
+
b(c) && (typeof c.id == "number" || typeof c.id == "string") && typeof c.name == "string" ? s = { id: c.id, name: c.name } : t.push("impersonator: expected { id, name }");
|
|
108
|
+
}
|
|
109
|
+
const r = T(e.access);
|
|
110
|
+
t.push(...r.issues);
|
|
111
|
+
const i = e.navigation === void 0 || e.navigation === null ? void 0 : j(e.navigation, t);
|
|
112
|
+
if (o === null || t.length > 0) throw w(t);
|
|
113
|
+
return { user: o, expiresAt: u, access: r.snapshot, ...s && { impersonator: s }, ...i && { navigation: i } };
|
|
114
|
+
}
|
|
115
|
+
const w = (e) => new U({ kind: "malformed", message: `Unreadable session payload: ${e.join("; ")}` });
|
|
116
|
+
function H(e, n = {}) {
|
|
117
|
+
const { mePath: t = "/auth/me", signOutPath: o = "/auth/logout", parseUser: u } = n;
|
|
118
|
+
return {
|
|
119
|
+
async load(s) {
|
|
120
|
+
try {
|
|
121
|
+
const { data: r } = await e.get(t, { signal: s, handleUnauthorized: !1 });
|
|
122
|
+
return F(r, u);
|
|
123
|
+
} catch (r) {
|
|
124
|
+
if (x(r) && r.kind === "unauthorized") return null;
|
|
125
|
+
throw r;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async signOut() {
|
|
129
|
+
try {
|
|
130
|
+
await e.post(o, void 0, { handleUnauthorized: !1 });
|
|
131
|
+
} catch (s) {
|
|
132
|
+
if (!(x(s) && s.kind === "unauthorized")) throw s;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function E(e) {
|
|
138
|
+
return e.status === "authenticated" ? e : e.status === "anonymous" && e.reason === "expired" ? e.previous ?? null : null;
|
|
139
|
+
}
|
|
140
|
+
const O = 3e3;
|
|
141
|
+
function Q(e, n = {}) {
|
|
142
|
+
const t = _({ status: "unknown" });
|
|
143
|
+
let o = 0;
|
|
144
|
+
const u = new Set(n.beforeSignOut ? [n.beforeSignOut] : []);
|
|
145
|
+
let s = !1, r = null, i = null;
|
|
146
|
+
function c() {
|
|
147
|
+
o++, i?.controller.abort(), i = null;
|
|
148
|
+
}
|
|
149
|
+
async function f(a) {
|
|
150
|
+
const l = new AbortController();
|
|
151
|
+
let h;
|
|
152
|
+
const y = new Promise((p) => {
|
|
153
|
+
h = setTimeout(() => {
|
|
154
|
+
l.abort(), n.onError?.(new Error(`A before-sign-out hook did not finish within ${O} ms; signing out without it.`)), p();
|
|
155
|
+
}, O);
|
|
156
|
+
}), v = Promise.all(
|
|
157
|
+
[...u].map(async (p) => {
|
|
158
|
+
try {
|
|
159
|
+
await p(a, l.signal);
|
|
160
|
+
} catch (d) {
|
|
161
|
+
n.onError?.(d);
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
).then(() => {
|
|
165
|
+
});
|
|
166
|
+
await Promise.race([v, y]), clearTimeout(h);
|
|
167
|
+
}
|
|
168
|
+
function g() {
|
|
169
|
+
if (i) return i.promise;
|
|
170
|
+
const a = o, l = new AbortController(), h = t.value, y = E(h) !== null;
|
|
171
|
+
y || (t.value = { status: "loading" });
|
|
172
|
+
const v = async () => {
|
|
173
|
+
try {
|
|
174
|
+
const d = await e.load(l.signal);
|
|
175
|
+
if (o !== a) return t.value;
|
|
176
|
+
t.value = d ? { status: "authenticated", ...d } : { status: "anonymous", reason: "none" };
|
|
177
|
+
} catch (d) {
|
|
178
|
+
if (o !== a) return t.value;
|
|
179
|
+
n.onError?.(d), t.value = y ? h : { status: "failed", error: d };
|
|
180
|
+
} finally {
|
|
181
|
+
o === a && (i = null);
|
|
182
|
+
}
|
|
183
|
+
return t.value;
|
|
184
|
+
}, p = Promise.resolve().then(v);
|
|
185
|
+
return i = { controller: l, promise: p }, p;
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
state: t,
|
|
189
|
+
restore: () => t.value.status === "unknown" || t.value.status === "failed" ? g() : i?.promise ?? Promise.resolve(t.value),
|
|
190
|
+
refresh: g,
|
|
191
|
+
establish(a) {
|
|
192
|
+
c(), t.value = { status: "authenticated", ...a };
|
|
193
|
+
},
|
|
194
|
+
update(a) {
|
|
195
|
+
const l = t.value;
|
|
196
|
+
if (l.status === "authenticated") {
|
|
197
|
+
if (a.user && a.user.id !== l.user.id)
|
|
198
|
+
throw new Error(`session.update cannot change who is signed in (user ${String(l.user.id)} to ${String(a.user.id)}); use session.establish for a different person.`);
|
|
199
|
+
t.value = {
|
|
200
|
+
...l,
|
|
201
|
+
user: a.user ?? l.user,
|
|
202
|
+
access: a.access ?? l.access,
|
|
203
|
+
...(a.navigation ?? l.navigation) && { navigation: a.navigation ?? l.navigation }
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
expire() {
|
|
208
|
+
if (t.value.status !== "authenticated") return;
|
|
209
|
+
const { status: a, ...l } = t.value;
|
|
210
|
+
c(), t.value = s && !t.value.impersonator ? { status: "anonymous", reason: "expired", previous: l } : { status: "anonymous", reason: "expired" }, n.onExpired?.();
|
|
211
|
+
},
|
|
212
|
+
signOut() {
|
|
213
|
+
return r ?? (r = (async () => {
|
|
214
|
+
try {
|
|
215
|
+
const a = t.value;
|
|
216
|
+
a.status === "authenticated" && u.size > 0 && await f(a.user), c(), t.value = { status: "anonymous", reason: "signedOut" }, await e.signOut();
|
|
217
|
+
} finally {
|
|
218
|
+
r = null;
|
|
219
|
+
}
|
|
220
|
+
})()), r;
|
|
221
|
+
},
|
|
222
|
+
holdExpired(a) {
|
|
223
|
+
s = a;
|
|
224
|
+
},
|
|
225
|
+
onBeforeSignOut(a) {
|
|
226
|
+
return u.add(a), () => void u.delete(a);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function G(e) {
|
|
231
|
+
let n = null;
|
|
232
|
+
const t = k({
|
|
233
|
+
baseUrl: e.config.apiBase,
|
|
234
|
+
transport: e.transport,
|
|
235
|
+
headers: e.headers,
|
|
236
|
+
credentials: e.credentials,
|
|
237
|
+
requestId: e.requestId,
|
|
238
|
+
async onUnauthorized() {
|
|
239
|
+
return s.state.value.status !== "authenticated" ? "fail" : e.renewSession && (n ?? (n = e.renewSession(s, t).then(
|
|
240
|
+
(i) => i,
|
|
241
|
+
() => !1
|
|
242
|
+
).finally(() => {
|
|
243
|
+
n = null;
|
|
244
|
+
})), await n) ? "retry" : (s.expire(), "fail");
|
|
245
|
+
}
|
|
246
|
+
}), o = e.session ?? ((i) => H(i)), u = typeof o == "function" ? o(t) : o, s = Q(u, { onError: e.onSessionError, onExpired: e.onSessionExpired, beforeSignOut: e.beforeSignOut }), r = I(
|
|
247
|
+
() => E(s.state.value)?.access ?? null,
|
|
248
|
+
{ covers: e.covers }
|
|
249
|
+
);
|
|
250
|
+
return { config: e.config, http: t, session: s, access: r };
|
|
251
|
+
}
|
|
252
|
+
const P = q("platform"), R = P[0], J = P[1];
|
|
253
|
+
function V(e, n) {
|
|
254
|
+
e.provide(R, n);
|
|
255
|
+
}
|
|
256
|
+
export {
|
|
257
|
+
G as a,
|
|
258
|
+
O as b,
|
|
259
|
+
I as c,
|
|
260
|
+
Q as d,
|
|
261
|
+
H as e,
|
|
262
|
+
F as f,
|
|
263
|
+
R as g,
|
|
264
|
+
E as h,
|
|
265
|
+
V as i,
|
|
266
|
+
j as p,
|
|
267
|
+
J as u
|
|
268
|
+
};
|
package/dist/router/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { _ as a, c as o, a as r, i as t } from "../NoAccess.vue_vue_type_script_setup_true_lang-DWxq-MTM.js";
|
|
2
2
|
import { d as c } from "../defineRoutes-BGAdiIrt.js";
|
|
3
3
|
import { A as u, f as p, i as f, r as A, u as m } from "../access-DmAceEo5.js";
|
|
4
|
-
import { i as l, r as x } from "../guards-
|
|
5
|
-
import { u as y } from "../sections-
|
|
6
|
-
import { b as v, c as N, n as H, u as b } from "../navigation-
|
|
4
|
+
import { i as l, r as x } from "../guards-BJZjc3FZ.js";
|
|
5
|
+
import { u as y } from "../sections-CeZl-Jxg.js";
|
|
6
|
+
import { b as v, c as N, n as H, u as b } from "../navigation-DpcDF0rX.js";
|
|
7
7
|
export {
|
|
8
8
|
u as AppRouterView,
|
|
9
9
|
a as NoAccess,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { computed as n, watch as h } from "vue";
|
|
2
2
|
import { useI18n as b } from "vue-i18n";
|
|
3
3
|
import { useRoute as g, useRouter as p } from "vue-router";
|
|
4
|
-
import { u as y } from "./platform-
|
|
4
|
+
import { u as y } from "./platform-PZpUkkMS.js";
|
|
5
5
|
import { i as w } from "./access-DmAceEo5.js";
|
|
6
6
|
function j() {
|
|
7
7
|
const t = g(), u = p(), { access: c } = y(), { t: r } = b(), i = n(() => {
|
package/dist/shell/index.js
CHANGED
|
@@ -3,12 +3,12 @@ import { useI18n as B } from "vue-i18n";
|
|
|
3
3
|
import { _ as we } from "../Avatar.vue_vue_type_script_setup_true_lang-CFIheaSr.js";
|
|
4
4
|
import { _ as P, u as Xe, c as Ue } from "../Icon.vue_vue_type_script_lang-D7oC-d-S.js";
|
|
5
5
|
import { _ as We } from "../Popover.vue_vue_type_script_setup_true_lang-C70GrCP7.js";
|
|
6
|
-
import { u as xe, S as X } from "../contributions-
|
|
6
|
+
import { u as xe, S as X } from "../contributions-BVBZP5Jb.js";
|
|
7
7
|
import { u as Ye } from "../environment-Dva-SG8D.js";
|
|
8
8
|
import { _ as He } from "../CountryFlag.vue_vue_type_script_setup_true_lang-Kry_vPPZ.js";
|
|
9
9
|
import { l as pe } from "../languageName-CItV_SOv.js";
|
|
10
10
|
import { t as _e } from "../toast-CqSDTWRX.js";
|
|
11
|
-
import { u as J, h as ue } from "../platform-
|
|
11
|
+
import { u as J, h as ue } from "../platform-PZpUkkMS.js";
|
|
12
12
|
import { a as qe, _ as ve, h as ke } from "../AccountMenuItem.vue_vue_type_script_setup_true_lang-CPeNxh5K.js";
|
|
13
13
|
import { _ as Ge } from "../Sheet.vue_vue_type_script_setup_true_lang-DgOFV4fa.js";
|
|
14
14
|
import { _ as Qe } from "../LeaveGuardRoot.vue_vue_type_script_setup_true_lang-Cv7KlA5y.js";
|
|
@@ -17,7 +17,7 @@ import { _ as Ze } from "../BottomDock.vue_vue_type_script_setup_true_lang-CjN7x
|
|
|
17
17
|
import { b as $e } from "../chrome-nUcmVu8G.js";
|
|
18
18
|
import { p as Se, A as et } from "../access-DmAceEo5.js";
|
|
19
19
|
import { RouterLink as Le, useRoute as tt, useRouter as de } from "vue-router";
|
|
20
|
-
import { u as nt } from "../navigation-
|
|
20
|
+
import { u as nt } from "../navigation-DpcDF0rX.js";
|
|
21
21
|
import { u as at } from "../leaveGuard-Cc8yeLxM.js";
|
|
22
22
|
import { u as ot, S as st } from "../dialogStack-DZZg55w0.js";
|
|
23
23
|
import { a as H } from "../mediaQuery-CygcXmFW.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a, r as o } from "./http-
|
|
2
|
-
import { i as r } from "./index-
|
|
1
|
+
import { a, r as o } from "./http-BFfkA7gN.js";
|
|
2
|
+
import { i as r } from "./index-BVU76sBO.js";
|
|
3
3
|
const n = ["active", "locked", "inactive", "all"];
|
|
4
4
|
function l(i) {
|
|
5
5
|
return a({
|
package/dist/testing/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { nextTick as b, createApp as j, defineComponent as m, h as u } from "vue";
|
|
2
2
|
import { createMemoryHistory as P, createRouter as E, RouterView as $ } from "vue-router";
|
|
3
|
-
import { a as A, i as O } from "../platform-
|
|
3
|
+
import { a as A, i as O } from "../platform-PZpUkkMS.js";
|
|
4
4
|
import { createI18n as k } from "vue-i18n";
|
|
5
5
|
import { coreMessages as M } from "../i18n/index.js";
|
|
6
6
|
import { i as R, c as S } from "../format-D8X4zsx6.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AccessClause, type AccessQualifier, type BootstrapConfig, type HeldAccess, type NavigationNode, type Platform, type PlatformOptions, type SessionAdapter, type SessionSnapshot, type SessionUser } from "../platform";
|
|
1
|
+
import { type AccessClause, type AccessQualifier, type BootstrapConfig, type HeldAccess, type NavigationNode, type Platform, type PlatformOptions, type RegisteredConfig, type RegisteredUser, type SessionAdapter, type SessionSnapshot, type SessionUser } from "../platform";
|
|
2
2
|
import type { Transport } from "../client";
|
|
3
3
|
/**
|
|
4
4
|
* How a permission is held: at a level of your scope hierarchy (`organization`, `dealer`, ...) with an
|
|
@@ -6,7 +6,7 @@ import type { Transport } from "../client";
|
|
|
6
6
|
* `permissions` record of `createTestSession`; a plain permission name there means "everything, at the organization".
|
|
7
7
|
*/
|
|
8
8
|
export declare function heldAccess(level: string, id?: number, qualifier?: AccessQualifier, clauses?: readonly AccessClause[]): HeldAccess;
|
|
9
|
-
export interface TestSessionOptions<U extends SessionUser =
|
|
9
|
+
export interface TestSessionOptions<U extends SessionUser = RegisteredUser> {
|
|
10
10
|
/** Default `{ id: 1 }`. */
|
|
11
11
|
user?: U;
|
|
12
12
|
/** Permissions held at the organization for every record (names), or exactly how each is held (`heldAccess`). */
|
|
@@ -19,14 +19,17 @@ export interface TestSessionOptions<U extends SessionUser = SessionUser> {
|
|
|
19
19
|
expiresAt?: Date | null;
|
|
20
20
|
}
|
|
21
21
|
/** What `/auth/me` would say for a user: for `session.establish(...)` mid-test, or an adapter that answers it. */
|
|
22
|
-
export declare function createTestSession<U extends SessionUser =
|
|
23
|
-
export interface TestPlatformOptions<U extends SessionUser =
|
|
22
|
+
export declare function createTestSession<U extends SessionUser = RegisteredUser>(options?: TestSessionOptions<U>): SessionSnapshot<U>;
|
|
23
|
+
export interface TestPlatformOptions<U extends SessionUser = RegisteredUser> extends Omit<TestSessionOptions<U>, "user">, Omit<PlatformOptions<U, BootstrapConfig>, "config" | "transport" | "session"> {
|
|
24
24
|
/** `null`: nobody is signed in (the session answers "none" when asked). Default: the user of `createTestSession`. */
|
|
25
25
|
user?: U | null;
|
|
26
26
|
/** Answers the requests the code under test makes: `scriptedTransport` or `routedTransport`. Default: any request fails the test. */
|
|
27
27
|
transport?: Transport;
|
|
28
|
-
/**
|
|
29
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Fields of the bootstrap config over the test's (`apiBase: ""`, `locale: "en"`, `appName: "Test app"`). The
|
|
30
|
+
* fields a registered config adds (`PlatformRegistry`) are required here: the test has no other source for them.
|
|
31
|
+
*/
|
|
32
|
+
config?: Partial<BootstrapConfig> & Omit<RegisteredConfig, keyof BootstrapConfig>;
|
|
30
33
|
/** A session adapter of your own; then `user`, `permissions` and the like are not used and the session starts unasked. */
|
|
31
34
|
session?: SessionAdapter<U>;
|
|
32
35
|
}
|
|
@@ -37,4 +40,4 @@ export interface TestPlatformOptions<U extends SessionUser = SessionUser> extend
|
|
|
37
40
|
* const platform = createTestPlatform({ user: { id: 7 }, permissions: ["tickets:view"], transport });
|
|
38
41
|
* platform.access.can("tickets:view"); // true, at once
|
|
39
42
|
*/
|
|
40
|
-
export declare function createTestPlatform<U extends SessionUser =
|
|
43
|
+
export declare function createTestPlatform<U extends SessionUser = RegisteredUser>(options?: TestPlatformOptions<U>): Platform<U>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wssto2/vue-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.26",
|
|
4
4
|
"goCore": "v1.7.0",
|
|
5
5
|
"description": "Shared Vue 3 library for go-core applications: app shell, list / record / form pages and their controls.",
|
|
6
6
|
"keywords": [
|
|
@@ -138,10 +138,11 @@
|
|
|
138
138
|
"typecheck": "vue-tsc --noEmit",
|
|
139
139
|
"typecheck:docs": "vue-tsc --noEmit -p docs/examples/tsconfig.json",
|
|
140
140
|
"typecheck:fixtures": "vue-tsc --noEmit -p test-data/tsconfig.json",
|
|
141
|
+
"typecheck:registry": "vue-tsc --noEmit -p test-data/registry/tsconfig.json",
|
|
141
142
|
"test": "vitest run",
|
|
142
143
|
"build": "vite build && vite build -c vite.styles.config.ts && vue-tsc -p tsconfig.build.json",
|
|
143
144
|
"check:consumer": "node scripts/check-consumer.mjs",
|
|
144
|
-
"check": "npm run lint && npm run typecheck && npm run typecheck:docs && npm run typecheck:fixtures && npm run check:modules && npm run check:docs && npm run test && npm run build && npm run check:consumer",
|
|
145
|
+
"check": "npm run lint && npm run typecheck && npm run typecheck:docs && npm run typecheck:fixtures && npm run typecheck:registry && npm run check:modules && npm run check:docs && npm run test && npm run build && npm run check:consumer",
|
|
145
146
|
"check:docs": "node scripts/check-docs.mjs",
|
|
146
147
|
"prepublishOnly": "npm run check",
|
|
147
148
|
"modules:sync": "node scripts/modules.mjs sync",
|