@unisim/sdk 0.1.0 → 0.1.3

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.
@@ -0,0 +1,18 @@
1
+ export interface UniversalBarProps {
2
+ /** Height in px — default 4 */
3
+ height?: number;
4
+ /** Center colour of the gradient — default UNISIM orange */
5
+ color?: string;
6
+ /** Pulse animation (default true). Respects user `prefers-reduced-motion` automatically. */
7
+ animated?: boolean;
8
+ }
9
+ /**
10
+ * The Universal Suite "brand strip" — a thin gradient bar that sits at the top
11
+ * of every product's app shell for cross-suite visual consistency.
12
+ *
13
+ * Matches the design used on unisim.co.uk: 4px tall, transparent → orange →
14
+ * transparent gradient, with a subtle 2.4s opacity pulse. Edges fade to
15
+ * transparent so it works on both light and dark page backgrounds.
16
+ */
17
+ export declare function UniversalBar({ height, color, animated, }?: UniversalBarProps): import("react/jsx-runtime").JSX.Element;
18
+ //# sourceMappingURL=UniversalBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UniversalBar.d.ts","sourceRoot":"","sources":["../src/UniversalBar.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IAChC,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAU,EACV,KAAiB,EACjB,QAAe,GAChB,GAAE,iBAAsB,2CA4BxB"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ /**
4
+ * The Universal Suite "brand strip" — a thin gradient bar that sits at the top
5
+ * of every product's app shell for cross-suite visual consistency.
6
+ *
7
+ * Matches the design used on unisim.co.uk: 4px tall, transparent → orange →
8
+ * transparent gradient, with a subtle 2.4s opacity pulse. Edges fade to
9
+ * transparent so it works on both light and dark page backgrounds.
10
+ */
11
+ export function UniversalBar({ height = 4, color = '#e05504', animated = true, } = {}) {
12
+ const ref = useRef(null);
13
+ useEffect(() => {
14
+ if (!animated || !ref.current)
15
+ return;
16
+ // Skip animation if the user prefers reduced motion
17
+ const reduced = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
18
+ if (reduced)
19
+ return;
20
+ const animation = ref.current.animate([{ opacity: 1 }, { opacity: 0.35 }, { opacity: 1 }], { duration: 2400, iterations: Infinity, easing: 'ease-in-out' });
21
+ return () => animation.cancel();
22
+ }, [animated]);
23
+ return (_jsx("div", { ref: ref, "aria-hidden": "true", style: {
24
+ height: `${height}px`,
25
+ background: `linear-gradient(90deg, transparent 0%, ${color} 50%, transparent 100%)`,
26
+ flexShrink: 0,
27
+ width: '100%',
28
+ } }));
29
+ }
30
+ //# sourceMappingURL=UniversalBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UniversalBar.js","sourceRoot":"","sources":["../src/UniversalBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAWzC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,MAAM,GAAG,CAAC,EACV,KAAK,GAAG,SAAS,EACjB,QAAQ,GAAG,IAAI,MACM,EAAE;IACvB,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAExC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,OAAM;QACrC,oDAAoD;QACpD,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,kCAAkC,CAAC,CAAC,OAAO,CAAA;QAC/E,IAAI,OAAO;YAAE,OAAM;QAEnB,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CACnC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EACnD,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,CAChE,CAAA;QACD,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,CAAA;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,OAAO,CACL,cACE,GAAG,EAAE,GAAG,iBACI,MAAM,EAClB,KAAK,EAAE;YACL,MAAM,EAAE,GAAG,MAAM,IAAI;YACrB,UAAU,EAAE,0CAA0C,KAAK,yBAAyB;YACpF,UAAU,EAAE,CAAC;YACb,KAAK,EAAE,MAAM;SACd,GACD,CACH,CAAA;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ProductCode, Seat } from './types.js';
2
+ /** Whether the active org has base access to a product. */
3
+ export declare function useHasAccess(product: ProductCode): boolean;
4
+ /** Whether the active org has a specific feature flag granted. */
5
+ export declare function useHasFeature(featureKey: string): boolean;
6
+ export interface UseSeatResult {
7
+ seat: Seat | null;
8
+ active: boolean;
9
+ loading: boolean;
10
+ }
11
+ /** The current user's seat status in the active org. */
12
+ export declare function useSeat(): UseSeatResult;
13
+ //# sourceMappingURL=access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AA6CnD,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAG1D;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAQzD;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wDAAwD;AACxD,wBAAgB,OAAO,IAAI,aAAa,CAkCvC"}
package/dist/access.js ADDED
@@ -0,0 +1,75 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useUniversal } from './provider.js';
3
+ function useAccessRows() {
4
+ const { supabase, session, activeOrgId } = useUniversal();
5
+ const [state, setState] = useState({ rows: [], loading: true });
6
+ useEffect(() => {
7
+ if (!session || !activeOrgId) {
8
+ setState({ rows: [], loading: false });
9
+ return;
10
+ }
11
+ let cancelled = false;
12
+ setState((s) => ({ ...s, loading: true }));
13
+ supabase
14
+ .from('product_access')
15
+ .select('org_id, product, feature, granted')
16
+ .eq('org_id', activeOrgId)
17
+ .then(({ data, error }) => {
18
+ if (cancelled)
19
+ return;
20
+ if (error)
21
+ console.error('[unisim/sdk] failed to load product_access', error);
22
+ setState({ rows: data ?? [], loading: false });
23
+ });
24
+ return () => {
25
+ cancelled = true;
26
+ };
27
+ }, [supabase, session, activeOrgId]);
28
+ return state;
29
+ }
30
+ /** Whether the active org has base access to a product. */
31
+ export function useHasAccess(product) {
32
+ const { rows } = useAccessRows();
33
+ return rows.some((r) => r.product === product && r.feature === null && r.granted);
34
+ }
35
+ /** Whether the active org has a specific feature flag granted. */
36
+ export function useHasFeature(featureKey) {
37
+ const { rows } = useAccessRows();
38
+ // featureKey format is 'product.feature_name', e.g. 'webinar.anonymous_attendees'
39
+ const [product, ...rest] = featureKey.split('.');
40
+ const feature = rest.join('.');
41
+ return rows.some((r) => r.product === product && r.feature === feature && r.granted);
42
+ }
43
+ /** The current user's seat status in the active org. */
44
+ export function useSeat() {
45
+ const { supabase, session, activeOrgId } = useUniversal();
46
+ const [state, setState] = useState({ seat: null, active: false, loading: true });
47
+ useEffect(() => {
48
+ if (!session || !activeOrgId) {
49
+ setState({ seat: null, active: false, loading: false });
50
+ return;
51
+ }
52
+ let cancelled = false;
53
+ supabase
54
+ .from('seats')
55
+ .select('*')
56
+ .eq('org_id', activeOrgId)
57
+ .eq('assigned_user_id', session.user.id)
58
+ .eq('status', 'active')
59
+ .maybeSingle()
60
+ .then(({ data }) => {
61
+ if (cancelled)
62
+ return;
63
+ setState({
64
+ seat: data ?? null,
65
+ active: !!data,
66
+ loading: false,
67
+ });
68
+ });
69
+ return () => {
70
+ cancelled = true;
71
+ };
72
+ }, [supabase, session, activeOrgId]);
73
+ return state;
74
+ }
75
+ //# sourceMappingURL=access.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access.js","sourceRoot":"","sources":["../src/access.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAe5C,SAAS,aAAa;IACpB,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAAA;IACzD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAiB,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAE/E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;YACtC,OAAM;QACR,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAE1C,QAAQ;aACL,IAAI,CAAC,gBAAgB,CAAC;aACtB,MAAM,CAAC,mCAAmC,CAAC;aAC3C,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;aACzB,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;YACxB,IAAI,SAAS;gBAAE,OAAM;YACrB,IAAI,KAAK;gBAAE,OAAO,CAAC,KAAK,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAA;YAC7E,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;IAEpC,OAAO,KAAK,CAAA;AACd,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,YAAY,CAAC,OAAoB;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,CAAA;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,CAAA;AACnF,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,CAAA;IAChC,kFAAkF;IAClF,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9B,OAAO,IAAI,CAAC,IAAI,CACd,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,CACnE,CAAA;AACH,CAAC;AAQD,wDAAwD;AACxD,MAAM,UAAU,OAAO;IACrB,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,YAAY,EAAE,CAAA;IACzD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAE/F,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;YACvD,OAAM;QACR,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAA;QAErB,QAAQ;aACL,IAAI,CAAC,OAAO,CAAC;aACb,MAAM,CAAC,GAAG,CAAC;aACX,EAAE,CAAC,QAAQ,EAAE,WAAW,CAAC;aACzB,EAAE,CAAC,kBAAkB,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;aACvC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;aACtB,WAAW,EAAE;aACb,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YACjB,IAAI,SAAS;gBAAE,OAAM;YACrB,QAAQ,CAAC;gBACP,IAAI,EAAE,IAAI,IAAI,IAAI;gBAClB,MAAM,EAAE,CAAC,CAAC,IAAI;gBACd,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAA;IAEpC,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { useUniversal } from './provider.js';
2
+ import type { OrgMember, Seat, SeatPool, AuditLogEntry } from './types.js';
3
+ export interface UseOrgMembersResult {
4
+ members: OrgMember[];
5
+ loading: boolean;
6
+ refresh: () => void;
7
+ }
8
+ export declare function useOrgMembers(orgId?: string): UseOrgMembersResult;
9
+ export interface UseOrgSeatsResult {
10
+ seats: Seat[];
11
+ pool: SeatPool;
12
+ loading: boolean;
13
+ refresh: () => void;
14
+ }
15
+ export declare function useOrgSeats(orgId?: string): UseOrgSeatsResult;
16
+ export declare function assignSeat(supabase: ReturnType<typeof useUniversal>['supabase'], args: {
17
+ orgId: string;
18
+ userId: string;
19
+ assignedByUserId: string;
20
+ }): Promise<{
21
+ ok: true;
22
+ } | {
23
+ ok: false;
24
+ error: string;
25
+ }>;
26
+ export declare function revokeSeat(supabase: ReturnType<typeof useUniversal>['supabase'], seatId: string): Promise<{
27
+ ok: true;
28
+ } | {
29
+ ok: false;
30
+ error: string;
31
+ }>;
32
+ export declare function reassignSeat(supabase: ReturnType<typeof useUniversal>['supabase'], args: {
33
+ seatId: string;
34
+ newUserId: string;
35
+ assignedByUserId: string;
36
+ }): Promise<{
37
+ ok: true;
38
+ } | {
39
+ ok: false;
40
+ error: string;
41
+ }>;
42
+ export interface UseAuditLogOptions {
43
+ limit?: number;
44
+ orgId?: string;
45
+ }
46
+ export declare function useAuditLog(opts?: UseAuditLogOptions): {
47
+ entries: AuditLogEntry[];
48
+ loading: boolean;
49
+ };
50
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAM1E,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,mBAAmB,CA+BjE;AAMD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,IAAI,EAAE,CAAA;IACb,IAAI,EAAE,QAAQ,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAwC7D;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC,EACrD,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAyBtD;AAED,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC,EACrD,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAUtD;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC,EACrD,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GACpE,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAYtD;AAMD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG;IAC1D,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;CACjB,CAiCA"}
package/dist/admin.js ADDED
@@ -0,0 +1,158 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useUniversal } from './provider.js';
3
+ export function useOrgMembers(orgId) {
4
+ const { supabase, activeOrgId } = useUniversal();
5
+ const id = orgId ?? activeOrgId;
6
+ const [members, setMembers] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [tick, setTick] = useState(0);
9
+ useEffect(() => {
10
+ if (!id) {
11
+ setMembers([]);
12
+ setLoading(false);
13
+ return;
14
+ }
15
+ let cancelled = false;
16
+ setLoading(true);
17
+ supabase
18
+ .from('org_members')
19
+ .select('org_id, user_id, role, joined_at, profile:profiles(*)')
20
+ .eq('org_id', id)
21
+ .then(({ data, error }) => {
22
+ if (cancelled)
23
+ return;
24
+ if (error)
25
+ console.error('[unisim/sdk] failed to load org_members', error);
26
+ setMembers(data ?? []);
27
+ setLoading(false);
28
+ });
29
+ return () => {
30
+ cancelled = true;
31
+ };
32
+ }, [supabase, id, tick]);
33
+ return { members, loading, refresh: () => setTick((t) => t + 1) };
34
+ }
35
+ export function useOrgSeats(orgId) {
36
+ const { supabase, activeOrgId } = useUniversal();
37
+ const id = orgId ?? activeOrgId;
38
+ const [seats, setSeats] = useState([]);
39
+ const [loading, setLoading] = useState(true);
40
+ const [tick, setTick] = useState(0);
41
+ useEffect(() => {
42
+ if (!id) {
43
+ setSeats([]);
44
+ setLoading(false);
45
+ return;
46
+ }
47
+ let cancelled = false;
48
+ setLoading(true);
49
+ supabase
50
+ .from('seats')
51
+ .select('*')
52
+ .eq('org_id', id)
53
+ .then(({ data, error }) => {
54
+ if (cancelled)
55
+ return;
56
+ if (error)
57
+ console.error('[unisim/sdk] failed to load seats', error);
58
+ setSeats(data ?? []);
59
+ setLoading(false);
60
+ });
61
+ return () => {
62
+ cancelled = true;
63
+ };
64
+ }, [supabase, id, tick]);
65
+ const total = seats.length;
66
+ const assigned = seats.filter((s) => s.status === 'active').length;
67
+ const available = total - assigned;
68
+ return {
69
+ seats,
70
+ pool: { total, assigned, available },
71
+ loading,
72
+ refresh: () => setTick((t) => t + 1),
73
+ };
74
+ }
75
+ export async function assignSeat(supabase, args) {
76
+ // Find an unassigned seat in the pool, then claim it.
77
+ const { data: pool, error: poolError } = await supabase
78
+ .from('seats')
79
+ .select('id')
80
+ .eq('org_id', args.orgId)
81
+ .eq('status', 'unassigned')
82
+ .limit(1)
83
+ .maybeSingle();
84
+ if (poolError)
85
+ return { ok: false, error: poolError.message };
86
+ if (!pool)
87
+ return { ok: false, error: 'No seats available in the pool' };
88
+ const { error } = await supabase
89
+ .from('seats')
90
+ .update({
91
+ assigned_user_id: args.userId,
92
+ assigned_by_user_id: args.assignedByUserId,
93
+ assigned_at: new Date().toISOString(),
94
+ status: 'active',
95
+ revoked_at: null,
96
+ })
97
+ .eq('id', pool.id);
98
+ return error ? { ok: false, error: error.message } : { ok: true };
99
+ }
100
+ export async function revokeSeat(supabase, seatId) {
101
+ const { error } = await supabase
102
+ .from('seats')
103
+ .update({
104
+ status: 'unassigned',
105
+ assigned_user_id: null,
106
+ revoked_at: new Date().toISOString(),
107
+ })
108
+ .eq('id', seatId);
109
+ return error ? { ok: false, error: error.message } : { ok: true };
110
+ }
111
+ export async function reassignSeat(supabase, args) {
112
+ const { error } = await supabase
113
+ .from('seats')
114
+ .update({
115
+ assigned_user_id: args.newUserId,
116
+ assigned_by_user_id: args.assignedByUserId,
117
+ assigned_at: new Date().toISOString(),
118
+ status: 'active',
119
+ revoked_at: null,
120
+ })
121
+ .eq('id', args.seatId);
122
+ return error ? { ok: false, error: error.message } : { ok: true };
123
+ }
124
+ export function useAuditLog(opts = {}) {
125
+ const { supabase, activeOrgId } = useUniversal();
126
+ const id = opts.orgId ?? activeOrgId;
127
+ const limit = opts.limit ?? 100;
128
+ const [entries, setEntries] = useState([]);
129
+ const [loading, setLoading] = useState(true);
130
+ useEffect(() => {
131
+ if (!id) {
132
+ setEntries([]);
133
+ setLoading(false);
134
+ return;
135
+ }
136
+ let cancelled = false;
137
+ setLoading(true);
138
+ supabase
139
+ .from('audit_log')
140
+ .select('*')
141
+ .eq('org_id', id)
142
+ .order('occurred_at', { ascending: false })
143
+ .limit(limit)
144
+ .then(({ data, error }) => {
145
+ if (cancelled)
146
+ return;
147
+ if (error)
148
+ console.error('[unisim/sdk] failed to load audit_log', error);
149
+ setEntries(data ?? []);
150
+ setLoading(false);
151
+ });
152
+ return () => {
153
+ cancelled = true;
154
+ };
155
+ }, [supabase, id, limit]);
156
+ return { entries, loading };
157
+ }
158
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { useUniversal } from './provider.js';
2
+ import type { Organisation } from './types.js';
3
+ export interface UseUserResult {
4
+ user: {
5
+ id: string;
6
+ email: string | null;
7
+ } | null;
8
+ loading: boolean;
9
+ }
10
+ export declare function useUser(): UseUserResult;
11
+ export interface UseOrgResult {
12
+ org: Organisation | null;
13
+ orgs: Organisation[];
14
+ loading: boolean;
15
+ setActiveOrg: (orgId: string | null) => void;
16
+ }
17
+ export declare function useOrg(): UseOrgResult;
18
+ export declare function signInWithPassword(supabase: ReturnType<typeof useUniversal>['supabase'], email: string, password: string): Promise<import("@supabase/auth-js").AuthTokenResponsePassword>;
19
+ export declare function signOut(supabase: ReturnType<typeof useUniversal>['supabase']): Promise<{
20
+ error: import("@supabase/auth-js").AuthError | null;
21
+ }>;
22
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;IACjD,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,OAAO,IAAI,aAAa,CAMvC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,YAAY,GAAG,IAAI,CAAA;IACxB,IAAI,EAAE,YAAY,EAAE,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC7C;AAED,wBAAgB,MAAM,IAAI,YAAY,CAwCrC;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC,EACrD,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,kEAGjB;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,UAAU,CAAC;;GAElF"}
package/dist/auth.js ADDED
@@ -0,0 +1,53 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useUniversal } from './provider.js';
3
+ export function useUser() {
4
+ const { session, loading } = useUniversal();
5
+ return {
6
+ user: session?.user ? { id: session.user.id, email: session.user.email ?? null } : null,
7
+ loading,
8
+ };
9
+ }
10
+ export function useOrg() {
11
+ const { supabase, session, activeOrgId, setActiveOrgId } = useUniversal();
12
+ const [orgs, setOrgs] = useState([]);
13
+ const [loading, setLoading] = useState(true);
14
+ useEffect(() => {
15
+ if (!session) {
16
+ setOrgs([]);
17
+ setLoading(false);
18
+ return;
19
+ }
20
+ let cancelled = false;
21
+ setLoading(true);
22
+ supabase
23
+ .from('organisations')
24
+ .select('id, slug, name, logo_url, brand_color, billing_email')
25
+ .then(({ data, error }) => {
26
+ if (cancelled)
27
+ return;
28
+ if (error) {
29
+ console.error('[unisim/sdk] failed to load organisations', error);
30
+ setOrgs([]);
31
+ }
32
+ else {
33
+ setOrgs(data ?? []);
34
+ if (!activeOrgId && data && data.length > 0) {
35
+ setActiveOrgId(data[0].id);
36
+ }
37
+ }
38
+ setLoading(false);
39
+ });
40
+ return () => {
41
+ cancelled = true;
42
+ };
43
+ }, [supabase, session, activeOrgId, setActiveOrgId]);
44
+ const org = orgs.find((o) => o.id === activeOrgId) ?? null;
45
+ return { org, orgs, loading, setActiveOrg: setActiveOrgId };
46
+ }
47
+ export async function signInWithPassword(supabase, email, password) {
48
+ return supabase.auth.signInWithPassword({ email, password });
49
+ }
50
+ export async function signOut(supabase) {
51
+ return supabase.auth.signOut();
52
+ }
53
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAQ5C,MAAM,UAAU,OAAO;IACrB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAA;IAC3C,OAAO;QACL,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QACvF,OAAO;KACR,CAAA;AACH,CAAC;AASD,MAAM,UAAU,MAAM;IACpB,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,YAAY,EAAE,CAAA;IACzE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAiB,EAAE,CAAC,CAAA;IACpD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,EAAE,CAAC,CAAA;YACX,UAAU,CAAC,KAAK,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QAED,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,QAAQ;aACL,IAAI,CAAC,eAAe,CAAC;aACrB,MAAM,CAAC,sDAAsD,CAAC;aAC9D,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;YACxB,IAAI,SAAS;gBAAE,OAAM;YACrB,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,KAAK,CAAC,CAAA;gBACjE,OAAO,CAAC,EAAE,CAAC,CAAA;YACb,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;gBACnB,IAAI,CAAC,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5C,cAAc,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;YACD,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAA;IAEpD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,IAAI,IAAI,CAAA;IAE1D,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,CAAA;AAC7D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAqD,EACrD,KAAa,EACb,QAAgB;IAEhB,OAAO,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAqD;IACjF,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;AAChC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { OrgBranding } from './types.js';
2
+ /**
3
+ * Returns the active org's branding for product UI chrome.
4
+ * Falls back to suite defaults if no org is active or no branding is set.
5
+ */
6
+ export declare function useOrgBranding(): OrgBranding;
7
+ //# sourceMappingURL=branding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../src/branding.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAO7C;;;GAGG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAO5C"}
@@ -0,0 +1,19 @@
1
+ import { useOrg } from './auth.js';
2
+ const DEFAULT_BRANDING = {
3
+ logo_url: null,
4
+ brand_color: null,
5
+ };
6
+ /**
7
+ * Returns the active org's branding for product UI chrome.
8
+ * Falls back to suite defaults if no org is active or no branding is set.
9
+ */
10
+ export function useOrgBranding() {
11
+ const { org } = useOrg();
12
+ if (!org)
13
+ return DEFAULT_BRANDING;
14
+ return {
15
+ logo_url: org.logo_url,
16
+ brand_color: org.brand_color,
17
+ };
18
+ }
19
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../src/branding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAGlC,MAAM,gBAAgB,GAAgB;IACpC,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,IAAI;CAClB,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAAA;IACxB,IAAI,CAAC,GAAG;QAAE,OAAO,gBAAgB,CAAA;IACjC,OAAO;QACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,GAAG,CAAC,WAAW;KAC7B,CAAA;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { ChangelogRelease } from './types.js';
2
+ export interface UseChangelogOptions {
3
+ limit?: number;
4
+ productFilter?: string;
5
+ }
6
+ export interface UseChangelogResult {
7
+ releases: ChangelogRelease[];
8
+ currentVersion: string | null;
9
+ loading: boolean;
10
+ error: Error | null;
11
+ }
12
+ export declare function useChangelog(opts?: UseChangelogOptions): UseChangelogResult;
13
+ //# sourceMappingURL=changelog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../src/changelog.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIjE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAMD,wBAAgB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,kBAAkB,CA4D/E"}
@@ -0,0 +1,59 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useUniversal } from './provider.js';
3
+ const DEFAULT_CHANGELOG_URL = 'https://changelog.unisim.co.uk/changelog.json';
4
+ let cachedFeed = null;
5
+ let cachedAt = 0;
6
+ const CACHE_TTL_MS = 5 * 60 * 1000;
7
+ export function useChangelog(opts = {}) {
8
+ const { config } = useUniversal();
9
+ const [releases, setReleases] = useState([]);
10
+ const [error, setError] = useState(null);
11
+ const [loading, setLoading] = useState(true);
12
+ const url = config.changelogUrl ?? DEFAULT_CHANGELOG_URL;
13
+ useEffect(() => {
14
+ let cancelled = false;
15
+ const apply = (feed) => {
16
+ const filtered = opts.productFilter
17
+ ? feed.releases
18
+ .map((r) => ({
19
+ ...r,
20
+ entries: r.entries.filter((e) => e.product === opts.productFilter || e.product === 'suite'),
21
+ }))
22
+ .filter((r) => r.entries.length > 0)
23
+ : feed.releases;
24
+ const limited = opts.limit ? filtered.slice(0, opts.limit) : filtered;
25
+ if (!cancelled) {
26
+ setReleases(limited);
27
+ setLoading(false);
28
+ }
29
+ };
30
+ if (cachedFeed && Date.now() - cachedAt < CACHE_TTL_MS) {
31
+ apply(cachedFeed);
32
+ return;
33
+ }
34
+ fetch(url, { cache: 'no-cache' })
35
+ .then((r) => {
36
+ if (!r.ok)
37
+ throw new Error(`changelog fetch failed: ${r.status}`);
38
+ return r.json();
39
+ })
40
+ .then((feed) => {
41
+ cachedFeed = feed;
42
+ cachedAt = Date.now();
43
+ apply(feed);
44
+ })
45
+ .catch((err) => {
46
+ if (cancelled)
47
+ return;
48
+ console.error('[unisim/sdk] changelog fetch failed', err);
49
+ setError(err);
50
+ setLoading(false);
51
+ });
52
+ return () => {
53
+ cancelled = true;
54
+ };
55
+ }, [url, opts.limit, opts.productFilter]);
56
+ const currentVersion = releases.length > 0 ? releases[0].version : null;
57
+ return { releases, currentVersion, loading, error };
58
+ }
59
+ //# sourceMappingURL=changelog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../src/changelog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export { UniversalProvider, useUniversal } from './provider.js';
2
+ export type { UniversalConfig, UniversalProviderProps } from './provider.js';
3
+ export { useUser, useOrg, signInWithPassword, signOut } from './auth.js';
4
+ export type { UseUserResult, UseOrgResult } from './auth.js';
5
+ export { useHasAccess, useHasFeature, useSeat } from './access.js';
6
+ export type { UseSeatResult } from './access.js';
7
+ export { useChangelog } from './changelog.js';
8
+ export type { UseChangelogOptions, UseChangelogResult } from './changelog.js';
9
+ export { track, useUsageTracker } from './usage.js';
10
+ export { useOrgBranding } from './branding.js';
11
+ export { UniversalBar } from './UniversalBar.js';
12
+ export type { UniversalBarProps } from './UniversalBar.js';
13
+ export { useOrgMembers, useOrgSeats, useAuditLog, assignSeat, revokeSeat, reassignSeat, } from './admin.js';
14
+ export type { UseOrgMembersResult, UseOrgSeatsResult, UseAuditLogOptions, } from './admin.js';
15
+ export type { ProductCode, SubTier, OrgRole, SeatStatus, AccessSource, Profile, Organisation, OrgBranding, OrgMember, Subscription, Seat, SeatPool, ChangelogEntry, ChangelogRelease, ChangelogFeed, AuditLogEntry, } from './types.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC/D,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACxE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE5D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAClE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE7E,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE1D,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,WAAW,EACX,OAAO,EACP,OAAO,EACP,UAAU,EACV,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,YAAY,EACZ,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ // @unisim/sdk — public API.
2
+ // Every product depends on this; no product should import @supabase/supabase-js directly.
3
+ export { UniversalProvider, useUniversal } from './provider.js';
4
+ export { useUser, useOrg, signInWithPassword, signOut } from './auth.js';
5
+ export { useHasAccess, useHasFeature, useSeat } from './access.js';
6
+ export { useChangelog } from './changelog.js';
7
+ export { track, useUsageTracker } from './usage.js';
8
+ export { useOrgBranding } from './branding.js';
9
+ export { UniversalBar } from './UniversalBar.js';
10
+ export { useOrgMembers, useOrgSeats, useAuditLog, assignSeat, revokeSeat, reassignSeat, } from './admin.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,0FAA0F;AAE1F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG/D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAG7C,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EACL,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { type SupabaseClient, type Session } from '@supabase/supabase-js';
2
+ import { type ReactNode } from 'react';
3
+ import type { ProductCode } from './types.js';
4
+ export interface UniversalConfig {
5
+ supabaseUrl: string;
6
+ supabaseAnonKey: string;
7
+ product: ProductCode;
8
+ changelogUrl?: string;
9
+ cookieDomain?: string;
10
+ }
11
+ interface UniversalContextValue {
12
+ config: UniversalConfig;
13
+ supabase: SupabaseClient;
14
+ session: Session | null;
15
+ loading: boolean;
16
+ activeOrgId: string | null;
17
+ setActiveOrgId: (orgId: string | null) => void;
18
+ }
19
+ export interface UniversalProviderProps {
20
+ config: UniversalConfig;
21
+ children: ReactNode;
22
+ }
23
+ export declare function UniversalProvider({ config, children }: UniversalProviderProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function useUniversal(): UniversalContextValue;
25
+ export {};
26
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAA;AACvF,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,WAAW,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,UAAU,qBAAqB;IAC7B,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAA;IACxB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;CAC/C;AAMD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAA;IACvB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CA6D7E;AAED,wBAAgB,YAAY,IAAI,qBAAqB,CAMpD"}
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createClient } from '@supabase/supabase-js';
3
+ import { createContext, useContext, useEffect, useMemo, useRef, useState, } from 'react';
4
+ const UniversalContext = createContext(null);
5
+ const ACTIVE_ORG_STORAGE_KEY = 'universal:active_org_id';
6
+ export function UniversalProvider({ config, children }) {
7
+ const supabase = useMemo(() => createClient(config.supabaseUrl, config.supabaseAnonKey, {
8
+ auth: {
9
+ persistSession: true,
10
+ autoRefreshToken: true,
11
+ detectSessionInUrl: true,
12
+ storageKey: 'universal-suite-auth',
13
+ ...(config.cookieDomain
14
+ ? { cookieOptions: { domain: config.cookieDomain, sameSite: 'lax' } }
15
+ : {}),
16
+ },
17
+ }), [config.supabaseUrl, config.supabaseAnonKey, config.cookieDomain]);
18
+ const [session, setSession] = useState(null);
19
+ const [loading, setLoading] = useState(true);
20
+ const [activeOrgId, setActiveOrgIdState] = useState(() => {
21
+ if (typeof window === 'undefined')
22
+ return null;
23
+ return window.localStorage.getItem(ACTIVE_ORG_STORAGE_KEY);
24
+ });
25
+ const initialised = useRef(false);
26
+ useEffect(() => {
27
+ if (initialised.current)
28
+ return;
29
+ initialised.current = true;
30
+ supabase.auth.getSession().then(({ data }) => {
31
+ setSession(data.session);
32
+ setLoading(false);
33
+ });
34
+ const { data: subscription } = supabase.auth.onAuthStateChange((_event, newSession) => {
35
+ setSession(newSession);
36
+ });
37
+ return () => {
38
+ subscription.subscription.unsubscribe();
39
+ };
40
+ }, [supabase]);
41
+ const setActiveOrgId = (orgId) => {
42
+ setActiveOrgIdState(orgId);
43
+ if (typeof window !== 'undefined') {
44
+ if (orgId)
45
+ window.localStorage.setItem(ACTIVE_ORG_STORAGE_KEY, orgId);
46
+ else
47
+ window.localStorage.removeItem(ACTIVE_ORG_STORAGE_KEY);
48
+ }
49
+ };
50
+ const value = {
51
+ config,
52
+ supabase,
53
+ session,
54
+ loading,
55
+ activeOrgId,
56
+ setActiveOrgId,
57
+ };
58
+ return _jsx(UniversalContext.Provider, { value: value, children: children });
59
+ }
60
+ export function useUniversal() {
61
+ const ctx = useContext(UniversalContext);
62
+ if (!ctx) {
63
+ throw new Error('useUniversal() must be called inside <UniversalProvider>');
64
+ }
65
+ return ctx;
66
+ }
67
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAqC,MAAM,uBAAuB,CAAA;AACvF,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,OAAO,EACP,MAAM,EACN,QAAQ,GAET,MAAM,OAAO,CAAA;AAoBd,MAAM,gBAAgB,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAA;AAE1E,MAAM,sBAAsB,GAAG,yBAAyB,CAAA;AAOxD,MAAM,UAAU,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAA0B;IAC5E,MAAM,QAAQ,GAAG,OAAO,CACtB,GAAG,EAAE,CACH,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,EAAE;QACvD,IAAI,EAAE;YACJ,cAAc,EAAE,IAAI;YACpB,gBAAgB,EAAE,IAAI;YACtB,kBAAkB,EAAE,IAAI;YACxB,UAAU,EAAE,sBAAsB;YAClC,GAAG,CAAC,MAAM,CAAC,YAAY;gBACrB,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;gBACrE,CAAC,CAAC,EAAE,CAAC;SACR;KACF,CAAC,EACJ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,YAAY,CAAC,CAClE,CAAA;IAED,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAiB,IAAI,CAAC,CAAA;IAC5D,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAgB,GAAG,EAAE;QACtE,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAA;QAC9C,OAAO,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAC5D,CAAC,CAAC,CAAA;IAEF,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IACjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,CAAC,OAAO;YAAE,OAAM;QAC/B,WAAW,CAAC,OAAO,GAAG,IAAI,CAAA;QAE1B,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;YAC3C,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACxB,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;QAEF,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE;YACpF,UAAU,CAAC,UAAU,CAAC,CAAA;QACxB,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,YAAY,CAAC,WAAW,EAAE,CAAA;QACzC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,cAAc,GAAG,CAAC,KAAoB,EAAE,EAAE;QAC9C,mBAAmB,CAAC,KAAK,CAAC,CAAA;QAC1B,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,IAAI,KAAK;gBAAE,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAA;;gBAChE,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC,CAAA;IAED,MAAM,KAAK,GAA0B;QACnC,MAAM;QACN,QAAQ;QACR,OAAO;QACP,OAAO;QACP,WAAW;QACX,cAAc;KACf,CAAA;IAED,OAAO,KAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA6B,CAAA;AACxF,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAA;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,74 @@
1
+ export type ProductCode = 'pdf' | 'webinar' | 'exports' | 'cyber_assess' | 'ergo_assess';
2
+ export type SubTier = 'free' | 'pro' | 'enterprise';
3
+ export type OrgRole = 'owner' | 'admin' | 'member';
4
+ export type SeatStatus = 'active' | 'unassigned' | 'revoked';
5
+ export type AccessSource = 'tier' | 'addon' | 'trial' | 'manual';
6
+ export interface Profile {
7
+ id: string;
8
+ display_name: string | null;
9
+ avatar_url: string | null;
10
+ locale: string;
11
+ }
12
+ export interface Organisation {
13
+ id: string;
14
+ slug: string;
15
+ name: string;
16
+ logo_url: string | null;
17
+ brand_color: string | null;
18
+ billing_email: string | null;
19
+ }
20
+ export interface OrgBranding {
21
+ logo_url: string | null;
22
+ brand_color: string | null;
23
+ }
24
+ export interface OrgMember {
25
+ org_id: string;
26
+ user_id: string;
27
+ role: OrgRole;
28
+ joined_at: string;
29
+ profile?: Profile;
30
+ }
31
+ export interface Subscription {
32
+ org_id: string;
33
+ tier: SubTier;
34
+ status: 'active' | 'past_due' | 'canceled' | 'trialing' | 'incomplete';
35
+ seat_count: number;
36
+ current_period_end: string | null;
37
+ }
38
+ export interface Seat {
39
+ id: string;
40
+ org_id: string;
41
+ assigned_user_id: string | null;
42
+ assigned_at: string | null;
43
+ revoked_at: string | null;
44
+ status: SeatStatus;
45
+ }
46
+ export interface SeatPool {
47
+ total: number;
48
+ assigned: number;
49
+ available: number;
50
+ }
51
+ export interface ChangelogEntry {
52
+ product: ProductCode | 'suite';
53
+ type: 'added' | 'changed' | 'fixed' | 'removed' | 'deprecated' | 'security';
54
+ summary: string;
55
+ }
56
+ export interface ChangelogRelease {
57
+ version: string;
58
+ date: string;
59
+ entries: ChangelogEntry[];
60
+ }
61
+ export interface ChangelogFeed {
62
+ releases: ChangelogRelease[];
63
+ }
64
+ export interface AuditLogEntry {
65
+ id: number;
66
+ org_id: string | null;
67
+ actor_user_id: string | null;
68
+ action: string;
69
+ target_type: string | null;
70
+ target_id: string | null;
71
+ properties: Record<string, unknown>;
72
+ occurred_at: string;
73
+ }
74
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ // Shared types for the Universal SDK.
2
+ // Mirrors the platform schema in supabase/migrations/0001_initial_schema.sql.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,8EAA8E"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hook variant: registers the queue with the current Supabase client and ensures
3
+ * pending events are flushed before unmount.
4
+ */
5
+ export declare function useUsageTracker(): void;
6
+ /**
7
+ * Track a usage event from anywhere in the product. Buffered + sent in batches.
8
+ * Safe to call when signed out — events without a session are dropped, not stored.
9
+ */
10
+ export declare function track(eventName: string, properties?: Record<string, unknown>): void;
11
+ //# sourceMappingURL=usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AAmDA;;;GAGG;AACH,wBAAgB,eAAe,IAAI,IAAI,CA8BtC;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI,CAavF"}
package/dist/usage.js ADDED
@@ -0,0 +1,97 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { useUniversal } from './provider.js';
3
+ const FLUSH_INTERVAL_MS = 5_000;
4
+ const MAX_BATCH_SIZE = 50;
5
+ class UsageQueue {
6
+ send;
7
+ buffer = [];
8
+ flushing = false;
9
+ timer = null;
10
+ constructor(send) {
11
+ this.send = send;
12
+ }
13
+ enqueue(event) {
14
+ this.buffer.push(event);
15
+ if (this.buffer.length >= MAX_BATCH_SIZE) {
16
+ void this.flush();
17
+ }
18
+ else if (!this.timer) {
19
+ this.timer = setTimeout(() => void this.flush(), FLUSH_INTERVAL_MS);
20
+ }
21
+ }
22
+ async flush() {
23
+ if (this.flushing || this.buffer.length === 0)
24
+ return;
25
+ this.flushing = true;
26
+ if (this.timer) {
27
+ clearTimeout(this.timer);
28
+ this.timer = null;
29
+ }
30
+ const batch = this.buffer.splice(0, this.buffer.length);
31
+ try {
32
+ await this.send(batch);
33
+ }
34
+ catch (err) {
35
+ console.error('[unisim/sdk] usage flush failed; re-queuing', err);
36
+ this.buffer.unshift(...batch);
37
+ }
38
+ finally {
39
+ this.flushing = false;
40
+ }
41
+ }
42
+ }
43
+ let queue = null;
44
+ /**
45
+ * Hook variant: registers the queue with the current Supabase client and ensures
46
+ * pending events are flushed before unmount.
47
+ */
48
+ export function useUsageTracker() {
49
+ const { supabase, session, activeOrgId, config } = useUniversal();
50
+ const sessionRef = useRef(session);
51
+ const orgRef = useRef(activeOrgId);
52
+ sessionRef.current = session;
53
+ orgRef.current = activeOrgId;
54
+ useEffect(() => {
55
+ queue ??= new UsageQueue(async (events) => {
56
+ const sess = sessionRef.current;
57
+ const org = orgRef.current;
58
+ if (!sess || !org)
59
+ return; // drop events when signed out / no org
60
+ const rows = events.map((e) => ({
61
+ org_id: org,
62
+ user_id: sess.user.id,
63
+ product: config.product,
64
+ event_name: e.event_name,
65
+ properties: e.properties,
66
+ occurred_at: e.occurred_at,
67
+ }));
68
+ const { error } = await supabase.from('usage_events').insert(rows);
69
+ if (error)
70
+ throw error;
71
+ });
72
+ const onBeforeUnload = () => {
73
+ void queue?.flush();
74
+ };
75
+ window.addEventListener('beforeunload', onBeforeUnload);
76
+ return () => window.removeEventListener('beforeunload', onBeforeUnload);
77
+ }, [supabase, config.product]);
78
+ }
79
+ /**
80
+ * Track a usage event from anywhere in the product. Buffered + sent in batches.
81
+ * Safe to call when signed out — events without a session are dropped, not stored.
82
+ */
83
+ export function track(eventName, properties = {}) {
84
+ if (!queue) {
85
+ // Provider not mounted yet; drop silently. In dev this would log via console below.
86
+ if (typeof window !== 'undefined' && window.__DEV__) {
87
+ console.warn('[unisim/sdk] track() called before <UniversalProvider> mounted');
88
+ }
89
+ return;
90
+ }
91
+ queue.enqueue({
92
+ event_name: eventName,
93
+ properties,
94
+ occurred_at: new Date().toISOString(),
95
+ });
96
+ }
97
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,16 @@
1
1
  {
2
2
  "name": "@unisim/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "description": "Shared React SDK for the Universal Suite — auth, entitlements, usage telemetry, changelog, org admin.",
5
+ "homepage": "https://github.com/universal-simulation-ltd/universal-platform/tree/main/packages/sdk#readme",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/universal-simulation-ltd/universal-platform.git",
9
+ "directory": "packages/sdk"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/universal-simulation-ltd/universal-platform/issues"
13
+ },
5
14
  "type": "module",
6
15
  "main": "./dist/index.js",
7
16
  "module": "./dist/index.js",
@@ -19,7 +28,8 @@
19
28
  "scripts": {
20
29
  "build": "tsc -p tsconfig.build.json",
21
30
  "dev": "tsc -p tsconfig.build.json --watch",
22
- "typecheck": "tsc --noEmit"
31
+ "typecheck": "tsc --noEmit",
32
+ "prepublishOnly": "npm run build"
23
33
  },
24
34
  "peerDependencies": {
25
35
  "react": "^18.0.0 || ^19.0.0"