@nexical/cli 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-FDJVHO4O.js → chunk-JDRAVUKK.js} +11 -4
- package/dist/chunk-JDRAVUKK.js.map +1 -0
- package/dist/src/commands/admin/create-user.js +1 -1
- package/dist/src/commands/branch/create.js +1 -1
- package/dist/src/commands/branch/delete.js +1 -1
- package/dist/src/commands/branch/get.js +1 -1
- package/dist/src/commands/branch/list.js +1 -1
- package/dist/src/commands/job/get.js +1 -1
- package/dist/src/commands/job/list.js +1 -1
- package/dist/src/commands/job/logs.js +1 -1
- package/dist/src/commands/job/trigger.js +1 -1
- package/dist/src/commands/login.js +1 -1
- package/dist/src/commands/project/create.js +1 -1
- package/dist/src/commands/project/delete.js +1 -1
- package/dist/src/commands/project/get.js +1 -1
- package/dist/src/commands/project/list.js +1 -1
- package/dist/src/commands/project/update.js +1 -1
- package/dist/src/commands/team/create.js +1 -1
- package/dist/src/commands/team/delete.js +1 -1
- package/dist/src/commands/team/get.js +1 -1
- package/dist/src/commands/team/list.js +1 -1
- package/dist/src/commands/team/member/invite.js +1 -1
- package/dist/src/commands/team/member/remove.js +1 -1
- package/dist/src/commands/team/update.js +1 -1
- package/dist/src/commands/token/generate.js +1 -1
- package/dist/src/commands/token/list.js +1 -1
- package/dist/src/commands/token/revoke.js +1 -1
- package/dist/src/commands/whoami.js +1 -1
- package/dist/src/utils/nexical-client.js +1 -1
- package/package.json +5 -5
- package/src/utils/nexical-client.ts +9 -2
- package/test/e2e/auth.e2e.test.ts +46 -0
- package/test/e2e/job-workflow.e2e.test.ts +33 -0
- package/test/e2e/project-lifecycle.e2e.test.ts +48 -0
- package/test/e2e/setup.ts +237 -0
- package/test/e2e/utils.ts +33 -0
- package/test/unit/utils/nexical-client.test.ts +16 -1
- package/vitest.e2e.config.ts +1 -0
- package/dist/chunk-FDJVHO4O.js.map +0 -1
- package/test/e2e/.gitkeep +0 -0
- package/test/utils/integration-helpers.ts +0 -22
|
@@ -5,9 +5,14 @@ import { NexicalClient } from "@nexical/sdk";
|
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import os from "os";
|
|
8
|
-
var
|
|
9
|
-
|
|
8
|
+
var getConfigPaths = () => {
|
|
9
|
+
const HOME = process.env.HOME || os.homedir();
|
|
10
|
+
const CONFIG_DIR = path.join(HOME, ".nexical");
|
|
11
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
12
|
+
return { CONFIG_DIR, CONFIG_FILE };
|
|
13
|
+
};
|
|
10
14
|
function getConfig() {
|
|
15
|
+
const { CONFIG_FILE } = getConfigPaths();
|
|
11
16
|
if (!fs.existsSync(CONFIG_FILE)) {
|
|
12
17
|
return {};
|
|
13
18
|
}
|
|
@@ -19,6 +24,7 @@ function getConfig() {
|
|
|
19
24
|
}
|
|
20
25
|
}
|
|
21
26
|
function saveToken(token) {
|
|
27
|
+
const { CONFIG_DIR, CONFIG_FILE } = getConfigPaths();
|
|
22
28
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
23
29
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
24
30
|
}
|
|
@@ -29,7 +35,8 @@ function saveToken(token) {
|
|
|
29
35
|
function getClient() {
|
|
30
36
|
const config = getConfig();
|
|
31
37
|
return new NexicalClient({
|
|
32
|
-
token: config.token
|
|
38
|
+
token: config.token,
|
|
39
|
+
baseURL: process.env.NEXICAL_API_URL
|
|
33
40
|
});
|
|
34
41
|
}
|
|
35
42
|
|
|
@@ -38,4 +45,4 @@ export {
|
|
|
38
45
|
saveToken,
|
|
39
46
|
getClient
|
|
40
47
|
};
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
48
|
+
//# sourceMappingURL=chunk-JDRAVUKK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/nexical-client.ts"],"sourcesContent":["\nimport { NexicalClient } from '@nexical/sdk';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst getConfigPaths = () => {\n const HOME = process.env.HOME || os.homedir();\n const CONFIG_DIR = path.join(HOME, '.nexical');\n const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n return { CONFIG_DIR, CONFIG_FILE };\n};\n\ninterface Config {\n token?: string;\n}\n\nexport function getConfig(): Config {\n const { CONFIG_FILE } = getConfigPaths();\n if (!fs.existsSync(CONFIG_FILE)) {\n return {};\n }\n try {\n const content = fs.readFileSync(CONFIG_FILE, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n return {};\n }\n}\n\nexport function saveToken(token: string) {\n const { CONFIG_DIR, CONFIG_FILE } = getConfigPaths();\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n const config = getConfig();\n config.token = token;\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));\n}\n\nexport function getClient(): NexicalClient {\n const config = getConfig();\n return new NexicalClient({\n token: config.token,\n baseURL: process.env.NEXICAL_API_URL,\n });\n}\n"],"mappings":";;;AACA,SAAS,qBAAqB;AAC9B,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAEf,IAAM,iBAAiB,MAAM;AACzB,QAAM,OAAO,QAAQ,IAAI,QAAQ,GAAG,QAAQ;AAC5C,QAAM,aAAa,KAAK,KAAK,MAAM,UAAU;AAC7C,QAAM,cAAc,KAAK,KAAK,YAAY,aAAa;AACvD,SAAO,EAAE,YAAY,YAAY;AACrC;AAMO,SAAS,YAAoB;AAChC,QAAM,EAAE,YAAY,IAAI,eAAe;AACvC,MAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC7B,WAAO,CAAC;AAAA,EACZ;AACA,MAAI;AACA,UAAM,UAAU,GAAG,aAAa,aAAa,OAAO;AACpD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC7B,SAAS,OAAO;AACZ,WAAO,CAAC;AAAA,EACZ;AACJ;AAEO,SAAS,UAAU,OAAe;AACrC,QAAM,EAAE,YAAY,YAAY,IAAI,eAAe;AACnD,MAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC5B,OAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AACA,QAAM,SAAS,UAAU;AACzB,SAAO,QAAQ;AACf,KAAG,cAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACjE;AAEO,SAAS,YAA2B;AACvC,QAAM,SAAS,UAAU;AACzB,SAAO,IAAI,cAAc;AAAA,IACrB,OAAO,OAAO;AAAA,IACd,SAAS,QAAQ,IAAI;AAAA,EACzB,CAAC;AACL;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/admin/create-user.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/branch/create.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/branch/delete.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/branch/get.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/branch/list.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/job/get.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/job/list.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/job/logs.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/job/trigger.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -2,7 +2,7 @@ import { createRequire } from "module"; const require = createRequire(import.met
|
|
|
2
2
|
import {
|
|
3
3
|
getClient,
|
|
4
4
|
saveToken
|
|
5
|
-
} from "../../chunk-
|
|
5
|
+
} from "../../chunk-JDRAVUKK.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/login.ts
|
|
8
8
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/project/create.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/project/delete.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/project/get.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/project/list.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/project/update.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/create.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/delete.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/get.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/list.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../../chunk-
|
|
4
|
+
} from "../../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/member/invite.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../../chunk-
|
|
4
|
+
} from "../../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/member/remove.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/team/update.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/token/generate.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/token/list.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getClient
|
|
4
|
-
} from "../../../chunk-
|
|
4
|
+
} from "../../../chunk-JDRAVUKK.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/token/revoke.ts
|
|
7
7
|
import { BaseCommand } from "@nexical/cli-core";
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexical/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
|
-
"
|
|
6
|
+
"nexical": "./dist/index.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsup",
|
|
10
10
|
"dev": "tsup --watch",
|
|
11
11
|
"start": "node dist/index.js",
|
|
12
|
-
"test": "npm run test:unit && npm run test:integration",
|
|
12
|
+
"test": "npm run test:unit && npm run test:integration && npm run test:e2e",
|
|
13
13
|
"test:unit": "vitest run --config vitest.config.ts --coverage",
|
|
14
14
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
15
15
|
"test:e2e": "npm run build && vitest run --config vitest.e2e.config.ts",
|
|
16
16
|
"test:watch": "vitest"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@nexical/cli-core": "^0.1.
|
|
19
|
+
"@nexical/cli-core": "^0.1.5",
|
|
20
20
|
"@nexical/sdk": "^0.4.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
"typescript": "^5.3.3",
|
|
30
30
|
"vitest": "^4.0.15"
|
|
31
31
|
}
|
|
32
|
-
}
|
|
32
|
+
}
|
|
@@ -4,14 +4,19 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const getConfigPaths = () => {
|
|
8
|
+
const HOME = process.env.HOME || os.homedir();
|
|
9
|
+
const CONFIG_DIR = path.join(HOME, '.nexical');
|
|
10
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
11
|
+
return { CONFIG_DIR, CONFIG_FILE };
|
|
12
|
+
};
|
|
9
13
|
|
|
10
14
|
interface Config {
|
|
11
15
|
token?: string;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export function getConfig(): Config {
|
|
19
|
+
const { CONFIG_FILE } = getConfigPaths();
|
|
15
20
|
if (!fs.existsSync(CONFIG_FILE)) {
|
|
16
21
|
return {};
|
|
17
22
|
}
|
|
@@ -24,6 +29,7 @@ export function getConfig(): Config {
|
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export function saveToken(token: string) {
|
|
32
|
+
const { CONFIG_DIR, CONFIG_FILE } = getConfigPaths();
|
|
27
33
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
28
34
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
29
35
|
}
|
|
@@ -36,5 +42,6 @@ export function getClient(): NexicalClient {
|
|
|
36
42
|
const config = getConfig();
|
|
37
43
|
return new NexicalClient({
|
|
38
44
|
token: config.token,
|
|
45
|
+
baseURL: process.env.NEXICAL_API_URL,
|
|
39
46
|
});
|
|
40
47
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import { runCLI, TEST_HOME } from './utils.js';
|
|
3
|
+
import { resetMockStore } from './setup.js';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
describe('Authentication E2E', () => {
|
|
8
|
+
// Isolate config for tests
|
|
9
|
+
const TEST_CONFIG_DIR = path.join(TEST_HOME, '.nexical');
|
|
10
|
+
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
resetMockStore();
|
|
14
|
+
// Clean up any existing config
|
|
15
|
+
if (await fs.pathExists(TEST_CONFIG_FILE)) {
|
|
16
|
+
await fs.remove(TEST_CONFIG_FILE);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should show not logged in initially', async () => {
|
|
21
|
+
const { stdout } = await runCLI(['whoami']);
|
|
22
|
+
expect(stdout).toContain('Not logged in or token expired');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should login successfully', async () => {
|
|
26
|
+
// Simulate login
|
|
27
|
+
// Since login is interactive (browser open), we might mock the open module or
|
|
28
|
+
// just trust runCLI can handle the non-interactive part until the prompt.
|
|
29
|
+
// However, key to this test is that we can MANUALLY set the token via CLI
|
|
30
|
+
// OR we just simulate the token save if the CLI doesn't support non-interactive login easily.
|
|
31
|
+
|
|
32
|
+
// For E2E of the CLI 'login' command specifically, it's hard without a browser.
|
|
33
|
+
// But we can verify "whoami" works IF we have a token.
|
|
34
|
+
|
|
35
|
+
// Let's manually inject a token to simulate a successful login state for now
|
|
36
|
+
// as true E2E of OAuth device flow requires browser automation which is out of scope.
|
|
37
|
+
|
|
38
|
+
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
39
|
+
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
40
|
+
|
|
41
|
+
const { stdout } = await runCLI(['whoami']);
|
|
42
|
+
expect(stdout).toContain('Logged in as:');
|
|
43
|
+
expect(stdout).toContain('Name: Test User');
|
|
44
|
+
expect(stdout).toContain('Email: test@example.com');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import { runCLI } from './utils.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { resetMockStore } from './setup.js';
|
|
7
|
+
|
|
8
|
+
describe('Job Workflow E2E', () => {
|
|
9
|
+
const TEST_CONFIG_DIR = path.join(os.homedir(), '.nexical');
|
|
10
|
+
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
resetMockStore();
|
|
14
|
+
resetMockStore();
|
|
15
|
+
// Ensure logged in
|
|
16
|
+
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
17
|
+
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should trigger a job', async () => {
|
|
21
|
+
// We use "3" as branchId (must be numeric for CLI validation)
|
|
22
|
+
const { stdout } = await runCLI(['job', 'trigger', '1', '101', '3', 'deploy']);
|
|
23
|
+
expect(stdout).toContain('Job 123 triggered successfully!');
|
|
24
|
+
expect(stdout).toContain('Status: pending');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should get job logs', async () => {
|
|
28
|
+
const { stdout } = await runCLI(['job', 'logs', '1', '101', '3', '123']);
|
|
29
|
+
expect(stdout).toContain('Logs for Job 123:');
|
|
30
|
+
expect(stdout).toContain('Build initialized');
|
|
31
|
+
expect(stdout).toContain('Build successful');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import { runCLI } from './utils.js';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import { resetMockStore } from './setup.js';
|
|
7
|
+
|
|
8
|
+
describe('Project Lifecycle E2E', () => {
|
|
9
|
+
const TEST_CONFIG_DIR = path.join(os.homedir(), '.nexical');
|
|
10
|
+
const TEST_CONFIG_FILE = path.join(TEST_CONFIG_DIR, 'config.json');
|
|
11
|
+
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
resetMockStore();
|
|
14
|
+
// Ensure logged intMockStore();
|
|
15
|
+
// Ensure logged in
|
|
16
|
+
await fs.mkdirp(TEST_CONFIG_DIR);
|
|
17
|
+
await fs.writeJSON(TEST_CONFIG_FILE, { token: 'mock-access-token' });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create a new project', async () => {
|
|
21
|
+
const { stdout } = await runCLI(['project', 'create', '1', 'My Project', '--repo', 'https://github.com/test/repo']);
|
|
22
|
+
expect(stdout).toContain('Project "My Project" set up successfully!');
|
|
23
|
+
expect(stdout).toContain('ID: 101');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should list projects', async () => {
|
|
27
|
+
const { stdout } = await runCLI(['project', 'list', '1']);
|
|
28
|
+
expect(stdout).toContain('Projects in Team 1:');
|
|
29
|
+
expect(stdout).toContain('My Project (ID: 101)');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should update project', async () => {
|
|
33
|
+
const { stdout } = await runCLI(['project', 'update', '1', '101', '--name', 'Updated Project']);
|
|
34
|
+
// Note: The CLI success message format depends on command impl.
|
|
35
|
+
expect(stdout).toContain('Project 101 updated!');
|
|
36
|
+
// expect(stdout).toContain('Name: Updated Project'); // CLI might not print details
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should delete project', async () => {
|
|
40
|
+
const { stdout } = await runCLI(['project', 'delete', '1', '101', '--confirm']);
|
|
41
|
+
expect(stdout).toContain('Project 101 deleted.');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should verify deletion', async () => {
|
|
45
|
+
const { stdout } = await runCLI(['project', 'list', '1']);
|
|
46
|
+
expect(stdout).not.toContain('ID: 101');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { beforeAll, afterAll } from 'vitest';
|
|
2
|
+
import http from 'http';
|
|
3
|
+
|
|
4
|
+
const MOCK_PORT = 3333;
|
|
5
|
+
export const TEST_API_URL = `http://localhost:${MOCK_PORT}`;
|
|
6
|
+
|
|
7
|
+
// Simple in-memory mock store
|
|
8
|
+
export const mockStore = {
|
|
9
|
+
users: [] as any[],
|
|
10
|
+
tokens: [] as any[],
|
|
11
|
+
teams: [] as any[],
|
|
12
|
+
projects: [] as any[],
|
|
13
|
+
jobs: [] as any[],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const resetMockStore = () => {
|
|
17
|
+
mockStore.users = [];
|
|
18
|
+
mockStore.tokens = [];
|
|
19
|
+
mockStore.teams = [
|
|
20
|
+
{ id: 1, name: 'My Team', slug: 'my-team' }
|
|
21
|
+
];
|
|
22
|
+
mockStore.projects = [];
|
|
23
|
+
mockStore.jobs = [];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const server = http.createServer((req, res) => {
|
|
27
|
+
const { method, url } = req;
|
|
28
|
+
let body = '';
|
|
29
|
+
|
|
30
|
+
req.on('data', chunk => {
|
|
31
|
+
body += chunk.toString();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
req.on('end', () => {
|
|
35
|
+
let parsedBody: any = {};
|
|
36
|
+
try {
|
|
37
|
+
if (body) parsedBody = JSON.parse(body);
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// ignore
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`[MOCK API] ${method} ${url}`, parsedBody);
|
|
43
|
+
|
|
44
|
+
res.setHeader('Content-Type', 'application/json');
|
|
45
|
+
|
|
46
|
+
// --- Mock Routes ---
|
|
47
|
+
|
|
48
|
+
// AUTH
|
|
49
|
+
if (method === 'POST' && url === '/auth/device') {
|
|
50
|
+
res.writeHead(200);
|
|
51
|
+
res.end(JSON.stringify({ deviceCode: '1234', userCode: 'ABCD-1234', verificationUrl: 'http://localhost:3000/verify' }));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (method === 'POST' && url === '/auth/token') {
|
|
56
|
+
res.writeHead(200);
|
|
57
|
+
res.end(JSON.stringify({ accessToken: 'mock-access-token', refreshToken: 'mock-refresh-token' }));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (method === 'POST' && url === '/auth/logout') {
|
|
62
|
+
res.writeHead(200);
|
|
63
|
+
res.end(JSON.stringify({ success: true }));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Auth
|
|
68
|
+
if (method === 'GET' && url === '/users/me') {
|
|
69
|
+
const authHeader = req.headers['authorization'];
|
|
70
|
+
const token = authHeader?.split(' ')[1];
|
|
71
|
+
|
|
72
|
+
if (!token || token === 'expired') {
|
|
73
|
+
res.writeHead(401);
|
|
74
|
+
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const user = mockStore.users[0] || {
|
|
79
|
+
id: '123e4567-e89b-12d3-a456-426614174000', // Valid UUID
|
|
80
|
+
email: 'test@example.com',
|
|
81
|
+
fullName: 'Test User',
|
|
82
|
+
avatarUrl: null,
|
|
83
|
+
role: 'user',
|
|
84
|
+
createdAt: new Date().toISOString(),
|
|
85
|
+
updatedAt: new Date().toISOString()
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Wrap in { user: ... }
|
|
89
|
+
res.writeHead(200);
|
|
90
|
+
res.end(JSON.stringify({ user }));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// PROJECTS
|
|
95
|
+
if (method === 'POST' && url === '/teams/1/projects') {
|
|
96
|
+
const newProject = {
|
|
97
|
+
id: 101, // SDK expects number
|
|
98
|
+
teamId: 1,
|
|
99
|
+
name: parsedBody.name,
|
|
100
|
+
repoUrl: parsedBody.repoUrl || null,
|
|
101
|
+
productionUrl: null,
|
|
102
|
+
contextHash: null,
|
|
103
|
+
mode: 'managed',
|
|
104
|
+
createdAt: new Date().toISOString(),
|
|
105
|
+
updatedAt: new Date().toISOString(),
|
|
106
|
+
};
|
|
107
|
+
mockStore.projects.push(newProject);
|
|
108
|
+
|
|
109
|
+
// Wrap in { project: ... }
|
|
110
|
+
res.writeHead(201);
|
|
111
|
+
res.end(JSON.stringify({ project: newProject }));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (method === 'GET' && url === '/teams/1/projects') {
|
|
116
|
+
// Wrap in { projects: ... }
|
|
117
|
+
res.writeHead(200);
|
|
118
|
+
res.end(JSON.stringify({ projects: mockStore.projects }));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (method === 'PUT' && url?.match(/\/teams\/1\/projects\/\d+$/)) {
|
|
123
|
+
const id = parseInt(url.split('/').pop() || '0');
|
|
124
|
+
const project = mockStore.projects.find((p: any) => p.id === id);
|
|
125
|
+
if (project) {
|
|
126
|
+
// Update logic mimicking body parse (simplification)
|
|
127
|
+
// content-length usually small in tests
|
|
128
|
+
// For now, return existing or updated stub
|
|
129
|
+
project.name = 'Updated Project'; // Hardcode for test expectation
|
|
130
|
+
res.writeHead(200);
|
|
131
|
+
res.end(JSON.stringify({ project }));
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
res.writeHead(404);
|
|
135
|
+
res.end('Not Found');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (method === 'DELETE' && url?.match(/\/teams\/1\/projects\/\d+$/)) {
|
|
140
|
+
const id = parseInt(url.split('/').pop() || '0');
|
|
141
|
+
const index = mockStore.projects.findIndex((p: any) => p.id === id);
|
|
142
|
+
if (index !== -1) {
|
|
143
|
+
mockStore.projects.splice(index, 1);
|
|
144
|
+
res.writeHead(200);
|
|
145
|
+
res.end(JSON.stringify({ message: 'Project deleted' }));
|
|
146
|
+
} else {
|
|
147
|
+
res.writeHead(404);
|
|
148
|
+
res.end(JSON.stringify({ message: "Not Found" }));
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// TEAMS
|
|
154
|
+
if (method === 'GET' && url === '/teams/1') {
|
|
155
|
+
// Return team 1 mock
|
|
156
|
+
res.writeHead(200);
|
|
157
|
+
res.end(JSON.stringify({
|
|
158
|
+
id: 1,
|
|
159
|
+
name: 'My Team',
|
|
160
|
+
slug: 'my-team',
|
|
161
|
+
billingPlan: 'free',
|
|
162
|
+
creditsBalance: 100,
|
|
163
|
+
createdAt: new Date().toISOString(),
|
|
164
|
+
updatedAt: new Date().toISOString(),
|
|
165
|
+
role: 'owner'
|
|
166
|
+
}));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Jobs
|
|
171
|
+
if (method === 'POST' && url?.includes('/jobs') && !url.includes('/logs')) {
|
|
172
|
+
const newJob = {
|
|
173
|
+
id: 123,
|
|
174
|
+
branchId: 3,
|
|
175
|
+
type: 'deploy',
|
|
176
|
+
status: 'pending',
|
|
177
|
+
queue: 'public',
|
|
178
|
+
inputs: null,
|
|
179
|
+
outputs: null,
|
|
180
|
+
assignedFactoryId: null,
|
|
181
|
+
startedAt: null,
|
|
182
|
+
completedAt: null,
|
|
183
|
+
createdAt: new Date().toISOString(),
|
|
184
|
+
};
|
|
185
|
+
mockStore.jobs.push(newJob);
|
|
186
|
+
// Wrap in { job: ... }
|
|
187
|
+
res.writeHead(201);
|
|
188
|
+
res.end(JSON.stringify({ job: newJob }));
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Logs
|
|
193
|
+
if (method === 'GET' && url?.includes('/logs')) {
|
|
194
|
+
const stubLogs = [
|
|
195
|
+
{
|
|
196
|
+
id: 1,
|
|
197
|
+
jobId: 123,
|
|
198
|
+
level: 'info',
|
|
199
|
+
message: 'Build initialized',
|
|
200
|
+
metadata: null,
|
|
201
|
+
timestamp: new Date().toISOString()
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
id: 2,
|
|
205
|
+
jobId: 123,
|
|
206
|
+
level: 'info',
|
|
207
|
+
message: 'Build successful',
|
|
208
|
+
metadata: null,
|
|
209
|
+
timestamp: new Date().toISOString()
|
|
210
|
+
}
|
|
211
|
+
];
|
|
212
|
+
// Wrap in { logs: ... }
|
|
213
|
+
res.writeHead(200);
|
|
214
|
+
res.end(JSON.stringify({ logs: stubLogs }));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Default 404
|
|
219
|
+
res.writeHead(404);
|
|
220
|
+
res.end(JSON.stringify({ message: 'Not Found' }));
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
beforeAll(async () => {
|
|
225
|
+
return new Promise<void>((resolve) => {
|
|
226
|
+
server.listen(MOCK_PORT, () => {
|
|
227
|
+
console.log(`Mock API running on port ${MOCK_PORT}`);
|
|
228
|
+
resolve();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
afterAll(async () => {
|
|
234
|
+
return new Promise<void>((resolve) => {
|
|
235
|
+
server.close(() => resolve());
|
|
236
|
+
});
|
|
237
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
|
|
7
|
+
// Constants
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const CLI_BIN = path.resolve(__dirname, '../../dist/index.js');
|
|
10
|
+
const TEST_API_URL = 'http://localhost:3333';
|
|
11
|
+
export const TEST_HOME = path.resolve(__dirname, '../../test-home');
|
|
12
|
+
|
|
13
|
+
// Ensure test home exists
|
|
14
|
+
if (!fs.existsSync(TEST_HOME)) {
|
|
15
|
+
fs.mkdirpSync(TEST_HOME);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Runs the CLI command against the compiled binary (E2E style)
|
|
20
|
+
*/
|
|
21
|
+
export async function runCLI(args: string[], options: any = {}) {
|
|
22
|
+
return execa("node", [CLI_BIN, ...args], {
|
|
23
|
+
cwd: options.cwd || process.cwd(),
|
|
24
|
+
...options,
|
|
25
|
+
env: {
|
|
26
|
+
...process.env,
|
|
27
|
+
NEXICAL_API_URL: TEST_API_URL, // Point to Mock API
|
|
28
|
+
HOME: TEST_HOME, // Isolate config
|
|
29
|
+
...options.env,
|
|
30
|
+
},
|
|
31
|
+
reject: false, // Allow checking exit code in tests
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -10,7 +10,7 @@ vi.mock('node:fs');
|
|
|
10
10
|
vi.mock('node:fs');
|
|
11
11
|
vi.mock('node:os', () => ({
|
|
12
12
|
default: {
|
|
13
|
-
homedir: () => '/home/user'
|
|
13
|
+
homedir: vi.fn(() => '/home/user')
|
|
14
14
|
}
|
|
15
15
|
}));
|
|
16
16
|
vi.mock('@nexical/sdk');
|
|
@@ -22,9 +22,24 @@ describe('nexical-client', () => {
|
|
|
22
22
|
|
|
23
23
|
beforeEach(() => {
|
|
24
24
|
vi.resetAllMocks();
|
|
25
|
+
vi.stubEnv('HOME', '/home/user');
|
|
25
26
|
// os.homedir is already mocked by factory
|
|
26
27
|
});
|
|
27
28
|
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
vi.unstubAllEnvs();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should use os.homedir() if HOME env var is not set', () => {
|
|
34
|
+
vi.unstubAllEnvs();
|
|
35
|
+
vi.stubEnv('HOME', '');
|
|
36
|
+
|
|
37
|
+
// Trigger path resolution
|
|
38
|
+
getConfig();
|
|
39
|
+
|
|
40
|
+
expect(os.homedir).toHaveBeenCalled();
|
|
41
|
+
});
|
|
42
|
+
|
|
28
43
|
describe('getConfig', () => {
|
|
29
44
|
it('should return empty object if config file does not exist', () => {
|
|
30
45
|
vi.mocked(fs.existsSync).mockReturnValue(false);
|
package/vitest.e2e.config.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/nexical-client.ts"],"sourcesContent":["\nimport { NexicalClient } from '@nexical/sdk';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst CONFIG_DIR = path.join(os.homedir(), '.nexical');\nconst CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n\ninterface Config {\n token?: string;\n}\n\nexport function getConfig(): Config {\n if (!fs.existsSync(CONFIG_FILE)) {\n return {};\n }\n try {\n const content = fs.readFileSync(CONFIG_FILE, 'utf-8');\n return JSON.parse(content);\n } catch (error) {\n return {};\n }\n}\n\nexport function saveToken(token: string) {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n const config = getConfig();\n config.token = token;\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));\n}\n\nexport function getClient(): NexicalClient {\n const config = getConfig();\n return new NexicalClient({\n token: config.token,\n });\n}\n"],"mappings":";;;AACA,SAAS,qBAAqB;AAC9B,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAEf,IAAM,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,UAAU;AACrD,IAAM,cAAc,KAAK,KAAK,YAAY,aAAa;AAMhD,SAAS,YAAoB;AAChC,MAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC7B,WAAO,CAAC;AAAA,EACZ;AACA,MAAI;AACA,UAAM,UAAU,GAAG,aAAa,aAAa,OAAO;AACpD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC7B,SAAS,OAAO;AACZ,WAAO,CAAC;AAAA,EACZ;AACJ;AAEO,SAAS,UAAU,OAAe;AACrC,MAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC5B,OAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAChD;AACA,QAAM,SAAS,UAAU;AACzB,SAAO,QAAQ;AACf,KAAG,cAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AACjE;AAEO,SAAS,YAA2B;AACvC,QAAM,SAAS,UAAU;AACzB,SAAO,IAAI,cAAc;AAAA,IACrB,OAAO,OAAO;AAAA,EAClB,CAAC;AACL;","names":[]}
|
package/test/e2e/.gitkeep
DELETED
|
File without changes
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { execa } from "execa";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
|
|
5
|
-
// Constants
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
export const CLI_BIN = path.resolve(__dirname, "../../dist/index.js");
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Runs the CLI command against the compiled binary (E2E style)
|
|
11
|
-
*/
|
|
12
|
-
export async function runCLI(args: string[], cwd: string, options: any = {}) {
|
|
13
|
-
return execa("node", [CLI_BIN, ...args], {
|
|
14
|
-
cwd,
|
|
15
|
-
...options,
|
|
16
|
-
env: {
|
|
17
|
-
...process.env,
|
|
18
|
-
...options.env,
|
|
19
|
-
},
|
|
20
|
-
reject: false, // Allow checking exit code in tests
|
|
21
|
-
});
|
|
22
|
-
}
|