@sap/joule-studio-dev-cli 0.1.20-alpha.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.
- package/LICENSE +38 -0
- package/README.md +53 -0
- package/dist/bin/commands/a2a.js +12 -0
- package/dist/bin/commands/a2a.js.map +1 -0
- package/dist/bin/commands/asset.js +20 -0
- package/dist/bin/commands/asset.js.map +1 -0
- package/dist/bin/commands/auth.js +16 -0
- package/dist/bin/commands/auth.js.map +1 -0
- package/dist/bin/commands/init.js +20 -0
- package/dist/bin/commands/init.js.map +1 -0
- package/dist/bin/commands/mcp.js +42 -0
- package/dist/bin/commands/mcp.js.map +1 -0
- package/dist/bin/commands/pro-code.js +12 -0
- package/dist/bin/commands/pro-code.js.map +1 -0
- package/dist/bin/commands/skills.js +27 -0
- package/dist/bin/commands/skills.js.map +1 -0
- package/dist/bin/commands/solution.js +52 -0
- package/dist/bin/commands/solution.js.map +1 -0
- package/dist/bin/help.js +42 -0
- package/dist/bin/help.js.map +1 -0
- package/dist/bin/jl.js +59 -0
- package/dist/bin/jl.js.map +1 -0
- package/dist/bin/login.js +60 -0
- package/dist/bin/login.js.map +1 -0
- package/dist/bin/logout.js +21 -0
- package/dist/bin/logout.js.map +1 -0
- package/dist/lib/a2a/message.js +74 -0
- package/dist/lib/a2a/message.js.map +1 -0
- package/dist/lib/asset/create.js +38 -0
- package/dist/lib/asset/create.js.map +1 -0
- package/dist/lib/asset/delete.js +57 -0
- package/dist/lib/asset/delete.js.map +1 -0
- package/dist/lib/asset/discover.js +46 -0
- package/dist/lib/asset/discover.js.map +1 -0
- package/dist/lib/auth-crypto.js +146 -0
- package/dist/lib/auth-crypto.js.map +1 -0
- package/dist/lib/auth.js +488 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/context.js +35 -0
- package/dist/lib/context.js.map +1 -0
- package/dist/lib/errors.js +47 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/fs-utils.js +34 -0
- package/dist/lib/fs-utils.js.map +1 -0
- package/dist/lib/init/agents.js +55 -0
- package/dist/lib/init/agents.js.map +1 -0
- package/dist/lib/init/shared.js +172 -0
- package/dist/lib/init/shared.js.map +1 -0
- package/dist/lib/mcp/call.js +158 -0
- package/dist/lib/mcp/call.js.map +1 -0
- package/dist/lib/mcp/client.js +100 -0
- package/dist/lib/mcp/client.js.map +1 -0
- package/dist/lib/mcp/list.js +20 -0
- package/dist/lib/mcp/list.js.map +1 -0
- package/dist/lib/mcp/start.js +120 -0
- package/dist/lib/mcp/start.js.map +1 -0
- package/dist/lib/mcp/tools.js +162 -0
- package/dist/lib/mcp/tools.js.map +1 -0
- package/dist/lib/plugin.js +77 -0
- package/dist/lib/plugin.js.map +1 -0
- package/dist/lib/plugins/agent/index.js +32 -0
- package/dist/lib/plugins/agent/index.js.map +1 -0
- package/dist/lib/plugins/agent/templates/asset.yaml.hbs +31 -0
- package/dist/lib/plugins/agent-extension/index.js +32 -0
- package/dist/lib/plugins/agent-extension/index.js.map +1 -0
- package/dist/lib/plugins/agent-extension/templates/asset.yaml.hbs +15 -0
- package/dist/lib/plugins/base-ui/index.js +32 -0
- package/dist/lib/plugins/base-ui/index.js.map +1 -0
- package/dist/lib/plugins/base-ui/templates/asset.yaml.hbs +8 -0
- package/dist/lib/plugins/cap-app/index.js +32 -0
- package/dist/lib/plugins/cap-app/index.js.map +1 -0
- package/dist/lib/plugins/cap-app/templates/asset.yaml.hbs +37 -0
- package/dist/lib/plugins/data-product/index.js +32 -0
- package/dist/lib/plugins/data-product/index.js.map +1 -0
- package/dist/lib/plugins/data-product/templates/asset.yaml.hbs +9 -0
- package/dist/lib/plugins/domain-model-extension/index.js +37 -0
- package/dist/lib/plugins/domain-model-extension/index.js.map +1 -0
- package/dist/lib/plugins/domain-model-extension/templates/asset.yaml.hbs +15 -0
- package/dist/lib/plugins/mcp-server/index.js +36 -0
- package/dist/lib/plugins/mcp-server/index.js.map +1 -0
- package/dist/lib/plugins/mcp-server/templates/asset.yaml.hbs +9 -0
- package/dist/lib/plugins/n8n-workflow/index.js +52 -0
- package/dist/lib/plugins/n8n-workflow/index.js.map +1 -0
- package/dist/lib/plugins/n8n-workflow/templates/asset.yaml.hbs +18 -0
- package/dist/lib/plugins/n8n-workflow/validation/asset-validator.js +62 -0
- package/dist/lib/plugins/n8n-workflow/validation/asset-validator.js.map +1 -0
- package/dist/lib/plugins/n8n-workflow/validation/yaml-validator.js +51 -0
- package/dist/lib/plugins/n8n-workflow/validation/yaml-validator.js.map +1 -0
- package/dist/lib/plugins/vercel-app/index.js +32 -0
- package/dist/lib/plugins/vercel-app/index.js.map +1 -0
- package/dist/lib/plugins/vercel-app/templates/asset.yaml.hbs +12 -0
- package/dist/lib/rule.js +2 -0
- package/dist/lib/rule.js.map +1 -0
- package/dist/lib/schemas/solution-schema.json +178 -0
- package/dist/lib/solution/build.js +186 -0
- package/dist/lib/solution/build.js.map +1 -0
- package/dist/lib/solution/create.js +42 -0
- package/dist/lib/solution/create.js.map +1 -0
- package/dist/lib/solution/deploy.js +66 -0
- package/dist/lib/solution/deploy.js.map +1 -0
- package/dist/lib/solution/list.js +21 -0
- package/dist/lib/solution/list.js.map +1 -0
- package/dist/lib/solution/logs.js +130 -0
- package/dist/lib/solution/logs.js.map +1 -0
- package/dist/lib/solution/status.js +161 -0
- package/dist/lib/solution/status.js.map +1 -0
- package/dist/lib/solution/templates/solution.yaml.hbs +9 -0
- package/dist/lib/solution/util/build-file.js +4 -0
- package/dist/lib/solution/util/build-file.js.map +1 -0
- package/dist/lib/template.js +74 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/lib/term.js +16 -0
- package/dist/lib/term.js.map +1 -0
- package/dist/lib/validate.js +287 -0
- package/dist/lib/validate.js.map +1 -0
- package/dist/lib/yaml.js +33 -0
- package/dist/lib/yaml.js.map +1 -0
- package/dist/package.json +77 -0
- package/package.json +77 -0
package/dist/lib/auth.js
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import https from 'node:https';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { CliError } from './errors.js';
|
|
6
|
+
import { encrypt, decrypt } from './auth-crypto.js';
|
|
7
|
+
import term from './term.js';
|
|
8
|
+
const JOULEWORK_DIR = path.join(os.homedir(), '.joulestudio');
|
|
9
|
+
const CREDENTIALS_FILE = path.join(JOULEWORK_DIR, 'credentials.json');
|
|
10
|
+
const MAX_RESPONSE_BYTES = 1 * 1024 * 1024; // 1 MB
|
|
11
|
+
const FETCH_TIMEOUT_MS = 30_000;
|
|
12
|
+
// Matches: location="https://.../oauth2/authorize?...client_id=...&app_tid=..."
|
|
13
|
+
const JS_REDIRECT_RE = /location\s*=\s*"(https?:\/\/[^"]*\/oauth2\/authorize\?[^"]+)"/;
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Headless login helpers
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
class _CookieJar {
|
|
18
|
+
#store = new Map();
|
|
19
|
+
#expiries = new Map();
|
|
20
|
+
update(rawHeaders, url) {
|
|
21
|
+
const host = new URL(url).hostname;
|
|
22
|
+
if (!this.#store.has(host)) {
|
|
23
|
+
this.#store.set(host, new Map());
|
|
24
|
+
}
|
|
25
|
+
const jar = this.#store.get(host);
|
|
26
|
+
const setCookies = Array.isArray(rawHeaders['set-cookie'])
|
|
27
|
+
? rawHeaders['set-cookie']
|
|
28
|
+
: rawHeaders['set-cookie']
|
|
29
|
+
? [rawHeaders['set-cookie']]
|
|
30
|
+
: [];
|
|
31
|
+
for (const raw of setCookies) {
|
|
32
|
+
const [nameVal, ...attrs] = raw.split(';');
|
|
33
|
+
const eq = nameVal.indexOf('=');
|
|
34
|
+
if (eq < 0) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const name = nameVal.slice(0, eq).trim();
|
|
38
|
+
jar.set(name, nameVal.slice(eq + 1).trim());
|
|
39
|
+
const maxAge = attrs.find(a => /^\s*max-age\s*=/i.test(a));
|
|
40
|
+
const expires = attrs.find(a => /^\s*expires\s*=/i.test(a));
|
|
41
|
+
if (maxAge) {
|
|
42
|
+
const s = parseInt(maxAge.split('=')[1], 10);
|
|
43
|
+
if (!isNaN(s) && s > 0) {
|
|
44
|
+
this.#expiries.set(`${host}:${name}`, Date.now() + s * 1000);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (expires) {
|
|
48
|
+
const ms = new Date(expires.split('=').slice(1).join('=').trim()).getTime();
|
|
49
|
+
if (!isNaN(ms)) {
|
|
50
|
+
this.#expiries.set(`${host}:${name}`, ms);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
expiryFor(url, names) {
|
|
56
|
+
const host = new URL(url).hostname;
|
|
57
|
+
let earliest = null;
|
|
58
|
+
for (const name of names) {
|
|
59
|
+
const exp = this.#expiries.get(`${host}:${name}`);
|
|
60
|
+
if (exp && (!earliest || exp < earliest)) {
|
|
61
|
+
earliest = exp;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return earliest;
|
|
65
|
+
}
|
|
66
|
+
set(hostname, name, value) {
|
|
67
|
+
if (!this.#store.has(hostname)) {
|
|
68
|
+
this.#store.set(hostname, new Map());
|
|
69
|
+
}
|
|
70
|
+
this.#store.get(hostname).set(name, value);
|
|
71
|
+
}
|
|
72
|
+
header(url) {
|
|
73
|
+
const host = new URL(url).hostname;
|
|
74
|
+
const cookies = [];
|
|
75
|
+
for (const [h, jar] of this.#store) {
|
|
76
|
+
if (host === h || host.endsWith(`.${h}`)) {
|
|
77
|
+
for (const [k, v] of jar) {
|
|
78
|
+
cookies.push(`${k}=${v}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return cookies.length ? cookies.join('; ') : null;
|
|
83
|
+
}
|
|
84
|
+
forHost(url) {
|
|
85
|
+
return Object.fromEntries(this.#store.get(new URL(url).hostname) ?? []);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function _rawRequest(url, { method = 'GET', headers = {}, body } = {}) {
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
const u = new URL(url);
|
|
91
|
+
if (u.protocol !== 'https:') {
|
|
92
|
+
reject(new Error(`Insecure protocol rejected: ${u.protocol} — only https: is allowed`));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const port = u.port ? Number(u.port) : 443;
|
|
96
|
+
const req = https.request({ method, hostname: u.hostname, port, path: u.pathname + u.search, headers }, res => {
|
|
97
|
+
const chunks = [];
|
|
98
|
+
let received = 0;
|
|
99
|
+
let destroyed = false;
|
|
100
|
+
res.on('data', (c) => {
|
|
101
|
+
received += c.byteLength;
|
|
102
|
+
if (received > MAX_RESPONSE_BYTES) {
|
|
103
|
+
destroyed = true;
|
|
104
|
+
res.destroy();
|
|
105
|
+
req.destroy();
|
|
106
|
+
reject(new Error(`Response exceeded ${MAX_RESPONSE_BYTES / (1024 * 1024)} MB limit`));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
chunks.push(c);
|
|
110
|
+
});
|
|
111
|
+
res.on('end', () => {
|
|
112
|
+
if (destroyed) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
resolve({
|
|
116
|
+
status: res.statusCode ?? 500,
|
|
117
|
+
headers: res.headers,
|
|
118
|
+
text: () => Buffer.concat(chunks).toString(),
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
req.on('error', reject);
|
|
123
|
+
req.setTimeout(15000, () => {
|
|
124
|
+
req.destroy();
|
|
125
|
+
reject(new Error('Request timed out'));
|
|
126
|
+
});
|
|
127
|
+
if (body) {
|
|
128
|
+
req.write(body);
|
|
129
|
+
}
|
|
130
|
+
req.end();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function _htmlDecode(str) {
|
|
134
|
+
return str
|
|
135
|
+
.replace(/&/g, '&')
|
|
136
|
+
.replace(/</g, '<')
|
|
137
|
+
.replace(/>/g, '>')
|
|
138
|
+
.replace(/"/g, '"')
|
|
139
|
+
.replace(/&#x([0-9a-f]+);/gi, (_, h) => String.fromCodePoint(parseInt(h, 16)))
|
|
140
|
+
.replace(/&#(\d+);/g, (_, d) => String.fromCodePoint(parseInt(d, 10)));
|
|
141
|
+
}
|
|
142
|
+
function _parseLoginForm(html, baseUrl) {
|
|
143
|
+
const actionMatch = /action=["']([^"']+)["']/i.exec(html);
|
|
144
|
+
if (!actionMatch) {
|
|
145
|
+
throw new Error('No login form found in IAS page.');
|
|
146
|
+
}
|
|
147
|
+
const action = new URL(_htmlDecode(actionMatch[1]), baseUrl).toString();
|
|
148
|
+
const fields = {};
|
|
149
|
+
let m;
|
|
150
|
+
const re = /<input([^>]*)>/gi;
|
|
151
|
+
while ((m = re.exec(html)) !== null) {
|
|
152
|
+
const a = m[1];
|
|
153
|
+
const name = /name=["']([^"']+)["']/i.exec(a)?.[1];
|
|
154
|
+
const value = /value=["']([^"']*)["']/i.exec(a)?.[1] ?? '';
|
|
155
|
+
const type = /type=["']([^"']+)["']/i.exec(a)?.[1]?.toLowerCase() ?? 'text';
|
|
156
|
+
if (name && type !== 'submit' && type !== 'button') {
|
|
157
|
+
fields[name] = _htmlDecode(value);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { action, fields };
|
|
161
|
+
}
|
|
162
|
+
async function _followRedirects(startUrl, { method = 'GET', headers = {}, body } = {}, cookieJar, maxHops = 10, allowedOrigins) {
|
|
163
|
+
let url = startUrl;
|
|
164
|
+
let currentMethod = method;
|
|
165
|
+
let currentBody = body ?? null;
|
|
166
|
+
const currentHeaders = { ...headers };
|
|
167
|
+
for (let i = 0; i < maxHops; i++) {
|
|
168
|
+
const cookieHeader = cookieJar.header(url);
|
|
169
|
+
const reqHeaders = {
|
|
170
|
+
...currentHeaders,
|
|
171
|
+
'User-Agent': 'Mozilla/5.0 (compatible; joule-studio-dev-cli)',
|
|
172
|
+
...(cookieHeader && { Cookie: cookieHeader }),
|
|
173
|
+
};
|
|
174
|
+
const res = await _rawRequest(url, { method: currentMethod, headers: reqHeaders, body: currentBody });
|
|
175
|
+
cookieJar.update(res.headers, url);
|
|
176
|
+
if (res.status >= 300 && res.status < 400) {
|
|
177
|
+
const loc = res.headers.location;
|
|
178
|
+
if (!loc) {
|
|
179
|
+
throw new Error('Redirect with no Location header.');
|
|
180
|
+
}
|
|
181
|
+
const nextUrl = new URL(Array.isArray(loc) ? loc[0] : loc, url).toString();
|
|
182
|
+
if (allowedOrigins && !allowedOrigins.has(new URL(nextUrl).origin)) {
|
|
183
|
+
throw new Error(`Redirect to disallowed origin blocked: ${new URL(nextUrl).origin}`);
|
|
184
|
+
}
|
|
185
|
+
url = nextUrl;
|
|
186
|
+
currentMethod = 'GET';
|
|
187
|
+
currentBody = null;
|
|
188
|
+
delete currentHeaders['Content-Type'];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return { status: res.status, body: res.text(), finalUrl: url };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
throw new Error('Too many redirects during login.');
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Headless OAuth login: submits credentials directly to the IAS form,
|
|
198
|
+
* follows the redirect chain through the AppRouter callback, and returns
|
|
199
|
+
* the session cookies set by the backend.
|
|
200
|
+
*/
|
|
201
|
+
export async function headlessLogin(backendUrl, username, password) {
|
|
202
|
+
const url = _normalize(backendUrl);
|
|
203
|
+
if (new URL(url).protocol !== 'https:') {
|
|
204
|
+
throw new CliError('AUTH_INSECURE_URL', `Backend URL must use HTTPS: ${backendUrl}`);
|
|
205
|
+
}
|
|
206
|
+
const cookieJar = new _CookieJar();
|
|
207
|
+
// Step 1: Hit the backend to trigger the AppRouter's OAuth initiation.
|
|
208
|
+
// The response is an HTML page whose JS sets cookies (signature, locationAfterLogin,
|
|
209
|
+
// fragmentAfterLogin) and then redirects to IAS. We use _rawRequest so HTTP cookies
|
|
210
|
+
// from the AppRouter are captured, and we manually simulate the JS cookie assignments.
|
|
211
|
+
let authorizeUrl = null;
|
|
212
|
+
for (const p of ['/', '/destinations/', '/api/', '/api/v1/']) {
|
|
213
|
+
const targetUrl = `${url}${p}`;
|
|
214
|
+
const ck = cookieJar.header(targetUrl);
|
|
215
|
+
const res = await _rawRequest(targetUrl, {
|
|
216
|
+
headers: {
|
|
217
|
+
'Accept': 'text/html',
|
|
218
|
+
'User-Agent': 'Mozilla/5.0 (compatible; joule-studio-dev-cli)',
|
|
219
|
+
...(ck && { Cookie: ck }),
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
cookieJar.update(res.headers, targetUrl);
|
|
223
|
+
const body = res.text();
|
|
224
|
+
const match = JS_REDIRECT_RE.exec(body);
|
|
225
|
+
if (!match) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
authorizeUrl = match[1];
|
|
229
|
+
// Simulate the document.cookie assignments that the browser JS would execute.
|
|
230
|
+
// The AppRouter embeds a signed 'signature' token in the page for CSRF protection.
|
|
231
|
+
const backendHost = new URL(url).hostname;
|
|
232
|
+
const sigMatch = /document\.cookie="signature=([^";]+)/.exec(body);
|
|
233
|
+
if (sigMatch) {
|
|
234
|
+
cookieJar.set(backendHost, 'signature', sigMatch[1]);
|
|
235
|
+
}
|
|
236
|
+
cookieJar.set(backendHost, 'locationAfterLogin', encodeURIComponent(new URL(targetUrl).pathname));
|
|
237
|
+
cookieJar.set(backendHost, 'fragmentAfterLogin', '');
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
if (!authorizeUrl) {
|
|
241
|
+
throw new Error(`Could not trigger OAuth flow from ${url}`);
|
|
242
|
+
}
|
|
243
|
+
const iasOrigin = new URL(authorizeUrl).origin;
|
|
244
|
+
// Step 2: GET the IAS username form (also captures XSRF cookies)
|
|
245
|
+
const r1 = await _rawRequest(authorizeUrl, {
|
|
246
|
+
headers: { 'Accept': 'text/html', 'User-Agent': 'Mozilla/5.0 (compatible; joule-studio-dev-cli)' },
|
|
247
|
+
});
|
|
248
|
+
cookieJar.update(r1.headers, authorizeUrl);
|
|
249
|
+
if (r1.status !== 200) {
|
|
250
|
+
throw new Error(`IAS login page returned ${r1.status}.`);
|
|
251
|
+
}
|
|
252
|
+
const { action: action1, fields: fields1 } = _parseLoginForm(r1.text(), iasOrigin);
|
|
253
|
+
fields1.j_username = username;
|
|
254
|
+
// Step 3: Submit username — IAS returns the password form (two-step login)
|
|
255
|
+
const { status: s2, body: b2 } = await _followRedirects(action1, {
|
|
256
|
+
method: 'POST',
|
|
257
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/html' },
|
|
258
|
+
body: new URLSearchParams(fields1).toString(),
|
|
259
|
+
}, cookieJar, 5, new Set([iasOrigin]));
|
|
260
|
+
if (s2 !== 200) {
|
|
261
|
+
throw new Error(`Unexpected status ${s2} after username submission.`);
|
|
262
|
+
}
|
|
263
|
+
if (!b2.includes('j_password')) {
|
|
264
|
+
throw new Error('Password field not found — login flow may have changed.');
|
|
265
|
+
}
|
|
266
|
+
// Step 4: Parse password form and submit credentials
|
|
267
|
+
const { action: action2, fields: fields2 } = _parseLoginForm(b2, iasOrigin);
|
|
268
|
+
fields2.j_username = username;
|
|
269
|
+
fields2.j_password = password;
|
|
270
|
+
// Step 5: Follow the full redirect chain:
|
|
271
|
+
// IAS → 302 → AppRouter /login/callback?code=... (sends signature cookie) → 302 → 200
|
|
272
|
+
await _followRedirects(action2, {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'text/html' },
|
|
275
|
+
body: new URLSearchParams(fields2).toString(),
|
|
276
|
+
}, cookieJar, 10, new Set([iasOrigin, new URL(url).origin]));
|
|
277
|
+
// Step 6: Extract the backend session cookies, filtering out the init cookies we set manually
|
|
278
|
+
const sessionCookies = cookieJar.forHost(url);
|
|
279
|
+
const initKeys = new Set(['signature', 'locationAfterLogin', 'fragmentAfterLogin']);
|
|
280
|
+
const realSession = Object.fromEntries(Object.entries(sessionCookies).filter(([k]) => !initKeys.has(k)));
|
|
281
|
+
if (!Object.keys(realSession).length) {
|
|
282
|
+
throw new Error('Login failed: no session received. Check your credentials.');
|
|
283
|
+
}
|
|
284
|
+
return { cookies: realSession, expiresAt: cookieJar.expiryFor(url, Object.keys(realSession)) };
|
|
285
|
+
}
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
export function saveCookies(backendUrl, cookies, expiresAt) {
|
|
288
|
+
const all = _load();
|
|
289
|
+
const key = _normalize(backendUrl);
|
|
290
|
+
delete all[key];
|
|
291
|
+
all[key] = {
|
|
292
|
+
cookies,
|
|
293
|
+
loggedInAt: Date.now(),
|
|
294
|
+
...(expiresAt !== null && typeof expiresAt !== 'undefined' && { expiresAt }),
|
|
295
|
+
};
|
|
296
|
+
_persist(all);
|
|
297
|
+
}
|
|
298
|
+
export function getStoredUrl() {
|
|
299
|
+
return Object.keys(_load()).at(-1) ?? null;
|
|
300
|
+
}
|
|
301
|
+
export function getAuthHeaders(backendUrl) {
|
|
302
|
+
const creds = _loadCreds(backendUrl);
|
|
303
|
+
if (!creds) {
|
|
304
|
+
return {};
|
|
305
|
+
}
|
|
306
|
+
if (creds.cookies) {
|
|
307
|
+
return {
|
|
308
|
+
Cookie: Object.entries(creds.cookies)
|
|
309
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
310
|
+
.join('; '),
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
if (creds.token) {
|
|
314
|
+
return { Authorization: `Bearer ${creds.token}` };
|
|
315
|
+
}
|
|
316
|
+
return {};
|
|
317
|
+
}
|
|
318
|
+
export function isSessionExpired(backendUrl) {
|
|
319
|
+
const creds = _loadCreds(backendUrl);
|
|
320
|
+
if (!creds?.expiresAt) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return Date.now() > creds.expiresAt;
|
|
324
|
+
}
|
|
325
|
+
export function loadCredentials(backendUrl) {
|
|
326
|
+
const entry = _load()[_normalize(backendUrl)] ?? null;
|
|
327
|
+
if (!entry || (!entry.cookies && !entry.token))
|
|
328
|
+
return null;
|
|
329
|
+
return entry;
|
|
330
|
+
}
|
|
331
|
+
function _loadCreds(backendUrl) {
|
|
332
|
+
const url = _normalize(backendUrl);
|
|
333
|
+
return loadCredentials(url) ?? loadCredentials(new URL(url).origin);
|
|
334
|
+
}
|
|
335
|
+
function _headersToRecord(h) {
|
|
336
|
+
if (!h) {
|
|
337
|
+
return {};
|
|
338
|
+
}
|
|
339
|
+
if (h instanceof Headers) {
|
|
340
|
+
const out = {};
|
|
341
|
+
h.forEach((v, k) => {
|
|
342
|
+
out[k] = v;
|
|
343
|
+
});
|
|
344
|
+
return out;
|
|
345
|
+
}
|
|
346
|
+
if (Array.isArray(h)) {
|
|
347
|
+
return Object.fromEntries(h);
|
|
348
|
+
}
|
|
349
|
+
return h;
|
|
350
|
+
}
|
|
351
|
+
export async function authorizedFetch(urlPath, init = {}) {
|
|
352
|
+
const backendUrl = getStoredUrl();
|
|
353
|
+
if (!backendUrl || !loadCredentials(backendUrl)) {
|
|
354
|
+
throw new CliError('AUTH_NOT_LOGGED_IN', 'Not logged in. Run: jl login <url>');
|
|
355
|
+
}
|
|
356
|
+
if (new URL(backendUrl).protocol !== 'https:') {
|
|
357
|
+
throw new CliError('AUTH_INSECURE_URL', `Backend URL must use HTTPS: ${backendUrl}`);
|
|
358
|
+
}
|
|
359
|
+
if (isSessionExpired(backendUrl)) {
|
|
360
|
+
throw new CliError('AUTH_SESSION_EXPIRED', 'Session expired. Run: jl login');
|
|
361
|
+
}
|
|
362
|
+
const controller = new AbortController();
|
|
363
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
364
|
+
const signal = init.signal ? AbortSignal.any([init.signal, controller.signal]) : controller.signal;
|
|
365
|
+
const res = await fetch(`${backendUrl}${urlPath}`, {
|
|
366
|
+
...init,
|
|
367
|
+
signal,
|
|
368
|
+
redirect: 'manual',
|
|
369
|
+
headers: { ...getAuthHeaders(backendUrl), ..._headersToRecord(init.headers) },
|
|
370
|
+
}).finally(() => clearTimeout(timer));
|
|
371
|
+
if (res.status >= 300 && res.status < 400) {
|
|
372
|
+
throw new CliError('AUTH_SESSION_EXPIRED', 'Session no longer active. Run: jl login');
|
|
373
|
+
}
|
|
374
|
+
if (res.status === 401) {
|
|
375
|
+
throw new CliError('AUTH_UNAUTHORIZED', 'Unauthorized. Run: jl login');
|
|
376
|
+
}
|
|
377
|
+
const ct = res.headers.get('content-type') ?? '';
|
|
378
|
+
if (ct.includes('text/html')) {
|
|
379
|
+
throw new CliError('AUTH_SESSION_EXPIRED', 'Session no longer active. Run: jl login');
|
|
380
|
+
}
|
|
381
|
+
_refreshStoredCookies(backendUrl, res.headers);
|
|
382
|
+
return res;
|
|
383
|
+
}
|
|
384
|
+
function _refreshStoredCookies(backendUrl, headers) {
|
|
385
|
+
const setCookies = headers.getSetCookie?.() ?? [];
|
|
386
|
+
if (!setCookies.length) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const creds = _loadCreds(backendUrl);
|
|
390
|
+
if (!creds?.cookies) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const updatedCookies = { ...creds.cookies };
|
|
394
|
+
let newExpiry = creds.expiresAt ?? null;
|
|
395
|
+
for (const raw of setCookies) {
|
|
396
|
+
const [nameVal, ...attrs] = raw.split(';');
|
|
397
|
+
const eq = nameVal.indexOf('=');
|
|
398
|
+
if (eq < 0) {
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
updatedCookies[nameVal.slice(0, eq).trim()] = nameVal.slice(eq + 1).trim();
|
|
402
|
+
const maxAge = attrs.find(a => /^\s*max-age\s*=/i.test(a));
|
|
403
|
+
const expires = attrs.find(a => /^\s*expires\s*=/i.test(a));
|
|
404
|
+
if (maxAge) {
|
|
405
|
+
const s = parseInt(maxAge.split('=')[1], 10);
|
|
406
|
+
if (!Number.isNaN(s) && s > 0) {
|
|
407
|
+
newExpiry = Date.now() + s * 1000;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else if (expires) {
|
|
411
|
+
const ms = new Date(expires.split('=').slice(1).join('=').trim()).getTime();
|
|
412
|
+
if (!Number.isNaN(ms)) {
|
|
413
|
+
newExpiry = ms;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
saveCookies(backendUrl, updatedCookies, newExpiry);
|
|
418
|
+
}
|
|
419
|
+
export async function serverLogout(backendUrl) {
|
|
420
|
+
const url = _normalize(backendUrl);
|
|
421
|
+
const cookieHeader = getAuthHeaders(url).Cookie;
|
|
422
|
+
if (!cookieHeader) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
await _rawRequest(`${url}/logout`, {
|
|
426
|
+
headers: {
|
|
427
|
+
'Cookie': cookieHeader,
|
|
428
|
+
'User-Agent': 'Mozilla/5.0 (compatible; joule-studio-dev-cli)',
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
export function deleteCredentials(backendUrl) {
|
|
433
|
+
const all = _load();
|
|
434
|
+
const key = _normalize(backendUrl);
|
|
435
|
+
// Keep the key as an empty stub so getStoredUrl() still returns this as the last-used URL.
|
|
436
|
+
// Delete and re-insert to move it to the end (MRU position).
|
|
437
|
+
delete all[key];
|
|
438
|
+
all[key] = {};
|
|
439
|
+
_persist(all);
|
|
440
|
+
}
|
|
441
|
+
function _load() {
|
|
442
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
443
|
+
return {};
|
|
444
|
+
}
|
|
445
|
+
try {
|
|
446
|
+
const raw = readFileSync(CREDENTIALS_FILE, 'utf8').trim();
|
|
447
|
+
// Encrypted format: "ivB64.tagB64.ctB64" — does not start with '{'
|
|
448
|
+
if (!raw.startsWith('{')) {
|
|
449
|
+
const plaintext = decrypt(raw);
|
|
450
|
+
if (!plaintext) {
|
|
451
|
+
process.stderr.write(`${term.yellow('!')} credentials file could not be decrypted — run: jl login\n`);
|
|
452
|
+
return {};
|
|
453
|
+
}
|
|
454
|
+
try {
|
|
455
|
+
return JSON.parse(plaintext);
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
process.stderr.write(`${term.yellow('!')} credentials file is corrupted — run: jl login\n`);
|
|
459
|
+
return {};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// Plaintext JSON (pre-encryption): migrate transparently by re-persisting encrypted
|
|
463
|
+
const data = JSON.parse(raw);
|
|
464
|
+
try {
|
|
465
|
+
_persist(data);
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
/* best-effort migration; credentials still returned */
|
|
469
|
+
}
|
|
470
|
+
return data;
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
process.stderr.write(`${term.yellow('!')} credentials file is corrupted — run: jl login\n`);
|
|
474
|
+
return {};
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function _persist(data) {
|
|
478
|
+
mkdirSync(JOULEWORK_DIR, { recursive: true });
|
|
479
|
+
writeFileSync(CREDENTIALS_FILE, encrypt(JSON.stringify(data)));
|
|
480
|
+
if (process.platform !== 'win32') {
|
|
481
|
+
chmodSync(CREDENTIALS_FILE, 0o600);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
function _normalize(url) {
|
|
485
|
+
const normalized = url.startsWith('http') ? url : 'https://' + url;
|
|
486
|
+
return normalized.replace(/\/+$/, '');
|
|
487
|
+
}
|
|
488
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../lib/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const BUILD_FILE = '.build';
|
|
4
|
+
function buildPath(cwd = process.cwd()) {
|
|
5
|
+
return path.join(cwd, BUILD_FILE);
|
|
6
|
+
}
|
|
7
|
+
/** Read all key=value pairs from .build. Lines starting with # are ignored. */
|
|
8
|
+
export function get(cwd = process.cwd()) {
|
|
9
|
+
const file = buildPath(cwd);
|
|
10
|
+
if (!fs.existsSync(file))
|
|
11
|
+
return {};
|
|
12
|
+
const result = {};
|
|
13
|
+
for (const line of fs.readFileSync(file, 'utf8').split(/\r?\n/)) {
|
|
14
|
+
const trimmed = line.trim();
|
|
15
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
16
|
+
continue;
|
|
17
|
+
const eq = trimmed.indexOf('=');
|
|
18
|
+
if (eq < 1)
|
|
19
|
+
continue;
|
|
20
|
+
result[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim();
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
/** Add or update a single key in .build. */
|
|
25
|
+
export function set(key, value, cwd = process.cwd()) {
|
|
26
|
+
const file = buildPath(cwd);
|
|
27
|
+
const existing = fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : '';
|
|
28
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
29
|
+
const re = new RegExp(`^(${escapedKey}=)[^\\r\\n]*`, 'm');
|
|
30
|
+
const updated = re.test(existing)
|
|
31
|
+
? existing.replace(re, `$1${value}`)
|
|
32
|
+
: existing + (existing.endsWith('\n') || existing === '' ? '' : '\n') + `${key}=${value}\n`;
|
|
33
|
+
fs.writeFileSync(file, updated, 'utf8');
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../lib/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,UAAU,GAAG,QAAQ,CAAA;AAE3B,SAAS,SAAS,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;AACrC,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACnC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAQ;QACjD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,EAAE,GAAG,CAAC;YAAE,SAAQ;QACpB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IACtE,CAAC;IACD,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC/D,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;IAC3B,MAAM,QAAQ,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACzE,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;IAC7D,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,UAAU,cAAc,EAAE,GAAG,CAAC,CAAA;IACzD,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;QAC7B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACpC,CAAC,CAAC,QAAQ,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/F,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Add codes here as throw sites are migrated from plain strings to CliError.
|
|
2
|
+
// Convention: <DOMAIN>_<REASON> in SCREAMING_SNAKE_CASE.
|
|
3
|
+
// Examples:
|
|
4
|
+
// 'AUTH_REQUIRED'
|
|
5
|
+
// 'SOLUTION_NOT_FOUND'
|
|
6
|
+
// 'DEPLOY_FAILED'
|
|
7
|
+
// 'ASSET_NAME_INVALID'
|
|
8
|
+
// 'UNKNOWN'
|
|
9
|
+
export const CLI_ERROR_CODES = [
|
|
10
|
+
'AUTH_URL_REQUIRED',
|
|
11
|
+
'AUTH_NOT_LOGGED_IN',
|
|
12
|
+
'AUTH_SESSION_EXPIRED',
|
|
13
|
+
'AUTH_UNAUTHORIZED',
|
|
14
|
+
'AUTH_INSECURE_URL',
|
|
15
|
+
'ASSET_NAME_INVALID',
|
|
16
|
+
'MCP_NO_TOOLS',
|
|
17
|
+
'INVALID_PARAM',
|
|
18
|
+
'MCP_SERVER_NOT_FOUND',
|
|
19
|
+
'MCP_TOOL_NOT_FOUND',
|
|
20
|
+
'MCP_USAGE_ERROR',
|
|
21
|
+
'MCP_INVALID_RESPONSE',
|
|
22
|
+
'MCP_SERVER_ERROR',
|
|
23
|
+
'SKILLS_FETCH_FAILED',
|
|
24
|
+
'A2A_MISSING_SOLUTION',
|
|
25
|
+
'A2A_MISSING_ASSET',
|
|
26
|
+
'A2A_NO_PREVIOUS_CONTEXT',
|
|
27
|
+
'A2A_REQUEST_FAILED',
|
|
28
|
+
'SOLUTION_BUILD_FILE_MISSING',
|
|
29
|
+
'SOLUTION_BUILD_FILE_INVALID',
|
|
30
|
+
'SOLUTION_YAML_PARSE_ERROR',
|
|
31
|
+
'SOLUTION_BUILD_FAILED',
|
|
32
|
+
];
|
|
33
|
+
export class CliError extends Error {
|
|
34
|
+
code;
|
|
35
|
+
constructor(code, message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = 'CliError';
|
|
38
|
+
this.code = code;
|
|
39
|
+
if (Error.captureStackTrace) {
|
|
40
|
+
Error.captureStackTrace(this, CliError);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
static isCliError(err) {
|
|
44
|
+
return err instanceof CliError;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../lib/errors.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,yDAAyD;AACzD,YAAY;AACZ,oBAAoB;AACpB,yBAAyB;AACzB,oBAAoB;AACpB,yBAAyB;AACzB,cAAc;AACd,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,mBAAmB;IACnB,oBAAoB;IACpB,sBAAsB;IACtB,mBAAmB;IACnB,mBAAmB;IACnB,oBAAoB;IACpB,cAAc;IACd,eAAe;IACf,sBAAsB;IACtB,oBAAoB;IACpB,iBAAiB;IACjB,sBAAsB;IACtB,kBAAkB;IAClB,qBAAqB;IACrB,sBAAsB;IACtB,mBAAmB;IACnB,yBAAyB;IACzB,oBAAoB;IACpB,6BAA6B;IAC7B,6BAA6B;IAC7B,2BAA2B;IAC3B,uBAAuB;CACjB,CAAA;AAIV,MAAM,OAAO,QAAS,SAAQ,KAAK;IACtB,IAAI,CAAc;IAE3B,YAAY,IAAkB,EAAE,OAAe;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,UAAU,CAAA;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC1B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC3C,CAAC;IACL,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,GAAY;QAC1B,OAAO,GAAG,YAAY,QAAQ,CAAA;IAClC,CAAC;CACJ"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export default {
|
|
4
|
+
mkdirp(dirPath) {
|
|
5
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
6
|
+
},
|
|
7
|
+
exists(filePath) {
|
|
8
|
+
return fs.existsSync(filePath);
|
|
9
|
+
},
|
|
10
|
+
isDir(filePath) {
|
|
11
|
+
try {
|
|
12
|
+
return fs.statSync(filePath).isDirectory();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
readFile(filePath) {
|
|
19
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
20
|
+
},
|
|
21
|
+
writeFile(filePath, content) {
|
|
22
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
23
|
+
fs.writeFileSync(filePath, content, 'utf8');
|
|
24
|
+
},
|
|
25
|
+
copyFile(src, dst) {
|
|
26
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
27
|
+
fs.copyFileSync(src, dst);
|
|
28
|
+
},
|
|
29
|
+
rmSync(filePath, options) {
|
|
30
|
+
fs.rmSync(filePath, options);
|
|
31
|
+
},
|
|
32
|
+
readdirSync: fs.readdirSync.bind(fs),
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=fs-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../lib/fs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,eAAe;IACX,MAAM,CAAC,OAAe;QAClB,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9C,CAAC;IAED,MAAM,CAAC,QAAgB;QACnB,OAAO,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;IAED,KAAK,CAAC,QAAgB;QAClB,IAAI,CAAC;YACD,OAAO,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAA;QAChB,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,QAAgB;QACrB,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED,SAAS,CAAC,QAAgB,EAAE,OAAe;QACvC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACzD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;IAC/C,CAAC;IAED,QAAQ,CAAC,GAAW,EAAE,GAAW;QAC7B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACpD,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,MAAM,CAAC,QAAgB,EAAE,OAAsB;QAC3C,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAChC,CAAC;IAED,WAAW,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;CACvC,CAAA"}
|