@intuned/runtime 1.3.16 → 1.3.17
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/InterfaceTemplate/index.playwright.ts +1 -1
- package/WebTemplate.zip +0 -0
- package/dist/commands/api/run.js +4 -8
- package/dist/commands/auth-sessions/load.js +2 -2
- package/dist/commands/auth-sessions/run-check.js +5 -5
- package/dist/commands/auth-sessions/run-create.js +3 -3
- package/dist/commands/build.js +1 -1
- package/dist/commands/common/projectExclusions.js +1 -1
- package/dist/commands/common/tsNodeImport.js +9 -0
- package/dist/commands/interface/run.js +1 -1
- package/dist/commands/intuned-cli/commands/attempt_api.command.js +1 -1
- package/dist/commands/intuned-cli/commands/attempt_authsession.command.js +1 -1
- package/dist/commands/intuned-cli/commands/attempt_authsession_check.command.js +2 -2
- package/dist/commands/intuned-cli/commands/attempt_authsession_create.command.js +1 -1
- package/dist/commands/intuned-cli/commands/authsession.command.js +1 -1
- package/dist/commands/intuned-cli/commands/authsession_record.command.js +1 -1
- package/dist/commands/intuned-cli/commands/authsession_scaffold.command.d.ts +1 -0
- package/dist/commands/intuned-cli/commands/authsession_scaffold.command.js +16 -0
- package/dist/commands/intuned-cli/commands/deploy.command.js +13 -9
- package/dist/commands/intuned-cli/commands/index.d.ts +2 -2
- package/dist/commands/intuned-cli/commands/index.js +15 -15
- package/dist/commands/intuned-cli/commands/{save.command.d.ts → provision.command.d.ts} +1 -1
- package/dist/commands/intuned-cli/commands/provision.command.js +50 -0
- package/dist/commands/intuned-cli/commands/run_api.command.js +1 -1
- package/dist/commands/intuned-cli/commands/run_authsession.command.js +2 -2
- package/dist/commands/intuned-cli/commands/run_authsession_create.command.js +1 -1
- package/dist/commands/intuned-cli/commands/run_authsession_update.command.js +2 -2
- package/dist/commands/intuned-cli/commands/run_authsession_validate.command.js +2 -2
- package/dist/commands/intuned-cli/commands/types.js +2 -2
- package/dist/commands/intuned-cli/controller/__test__/api.test.js +6 -5
- package/dist/commands/intuned-cli/controller/__test__/authSession.test.js +12 -11
- package/dist/commands/intuned-cli/controller/api.js +4 -1
- package/dist/commands/intuned-cli/controller/authSession.js +28 -28
- package/dist/commands/intuned-cli/controller/deploy.js +52 -10
- package/dist/commands/intuned-cli/controller/index.js +1 -1
- package/dist/commands/intuned-cli/controller/{save.d.ts → provision.d.ts} +5 -1
- package/dist/commands/intuned-cli/controller/provision.js +300 -0
- package/dist/commands/intuned-cli/controller/scaffold.d.ts +1 -0
- package/dist/commands/intuned-cli/controller/scaffold.js +77 -0
- package/dist/commands/intuned-cli/helpers/__test__/browser.test.js +1 -0
- package/dist/commands/intuned-cli/helpers/__test__/tracing.test.js +1 -0
- package/dist/commands/intuned-cli/helpers/api.js +4 -7
- package/dist/commands/intuned-cli/helpers/auth.js +22 -19
- package/dist/commands/intuned-cli/helpers/backend.js +12 -4
- package/dist/commands/intuned-cli/helpers/context.js +2 -2
- package/dist/commands/intuned-cli/helpers/prompts.d.ts +3 -0
- package/dist/commands/intuned-cli/helpers/prompts.js +71 -0
- package/dist/commands/intuned-cli/helpers/wrapper.js +12 -2
- package/dist/commands/intuned-cli/main.js +21 -8
- package/dist/commands/intuned-cli/types.d.ts +42 -13
- package/dist/commands/intuned-cli/types.js +12 -2
- package/dist/common/backendFunctions/getAuthSessionParameters.js +1 -1
- package/dist/common/intunedJson.js +2 -2
- package/dist/common/jwtTokenManager.js +2 -2
- package/dist/common/launchBrowser.d.ts +2 -0
- package/dist/common/launchBrowser.js +28 -0
- package/dist/common/playwrightContext.js +7 -1
- package/dist/common/runApi/errors.js +1 -1
- package/dist/common/runApi/index.js +2 -2
- package/package.json +4 -2
- package/dist/commands/intuned-cli/commands/init.command.d.ts +0 -1
- package/dist/commands/intuned-cli/commands/init.command.js +0 -13
- package/dist/commands/intuned-cli/commands/save.command.js +0 -42
- package/dist/commands/intuned-cli/controller/save.js +0 -351
- /package/InterfaceTemplate/{utils.ts → __utils.ts} +0 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.projectNameSchema = void 0;
|
|
7
|
+
exports.runProvisionProject = runProvisionProject;
|
|
8
|
+
exports.validateProjectName = exports.validateIntunedProject = void 0;
|
|
9
|
+
var fs = _interopRequireWildcard(require("fs-extra"));
|
|
10
|
+
var path = _interopRequireWildcard(require("path"));
|
|
11
|
+
var _zod = require("zod");
|
|
12
|
+
var _projectExclusions = _interopRequireDefault(require("../../common/projectExclusions"));
|
|
13
|
+
var _constants = require("../constants");
|
|
14
|
+
var _helpers = require("../helpers");
|
|
15
|
+
var _terminal = require("../helpers/terminal");
|
|
16
|
+
var _build = require("./build");
|
|
17
|
+
var dotenv = _interopRequireWildcard(require("dotenv"));
|
|
18
|
+
var _constants2 = require("../../../common/constants");
|
|
19
|
+
var _ignore = _interopRequireDefault(require("ignore"));
|
|
20
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
22
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
23
|
+
const provisionProjectApiResponseSchema = _zod.z.string().transform((val, ctx) => {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(val);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
ctx.addIssue({
|
|
28
|
+
code: _zod.z.ZodIssueCode.custom,
|
|
29
|
+
message: "Response is not valid JSON"
|
|
30
|
+
});
|
|
31
|
+
return _zod.z.NEVER;
|
|
32
|
+
}
|
|
33
|
+
}).pipe(_zod.z.object({
|
|
34
|
+
id: _zod.z.string().uuid(),
|
|
35
|
+
enableFirstRunExperience: _zod.z.boolean().optional(),
|
|
36
|
+
environmentVariablesKeys: _zod.z.array(_zod.z.string()).default([]).catch(() => [])
|
|
37
|
+
}));
|
|
38
|
+
async function runProvisionProject(projectName, auth, silent = false) {
|
|
39
|
+
const {
|
|
40
|
+
workspaceId,
|
|
41
|
+
apiKey
|
|
42
|
+
} = auth;
|
|
43
|
+
const baseUrl = (0, _helpers.getBaseUrl)();
|
|
44
|
+
const url = `${baseUrl}/api/v1/workspace/${workspaceId}/projects/${projectName}`;
|
|
45
|
+
const headers = {
|
|
46
|
+
[_constants2.API_KEY_HEADER_NAME]: apiKey,
|
|
47
|
+
"Content-Type": "application/json"
|
|
48
|
+
};
|
|
49
|
+
const projectPath = process.cwd();
|
|
50
|
+
const codeTree = await convertProjectToCodeTree(projectPath);
|
|
51
|
+
const intunedSettingsFile = await (0, _helpers.getIntunedSettingsFile)();
|
|
52
|
+
codeTree["Intuned.json"] = {
|
|
53
|
+
file: {
|
|
54
|
+
contents: JSON.stringify(intunedSettingsFile.parse(await fs.readFile(intunedSettingsFile.path, "utf-8")))
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
codeTree["tsconfig.json"] = {
|
|
58
|
+
file: {
|
|
59
|
+
contents: JSON.stringify(_constants.tsConfigCli, null, 2)
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const upsertProjectPayload = {
|
|
63
|
+
codeTree,
|
|
64
|
+
platformType: "CLI",
|
|
65
|
+
language: "typescript"
|
|
66
|
+
};
|
|
67
|
+
const response = await fetch(url, {
|
|
68
|
+
headers,
|
|
69
|
+
method: "PUT",
|
|
70
|
+
body: JSON.stringify(upsertProjectPayload)
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
if (response.status === 401) {
|
|
74
|
+
throw new _helpers.CLIError(`Invalid API key. The provided API key is not authorized to access this workspace.\n` + `Please verify your API key at: https://app.intuned.io/settings/api-keys`);
|
|
75
|
+
}
|
|
76
|
+
throw new _helpers.CLIError(`^r^+Project provisioning failed:^:\n` + `^RServer returned status ${response.status}^:\n` + `^RResponse: ${await response.text()}^:\n\n` + `^yCommon causes:^:\n` + ` • Invalid workspace ID or project name\n` + ` • Insufficient permissions\n` + ` • Network connectivity issues\n` + ` • Project structure validation errors\n`, {
|
|
77
|
+
autoColor: false
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (!silent) {
|
|
81
|
+
(0, _terminal.terminal)("^g^+Project provisioned successfully!^:\n");
|
|
82
|
+
}
|
|
83
|
+
const body = await response.text();
|
|
84
|
+
const parseResult = provisionProjectApiResponseSchema.safeParse(body);
|
|
85
|
+
if (!parseResult.success) {
|
|
86
|
+
(0, _terminal.terminal)(`^yWarning: Could not parse provision project response:^:\n`);
|
|
87
|
+
(0, _terminal.terminal)(body + "\n");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const {
|
|
91
|
+
id: projectId,
|
|
92
|
+
enableFirstRunExperience,
|
|
93
|
+
environmentVariablesKeys
|
|
94
|
+
} = parseResult.data;
|
|
95
|
+
const dotEnvPath = path.join(projectPath, ".env");
|
|
96
|
+
if (!(await fs.exists(dotEnvPath))) {
|
|
97
|
+
await fs.writeFile(dotEnvPath, `${_constants2.PROJECT_ID_ENV_VAR_KEY}=${projectId}
|
|
98
|
+
${_constants2.WORKSPACE_ID_ENV_VAR_KEY}=${workspaceId}
|
|
99
|
+
${_constants2.API_KEY_ENV_VAR_KEY}=${apiKey}`);
|
|
100
|
+
(0, _terminal.terminal)(`^g^+Created .env file with project credentials.^:\n`);
|
|
101
|
+
return {
|
|
102
|
+
projectId,
|
|
103
|
+
enableFirstRunExperience,
|
|
104
|
+
environmentVariablesKeys,
|
|
105
|
+
dotenvContent: {}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const envContent = await fs.readFile(dotEnvPath, "utf-8");
|
|
109
|
+
const dotenvContent = dotenv.parse(envContent);
|
|
110
|
+
let contentToAppend = "";
|
|
111
|
+
const projectCredentialsEnvVars = {
|
|
112
|
+
[_constants2.PROJECT_ID_ENV_VAR_KEY]: projectId,
|
|
113
|
+
[_constants2.WORKSPACE_ID_ENV_VAR_KEY]: workspaceId,
|
|
114
|
+
[_constants2.API_KEY_ENV_VAR_KEY]: apiKey
|
|
115
|
+
};
|
|
116
|
+
for (const key in projectCredentialsEnvVars) {
|
|
117
|
+
if (dotenvContent[key] === projectCredentialsEnvVars[key]) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (dotenvContent[key]) {
|
|
121
|
+
(0, _terminal.terminal)(`^yWarning: Existing ${key} in .env has invalid value. Appending correct value.^:\n`);
|
|
122
|
+
}
|
|
123
|
+
contentToAppend += `${key}=${projectCredentialsEnvVars[key]}\n`;
|
|
124
|
+
}
|
|
125
|
+
if (contentToAppend) {
|
|
126
|
+
await fs.appendFile(dotEnvPath, contentToAppend + "\n");
|
|
127
|
+
(0, _terminal.terminal)(`^g^+Updated .env file with project credentials.^:\n`);
|
|
128
|
+
}
|
|
129
|
+
const dotenvContentToReturn = {
|
|
130
|
+
...dotenvContent
|
|
131
|
+
};
|
|
132
|
+
for (const key of [_constants2.PROJECT_ID_ENV_VAR_KEY, _constants2.WORKSPACE_ID_ENV_VAR_KEY, _constants2.API_KEY_ENV_VAR_KEY]) {
|
|
133
|
+
if (key in dotenvContentToReturn) {
|
|
134
|
+
delete dotenvContentToReturn[key];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
projectId,
|
|
139
|
+
enableFirstRunExperience,
|
|
140
|
+
environmentVariablesKeys,
|
|
141
|
+
dotenvContent: dotenvContentToReturn
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
const projectNameSchema = exports.projectNameSchema = _zod.z.string().min(1, "Name is required").max(200, "Must be 200 characters or less").regex(/^[a-z0-9]+(?:[-_][a-z0-9]+)*$/, "Can only contain lowercase letters, numbers, hyphens, and underscores in between").refine(value => !_zod.z.string().uuid().safeParse(value).success, {
|
|
145
|
+
message: "Cannot be a UUID"
|
|
146
|
+
});
|
|
147
|
+
const validateProjectName = projectName => {
|
|
148
|
+
const validation = projectNameSchema.safeParse(projectName);
|
|
149
|
+
if (!validation.success) {
|
|
150
|
+
return {
|
|
151
|
+
isValid: false,
|
|
152
|
+
errorMessage: validation.error.errors[0].message
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
isValid: true
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
exports.validateProjectName = validateProjectName;
|
|
160
|
+
const validateIntunedProject = async () => {
|
|
161
|
+
const currentDirectoryToProvision = process.cwd();
|
|
162
|
+
const intunedSettingsFile = await (0, _helpers.getIntunedSettingsFile)();
|
|
163
|
+
const validationSteps = [{
|
|
164
|
+
name: "build",
|
|
165
|
+
check: async () => {
|
|
166
|
+
try {
|
|
167
|
+
const buildResult = await (0, _build.runBuild)();
|
|
168
|
+
if (!buildResult) {
|
|
169
|
+
return {
|
|
170
|
+
isValid: false,
|
|
171
|
+
errorMessage: "Build failed"
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
isValid: true
|
|
176
|
+
};
|
|
177
|
+
} catch (error) {
|
|
178
|
+
return {
|
|
179
|
+
isValid: false,
|
|
180
|
+
errorMessage: "Build failed"
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}, {
|
|
185
|
+
name: intunedSettingsFile.name,
|
|
186
|
+
check: async () => {
|
|
187
|
+
try {
|
|
188
|
+
const intunedJsonPath = path.join(currentDirectoryToProvision, intunedSettingsFile.name);
|
|
189
|
+
await fs.exists(intunedJsonPath);
|
|
190
|
+
return {
|
|
191
|
+
isValid: true
|
|
192
|
+
};
|
|
193
|
+
} catch (error) {
|
|
194
|
+
return {
|
|
195
|
+
isValid: false,
|
|
196
|
+
errorMessage: `${intunedSettingsFile.name} file not found`
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}, {
|
|
201
|
+
name: "api folder",
|
|
202
|
+
check: async () => {
|
|
203
|
+
try {
|
|
204
|
+
const apiFolderPath = path.join(currentDirectoryToProvision, "api");
|
|
205
|
+
await fs.access(apiFolderPath);
|
|
206
|
+
return {
|
|
207
|
+
isValid: true
|
|
208
|
+
};
|
|
209
|
+
} catch (error) {
|
|
210
|
+
return {
|
|
211
|
+
isValid: false,
|
|
212
|
+
errorMessage: "API folder not found"
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}];
|
|
217
|
+
for (const step of validationSteps) {
|
|
218
|
+
const result = await step.check();
|
|
219
|
+
if (!result.isValid) {
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
isValid: true
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
exports.validateIntunedProject = validateIntunedProject;
|
|
228
|
+
async function convertProjectToCodeTree(projectPath) {
|
|
229
|
+
const ig = (0, _ignore.default)();
|
|
230
|
+
const gitIgnorePath = await findGitIgnoreFile(projectPath);
|
|
231
|
+
if (gitIgnorePath) {
|
|
232
|
+
const gitIgnoreContent = await fs.readFile(gitIgnorePath, "utf-8");
|
|
233
|
+
ig.add(gitIgnoreContent);
|
|
234
|
+
}
|
|
235
|
+
ig.add(_projectExclusions.default);
|
|
236
|
+
async function traverse(dirPath) {
|
|
237
|
+
const tree = {};
|
|
238
|
+
const fileNames = [];
|
|
239
|
+
const entries = await fs.readdir(dirPath, {
|
|
240
|
+
withFileTypes: true
|
|
241
|
+
});
|
|
242
|
+
for (const entry of entries) {
|
|
243
|
+
const entryPath = path.join(dirPath, entry.name);
|
|
244
|
+
if (ig.ignores(path.relative(projectPath, entryPath))) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (entry.isFile()) {
|
|
248
|
+
try {
|
|
249
|
+
const content = await fs.readFile(entryPath, "utf-8");
|
|
250
|
+
tree[entry.name] = {
|
|
251
|
+
file: {
|
|
252
|
+
contents: content
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
fileNames.push(path.relative(projectPath, entryPath));
|
|
256
|
+
} catch (error) {
|
|
257
|
+
(0, _terminal.terminal)(`^yWarning: Could not read file ${entryPath}^:\n`);
|
|
258
|
+
}
|
|
259
|
+
} else if (entry.isDirectory()) {
|
|
260
|
+
const {
|
|
261
|
+
tree: subTree,
|
|
262
|
+
fileNames: subFileNames
|
|
263
|
+
} = await traverse(entryPath);
|
|
264
|
+
fileNames.push(...subFileNames);
|
|
265
|
+
if (Object.keys(subTree).length > 0) {
|
|
266
|
+
tree[entry.name] = {
|
|
267
|
+
directory: subTree
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
tree,
|
|
274
|
+
fileNames
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const {
|
|
278
|
+
tree,
|
|
279
|
+
fileNames
|
|
280
|
+
} = await traverse(projectPath);
|
|
281
|
+
const filesToProvisionText = " " + fileNames.join("\n ");
|
|
282
|
+
(0, _terminal.terminal)("^CFiles to be provisioned:^:\n");
|
|
283
|
+
(0, _terminal.terminal)(filesToProvisionText + "\n");
|
|
284
|
+
return tree;
|
|
285
|
+
}
|
|
286
|
+
async function findGitIgnoreFile(projectPath) {
|
|
287
|
+
let currentDirectory = projectPath;
|
|
288
|
+
while (true) {
|
|
289
|
+
const gitIgnorePath = path.join(currentDirectory, ".gitignore");
|
|
290
|
+
if (await fs.exists(gitIgnorePath)) {
|
|
291
|
+
return gitIgnorePath;
|
|
292
|
+
}
|
|
293
|
+
const parentDirectory = path.dirname(currentDirectory);
|
|
294
|
+
if (parentDirectory === currentDirectory) {
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
currentDirectory = parentDirectory;
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function scaffoldAuthSessionFiles(): Promise<void>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.scaffoldAuthSessionFiles = scaffoldAuthSessionFiles;
|
|
7
|
+
var _zod = require("zod");
|
|
8
|
+
var _helpers = require("../helpers");
|
|
9
|
+
var _types = require("../types");
|
|
10
|
+
var _tsNodeImport = require("../../common/tsNodeImport");
|
|
11
|
+
var _constants = require("../../../common/constants");
|
|
12
|
+
var _fsExtra = require("fs-extra");
|
|
13
|
+
var _path = _interopRequireDefault(require("path"));
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
const authSessionTemplateResponseSchema = _zod.z.object({
|
|
16
|
+
"auth-sessions": _types.fileSystemTreeSchema
|
|
17
|
+
});
|
|
18
|
+
async function scaffoldAuthSessionFiles() {
|
|
19
|
+
const [createResult, checkResult] = await Promise.all([(0, _tsNodeImport.tsNodeImport)(`${_constants.AUTH_SESSIONS_FOLDER_NAME}/create`), (0, _tsNodeImport.tsNodeImport)(`${_constants.AUTH_SESSIONS_FOLDER_NAME}/check`)]);
|
|
20
|
+
const createExists = createResult.isOk() || createResult.error.type !== "not_found";
|
|
21
|
+
const checkExists = checkResult.isOk() || checkResult.error.type !== "not_found";
|
|
22
|
+
if (createExists && checkExists) {
|
|
23
|
+
(0, _helpers.terminal)("^g^+AuthSession files already exist^:\n");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
(0, _helpers.terminal)("^g^+Scaffolding...^:\n");
|
|
27
|
+
const authSessionTemplateUrl = new URL("/api/v1/templates/authsession", (0, _helpers.getBaseUrl)());
|
|
28
|
+
authSessionTemplateUrl.searchParams.append("language", "typescript");
|
|
29
|
+
const response = await fetch(authSessionTemplateUrl.toString(), {
|
|
30
|
+
method: "GET"
|
|
31
|
+
});
|
|
32
|
+
const text = await response.text();
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new Error(`Failed to fetch AuthSession template
|
|
35
|
+
Got ${response.status} ${response.statusText}
|
|
36
|
+
${text}`);
|
|
37
|
+
}
|
|
38
|
+
let json;
|
|
39
|
+
try {
|
|
40
|
+
json = JSON.parse(text);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
throw new Error(`Failed to parse AuthSession template response as JSON
|
|
43
|
+
${text}`);
|
|
44
|
+
}
|
|
45
|
+
const parseResult = authSessionTemplateResponseSchema.safeParse(json);
|
|
46
|
+
if (!parseResult.success) {
|
|
47
|
+
throw new Error(`AuthSession template response has invalid shape: ${JSON.stringify(parseResult.error.errors, null, 2)}`);
|
|
48
|
+
}
|
|
49
|
+
const authSessionsContent = parseResult.data["auth-sessions"];
|
|
50
|
+
const cwd = process.cwd();
|
|
51
|
+
const exists = {
|
|
52
|
+
create: createExists,
|
|
53
|
+
check: checkExists
|
|
54
|
+
};
|
|
55
|
+
await (0, _fsExtra.ensureDir)(_path.default.join(cwd, _constants.AUTH_SESSIONS_FOLDER_NAME));
|
|
56
|
+
for (const api in exists) {
|
|
57
|
+
if (exists[api]) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const [name, node] = Object.entries(authSessionsContent).find(entry => "file" in entry[1] && entry[0].replace(/\.[^/.]+$/, "") === api) ?? [undefined, undefined];
|
|
61
|
+
if (!name || !node) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const {
|
|
65
|
+
file: {
|
|
66
|
+
contents
|
|
67
|
+
}
|
|
68
|
+
} = node;
|
|
69
|
+
if (typeof contents !== "string") {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
await (0, _fsExtra.writeFile)(_path.default.join(cwd, _constants.AUTH_SESSIONS_FOLDER_NAME, name), contents, {
|
|
73
|
+
encoding: "utf-8"
|
|
74
|
+
});
|
|
75
|
+
(0, _helpers.terminal)(`^g^+Written ^_${_path.default.join(_constants.AUTH_SESSIONS_FOLDER_NAME, name)}^:\n`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -4,15 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.assertApiFileExists = assertApiFileExists;
|
|
7
|
-
var _path = _interopRequireDefault(require("path"));
|
|
8
|
-
var _fsExtra = require("fs-extra");
|
|
9
7
|
var _errors = require("./errors");
|
|
10
|
-
|
|
8
|
+
var _tsNodeImport = require("../../common/tsNodeImport");
|
|
11
9
|
async function assertApiFileExists(dirname, api) {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
throw new _errors.CLIAssertionError(`^+^r API^ ^+${dirname}/${api}^ ^r^+is not implemented.^:`, {
|
|
10
|
+
const result = await (0, _tsNodeImport.tsNodeImport)(`${dirname}/${api}`);
|
|
11
|
+
if (result.isErr() && result.error.type === "not_found") {
|
|
12
|
+
throw new _errors.CLIAssertionError(`^+^r API^ ^+${dirname}/${api}^ ^r^+does not exist. Make sure to use an existing API name.^:`, {
|
|
16
13
|
autoColor: false
|
|
17
14
|
});
|
|
18
15
|
}
|
|
@@ -20,25 +20,21 @@ var _formatZodError = require("../../../common/formatZodError");
|
|
|
20
20
|
var _asyncLocalStorage = require("../../../common/asyncLocalStorage");
|
|
21
21
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
22
|
async function isAuthEnabled() {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return Boolean(intunedJson?.authSessions?.enabled);
|
|
26
|
-
} catch (error) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
23
|
+
const intunedJson = await (0, _intunedJson.loadIntunedJson)();
|
|
24
|
+
return Boolean(intunedJson?.authSessions?.enabled);
|
|
29
25
|
}
|
|
30
26
|
async function assertAuthEnabled() {
|
|
31
27
|
if (!(await isAuthEnabled())) {
|
|
32
|
-
throw new _errors.CLIAssertionError(
|
|
28
|
+
throw new _errors.CLIAssertionError(await getAuthNotEnabledErrorMessage());
|
|
33
29
|
}
|
|
34
30
|
}
|
|
35
31
|
async function assertAuthConsistent(authSession) {
|
|
36
32
|
const _isAuthEnabled = await isAuthEnabled();
|
|
37
33
|
if (_isAuthEnabled && !authSession) {
|
|
38
|
-
throw new _errors.CLIAssertionError("
|
|
34
|
+
throw new _errors.CLIAssertionError("AuthSession is enabled, but no AuthSession is provided. Please provide an AuthSession using '--auth-session <id>' option.");
|
|
39
35
|
}
|
|
40
36
|
if (!_isAuthEnabled && authSession) {
|
|
41
|
-
throw new _errors.CLIAssertionError(
|
|
37
|
+
throw new _errors.CLIAssertionError(await getAuthNotEnabledErrorMessage());
|
|
42
38
|
}
|
|
43
39
|
}
|
|
44
40
|
async function loadAuthSessionInstance(authSessionId) {
|
|
@@ -47,12 +43,12 @@ async function loadAuthSessionInstance(authSessionId) {
|
|
|
47
43
|
const authSessionInstanceStoragePath = _path.default.join(authSessionInstancePath, `auth-session.json`);
|
|
48
44
|
const authSessionInstanceMetadataPath = _path.default.join(authSessionInstancePath, `metadata.json`);
|
|
49
45
|
if (!(await (0, _fsExtra.exists)(authSessionInstanceStoragePath))) {
|
|
50
|
-
throw new _errors.CLIError(`
|
|
46
|
+
throw new _errors.CLIError(`AuthSession instance with ID ${authSessionId} not found. Make sure the ID is correct.`);
|
|
51
47
|
}
|
|
52
48
|
const authSessionInstanceJson = await (0, _fsExtra.readJSON)(authSessionInstanceStoragePath);
|
|
53
49
|
const authSessionInstanceParseResult = _runApi.runApiStorageStateSchema.safeParse(authSessionInstanceJson);
|
|
54
50
|
if (!authSessionInstanceParseResult.success) {
|
|
55
|
-
throw new _errors.CLIError(`
|
|
51
|
+
throw new _errors.CLIError(`AuthSession instance with ID ${authSessionId} is not valid: ${(0, _formatZodError.formatZodError)(authSessionInstanceParseResult.error)}`);
|
|
56
52
|
}
|
|
57
53
|
const metadata = await (0, _fsExtra.readJSON)(authSessionInstanceMetadataPath);
|
|
58
54
|
return {
|
|
@@ -60,7 +56,7 @@ async function loadAuthSessionInstance(authSessionId) {
|
|
|
60
56
|
metadata
|
|
61
57
|
};
|
|
62
58
|
} catch (error) {
|
|
63
|
-
throw new _errors.CLIError(`Error
|
|
59
|
+
throw new _errors.CLIError(`Error loading AuthSession instance: ${error.message}`);
|
|
64
60
|
}
|
|
65
61
|
}
|
|
66
62
|
async function storeAuthSessionInstance({
|
|
@@ -81,7 +77,7 @@ async function storeAuthSessionInstance({
|
|
|
81
77
|
});
|
|
82
78
|
const projectAuthConfig = (await (0, _intunedJson.loadIntunedJson)()).authSessions;
|
|
83
79
|
if (!projectAuthConfig.enabled) {
|
|
84
|
-
throw new _errors.CLIError(`
|
|
80
|
+
throw new _errors.CLIError(`AuthSessions are not enabled in ${await (0, _intunedJson.getIntunedSettingsFileName)()}. Make sure they are enabled.`);
|
|
85
81
|
}
|
|
86
82
|
const authSessionInstanceMetadataPath = _path.default.join(authSessionInstancePath, `metadata.json`);
|
|
87
83
|
const authSessionMetadata = {
|
|
@@ -104,19 +100,19 @@ async function storeAuthSessionInstance({
|
|
|
104
100
|
});
|
|
105
101
|
return authSessionInstancePath;
|
|
106
102
|
} catch (error) {
|
|
107
|
-
throw new _errors.CLIError(`Error storing
|
|
103
|
+
throw new _errors.CLIError(`Error storing AuthSession instance: ${error.message}`);
|
|
108
104
|
}
|
|
109
105
|
}
|
|
110
106
|
function registerGetAuthSessionParameters(authSessionId) {
|
|
111
107
|
async function getAuthSessionParameters() {
|
|
112
108
|
if (!authSessionId) {
|
|
113
|
-
throw new Error("getAuthSessionParameters cannot be called without using an
|
|
109
|
+
throw new Error("getAuthSessionParameters cannot be called without using an AuthSession");
|
|
114
110
|
}
|
|
115
111
|
const {
|
|
116
112
|
metadata
|
|
117
113
|
} = await loadAuthSessionInstance(authSessionId);
|
|
118
114
|
if (metadata?.authSessionType === "MANUAL") {
|
|
119
|
-
throw new Error("
|
|
115
|
+
throw new Error("AuthSession is recorder-based, it does not have parameters.");
|
|
120
116
|
}
|
|
121
117
|
return metadata?.authSessionInput ?? {};
|
|
122
118
|
}
|
|
@@ -125,20 +121,27 @@ function registerGetAuthSessionParameters(authSessionId) {
|
|
|
125
121
|
async function getAuthSessionRecorderParameters() {
|
|
126
122
|
const intunedJson = await (0, _intunedJson.loadIntunedJson)();
|
|
127
123
|
if (!intunedJson.authSessions.enabled) {
|
|
128
|
-
throw new _errors.CLIError(`
|
|
124
|
+
throw new _errors.CLIError(`AuthSessions are not enabled in ${await (0, _intunedJson.getIntunedSettingsFileName)()}. Make sure they are enabled.`);
|
|
129
125
|
}
|
|
130
126
|
if (intunedJson.authSessions.type !== "MANUAL") {
|
|
131
|
-
throw new _errors.CLIError(`
|
|
127
|
+
throw new _errors.CLIError(`AuthSession type is not recorder-based in ${await (0, _intunedJson.getIntunedSettingsFileName)()}.
|
|
128
|
+
Make sure the AuthSession type is set to 'MANUAL'
|
|
129
|
+
For more details, check out https://docs.intunedhq.com/docs/05-references/intuned-json#configuration-properties.`);
|
|
132
130
|
}
|
|
133
131
|
const {
|
|
134
132
|
startUrl,
|
|
135
133
|
finishUrl
|
|
136
134
|
} = intunedJson.authSessions;
|
|
137
135
|
if (startUrl === undefined || finishUrl === undefined) {
|
|
138
|
-
throw new _errors.CLIError(`
|
|
136
|
+
throw new _errors.CLIError(`AuthSession type is recorder-based but start_url or finish_url is not set in ${await (0, _intunedJson.getIntunedSettingsFileName)()}.
|
|
137
|
+
Please set both values to use recorder-based AuthSessions.
|
|
138
|
+
For more details, check out https://docs.intunedhq.com/docs/05-references/intuned-json#configuration-properties`);
|
|
139
139
|
}
|
|
140
140
|
return {
|
|
141
141
|
startUrl,
|
|
142
142
|
finishUrl
|
|
143
143
|
};
|
|
144
|
+
}
|
|
145
|
+
async function getAuthNotEnabledErrorMessage() {
|
|
146
|
+
return "AuthSessions are not enabled.\n" + `Enable AuthSessions in ${await (0, _intunedJson.getIntunedSettingsFileName)()} to use this feature.\n` + "See https://docs.intunedhq.com/docs/02-features/auth-sessions#1-enable-authsessions-for-your-project for more information.";
|
|
144
147
|
}
|
|
@@ -8,14 +8,22 @@ exports.getBaseUrl = getBaseUrl;
|
|
|
8
8
|
var _constants = require("../../../common/constants");
|
|
9
9
|
var _errors = require("./errors");
|
|
10
10
|
var _intunedJson = require("./intunedJson");
|
|
11
|
+
var _prompts = require("./prompts");
|
|
11
12
|
async function getAuthCredentials(options) {
|
|
12
|
-
const
|
|
13
|
-
|
|
13
|
+
const settings = await (0, _intunedJson.loadIntunedJson)();
|
|
14
|
+
let workspaceId = options.workspaceId || settings.workspaceId || process.env[_constants.WORKSPACE_ID_ENV_VAR_KEY];
|
|
15
|
+
let apiKey = options.apiKey || process.env[_constants.API_KEY_ENV_VAR_KEY];
|
|
14
16
|
if (!workspaceId) {
|
|
15
|
-
|
|
17
|
+
workspaceId = await (0, _prompts.promptForWorkspaceId)();
|
|
18
|
+
}
|
|
19
|
+
if (!workspaceId) {
|
|
20
|
+
throw new _errors.CLIError(`Workspace ID is required. Please provide it via command line options or ${await (0, _intunedJson.getIntunedSettingsFileName)()}.\n` + `Expected format: UUID (e.g., 123e4567-e89b-12d3-a456-426614174000)\n` + `Find your workspace ID at: https://app.intuned.io/settings/api-keys`);
|
|
21
|
+
}
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
apiKey = await (0, _prompts.promptForApiKey)();
|
|
16
24
|
}
|
|
17
25
|
if (!apiKey) {
|
|
18
|
-
throw new _errors.CLIError(`API key is required. Please provide it via command line options or ${_constants.API_KEY_ENV_VAR_KEY} environment variable
|
|
26
|
+
throw new _errors.CLIError(`API key is required. Please provide it via command line options or ${_constants.API_KEY_ENV_VAR_KEY} environment variable.\n` + `Get your API key at: https://app.intuned.io/settings/api-keys`);
|
|
19
27
|
}
|
|
20
28
|
return {
|
|
21
29
|
workspaceId,
|
|
@@ -13,13 +13,13 @@ async function withCLIContext(fn, options) {
|
|
|
13
13
|
async function getAuthSessionParameters() {
|
|
14
14
|
const id = options?.authSessionId;
|
|
15
15
|
if (!id) {
|
|
16
|
-
throw new Error("getAuthSessionParameters cannot be called without using an
|
|
16
|
+
throw new Error("getAuthSessionParameters cannot be called without using an AuthSession");
|
|
17
17
|
}
|
|
18
18
|
const {
|
|
19
19
|
metadata
|
|
20
20
|
} = await (0, _auth.loadAuthSessionInstance)(id);
|
|
21
21
|
if (metadata?.authSessionType === "MANUAL") {
|
|
22
|
-
throw new Error("
|
|
22
|
+
throw new Error("AuthSession is recorder-based, it does not have parameters.");
|
|
23
23
|
}
|
|
24
24
|
return metadata?.authSessionInput ?? {};
|
|
25
25
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.promptForApiKey = promptForApiKey;
|
|
7
|
+
exports.promptForProjectName = promptForProjectName;
|
|
8
|
+
exports.promptForWorkspaceId = promptForWorkspaceId;
|
|
9
|
+
var _prompts = _interopRequireDefault(require("prompts"));
|
|
10
|
+
var _zod = require("zod");
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
async function promptForProjectName(validate) {
|
|
13
|
+
const {
|
|
14
|
+
projectName
|
|
15
|
+
} = await (0, _prompts.default)({
|
|
16
|
+
type: "text",
|
|
17
|
+
name: "projectName",
|
|
18
|
+
message: "Project name (required):",
|
|
19
|
+
validate
|
|
20
|
+
});
|
|
21
|
+
return projectName?.trim();
|
|
22
|
+
}
|
|
23
|
+
const workspaceIdSchema = _zod.z.string().uuid("Workspace ID must be a valid UUID");
|
|
24
|
+
async function promptForWorkspaceId() {
|
|
25
|
+
const {
|
|
26
|
+
workspaceId
|
|
27
|
+
} = await (0, _prompts.default)({
|
|
28
|
+
type: "text",
|
|
29
|
+
name: "workspaceId",
|
|
30
|
+
message: "Workspace ID (required):",
|
|
31
|
+
validate: value => {
|
|
32
|
+
const parsed = workspaceIdSchema.safeParse(String(value).trim());
|
|
33
|
+
return parsed.success ? true : parsed.error.errors[0].message;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return workspaceId.trim();
|
|
37
|
+
}
|
|
38
|
+
const apiKeySchema = _zod.z.string().min(1, "API Key cannot be empty").superRefine((val, ctx) => {
|
|
39
|
+
if (val.includes(" ")) {
|
|
40
|
+
ctx.addIssue({
|
|
41
|
+
code: "custom",
|
|
42
|
+
message: "API Key cannot contain spaces"
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (!val.startsWith("in1_")) {
|
|
46
|
+
ctx.addIssue({
|
|
47
|
+
code: "custom",
|
|
48
|
+
message: "API Key must start with 'in1_'"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (val.length !== 36) {
|
|
52
|
+
ctx.addIssue({
|
|
53
|
+
code: "custom",
|
|
54
|
+
message: "API Key must be 36 characters long"
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
async function promptForApiKey() {
|
|
59
|
+
const {
|
|
60
|
+
apiKey
|
|
61
|
+
} = await (0, _prompts.default)({
|
|
62
|
+
type: "text",
|
|
63
|
+
name: "apiKey",
|
|
64
|
+
message: "API Key (required, get it at: https://app.intuned.io/settings/api-keys):",
|
|
65
|
+
validate: value => {
|
|
66
|
+
const parsed = apiKeySchema.safeParse(String(value).trim());
|
|
67
|
+
return parsed.success ? true : parsed.error.errors.map(e => e.message).join(", ");
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return apiKey.trim();
|
|
71
|
+
}
|