@softacus-software/elwis-data-mcp 0.1.0
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 +15 -0
- package/LICENSE +6 -0
- package/README.md +183 -0
- package/dist/app-scope.js +92 -0
- package/dist/app-scope.js.map +1 -0
- package/dist/artifact-read.js +114 -0
- package/dist/artifact-read.js.map +1 -0
- package/dist/audit.js +36 -0
- package/dist/audit.js.map +1 -0
- package/dist/builders/artifact-type-execute.js +100 -0
- package/dist/builders/artifact-type-execute.js.map +1 -0
- package/dist/builders/artifact-type-plan.js +139 -0
- package/dist/builders/artifact-type-plan.js.map +1 -0
- package/dist/builders/design-interview.js +246 -0
- package/dist/builders/design-interview.js.map +1 -0
- package/dist/builders/entity-lifecycle-execute.js +12 -0
- package/dist/builders/entity-lifecycle-execute.js.map +1 -0
- package/dist/builders/entity-lifecycle-plan.js +345 -0
- package/dist/builders/entity-lifecycle-plan.js.map +1 -0
- package/dist/builders/links-execute.js +50 -0
- package/dist/builders/links-execute.js.map +1 -0
- package/dist/builders/links-plan.js +62 -0
- package/dist/builders/links-plan.js.map +1 -0
- package/dist/builders/page-execute.js +38 -0
- package/dist/builders/page-execute.js.map +1 -0
- package/dist/builders/page-plan.js +148 -0
- package/dist/builders/page-plan.js.map +1 -0
- package/dist/builders/records-execute.js +24 -0
- package/dist/builders/records-execute.js.map +1 -0
- package/dist/builders/records-lifecycle-execute.js +30 -0
- package/dist/builders/records-lifecycle-execute.js.map +1 -0
- package/dist/builders/records-lifecycle-plan.js +199 -0
- package/dist/builders/records-lifecycle-plan.js.map +1 -0
- package/dist/builders/records-plan.js +74 -0
- package/dist/builders/records-plan.js.map +1 -0
- package/dist/builders/update-page-execute.js +38 -0
- package/dist/builders/update-page-execute.js.map +1 -0
- package/dist/builders/update-page-plan.js +137 -0
- package/dist/builders/update-page-plan.js.map +1 -0
- package/dist/builders/workflow-execute.js +11 -0
- package/dist/builders/workflow-execute.js.map +1 -0
- package/dist/builders/workflow-plan.js +115 -0
- package/dist/builders/workflow-plan.js.map +1 -0
- package/dist/cli/client-configs.js +98 -0
- package/dist/cli/client-configs.js.map +1 -0
- package/dist/cli/login.js +64 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/prompter.js +77 -0
- package/dist/cli/prompter.js.map +1 -0
- package/dist/cli/setup.js +214 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/confirm.js +22 -0
- package/dist/confirm.js.map +1 -0
- package/dist/elwis-api.js +96 -0
- package/dist/elwis-api.js.map +1 -0
- package/dist/http-client.js +142 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.js +18 -0
- package/dist/jwt.js.map +1 -0
- package/dist/prune.js +9 -0
- package/dist/prune.js.map +1 -0
- package/dist/resolve.js +71 -0
- package/dist/resolve.js.map +1 -0
- package/dist/result.js +16 -0
- package/dist/result.js.map +1 -0
- package/dist/server.js +82 -0
- package/dist/server.js.map +1 -0
- package/dist/session-store.js +51 -0
- package/dist/session-store.js.map +1 -0
- package/dist/tools/build-artifact-type.js +36 -0
- package/dist/tools/build-artifact-type.js.map +1 -0
- package/dist/tools/build-links.js +33 -0
- package/dist/tools/build-links.js.map +1 -0
- package/dist/tools/build-page.js +40 -0
- package/dist/tools/build-page.js.map +1 -0
- package/dist/tools/build-workflow.js +36 -0
- package/dist/tools/build-workflow.js.map +1 -0
- package/dist/tools/create-application.js +44 -0
- package/dist/tools/create-application.js.map +1 -0
- package/dist/tools/create-artifacts.js +33 -0
- package/dist/tools/create-artifacts.js.map +1 -0
- package/dist/tools/create-folder.js +55 -0
- package/dist/tools/create-folder.js.map +1 -0
- package/dist/tools/delete-artifacts.js +33 -0
- package/dist/tools/delete-artifacts.js.map +1 -0
- package/dist/tools/delete-entity.js +35 -0
- package/dist/tools/delete-entity.js.map +1 -0
- package/dist/tools/explain-access.js +40 -0
- package/dist/tools/explain-access.js.map +1 -0
- package/dist/tools/get-entity.js +36 -0
- package/dist/tools/get-entity.js.map +1 -0
- package/dist/tools/get-page.js +75 -0
- package/dist/tools/get-page.js.map +1 -0
- package/dist/tools/list-apps.js +22 -0
- package/dist/tools/list-apps.js.map +1 -0
- package/dist/tools/list-entities.js +43 -0
- package/dist/tools/list-entities.js.map +1 -0
- package/dist/tools/propose-page-design.js +17 -0
- package/dist/tools/propose-page-design.js.map +1 -0
- package/dist/tools/raw-api.js +132 -0
- package/dist/tools/raw-api.js.map +1 -0
- package/dist/tools/read-artifacts.js +197 -0
- package/dist/tools/read-artifacts.js.map +1 -0
- package/dist/tools/resolve-entity.js +22 -0
- package/dist/tools/resolve-entity.js.map +1 -0
- package/dist/tools/update-artifacts.js +33 -0
- package/dist/tools/update-artifacts.js.map +1 -0
- package/dist/tools/update-entity.js +41 -0
- package/dist/tools/update-entity.js.map +1 -0
- package/dist/tools/update-page.js +40 -0
- package/dist/tools/update-page.js.map +1 -0
- package/dist/write-gate.js +25 -0
- package/dist/write-gate.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { stdout } from 'node:process';
|
|
2
|
+
import { NormalizeHost, PerformLogin } from './login.js';
|
|
3
|
+
import { Prompter } from './prompter.js';
|
|
4
|
+
import { SaveSession } from '../session-store.js';
|
|
5
|
+
import { BuildEnv, DetectClients, ServerCommand, WriteClientConfig } from './client-configs.js';
|
|
6
|
+
const FETCH_TIMEOUT = 10000;
|
|
7
|
+
async function LooksLikeElwis(host) {
|
|
8
|
+
try {
|
|
9
|
+
const response = await fetch(`${host}/api/tenant/user/info`, { headers: { Origin: host }, signal: AbortSignal.timeout(FETCH_TIMEOUT) });
|
|
10
|
+
if (response.status !== 200 && response.status !== 401 && response.status !== 403)
|
|
11
|
+
return 'no';
|
|
12
|
+
const body = await response.text();
|
|
13
|
+
try {
|
|
14
|
+
JSON.parse(body);
|
|
15
|
+
return 'yes';
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return 'no';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return 'unreachable';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function ListUserApps(host, token) {
|
|
26
|
+
try {
|
|
27
|
+
const filter = encodeURIComponent(JSON.stringify({ deleted: null }));
|
|
28
|
+
const response = await fetch(`${host}/api/tenant/application?filter=${filter}`, {
|
|
29
|
+
headers: { Origin: host, Cookie: `session-jwt=${token}` },
|
|
30
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT),
|
|
31
|
+
});
|
|
32
|
+
if (!response.ok)
|
|
33
|
+
return [];
|
|
34
|
+
const parsed = (await response.json());
|
|
35
|
+
return (parsed.data ?? []).map(a => a.name).filter((n) => Boolean(n));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function VerifyToken(host, token) {
|
|
42
|
+
const info = await fetch(`${host}/api/tenant/user/info`, {
|
|
43
|
+
headers: { Origin: host, Cookie: `session-jwt=${token}` },
|
|
44
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT),
|
|
45
|
+
}).catch(() => null);
|
|
46
|
+
if (!info?.ok)
|
|
47
|
+
return null;
|
|
48
|
+
const parsed = (await info.json());
|
|
49
|
+
return { host, token, tenantId: parsed.sessionUser?.tenant?.id ?? null, email: parsed.sessionUser?.email ?? null };
|
|
50
|
+
}
|
|
51
|
+
export async function RunSetup() {
|
|
52
|
+
const prompter = new Prompter();
|
|
53
|
+
const say = (line = '') => stdout.write(`${line}\n`);
|
|
54
|
+
try {
|
|
55
|
+
say('Welcome! This connects your AI assistant to ELWIS in a few questions. (Press Ctrl+C at any time to stop.)');
|
|
56
|
+
say();
|
|
57
|
+
let host = '';
|
|
58
|
+
for (;;) {
|
|
59
|
+
const answer = await prompter.ask('1) Where is your ELWIS? (you can paste the address straight from your browser): ');
|
|
60
|
+
if (!answer.trim()) {
|
|
61
|
+
say(' I need the address to continue, ask your administrator if you are not sure.');
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
host = NormalizeHost(answer);
|
|
65
|
+
const check = await LooksLikeElwis(host);
|
|
66
|
+
if (check === 'yes')
|
|
67
|
+
break;
|
|
68
|
+
if (check === 'no')
|
|
69
|
+
say(` ${host} answers, but it does not look like an ELWIS, double-check the address with your administrator.`);
|
|
70
|
+
else
|
|
71
|
+
say(` I could not reach ${host}, check the address (and your network) and try again.`);
|
|
72
|
+
}
|
|
73
|
+
say();
|
|
74
|
+
say('2) How should it sign in?');
|
|
75
|
+
say(' [1] With your own ELWIS email and password (recommended, acts as you, expires like a normal login)');
|
|
76
|
+
say(' [2] With an access token from your ELWIS administrator (for shared or automated setups)');
|
|
77
|
+
const authChoice = (await prompter.ask(' Pick 1 or 2 (press Enter for 1): ')).trim();
|
|
78
|
+
let login = null;
|
|
79
|
+
let sessionToken;
|
|
80
|
+
if (authChoice === '2') {
|
|
81
|
+
for (let attempt = 1; attempt <= 3 && !login; attempt++) {
|
|
82
|
+
const token = await prompter.askHidden(' Paste the access token (not shown while typing), or press Enter to sign in with email instead: ');
|
|
83
|
+
if (!token)
|
|
84
|
+
break;
|
|
85
|
+
login = await VerifyToken(host, token);
|
|
86
|
+
if (login) {
|
|
87
|
+
sessionToken = token;
|
|
88
|
+
say(` Connected as ${login.email ?? 'the token user'}.`);
|
|
89
|
+
}
|
|
90
|
+
else if (attempt < 3) {
|
|
91
|
+
say(' That token did not work. It may have been copied incompletely, paste it again.');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
say(' Still no luck with the token, let\'s sign in with your email instead.');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!login) {
|
|
99
|
+
let email = '';
|
|
100
|
+
for (let attempt = 1; attempt <= 3 && !login; attempt++) {
|
|
101
|
+
const emailPrompt = email ? ` Your ELWIS email [${email}]: ` : ' Your ELWIS email: ';
|
|
102
|
+
email = (await prompter.ask(emailPrompt)).trim() || email;
|
|
103
|
+
const password = await prompter.askHidden(' Your ELWIS password (not shown while typing): ');
|
|
104
|
+
try {
|
|
105
|
+
login = await PerformLogin(host, email, password);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
if (attempt === 3)
|
|
109
|
+
throw e;
|
|
110
|
+
say(` That did not work, ${e.message.replace(/^Sign-in failed, /, '')} (attempt ${attempt + 1} of 3)`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!login)
|
|
114
|
+
throw new Error('Sign-in did not succeed after three attempts. Check your details with your administrator and run setup again.');
|
|
115
|
+
SaveSession({ host, token: login.token, tenantId: login.tenantId, email: login.email, updatedAt: new Date().toISOString() });
|
|
116
|
+
say(` Signed in as ${login.email}. You'll stay signed in about as long as a normal ELWIS browser login (typically two weeks).`);
|
|
117
|
+
}
|
|
118
|
+
say();
|
|
119
|
+
say('3) What may the assistant do here?');
|
|
120
|
+
say(' [1] Only read and answer questions (recommended to start)');
|
|
121
|
+
say(' [2] Also build and change things, every change will still ask you for approval first');
|
|
122
|
+
const writeEnabled = (await prompter.ask(' Pick 1 or 2 (press Enter for 1): ')).trim() === '2';
|
|
123
|
+
say(` Okay, ${writeEnabled ? 'building allowed, with your approval before every change' : 'read-only'}.`);
|
|
124
|
+
say();
|
|
125
|
+
const appNames = await ListUserApps(host, login.token);
|
|
126
|
+
let allowedApps = [];
|
|
127
|
+
if (appNames.length > 0) {
|
|
128
|
+
say('4) Which parts of ELWIS may it see? You have access to these applications:');
|
|
129
|
+
appNames.forEach((name, index) => say(` [${index + 1}] ${name}`));
|
|
130
|
+
const appAnswer = (await prompter.ask(' Type numbers separated by commas, or press Enter for all of them: ')).trim();
|
|
131
|
+
allowedApps = appAnswer
|
|
132
|
+
? appAnswer.split(',').map(s => Number.parseInt(s.trim(), 10)).filter(n => Number.isInteger(n) && n >= 1 && n <= appNames.length).map(n => appNames[n - 1])
|
|
133
|
+
: [];
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const appAnswer = (await prompter.ask('4) Limit it to specific applications? Type names separated by commas, or press Enter for all you can access: ')).trim();
|
|
137
|
+
allowedApps = appAnswer ? appAnswer.split(',').map(s => s.trim()).filter(Boolean) : [];
|
|
138
|
+
}
|
|
139
|
+
say(` Okay, ${allowedApps.length ? `limited to: ${allowedApps.join(', ')}` : 'all applications you can access'}.`);
|
|
140
|
+
const choices = { host, tenantId: login.tenantId, sessionToken, writeEnabled, allowedApps };
|
|
141
|
+
const entry = { ...ServerCommand(), env: BuildEnv(choices) };
|
|
142
|
+
say();
|
|
143
|
+
const clients = DetectClients();
|
|
144
|
+
say('5) Which assistant should I set up? I can configure these:');
|
|
145
|
+
clients.forEach((client, index) => say(` [${index + 1}] ${client.label}${client.exists ? '' : ' (not detected on this computer, I can still write its config)'}`));
|
|
146
|
+
const picked = (await prompter.ask(' Type numbers separated by commas (e.g. 1,2): '))
|
|
147
|
+
.split(',')
|
|
148
|
+
.map(s => Number.parseInt(s.trim(), 10))
|
|
149
|
+
.filter(n => Number.isInteger(n) && n >= 1 && n <= clients.length)
|
|
150
|
+
.map(n => clients[n - 1]);
|
|
151
|
+
for (const target of picked) {
|
|
152
|
+
const written = WriteClientConfig(target, entry);
|
|
153
|
+
say(` ${target.label}: updated ${written.path}${written.backup ? ` (previous version saved as ${written.backup})` : ''}`);
|
|
154
|
+
}
|
|
155
|
+
say();
|
|
156
|
+
if (picked.length === 0) {
|
|
157
|
+
say('Nothing was selected, so no assistant configs were changed. Your sign-in is saved, run setup again any time to finish.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
say('Done! Now:');
|
|
161
|
+
say(' 1. Fully quit your assistant (on a Mac: Cmd+Q, not just closing the window) and open it again.');
|
|
162
|
+
say(' 2. Ask it in plain words: "Are you connected to ELWIS?"');
|
|
163
|
+
say('It should answer with your name and tenant.');
|
|
164
|
+
say(`Set up: ${login.email ?? 'token user'} on ${host}, ${writeEnabled ? 'building allowed (asks approval first)' : 'read-only'}, ${allowedApps.length ? `limited to: ${allowedApps.join(', ')}` : 'all your applications'}.`);
|
|
165
|
+
say('If it does not connect: make sure you fully quit and reopened, then run this setup again.');
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
prompter.close();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function RunCli(argv) {
|
|
172
|
+
const command = argv[2];
|
|
173
|
+
if (command === 'setup') {
|
|
174
|
+
await RunSetup();
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
if (command === 'login') {
|
|
178
|
+
const { RunLogin } = await import('./login.js');
|
|
179
|
+
await RunLogin(argv[3]);
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
if (command === 'logout') {
|
|
183
|
+
const { DeleteSession, ListSessions } = await import('../session-store.js');
|
|
184
|
+
const { NormalizeHost: Normalize } = await import('./login.js');
|
|
185
|
+
let host = argv[3] ? Normalize(argv[3]) : null;
|
|
186
|
+
if (!host) {
|
|
187
|
+
const sessions = ListSessions();
|
|
188
|
+
if (sessions.length === 1)
|
|
189
|
+
host = sessions[0].host;
|
|
190
|
+
else {
|
|
191
|
+
stdout.write(sessions.length ? 'You are signed in to several ELWIS servers, tell me which one: elwis-data-mcp logout <address>\n' : 'You are not signed in anywhere on this computer.\n');
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
DeleteSession(host);
|
|
196
|
+
stdout.write(`Signed out of ${host} on this computer. Sessions can also be revoked centrally in ELWIS.\n`);
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
if (command === 'help' || command === '--help' || command === '-h') {
|
|
200
|
+
stdout.write([
|
|
201
|
+
'elwis-data-mcp, connects your AI assistant to ELWIS',
|
|
202
|
+
'',
|
|
203
|
+
' setup guided setup in plain language (start here)',
|
|
204
|
+
' login [address] sign in again after your session expires',
|
|
205
|
+
' logout [address] sign out on this computer',
|
|
206
|
+
'',
|
|
207
|
+
'Without a command it starts the MCP server (used by your assistant, not by hand).',
|
|
208
|
+
'',
|
|
209
|
+
].join('\n'));
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/cli/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { LoadSession } from './session-store.js';
|
|
4
|
+
export function LoadConfig(env = process.env) {
|
|
5
|
+
const baseUrl = env.ELWIS_API_URL;
|
|
6
|
+
if (!baseUrl)
|
|
7
|
+
throw new Error('ELWIS_API_URL is not set');
|
|
8
|
+
const normalized = baseUrl.replace(/\/$/, '');
|
|
9
|
+
let token = env.ELWIS_SESSION_JWT;
|
|
10
|
+
let authMode = 'token';
|
|
11
|
+
if (!token) {
|
|
12
|
+
const session = LoadSession(normalized, env.ELWIS_SESSIONS_DIR?.trim() || undefined);
|
|
13
|
+
if (session) {
|
|
14
|
+
token = session.token;
|
|
15
|
+
authMode = 'session';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (!token) {
|
|
19
|
+
throw new Error(`No ELWIS login found for ${normalized}. Open Terminal and run: npx @softacus-software/elwis-data-mcp setup`);
|
|
20
|
+
}
|
|
21
|
+
const expectedTenant = env.ELWIS_TENANT?.trim();
|
|
22
|
+
if (expectedTenant && !/^[a-f0-9]{24}$/i.test(expectedTenant)) {
|
|
23
|
+
throw new Error('ELWIS_TENANT must be the 24-character tenant id shown by explain_elwis_access');
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
baseUrl: normalized,
|
|
27
|
+
token,
|
|
28
|
+
authMode,
|
|
29
|
+
writeEnabled: env.ELWIS_WRITE_ENABLED === 'true',
|
|
30
|
+
deleteEnabled: env.ELWIS_DELETE_ENABLED === 'true',
|
|
31
|
+
buildersEnabled: env.DATA_MCP_BUILDERS !== 'off',
|
|
32
|
+
allowedApps: (env.ELWIS_ALLOWED_APPS ?? '').split(',').map(s => s.trim()).filter(Boolean),
|
|
33
|
+
expectedTenant: expectedTenant || undefined,
|
|
34
|
+
requireConfirmation: env.ELWIS_REQUIRE_CONFIRMATION !== 'false',
|
|
35
|
+
auditLog: env.ELWIS_AUDIT_LOG?.trim() || join(homedir(), '.elwis', 'data-mcp-audit.jsonl'),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAejD,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC;IAClC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9C,IAAI,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC;IAClC,IAAI,QAAQ,GAAwB,OAAO,CAAC;IAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC,CAAC;QACrF,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YACtB,QAAQ,GAAG,SAAS,CAAC;QACvB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,4BAA4B,UAAU,sEAAsE,CAAC,CAAC;IAChI,CAAC;IACD,MAAM,cAAc,GAAG,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,cAAc,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;IACnG,CAAC;IACD,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,KAAK;QACL,QAAQ;QACR,YAAY,EAAE,GAAG,CAAC,mBAAmB,KAAK,MAAM;QAChD,aAAa,EAAE,GAAG,CAAC,oBAAoB,KAAK,MAAM;QAClD,eAAe,EAAE,GAAG,CAAC,iBAAiB,KAAK,KAAK;QAChD,WAAW,EAAE,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QACzF,cAAc,EAAE,cAAc,IAAI,SAAS;QAC3C,mBAAmB,EAAE,GAAG,CAAC,0BAA0B,KAAK,OAAO;QAC/D,QAAQ,EAAE,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,sBAAsB,CAAC;KAC3F,CAAC;AACJ,CAAC"}
|
package/dist/confirm.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export function StableStringify(value) {
|
|
3
|
+
if (Array.isArray(value))
|
|
4
|
+
return `[${value.map(v => (v === undefined ? 'null' : StableStringify(v))).join(',')}]`;
|
|
5
|
+
if (value !== null && typeof value === 'object') {
|
|
6
|
+
if (typeof value.toJSON === 'function')
|
|
7
|
+
return JSON.stringify(value);
|
|
8
|
+
const entries = Object.entries(value)
|
|
9
|
+
.filter(([, v]) => v !== undefined)
|
|
10
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
11
|
+
.map(([k, v]) => `${JSON.stringify(k)}:${StableStringify(v)}`);
|
|
12
|
+
return `{${entries.join(',')}}`;
|
|
13
|
+
}
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
}
|
|
16
|
+
export function PlanToken(cfg, tool, plan) {
|
|
17
|
+
return createHash('sha256')
|
|
18
|
+
.update(`${cfg.baseUrl}\n${cfg.expectedTenant ?? ''}\n${tool}\n${StableStringify(plan)}`)
|
|
19
|
+
.digest('hex')
|
|
20
|
+
.slice(0, 12);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confirm.js","sourceRoot":"","sources":["../src/confirm.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAClH,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,IAAI,OAAQ,KAA8B,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/F,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC;aAC7D,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;aAClC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAChD,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAgB,EAAE,IAAY,EAAE,IAAa;IACrE,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC,cAAc,IAAI,EAAE,KAAK,IAAI,KAAK,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;SACxF,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { TenantMismatchError, NoTenantError } from './app-scope.js';
|
|
2
|
+
export class ElwisApi {
|
|
3
|
+
client;
|
|
4
|
+
expectedTenant;
|
|
5
|
+
identityPromise = null;
|
|
6
|
+
tenantCheck = null;
|
|
7
|
+
constructor(client, expectedTenant) {
|
|
8
|
+
this.client = client;
|
|
9
|
+
this.expectedTenant = expectedTenant;
|
|
10
|
+
}
|
|
11
|
+
async whoAmI() {
|
|
12
|
+
const info = await this.client.get('/api/tenant/user/info');
|
|
13
|
+
const user = info.sessionUser ?? info.guestUser;
|
|
14
|
+
return { userId: user?.id ?? null, email: user?.email ?? null, tenantId: user?.tenant?.id ?? null, tenantAdmin: user?.tenant?.isAdmin ?? null };
|
|
15
|
+
}
|
|
16
|
+
identity() {
|
|
17
|
+
this.identityPromise = this.identityPromise ?? this.whoAmI();
|
|
18
|
+
return this.identityPromise;
|
|
19
|
+
}
|
|
20
|
+
ensureTenant() {
|
|
21
|
+
if (!this.expectedTenant)
|
|
22
|
+
return Promise.reject(new NoTenantError());
|
|
23
|
+
this.tenantCheck = this.tenantCheck ?? this.identity().then(id => {
|
|
24
|
+
if (id.tenantId !== this.expectedTenant)
|
|
25
|
+
throw new TenantMismatchError(this.expectedTenant, id.tenantId);
|
|
26
|
+
});
|
|
27
|
+
return this.tenantCheck;
|
|
28
|
+
}
|
|
29
|
+
async systemAttributes() {
|
|
30
|
+
await this.ensureTenant();
|
|
31
|
+
const info = await this.client.get('/api/tenant/user/info');
|
|
32
|
+
const tenant = (info.sessionUser ?? info.guestUser)?.tenant;
|
|
33
|
+
const sys = tenant?.systemAttributes;
|
|
34
|
+
if (!sys?.nameAttributeId)
|
|
35
|
+
throw new Error('Could not resolve system attributes from /api/tenant/user/info');
|
|
36
|
+
return {
|
|
37
|
+
nameAttributeId: sys.nameAttributeId,
|
|
38
|
+
sequenceAttributeId: sys.sequenceAttributeId,
|
|
39
|
+
primaryTextAttributeId: sys.primaryTextAttributeId,
|
|
40
|
+
fileArtifactTypeId: tenant?.fileArtifactTypeId,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
async list(kind, filter = {}, limit) {
|
|
44
|
+
await this.ensureTenant();
|
|
45
|
+
const params = new URLSearchParams();
|
|
46
|
+
params.set('filter', JSON.stringify({ ...filter, deleted: null }));
|
|
47
|
+
params.set('sort', JSON.stringify({ _id: -1 }));
|
|
48
|
+
if (limit !== undefined)
|
|
49
|
+
params.set('limit', String(limit));
|
|
50
|
+
const res = await this.client.get(`/api/tenant/${kind}?${params.toString()}`);
|
|
51
|
+
return res.data;
|
|
52
|
+
}
|
|
53
|
+
async create(kind, body) {
|
|
54
|
+
await this.ensureTenant();
|
|
55
|
+
return this.client.post(`/api/tenant/${kind}`, body);
|
|
56
|
+
}
|
|
57
|
+
async update(kind, body) {
|
|
58
|
+
await this.ensureTenant();
|
|
59
|
+
return this.client.put(`/api/tenant/${kind}`, body);
|
|
60
|
+
}
|
|
61
|
+
async getOne(kind, id) {
|
|
62
|
+
await this.ensureTenant();
|
|
63
|
+
return this.client.get(`/api/tenant/${kind}/${id}`);
|
|
64
|
+
}
|
|
65
|
+
async listRecords(collection, filter, opts = {}) {
|
|
66
|
+
await this.ensureTenant();
|
|
67
|
+
const body = { filter: JSON.stringify({ ...filter, deleted: null }) };
|
|
68
|
+
body.sort = JSON.stringify(opts.sort ?? { _id: -1 });
|
|
69
|
+
if (opts.skip !== undefined)
|
|
70
|
+
body.skip = opts.skip;
|
|
71
|
+
if (opts.limit !== undefined)
|
|
72
|
+
body.limit = opts.limit;
|
|
73
|
+
return this.client.post(`/api/tenant/${collection}/list`, body);
|
|
74
|
+
}
|
|
75
|
+
async createArtifact(body) {
|
|
76
|
+
await this.ensureTenant();
|
|
77
|
+
return this.client.post('/api/tenant/artifact', body);
|
|
78
|
+
}
|
|
79
|
+
async createLinks(body) {
|
|
80
|
+
await this.ensureTenant();
|
|
81
|
+
return this.client.post('/api/tenant/link', body);
|
|
82
|
+
}
|
|
83
|
+
async updateArtifact(body) {
|
|
84
|
+
await this.ensureTenant();
|
|
85
|
+
return this.client.put('/api/tenant/artifact?notify=false', body);
|
|
86
|
+
}
|
|
87
|
+
async softDeleteArtifact(id) {
|
|
88
|
+
await this.ensureTenant();
|
|
89
|
+
return this.client.delete(`/api/tenant/artifact/${id}?notify=false`);
|
|
90
|
+
}
|
|
91
|
+
async softDelete(kind, id) {
|
|
92
|
+
await this.ensureTenant();
|
|
93
|
+
return this.client.delete(`/api/tenant/${kind}/${id}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=elwis-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elwis-api.js","sourceRoot":"","sources":["../src/elwis-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { request as httpRequest } from 'node:http';
|
|
2
|
+
import { request as httpsRequest } from 'node:https';
|
|
3
|
+
import { URL } from 'node:url';
|
|
4
|
+
const REFRESH_PATH = '/api/tenant/session/refresh';
|
|
5
|
+
const REQUEST_TIMEOUT_MS = 30000;
|
|
6
|
+
export class ElwisHttpError extends Error {
|
|
7
|
+
status;
|
|
8
|
+
path;
|
|
9
|
+
body;
|
|
10
|
+
constructor(status, path, body) {
|
|
11
|
+
super(`ELWIS API ${status} for ${path}`);
|
|
12
|
+
this.name = 'ElwisHttpError';
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.path = path;
|
|
15
|
+
this.body = body;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class SessionExpiredError extends Error {
|
|
19
|
+
constructor() {
|
|
20
|
+
super('Your ELWIS session has expired or was revoked. Open Terminal and run: npx @softacus-software/elwis-data-mcp login');
|
|
21
|
+
this.name = 'SessionExpiredError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function HttpErrorDetail(error) {
|
|
25
|
+
return error instanceof ElwisHttpError && error.body !== undefined ? `: ${JSON.stringify(error.body)}` : '';
|
|
26
|
+
}
|
|
27
|
+
export function CookieToken(setCookies) {
|
|
28
|
+
for (const cookie of setCookies) {
|
|
29
|
+
const match = /^session-jwt=([^;]+)/.exec(cookie);
|
|
30
|
+
if (match && match[1].length > 0)
|
|
31
|
+
return match[1];
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
export class ElwisHttpClient {
|
|
36
|
+
cfg;
|
|
37
|
+
opts;
|
|
38
|
+
refreshing = null;
|
|
39
|
+
constructor(cfg, opts = {}) {
|
|
40
|
+
this.cfg = cfg;
|
|
41
|
+
this.opts = opts;
|
|
42
|
+
}
|
|
43
|
+
get(path) { return this.send('GET', path); }
|
|
44
|
+
post(path, body) { return this.send('POST', path, body); }
|
|
45
|
+
put(path, body) { return this.send('PUT', path, body); }
|
|
46
|
+
delete(path) { return this.send('DELETE', path); }
|
|
47
|
+
async send(method, path, body, isRetry = false) {
|
|
48
|
+
const tokenAtSend = this.cfg.token;
|
|
49
|
+
const res = await this.request(method, path, body);
|
|
50
|
+
this.adoptRotatedToken(res.setCookies);
|
|
51
|
+
if (res.status >= 200 && res.status < 300)
|
|
52
|
+
return res.parsed;
|
|
53
|
+
const original = new ElwisHttpError(res.status, path, res.parsed);
|
|
54
|
+
if (res.status === 401 && this.opts.refresh && !isRetry && path !== REFRESH_PATH) {
|
|
55
|
+
if (this.cfg.token !== tokenAtSend)
|
|
56
|
+
return this.send(method, path, body, true);
|
|
57
|
+
try {
|
|
58
|
+
await this.refreshToken();
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
if (e instanceof SessionExpiredError)
|
|
62
|
+
throw e;
|
|
63
|
+
throw original;
|
|
64
|
+
}
|
|
65
|
+
return this.send(method, path, body, true);
|
|
66
|
+
}
|
|
67
|
+
throw original;
|
|
68
|
+
}
|
|
69
|
+
adoptRotatedToken(setCookies) {
|
|
70
|
+
if (!this.opts.refresh)
|
|
71
|
+
return;
|
|
72
|
+
const rotated = CookieToken(setCookies);
|
|
73
|
+
if (!rotated || rotated === this.cfg.token)
|
|
74
|
+
return;
|
|
75
|
+
this.cfg.token = rotated;
|
|
76
|
+
try {
|
|
77
|
+
this.opts.persist?.(rotated);
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
process.stderr.write(`could not save the refreshed session: ${e.message}\n`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
refreshToken() {
|
|
84
|
+
this.refreshing = this.refreshing ?? this.doRefresh().finally(() => { this.refreshing = null; });
|
|
85
|
+
return this.refreshing;
|
|
86
|
+
}
|
|
87
|
+
async doRefresh() {
|
|
88
|
+
const onDisk = this.opts.reload?.() ?? null;
|
|
89
|
+
if (onDisk && onDisk !== this.cfg.token) {
|
|
90
|
+
this.cfg.token = onDisk;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const res = await this.request('PATCH', REFRESH_PATH);
|
|
94
|
+
const fromCookie = CookieToken(res.setCookies);
|
|
95
|
+
const fromBody = res.parsed?.clientData?.sessionJwt;
|
|
96
|
+
const token = fromCookie ?? (typeof fromBody === 'string' && fromBody.length > 0 ? fromBody : null);
|
|
97
|
+
if (res.status === 401)
|
|
98
|
+
throw new SessionExpiredError();
|
|
99
|
+
if (res.status < 200 || res.status >= 300 || !token)
|
|
100
|
+
throw new Error(`session refresh answered ${res.status}`);
|
|
101
|
+
this.adoptRotatedToken([`session-jwt=${token}`]);
|
|
102
|
+
}
|
|
103
|
+
request(method, path, body) {
|
|
104
|
+
const url = new URL(this.cfg.baseUrl + path);
|
|
105
|
+
const payload = body === undefined ? undefined : Buffer.from(JSON.stringify(body), 'utf8');
|
|
106
|
+
const requester = url.protocol === 'https:' ? httpsRequest : httpRequest;
|
|
107
|
+
const headers = { Cookie: `session-jwt=${this.cfg.token}`, Origin: this.cfg.baseUrl };
|
|
108
|
+
if (payload) {
|
|
109
|
+
headers['content-type'] = 'application/json';
|
|
110
|
+
headers['content-length'] = String(payload.length);
|
|
111
|
+
}
|
|
112
|
+
return new Promise((resolveValue, reject) => {
|
|
113
|
+
const req = requester(url, { method, headers }, res => {
|
|
114
|
+
const chunks = [];
|
|
115
|
+
res.on('data', (c) => chunks.push(c));
|
|
116
|
+
res.on('end', () => {
|
|
117
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
118
|
+
resolveValue({
|
|
119
|
+
status: res.statusCode ?? 0,
|
|
120
|
+
setCookies: res.headers['set-cookie'] ?? [],
|
|
121
|
+
parsed: text.length ? SafeJson(text) : undefined,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
res.on('error', reject);
|
|
125
|
+
});
|
|
126
|
+
req.setTimeout(REQUEST_TIMEOUT_MS, () => req.destroy(new Error(`ELWIS did not answer within ${REQUEST_TIMEOUT_MS / 1000}s for ${path}`)));
|
|
127
|
+
req.on('error', reject);
|
|
128
|
+
if (payload)
|
|
129
|
+
req.write(payload);
|
|
130
|
+
req.end();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function SafeJson(text) {
|
|
135
|
+
try {
|
|
136
|
+
return JSON.parse(text);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return text;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../src/http-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { BuildServer } from './server.js';
|
|
4
|
+
async function Main() {
|
|
5
|
+
if (process.argv[2]) {
|
|
6
|
+
const { RunCli } = await import('./cli/setup.js');
|
|
7
|
+
if (await RunCli(process.argv))
|
|
8
|
+
return;
|
|
9
|
+
process.stderr.write(`Unknown command "${process.argv[2]}". Try: elwis-data-mcp help\n`);
|
|
10
|
+
process.exit(2);
|
|
11
|
+
}
|
|
12
|
+
const server = BuildServer();
|
|
13
|
+
const transport = new StdioServerTransport();
|
|
14
|
+
await server.connect(transport);
|
|
15
|
+
}
|
|
16
|
+
Main().catch(e => {
|
|
17
|
+
process.stderr.write(`${e instanceof Error ? e.message : String(e)}\n`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,IAAI;IACjB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAClD,IAAI,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/jwt.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function DecodeJwtClaims(token) {
|
|
2
|
+
const parts = token.split('.');
|
|
3
|
+
if (parts.length < 2)
|
|
4
|
+
return {};
|
|
5
|
+
try {
|
|
6
|
+
const json = Buffer.from(parts[1], 'base64url').toString('utf8');
|
|
7
|
+
const obj = JSON.parse(json);
|
|
8
|
+
return {
|
|
9
|
+
sub: typeof obj.sub === 'string' ? obj.sub : undefined,
|
|
10
|
+
tenant: typeof obj.tenant === 'string' ? obj.tenant : undefined,
|
|
11
|
+
exp: typeof obj.exp === 'number' ? obj.exp : undefined,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=jwt.js.map
|
package/dist/jwt.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;QACxD,OAAO;YACL,GAAG,EAAE,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;YACtD,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;YAC/D,GAAG,EAAE,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;SACvD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AACxB,CAAC"}
|
package/dist/prune.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../src/prune.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK,CAAC,GAA4B;IAChD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|