@datatechsolutions/ui 2.11.81 → 2.11.83
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/dist/astrlabe/contracts.d.mts +5 -0
- package/dist/astrlabe/contracts.d.ts +5 -0
- package/dist/astrlabe/index.d.mts +59 -82
- package/dist/astrlabe/index.d.ts +59 -82
- package/dist/astrlabe/index.js +179 -4777
- package/dist/astrlabe/index.js.map +1 -1
- package/dist/astrlabe/index.mjs +3 -4740
- package/dist/astrlabe/index.mjs.map +1 -1
- package/dist/astrlabe/workflow-canvas.d.mts +69 -5
- package/dist/astrlabe/workflow-canvas.d.ts +69 -5
- package/dist/chunk-6PBTB5ZX.js +165 -0
- package/dist/chunk-6PBTB5ZX.js.map +1 -0
- package/dist/chunk-HZ4LOVHM.js +46 -0
- package/dist/chunk-HZ4LOVHM.js.map +1 -0
- package/dist/chunk-JFWZHROG.js +4996 -0
- package/dist/chunk-JFWZHROG.js.map +1 -0
- package/dist/chunk-UHHPBREK.mjs +135 -0
- package/dist/chunk-UHHPBREK.mjs.map +1 -0
- package/dist/chunk-UVGMKHWH.mjs +4951 -0
- package/dist/chunk-UVGMKHWH.mjs.map +1 -0
- package/dist/chunk-ZJPNP2YW.mjs +44 -0
- package/dist/chunk-ZJPNP2YW.mjs.map +1 -0
- package/dist/{workflow-canvas-NSxfr5dy.d.ts → index-AioB90qq.d.mts} +2 -67
- package/dist/{workflow-canvas-D4928AfA.d.mts → index-D5ai0cGZ.d.ts} +2 -67
- package/dist/platform/index.d.mts +41 -0
- package/dist/platform/index.d.ts +41 -0
- package/dist/platform/index.js +237 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +109 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/platform/pages/index.d.mts +272 -0
- package/dist/platform/pages/index.d.ts +272 -0
- package/dist/platform/pages/index.js +1793 -0
- package/dist/platform/pages/index.js.map +1 -0
- package/dist/platform/pages/index.mjs +1777 -0
- package/dist/platform/pages/index.mjs.map +1 -0
- package/dist/platform/rbac.d.mts +41 -0
- package/dist/platform/rbac.d.ts +41 -0
- package/dist/platform/rbac.js +13 -0
- package/dist/platform/rbac.js.map +1 -0
- package/dist/platform/rbac.mjs +4 -0
- package/dist/platform/rbac.mjs.map +1 -0
- package/dist/platform/utils/index.d.mts +32 -0
- package/dist/platform/utils/index.d.ts +32 -0
- package/dist/platform/utils/index.js +131 -0
- package/dist/platform/utils/index.js.map +1 -0
- package/dist/platform/utils/index.mjs +119 -0
- package/dist/platform/utils/index.mjs.map +1 -0
- package/dist/platform/windsock-admin-client.d.mts +57 -0
- package/dist/platform/windsock-admin-client.d.ts +57 -0
- package/dist/platform/windsock-admin-client.js +125 -0
- package/dist/platform/windsock-admin-client.js.map +1 -0
- package/dist/platform/windsock-admin-client.mjs +4 -0
- package/dist/platform/windsock-admin-client.mjs.map +1 -0
- package/dist/rule-form-F5jBOeqk.d.mts +79 -0
- package/dist/rule-form-F5jBOeqk.d.ts +79 -0
- package/package.json +27 -1
|
@@ -1,5 +1,69 @@
|
|
|
1
|
-
import 'react/jsx-runtime';
|
|
2
|
-
import 'react';
|
|
3
|
-
|
|
4
|
-
import '
|
|
5
|
-
import './contracts.mjs';
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import { NodeTypes } from '@xyflow/react';
|
|
4
|
+
import { A as AgentWithPrompts, W as WorkflowEntityDefinition } from '../index-AioB90qq.mjs';
|
|
5
|
+
import { AgentModel, WorkflowTool, AgentTool, AgentRule, WorkflowGraph, LogicNodeConfig } from './contracts.mjs';
|
|
6
|
+
|
|
7
|
+
type AgentModalRenderProps = {
|
|
8
|
+
agent: AgentWithPrompts | null;
|
|
9
|
+
models: AgentModel[];
|
|
10
|
+
open: boolean;
|
|
11
|
+
isCreateMode: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onSaved: () => void;
|
|
14
|
+
};
|
|
15
|
+
type LogicNodeModalRenderProps = {
|
|
16
|
+
nodeId: string | null;
|
|
17
|
+
nodeLabel: string;
|
|
18
|
+
config: LogicNodeConfig | null;
|
|
19
|
+
open: boolean;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
onSave: (nodeId: string, updatedConfig: LogicNodeConfig) => void;
|
|
22
|
+
entities: WorkflowEntityDefinition[];
|
|
23
|
+
};
|
|
24
|
+
type WorkflowCanvasProps = {
|
|
25
|
+
agents: AgentWithPrompts[];
|
|
26
|
+
models: AgentModel[];
|
|
27
|
+
tools?: WorkflowTool[];
|
|
28
|
+
agentTools?: AgentTool[];
|
|
29
|
+
rules?: AgentRule[];
|
|
30
|
+
entities?: WorkflowEntityDefinition[];
|
|
31
|
+
datasources?: Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
dialect: string;
|
|
35
|
+
}>;
|
|
36
|
+
onLoadTables?: (datasourceId: string) => Promise<string[]>;
|
|
37
|
+
onLoadSchema?: (datasourceId: string, table: string) => Promise<Array<{
|
|
38
|
+
name: string;
|
|
39
|
+
type: string;
|
|
40
|
+
nullable?: boolean;
|
|
41
|
+
}>>;
|
|
42
|
+
initialGraph?: WorkflowGraph | null;
|
|
43
|
+
onGraphChange?: (graph: WorkflowGraph) => void;
|
|
44
|
+
onEditTool?: (tool: WorkflowTool) => void;
|
|
45
|
+
onToggleTool?: (tool: WorkflowTool) => void;
|
|
46
|
+
onEditRule?: (rule: AgentRule) => void;
|
|
47
|
+
onToggleRule?: (rule: AgentRule) => void;
|
|
48
|
+
onCancelCreateAgent?: () => void;
|
|
49
|
+
onAgentSaved?: () => void;
|
|
50
|
+
isCreatingAgent?: boolean;
|
|
51
|
+
/** Custom node type components — merged with built-in edge types */
|
|
52
|
+
nodeTypes?: NodeTypes;
|
|
53
|
+
/** Optional: render the AgentModal externally (frontend provides the component) */
|
|
54
|
+
renderAgentModal?: (props: AgentModalRenderProps) => React.ReactNode;
|
|
55
|
+
/** Optional: render a custom LogicNodeModal; defaults to internal modal */
|
|
56
|
+
renderLogicNodeModal?: (props: LogicNodeModalRenderProps) => React.ReactNode;
|
|
57
|
+
};
|
|
58
|
+
declare function WorkflowCanvas(props: WorkflowCanvasProps): react_jsx_runtime.JSX.Element;
|
|
59
|
+
|
|
60
|
+
type BuilderCanvasProps = ComponentProps<typeof WorkflowCanvas>;
|
|
61
|
+
type WorkspaceProps = {
|
|
62
|
+
locale?: string;
|
|
63
|
+
messages?: Record<string, unknown>;
|
|
64
|
+
className?: string;
|
|
65
|
+
workflowId?: string;
|
|
66
|
+
} & Partial<BuilderCanvasProps>;
|
|
67
|
+
declare function Workspace({ locale, messages, className, workflowId, ...canvasProps }: WorkspaceProps): react_jsx_runtime.JSX.Element;
|
|
68
|
+
|
|
69
|
+
export { Workspace, type WorkspaceProps };
|
|
@@ -1,5 +1,69 @@
|
|
|
1
|
-
import 'react/jsx-runtime';
|
|
2
|
-
import 'react';
|
|
3
|
-
|
|
4
|
-
import '
|
|
5
|
-
import './contracts.js';
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ComponentProps } from 'react';
|
|
3
|
+
import { NodeTypes } from '@xyflow/react';
|
|
4
|
+
import { A as AgentWithPrompts, W as WorkflowEntityDefinition } from '../index-D5ai0cGZ.js';
|
|
5
|
+
import { AgentModel, WorkflowTool, AgentTool, AgentRule, WorkflowGraph, LogicNodeConfig } from './contracts.js';
|
|
6
|
+
|
|
7
|
+
type AgentModalRenderProps = {
|
|
8
|
+
agent: AgentWithPrompts | null;
|
|
9
|
+
models: AgentModel[];
|
|
10
|
+
open: boolean;
|
|
11
|
+
isCreateMode: boolean;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
onSaved: () => void;
|
|
14
|
+
};
|
|
15
|
+
type LogicNodeModalRenderProps = {
|
|
16
|
+
nodeId: string | null;
|
|
17
|
+
nodeLabel: string;
|
|
18
|
+
config: LogicNodeConfig | null;
|
|
19
|
+
open: boolean;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
onSave: (nodeId: string, updatedConfig: LogicNodeConfig) => void;
|
|
22
|
+
entities: WorkflowEntityDefinition[];
|
|
23
|
+
};
|
|
24
|
+
type WorkflowCanvasProps = {
|
|
25
|
+
agents: AgentWithPrompts[];
|
|
26
|
+
models: AgentModel[];
|
|
27
|
+
tools?: WorkflowTool[];
|
|
28
|
+
agentTools?: AgentTool[];
|
|
29
|
+
rules?: AgentRule[];
|
|
30
|
+
entities?: WorkflowEntityDefinition[];
|
|
31
|
+
datasources?: Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
dialect: string;
|
|
35
|
+
}>;
|
|
36
|
+
onLoadTables?: (datasourceId: string) => Promise<string[]>;
|
|
37
|
+
onLoadSchema?: (datasourceId: string, table: string) => Promise<Array<{
|
|
38
|
+
name: string;
|
|
39
|
+
type: string;
|
|
40
|
+
nullable?: boolean;
|
|
41
|
+
}>>;
|
|
42
|
+
initialGraph?: WorkflowGraph | null;
|
|
43
|
+
onGraphChange?: (graph: WorkflowGraph) => void;
|
|
44
|
+
onEditTool?: (tool: WorkflowTool) => void;
|
|
45
|
+
onToggleTool?: (tool: WorkflowTool) => void;
|
|
46
|
+
onEditRule?: (rule: AgentRule) => void;
|
|
47
|
+
onToggleRule?: (rule: AgentRule) => void;
|
|
48
|
+
onCancelCreateAgent?: () => void;
|
|
49
|
+
onAgentSaved?: () => void;
|
|
50
|
+
isCreatingAgent?: boolean;
|
|
51
|
+
/** Custom node type components — merged with built-in edge types */
|
|
52
|
+
nodeTypes?: NodeTypes;
|
|
53
|
+
/** Optional: render the AgentModal externally (frontend provides the component) */
|
|
54
|
+
renderAgentModal?: (props: AgentModalRenderProps) => React.ReactNode;
|
|
55
|
+
/** Optional: render a custom LogicNodeModal; defaults to internal modal */
|
|
56
|
+
renderLogicNodeModal?: (props: LogicNodeModalRenderProps) => React.ReactNode;
|
|
57
|
+
};
|
|
58
|
+
declare function WorkflowCanvas(props: WorkflowCanvasProps): react_jsx_runtime.JSX.Element;
|
|
59
|
+
|
|
60
|
+
type BuilderCanvasProps = ComponentProps<typeof WorkflowCanvas>;
|
|
61
|
+
type WorkspaceProps = {
|
|
62
|
+
locale?: string;
|
|
63
|
+
messages?: Record<string, unknown>;
|
|
64
|
+
className?: string;
|
|
65
|
+
workflowId?: string;
|
|
66
|
+
} & Partial<BuilderCanvasProps>;
|
|
67
|
+
declare function Workspace({ locale, messages, className, workflowId, ...canvasProps }: WorkspaceProps): react_jsx_runtime.JSX.Element;
|
|
68
|
+
|
|
69
|
+
export { Workspace, type WorkspaceProps };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var common = require('@datatechsolutions/shared-domain/common');
|
|
5
|
+
|
|
6
|
+
// src/platform/windsock-admin-client.ts
|
|
7
|
+
var _adminClient = null;
|
|
8
|
+
var _issuer = null;
|
|
9
|
+
var _authFetch = fetch;
|
|
10
|
+
function setWindsockAdminClient(client, issuer, authFetch) {
|
|
11
|
+
_adminClient = client;
|
|
12
|
+
_issuer = issuer.replace(/\/$/, "");
|
|
13
|
+
_authFetch = authFetch;
|
|
14
|
+
}
|
|
15
|
+
function requireClient() {
|
|
16
|
+
if (!_adminClient) {
|
|
17
|
+
throw new Error("Windsock admin client not initialized \u2014 did providers mount?");
|
|
18
|
+
}
|
|
19
|
+
return _adminClient;
|
|
20
|
+
}
|
|
21
|
+
async function listUsers(params) {
|
|
22
|
+
return requireClient().listUsers(params);
|
|
23
|
+
}
|
|
24
|
+
async function createUser(data) {
|
|
25
|
+
return requireClient().createUser(data);
|
|
26
|
+
}
|
|
27
|
+
async function updateUser(userId, data) {
|
|
28
|
+
return requireClient().updateUser(userId, data);
|
|
29
|
+
}
|
|
30
|
+
async function deleteUser(userId) {
|
|
31
|
+
return requireClient().deleteUser(userId);
|
|
32
|
+
}
|
|
33
|
+
async function resetUserPassword(userId, password) {
|
|
34
|
+
return requireClient().resetUserPassword(userId, password);
|
|
35
|
+
}
|
|
36
|
+
async function listOrganizations() {
|
|
37
|
+
return requireClient().listOrganizations();
|
|
38
|
+
}
|
|
39
|
+
async function createOrganization(data) {
|
|
40
|
+
return requireClient().createOrganization(data);
|
|
41
|
+
}
|
|
42
|
+
async function updateOrganization(organizationId, data) {
|
|
43
|
+
return requireClient().updateOrganization(organizationId, data);
|
|
44
|
+
}
|
|
45
|
+
async function deleteOrganization(organizationId) {
|
|
46
|
+
return requireClient().deleteOrganization(organizationId);
|
|
47
|
+
}
|
|
48
|
+
async function listOrganizationMembers(organizationId) {
|
|
49
|
+
return requireClient().listOrganizationMembers(organizationId);
|
|
50
|
+
}
|
|
51
|
+
async function addOrganizationMember(organizationId, userId, role) {
|
|
52
|
+
return requireClient().addOrganizationMember(organizationId, userId, role);
|
|
53
|
+
}
|
|
54
|
+
async function removeOrganizationMember(organizationId, userId) {
|
|
55
|
+
return requireClient().removeOrganizationMember(organizationId, userId);
|
|
56
|
+
}
|
|
57
|
+
async function listOrganizationInvitations(organizationId) {
|
|
58
|
+
return requireClient().listOrganizationInvitations(organizationId);
|
|
59
|
+
}
|
|
60
|
+
async function createOrganizationInvitation(organizationId, data) {
|
|
61
|
+
return requireClient().createOrganizationInvitation(organizationId, data);
|
|
62
|
+
}
|
|
63
|
+
async function listOrganizationDomains(organizationId) {
|
|
64
|
+
return requireClient().listOrganizationDomains(organizationId);
|
|
65
|
+
}
|
|
66
|
+
async function addOrganizationDomain(organizationId, domain) {
|
|
67
|
+
return requireClient().addOrganizationDomain(organizationId, domain);
|
|
68
|
+
}
|
|
69
|
+
async function verifyOrganizationDomain(organizationId, domain) {
|
|
70
|
+
return requireClient().verifyOrganizationDomain(organizationId, domain);
|
|
71
|
+
}
|
|
72
|
+
async function listPermissions() {
|
|
73
|
+
return requireClient().listPermissions();
|
|
74
|
+
}
|
|
75
|
+
async function createPermission(data) {
|
|
76
|
+
return requireClient().createPermission(data);
|
|
77
|
+
}
|
|
78
|
+
async function updatePermission(permissionId, data) {
|
|
79
|
+
return requireClient().updatePermission(permissionId, data);
|
|
80
|
+
}
|
|
81
|
+
async function deletePermission(permissionId) {
|
|
82
|
+
return requireClient().deletePermission(permissionId);
|
|
83
|
+
}
|
|
84
|
+
async function getUserPermissions(userId) {
|
|
85
|
+
return requireClient().getUserPermissions(userId);
|
|
86
|
+
}
|
|
87
|
+
async function setUserPermissions(userId, permissionIds) {
|
|
88
|
+
return requireClient().setUserPermissions(userId, permissionIds);
|
|
89
|
+
}
|
|
90
|
+
async function secretsRequest(path, init) {
|
|
91
|
+
if (!_issuer) throw new Error("Windsock issuer not initialized");
|
|
92
|
+
const response = await _authFetch(`${_issuer}${path}`, {
|
|
93
|
+
...init,
|
|
94
|
+
credentials: init?.credentials ?? "include",
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
...init?.headers
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (response.status === 204) return void 0;
|
|
101
|
+
const payload = await response.json().catch(() => null);
|
|
102
|
+
if (!response.ok) {
|
|
103
|
+
const message = payload?.message ?? payload?.error ?? `HTTP ${response.status}: ${response.statusText}`;
|
|
104
|
+
throw new common.HttpResponseError(message, response.status);
|
|
105
|
+
}
|
|
106
|
+
if (payload && typeof payload === "object" && "success" in payload && payload.success && "data" in payload) {
|
|
107
|
+
return payload.data;
|
|
108
|
+
}
|
|
109
|
+
return payload;
|
|
110
|
+
}
|
|
111
|
+
async function listSecrets(organizationId) {
|
|
112
|
+
return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets`);
|
|
113
|
+
}
|
|
114
|
+
async function getSecret(organizationId, secretId) {
|
|
115
|
+
return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`);
|
|
116
|
+
}
|
|
117
|
+
async function createSecret(organizationId, input) {
|
|
118
|
+
return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets`, {
|
|
119
|
+
method: "POST",
|
|
120
|
+
body: JSON.stringify(input)
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async function rotateSecret(organizationId, secretId, input) {
|
|
124
|
+
return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`, {
|
|
125
|
+
method: "PATCH",
|
|
126
|
+
body: JSON.stringify(input)
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
async function disableSecret(organizationId, secretId) {
|
|
130
|
+
return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`, {
|
|
131
|
+
method: "DELETE"
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
exports.addOrganizationDomain = addOrganizationDomain;
|
|
136
|
+
exports.addOrganizationMember = addOrganizationMember;
|
|
137
|
+
exports.createOrganization = createOrganization;
|
|
138
|
+
exports.createOrganizationInvitation = createOrganizationInvitation;
|
|
139
|
+
exports.createPermission = createPermission;
|
|
140
|
+
exports.createSecret = createSecret;
|
|
141
|
+
exports.createUser = createUser;
|
|
142
|
+
exports.deleteOrganization = deleteOrganization;
|
|
143
|
+
exports.deletePermission = deletePermission;
|
|
144
|
+
exports.deleteUser = deleteUser;
|
|
145
|
+
exports.disableSecret = disableSecret;
|
|
146
|
+
exports.getSecret = getSecret;
|
|
147
|
+
exports.getUserPermissions = getUserPermissions;
|
|
148
|
+
exports.listOrganizationDomains = listOrganizationDomains;
|
|
149
|
+
exports.listOrganizationInvitations = listOrganizationInvitations;
|
|
150
|
+
exports.listOrganizationMembers = listOrganizationMembers;
|
|
151
|
+
exports.listOrganizations = listOrganizations;
|
|
152
|
+
exports.listPermissions = listPermissions;
|
|
153
|
+
exports.listSecrets = listSecrets;
|
|
154
|
+
exports.listUsers = listUsers;
|
|
155
|
+
exports.removeOrganizationMember = removeOrganizationMember;
|
|
156
|
+
exports.resetUserPassword = resetUserPassword;
|
|
157
|
+
exports.rotateSecret = rotateSecret;
|
|
158
|
+
exports.setUserPermissions = setUserPermissions;
|
|
159
|
+
exports.setWindsockAdminClient = setWindsockAdminClient;
|
|
160
|
+
exports.updateOrganization = updateOrganization;
|
|
161
|
+
exports.updatePermission = updatePermission;
|
|
162
|
+
exports.updateUser = updateUser;
|
|
163
|
+
exports.verifyOrganizationDomain = verifyOrganizationDomain;
|
|
164
|
+
//# sourceMappingURL=chunk-6PBTB5ZX.js.map
|
|
165
|
+
//# sourceMappingURL=chunk-6PBTB5ZX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/windsock-admin-client.ts"],"names":["HttpResponseError"],"mappings":"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","file":"chunk-6PBTB5ZX.js","sourcesContent":["import type {\n AdminClient,\n AdminUserSummary,\n AdminListParams,\n AdminListResult,\n AdminCreateUserInput,\n AdminUpdateUserInput,\n AdminCreateOrganizationInput,\n AdminUpdateOrganizationInput,\n AdminOrganizationMember,\n AdminCreatePermissionInput,\n AdminUpdatePermissionInput,\n AdminCreateInvitationInput,\n AdminPermission,\n AuthOrganization,\n AuthOrganizationDomain,\n AuthOrganizationInvitation,\n AuthOrganizationRole,\n} from '@datatechsolutions/shared-domain'\nimport { HttpResponseError } from '@datatechsolutions/shared-domain/common'\n\nlet _adminClient: AdminClient | null = null\nlet _issuer: string | null = null\nlet _authFetch: typeof fetch = fetch\n\nexport function setWindsockAdminClient(client: AdminClient, issuer: string, authFetch: typeof fetch): void {\n _adminClient = client\n _issuer = issuer.replace(/\\/$/, '')\n _authFetch = authFetch\n}\n\nfunction requireClient(): AdminClient {\n if (!_adminClient) {\n throw new Error('Windsock admin client not initialized — did providers mount?')\n }\n return _adminClient\n}\n\n// ── Users ──────────────────────────────────────────────────────────────────\nexport async function listUsers(params?: AdminListParams): Promise<AdminListResult<AdminUserSummary>> {\n return requireClient().listUsers(params)\n}\nexport async function createUser(data: AdminCreateUserInput): Promise<AdminUserSummary> {\n return requireClient().createUser(data)\n}\nexport async function updateUser(userId: string, data: AdminUpdateUserInput): Promise<void> {\n return requireClient().updateUser(userId, data)\n}\nexport async function deleteUser(userId: string): Promise<void> {\n return requireClient().deleteUser(userId)\n}\nexport async function resetUserPassword(userId: string, password: string): Promise<void> {\n return requireClient().resetUserPassword(userId, password)\n}\n\n// ── Organizations ──────────────────────────────────────────────────────────\nexport async function listOrganizations(): Promise<AuthOrganization[]> {\n return requireClient().listOrganizations()\n}\nexport async function createOrganization(data: AdminCreateOrganizationInput): Promise<AuthOrganization> {\n return requireClient().createOrganization(data)\n}\nexport async function updateOrganization(organizationId: string, data: AdminUpdateOrganizationInput): Promise<AuthOrganization> {\n return requireClient().updateOrganization(organizationId, data)\n}\nexport async function deleteOrganization(organizationId: string): Promise<void> {\n return requireClient().deleteOrganization(organizationId)\n}\n\n// ── Organization Members ───────────────────────────────────────────────────\nexport async function listOrganizationMembers(organizationId: string): Promise<AdminOrganizationMember[]> {\n return requireClient().listOrganizationMembers(organizationId)\n}\nexport async function addOrganizationMember(organizationId: string, userId: string, role?: AuthOrganizationRole): Promise<void> {\n return requireClient().addOrganizationMember(organizationId, userId, role)\n}\nexport async function removeOrganizationMember(organizationId: string, userId: string): Promise<void> {\n return requireClient().removeOrganizationMember(organizationId, userId)\n}\n\n// ── Organization Invitations ───────────────────────────────────────────────\nexport async function listOrganizationInvitations(organizationId: string): Promise<AuthOrganizationInvitation[]> {\n return requireClient().listOrganizationInvitations(organizationId)\n}\nexport async function createOrganizationInvitation(organizationId: string, data: AdminCreateInvitationInput): Promise<void> {\n return requireClient().createOrganizationInvitation(organizationId, data)\n}\n\n// ── Organization Domains ───────────────────────────────────────────────────\nexport async function listOrganizationDomains(organizationId: string): Promise<AuthOrganizationDomain[]> {\n return requireClient().listOrganizationDomains(organizationId)\n}\nexport async function addOrganizationDomain(organizationId: string, domain: string): Promise<AuthOrganizationDomain> {\n return requireClient().addOrganizationDomain(organizationId, domain)\n}\nexport async function verifyOrganizationDomain(organizationId: string, domain: string): Promise<void> {\n return requireClient().verifyOrganizationDomain(organizationId, domain)\n}\n\n// ── Permissions ────────────────────────────────────────────────────────────\nexport async function listPermissions(): Promise<AdminPermission[]> {\n return requireClient().listPermissions()\n}\nexport async function createPermission(data: AdminCreatePermissionInput): Promise<AdminPermission> {\n return requireClient().createPermission(data)\n}\nexport async function updatePermission(permissionId: string, data: AdminUpdatePermissionInput): Promise<void> {\n return requireClient().updatePermission(permissionId, data)\n}\nexport async function deletePermission(permissionId: string): Promise<void> {\n return requireClient().deletePermission(permissionId)\n}\nexport async function getUserPermissions(userId: string): Promise<AdminPermission[]> {\n return requireClient().getUserPermissions(userId)\n}\nexport async function setUserPermissions(userId: string, permissionIds: string[]): Promise<void> {\n return requireClient().setUserPermissions(userId, permissionIds)\n}\n\n// ── Secrets (not in AdminClient SDK — windsock_org_secrets handler) ────────\n\nexport type SecretSummary = {\n secretId: string\n name: string\n secretType: string\n description: string | null\n expiresAt: string | null\n createdAt: string\n updatedAt: string\n disabled: boolean\n}\n\nexport type SecretDetail = SecretSummary & {\n value?: string\n}\n\nexport type CreateSecretInput = {\n name: string\n value: string\n secretType?: string\n description?: string\n leaseTtlSeconds?: number\n}\n\nexport type UpdateSecretInput = {\n value: string\n leaseTtlSeconds?: number\n}\n\nasync function secretsRequest<T>(path: string, init?: RequestInit): Promise<T> {\n if (!_issuer) throw new Error('Windsock issuer not initialized')\n const response = await _authFetch(`${_issuer}${path}`, {\n ...init,\n credentials: init?.credentials ?? 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...(init?.headers as Record<string, string> | undefined),\n },\n })\n if (response.status === 204) return undefined as T\n const payload = await response.json().catch(() => null)\n if (!response.ok) {\n const message = (payload as { error?: string; message?: string })?.message\n ?? (payload as { error?: string })?.error\n ?? `HTTP ${response.status}: ${response.statusText}`\n throw new HttpResponseError(message, response.status)\n }\n if (payload && typeof payload === 'object' && 'success' in payload && (payload as { success: boolean }).success && 'data' in payload) {\n return (payload as { data: T }).data\n }\n return payload as T\n}\n\nexport async function listSecrets(organizationId: string): Promise<SecretSummary[]> {\n return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets`)\n}\n\nexport async function getSecret(organizationId: string, secretId: string): Promise<SecretDetail> {\n return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`)\n}\n\nexport async function createSecret(organizationId: string, input: CreateSecretInput): Promise<SecretSummary> {\n return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets`, {\n method: 'POST',\n body: JSON.stringify(input),\n })\n}\n\nexport async function rotateSecret(organizationId: string, secretId: string, input: UpdateSecretInput): Promise<SecretSummary> {\n return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`, {\n method: 'PATCH',\n body: JSON.stringify(input),\n })\n}\n\nexport async function disableSecret(organizationId: string, secretId: string): Promise<void> {\n return secretsRequest(`/organizations/${encodeURIComponent(organizationId)}/secrets/${encodeURIComponent(secretId)}`, {\n method: 'DELETE',\n })\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// src/platform/rbac.ts
|
|
5
|
+
function matchPermission(pattern, target) {
|
|
6
|
+
if (pattern === "*") return true;
|
|
7
|
+
if (pattern === target) return true;
|
|
8
|
+
const patternParts = pattern.split(":");
|
|
9
|
+
const targetParts = target.split(":");
|
|
10
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
11
|
+
if (patternParts[i] === "*") return true;
|
|
12
|
+
if (patternParts[i] !== targetParts[i]) return false;
|
|
13
|
+
}
|
|
14
|
+
return patternParts.length === targetParts.length;
|
|
15
|
+
}
|
|
16
|
+
function createPlatformRbac(opts) {
|
|
17
|
+
const ROLE_DEFINITIONS = opts.roles;
|
|
18
|
+
const MODULE_PERMISSIONS = opts.modulePermissions ?? {};
|
|
19
|
+
const PERMISSION_CLAIMS_MAP = opts.permissionClaimsMap;
|
|
20
|
+
const knownRoles = Object.keys(ROLE_DEFINITIONS);
|
|
21
|
+
const fallbackRole = opts.defaultRole ?? knownRoles[0];
|
|
22
|
+
function normalizePlatformRole(input) {
|
|
23
|
+
if (typeof input === "string" && input in ROLE_DEFINITIONS) {
|
|
24
|
+
return input;
|
|
25
|
+
}
|
|
26
|
+
return fallbackRole;
|
|
27
|
+
}
|
|
28
|
+
function can(user, permission) {
|
|
29
|
+
if (!user) return false;
|
|
30
|
+
const userClaims = user.permissions ?? [];
|
|
31
|
+
const requiredClaims = PERMISSION_CLAIMS_MAP[permission] ?? [];
|
|
32
|
+
return requiredClaims.some(
|
|
33
|
+
(claim) => userClaims.some((userClaim) => matchPermission(userClaim, claim))
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
ROLE_DEFINITIONS,
|
|
38
|
+
MODULE_PERMISSIONS,
|
|
39
|
+
normalizePlatformRole,
|
|
40
|
+
can
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.createPlatformRbac = createPlatformRbac;
|
|
45
|
+
//# sourceMappingURL=chunk-HZ4LOVHM.js.map
|
|
46
|
+
//# sourceMappingURL=chunk-HZ4LOVHM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/rbac.ts"],"names":[],"mappings":";;;AAiDA,SAAS,eAAA,CAAgB,SAAiB,MAAA,EAAyB;AACjE,EAAA,IAAI,OAAA,KAAY,KAAK,OAAO,IAAA;AAC5B,EAAA,IAAI,OAAA,KAAY,QAAQ,OAAO,IAAA;AAC/B,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AACtC,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AACpC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,IAAA,IAAI,YAAA,CAAa,CAAC,CAAA,KAAM,GAAA,EAAK,OAAO,IAAA;AACpC,IAAA,IAAI,aAAa,CAAC,CAAA,KAAM,WAAA,CAAY,CAAC,GAAG,OAAO,KAAA;AAAA,EACjD;AACA,EAAA,OAAO,YAAA,CAAa,WAAW,WAAA,CAAY,MAAA;AAC7C;AAEO,SAAS,mBAGd,IAAA,EAAuF;AACvF,EAAA,MAAM,mBAAmB,IAAA,CAAK,KAAA;AAC9B,EAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,iBAAA,IAAsB,EAAC;AACvD,EAAA,MAAM,wBAAwB,IAAA,CAAK,mBAAA;AAInC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA;AAC/C,EAAA,MAAM,YAAA,GAAsB,IAAA,CAAK,WAAA,IAAgB,UAAA,CAAW,CAAC,CAAA;AAE7D,EAAA,SAAS,sBAAsB,KAAA,EAAuB;AACpD,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAa,KAAA,IAAmB,gBAAA,EAAkB;AACrE,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,SAAS,GAAA,CAAI,MAAuB,UAAA,EAAkC;AACpE,IAAA,IAAI,CAAC,MAAM,OAAO,KAAA;AAClB,IAAA,MAAM,UAAA,GAAc,IAAA,CAAK,WAAA,IAAe,EAAC;AAEzC,IAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,UAAU,CAAA,IAAK,EAAC;AAC7D,IAAA,OAAO,cAAA,CAAe,IAAA;AAAA,MAAK,CAAC,UAC1B,UAAA,CAAW,IAAA,CAAK,CAAC,SAAA,KAAc,eAAA,CAAgB,SAAA,EAAW,KAAK,CAAC;AAAA,KAClE;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,gBAAA;AAAA,IACA,kBAAA;AAAA,IACA,qBAAA;AAAA,IACA;AAAA,GACF;AACF","file":"chunk-HZ4LOVHM.js","sourcesContent":["import type { AuthUser } from '@datatechsolutions/windsock/client'\n\n/**\n * Generic role-based access factory shared across platform apps (astrlabe,\n * kori-erp, etc). Each app instantiates this with its own role + permission\n * unions and seed-claim mapping. The factory closes over the config and\n * exports `ROLE_DEFINITIONS`, `MODULE_PERMISSIONS`, `normalizePlatformRole`,\n * and `can()` — the same surface the per-app file used to expose.\n *\n * The factory deliberately does not hardcode any specific role enum here —\n * astrlabe, kori-erp, and future apps each pick their own union (admin,\n * manager, analyst, viewer, …) and pass the role definitions in.\n */\n\nexport type PlatformRoleDefinition<TRole extends string> = {\n id: TRole\n label: string\n description: string\n}\n\nexport type CreatePlatformRbacOptions<\n TRole extends string,\n TPermission extends string,\n> = {\n /** Definitions for every role the app supports (id/label/description). */\n roles: Record<TRole, PlatformRoleDefinition<TRole>>\n /**\n * Maps each app-level permission to one or more JWT permission claim\n * strings. `can()` returns true when ANY of the listed claims (using\n * wildcard matching) is present in the user's JWT permissions.\n */\n permissionClaimsMap: Record<TPermission, readonly string[]>\n /** Optional map from navigation/module IDs to required permissions. */\n modulePermissions?: Record<string, TPermission>\n /** Role to fall back to when an unknown role string comes in. */\n defaultRole?: TRole\n}\n\nexport type PlatformRbac<TRole extends string, TPermission extends string> = {\n ROLE_DEFINITIONS: Record<TRole, PlatformRoleDefinition<TRole>>\n MODULE_PERMISSIONS: Record<string, TPermission>\n normalizePlatformRole: (input: unknown) => TRole\n can: (user: AuthUser | null, permission: TPermission) => boolean\n}\n\n/**\n * Match a permission string against a pattern (supports wildcards).\n * Same logic as windsock's usePermissionChecker.\n */\nfunction matchPermission(pattern: string, target: string): boolean {\n if (pattern === '*') return true\n if (pattern === target) return true\n const patternParts = pattern.split(':')\n const targetParts = target.split(':')\n for (let i = 0; i < patternParts.length; i++) {\n if (patternParts[i] === '*') return true\n if (patternParts[i] !== targetParts[i]) return false\n }\n return patternParts.length === targetParts.length\n}\n\nexport function createPlatformRbac<\n TRole extends string,\n TPermission extends string,\n>(opts: CreatePlatformRbacOptions<TRole, TPermission>): PlatformRbac<TRole, TPermission> {\n const ROLE_DEFINITIONS = opts.roles\n const MODULE_PERMISSIONS = opts.modulePermissions ?? ({} as Record<string, TPermission>)\n const PERMISSION_CLAIMS_MAP = opts.permissionClaimsMap\n\n // Pick the fallback role: explicit `defaultRole` first, then the first\n // entry in the roles map. We assume there's at least one role.\n const knownRoles = Object.keys(ROLE_DEFINITIONS) as TRole[]\n const fallbackRole: TRole = opts.defaultRole ?? (knownRoles[0] as TRole)\n\n function normalizePlatformRole(input: unknown): TRole {\n if (typeof input === 'string' && (input as TRole) in ROLE_DEFINITIONS) {\n return input as TRole\n }\n return fallbackRole\n }\n\n function can(user: AuthUser | null, permission: TPermission): boolean {\n if (!user) return false\n const userClaims = (user.permissions ?? []) as string[]\n\n const requiredClaims = PERMISSION_CLAIMS_MAP[permission] ?? []\n return requiredClaims.some((claim) =>\n userClaims.some((userClaim) => matchPermission(userClaim, claim))\n )\n }\n\n return {\n ROLE_DEFINITIONS,\n MODULE_PERMISSIONS,\n normalizePlatformRole,\n can,\n }\n}\n"]}
|