@autifyhq/aximo-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +379 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +21 -0
- package/dist/client.d.ts +18 -0
- package/dist/client.js +90 -0
- package/dist/client.test.d.ts +1 -0
- package/dist/client.test.js +127 -0
- package/dist/commands/configure.d.ts +24 -0
- package/dist/commands/configure.js +103 -0
- package/dist/commands/configure.test.d.ts +1 -0
- package/dist/commands/configure.test.js +96 -0
- package/dist/commands/device/connect.d.ts +2 -0
- package/dist/commands/device/connect.js +84 -0
- package/dist/commands/device/doctor.d.ts +34 -0
- package/dist/commands/device/doctor.js +421 -0
- package/dist/commands/device/doctor.test.d.ts +1 -0
- package/dist/commands/device/doctor.test.js +89 -0
- package/dist/commands/device/index.d.ts +2 -0
- package/dist/commands/device/index.js +16 -0
- package/dist/commands/device/list.d.ts +20 -0
- package/dist/commands/device/list.js +40 -0
- package/dist/commands/device/list.test.d.ts +1 -0
- package/dist/commands/device/list.test.js +38 -0
- package/dist/commands/device/logs.d.ts +34 -0
- package/dist/commands/device/logs.js +160 -0
- package/dist/commands/device/logs.test.d.ts +1 -0
- package/dist/commands/device/logs.test.js +70 -0
- package/dist/commands/device/paths.d.ts +12 -0
- package/dist/commands/device/paths.js +40 -0
- package/dist/commands/device/ping.d.ts +21 -0
- package/dist/commands/device/ping.js +66 -0
- package/dist/commands/device/ping.test.d.ts +1 -0
- package/dist/commands/device/ping.test.js +68 -0
- package/dist/commands/device/register.d.ts +23 -0
- package/dist/commands/device/register.js +83 -0
- package/dist/commands/device/reset.d.ts +30 -0
- package/dist/commands/device/reset.js +67 -0
- package/dist/commands/device/reset.test.d.ts +1 -0
- package/dist/commands/device/reset.test.js +69 -0
- package/dist/commands/device/setup.d.ts +25 -0
- package/dist/commands/device/setup.js +105 -0
- package/dist/commands/device/setup.test.d.ts +1 -0
- package/dist/commands/device/setup.test.js +64 -0
- package/dist/commands/device/status.d.ts +16 -0
- package/dist/commands/device/status.js +20 -0
- package/dist/commands/device/unregister.d.ts +14 -0
- package/dist/commands/device/unregister.js +60 -0
- package/dist/commands/health/check.d.ts +5 -0
- package/dist/commands/health/check.js +20 -0
- package/dist/commands/health/check.test.d.ts +1 -0
- package/dist/commands/health/check.test.js +26 -0
- package/dist/commands/health/index.d.ts +2 -0
- package/dist/commands/health/index.js +7 -0
- package/dist/commands/project/index.d.ts +2 -0
- package/dist/commands/project/index.js +7 -0
- package/dist/commands/project/list.d.ts +7 -0
- package/dist/commands/project/list.js +20 -0
- package/dist/commands/project/list.test.d.ts +1 -0
- package/dist/commands/project/list.test.js +28 -0
- package/dist/commands/schema.d.ts +27 -0
- package/dist/commands/schema.js +146 -0
- package/dist/commands/schema.test.d.ts +1 -0
- package/dist/commands/schema.test.js +38 -0
- package/dist/commands/session/create.d.ts +78 -0
- package/dist/commands/session/create.js +89 -0
- package/dist/commands/session/get.d.ts +11 -0
- package/dist/commands/session/get.js +30 -0
- package/dist/commands/session/index.d.ts +2 -0
- package/dist/commands/session/index.js +8 -0
- package/dist/commands/session/session.test.d.ts +1 -0
- package/dist/commands/session/session.test.js +128 -0
- package/dist/commands/trigger/case/get.d.ts +14 -0
- package/dist/commands/trigger/case/get.js +33 -0
- package/dist/commands/trigger/case/index.d.ts +2 -0
- package/dist/commands/trigger/case/index.js +8 -0
- package/dist/commands/trigger/case/run.d.ts +58 -0
- package/dist/commands/trigger/case/run.js +81 -0
- package/dist/commands/trigger/index.d.ts +2 -0
- package/dist/commands/trigger/index.js +8 -0
- package/dist/commands/trigger/plan/get.d.ts +14 -0
- package/dist/commands/trigger/plan/get.js +33 -0
- package/dist/commands/trigger/plan/index.d.ts +2 -0
- package/dist/commands/trigger/plan/index.js +8 -0
- package/dist/commands/trigger/plan/run.d.ts +33 -0
- package/dist/commands/trigger/plan/run.js +63 -0
- package/dist/commands/trigger/trigger.test.d.ts +1 -0
- package/dist/commands/trigger/trigger.test.js +107 -0
- package/dist/commands/upload/create.d.ts +32 -0
- package/dist/commands/upload/create.js +65 -0
- package/dist/commands/upload/get.d.ts +10 -0
- package/dist/commands/upload/get.js +30 -0
- package/dist/commands/upload/index.d.ts +2 -0
- package/dist/commands/upload/index.js +11 -0
- package/dist/commands/upload/list.d.ts +15 -0
- package/dist/commands/upload/list.js +31 -0
- package/dist/commands/upload/put.d.ts +24 -0
- package/dist/commands/upload/put.js +62 -0
- package/dist/commands/upload/submit.d.ts +19 -0
- package/dist/commands/upload/submit.js +36 -0
- package/dist/commands/upload/upload.test.d.ts +1 -0
- package/dist/commands/upload/upload.test.js +133 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +36 -0
- package/dist/desktop-server/agent-sync.d.ts +19 -0
- package/dist/desktop-server/agent-sync.js +141 -0
- package/dist/desktop-server/agent-sync.test.d.ts +1 -0
- package/dist/desktop-server/agent-sync.test.js +130 -0
- package/dist/desktop-server/setup.d.ts +19 -0
- package/dist/desktop-server/setup.js +200 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +71 -0
- package/dist/errors.test.d.ts +1 -0
- package/dist/errors.test.js +88 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +17 -0
- package/dist/mutate.d.ts +13 -0
- package/dist/mutate.js +25 -0
- package/dist/mutate.test.d.ts +1 -0
- package/dist/mutate.test.js +49 -0
- package/dist/output.d.ts +5 -0
- package/dist/output.js +23 -0
- package/dist/output.test.d.ts +1 -0
- package/dist/output.test.js +42 -0
- package/dist/test-setup.d.ts +1 -0
- package/dist/test-setup.js +13 -0
- package/dist/test-utils.d.ts +4 -0
- package/dist/test-utils.js +5 -0
- package/dist/types.d.ts +121 -0
- package/dist/types.js +2 -0
- package/dist/validate.d.ts +14 -0
- package/dist/validate.js +103 -0
- package/dist/validate.test.d.ts +1 -0
- package/dist/validate.test.js +96 -0
- package/package.json +72 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export interface SuccessMeta {
|
|
2
|
+
total?: number | undefined;
|
|
3
|
+
}
|
|
4
|
+
export interface SuccessEnvelope<T> {
|
|
5
|
+
ok: true;
|
|
6
|
+
data: T;
|
|
7
|
+
meta?: SuccessMeta | undefined;
|
|
8
|
+
}
|
|
9
|
+
export type ErrorCode = "unauthorized" | "rate_limited" | "not_found" | "validation_error" | "api_error";
|
|
10
|
+
export interface ErrorEnvelope {
|
|
11
|
+
ok: false;
|
|
12
|
+
error: {
|
|
13
|
+
code: ErrorCode;
|
|
14
|
+
message: string;
|
|
15
|
+
hint?: string | undefined;
|
|
16
|
+
retryable: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export type Envelope<T> = SuccessEnvelope<T> | ErrorEnvelope;
|
|
20
|
+
export type Platform = "ANDROID" | "IOS";
|
|
21
|
+
export type FileType = "ANDROID_APP" | "IOS_APP";
|
|
22
|
+
export interface HealthStatus {
|
|
23
|
+
status: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CreateSessionInput {
|
|
26
|
+
title: string;
|
|
27
|
+
prompt: string;
|
|
28
|
+
projectId: string;
|
|
29
|
+
platform?: Platform | undefined;
|
|
30
|
+
model?: string | undefined;
|
|
31
|
+
startUrl?: string | undefined;
|
|
32
|
+
caseId?: string | undefined;
|
|
33
|
+
tags?: string[] | undefined;
|
|
34
|
+
deviceArn?: string | undefined;
|
|
35
|
+
deviceName?: string | undefined;
|
|
36
|
+
uploadArn?: string | undefined;
|
|
37
|
+
uploadType?: FileType | undefined;
|
|
38
|
+
appName?: string | undefined;
|
|
39
|
+
bundleId?: string | undefined;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateSessionResult {
|
|
42
|
+
success: boolean;
|
|
43
|
+
sessionId: string;
|
|
44
|
+
}
|
|
45
|
+
export interface Session {
|
|
46
|
+
id: string;
|
|
47
|
+
title?: string | undefined;
|
|
48
|
+
status?: string | undefined;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
export interface CaseRunInput {
|
|
52
|
+
model?: string | undefined;
|
|
53
|
+
hostnameOverrideIds?: string[] | undefined;
|
|
54
|
+
deviceArn?: string | undefined;
|
|
55
|
+
deviceName?: string | undefined;
|
|
56
|
+
platform?: Platform | undefined;
|
|
57
|
+
uploadArn?: string | undefined;
|
|
58
|
+
uploadType?: FileType | undefined;
|
|
59
|
+
appName?: string | undefined;
|
|
60
|
+
}
|
|
61
|
+
export interface CaseRunResult {
|
|
62
|
+
success: boolean;
|
|
63
|
+
sessionId: string;
|
|
64
|
+
}
|
|
65
|
+
export interface CaseRunStatus {
|
|
66
|
+
id: string;
|
|
67
|
+
status: string;
|
|
68
|
+
result?: string | undefined;
|
|
69
|
+
platform: string;
|
|
70
|
+
screenshotsCount: number;
|
|
71
|
+
startedAt?: string | undefined;
|
|
72
|
+
completedAt?: string | undefined;
|
|
73
|
+
}
|
|
74
|
+
export interface PlanRunInput {
|
|
75
|
+
model?: string | undefined;
|
|
76
|
+
mobileConfig?: Record<string, unknown> | undefined;
|
|
77
|
+
}
|
|
78
|
+
export interface PlanRunResult {
|
|
79
|
+
success: boolean;
|
|
80
|
+
planRunId: string;
|
|
81
|
+
totalCases: number;
|
|
82
|
+
}
|
|
83
|
+
export interface PlanRun {
|
|
84
|
+
id: string;
|
|
85
|
+
status?: string | undefined;
|
|
86
|
+
[key: string]: unknown;
|
|
87
|
+
}
|
|
88
|
+
export interface Device {
|
|
89
|
+
arn?: string | undefined;
|
|
90
|
+
name?: string | undefined;
|
|
91
|
+
platform?: Platform | undefined;
|
|
92
|
+
[key: string]: unknown;
|
|
93
|
+
}
|
|
94
|
+
export interface CreateUploadInput {
|
|
95
|
+
fileName: string;
|
|
96
|
+
fileSize?: number | undefined;
|
|
97
|
+
platform?: Platform | undefined;
|
|
98
|
+
}
|
|
99
|
+
export interface CreateUploadResult {
|
|
100
|
+
uploadId: string;
|
|
101
|
+
presignedUrl: string;
|
|
102
|
+
fileType: FileType;
|
|
103
|
+
}
|
|
104
|
+
export interface Upload {
|
|
105
|
+
id?: string | undefined;
|
|
106
|
+
fileName?: string | undefined;
|
|
107
|
+
fileType?: FileType | undefined;
|
|
108
|
+
[key: string]: unknown;
|
|
109
|
+
}
|
|
110
|
+
export interface UploadPutResult {
|
|
111
|
+
success: boolean;
|
|
112
|
+
}
|
|
113
|
+
export interface UploadSubmitResult {
|
|
114
|
+
success: boolean;
|
|
115
|
+
workflowId: string;
|
|
116
|
+
}
|
|
117
|
+
export interface Project {
|
|
118
|
+
id?: string | undefined;
|
|
119
|
+
name?: string | undefined;
|
|
120
|
+
[key: string]: unknown;
|
|
121
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Platform, FileType } from "./types.js";
|
|
2
|
+
export declare function optionalString(name: string, value: unknown): string | undefined;
|
|
3
|
+
export declare function parseStringList(name: string, value: unknown): string[] | undefined;
|
|
4
|
+
export declare function requireString(name: string, value: unknown): string;
|
|
5
|
+
export declare function requireId(name: string, value: unknown): string;
|
|
6
|
+
export declare function parsePlatform(value: unknown): Platform | undefined;
|
|
7
|
+
export declare function parseFileType(value: unknown): FileType | undefined;
|
|
8
|
+
export declare function parseTags(value: unknown): string[] | undefined;
|
|
9
|
+
export declare const OPENAPI_URL = "https://aximo.autify.com/openapi.yaml";
|
|
10
|
+
export declare class JsonBodyError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare function parseJsonBody(value: unknown): Record<string, unknown>;
|
|
14
|
+
export declare function parseJsonObject(name: string, value: unknown): Record<string, unknown> | undefined;
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Reject control characters in user-supplied identifiers (header injection guard).
|
|
2
|
+
// eslint-disable-next-line no-control-regex
|
|
3
|
+
const CONTROL_CHAR_RE = /[\u0000-\u001f\u007f]/;
|
|
4
|
+
export function optionalString(name, value) {
|
|
5
|
+
if (value === undefined || value === "")
|
|
6
|
+
return undefined;
|
|
7
|
+
return requireString(name, value);
|
|
8
|
+
}
|
|
9
|
+
export function parseStringList(name, value) {
|
|
10
|
+
if (value === undefined || value === "")
|
|
11
|
+
return undefined;
|
|
12
|
+
if (typeof value !== "string") {
|
|
13
|
+
throw new Error(`${name} must be a comma-separated string`);
|
|
14
|
+
}
|
|
15
|
+
const items = value
|
|
16
|
+
.split(",")
|
|
17
|
+
.map((s) => s.trim())
|
|
18
|
+
.filter((s) => s.length > 0);
|
|
19
|
+
return items.length > 0 ? items : undefined;
|
|
20
|
+
}
|
|
21
|
+
export function requireString(name, value) {
|
|
22
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
23
|
+
throw new Error(`${name} is required`);
|
|
24
|
+
}
|
|
25
|
+
if (CONTROL_CHAR_RE.test(value)) {
|
|
26
|
+
throw new Error(`${name} contains control characters`);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
// Agents sometimes hallucinate IDs like "caseId?fields=name" or pre-URL-encoded
|
|
31
|
+
// strings. requireId rejects characters that would smuggle query/path/escape
|
|
32
|
+
// semantics into what should be an opaque identifier.
|
|
33
|
+
const ID_FORBIDDEN_RE = /[?#%/\\\s]|\.\./;
|
|
34
|
+
export function requireId(name, value) {
|
|
35
|
+
const str = requireString(name, value);
|
|
36
|
+
if (ID_FORBIDDEN_RE.test(str)) {
|
|
37
|
+
throw new Error(`${name} contains forbidden characters (?, #, %, /, \\, .., whitespace)`);
|
|
38
|
+
}
|
|
39
|
+
return str;
|
|
40
|
+
}
|
|
41
|
+
const PLATFORMS = new Set(["ANDROID", "IOS"]);
|
|
42
|
+
export function parsePlatform(value) {
|
|
43
|
+
if (value === undefined || value === "")
|
|
44
|
+
return undefined;
|
|
45
|
+
if (typeof value !== "string" || !PLATFORMS.has(value)) {
|
|
46
|
+
throw new Error(`platform must be ANDROID or IOS (got ${String(value)})`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
const FILE_TYPES = new Set(["ANDROID_APP", "IOS_APP"]);
|
|
51
|
+
export function parseFileType(value) {
|
|
52
|
+
if (value === undefined || value === "")
|
|
53
|
+
return undefined;
|
|
54
|
+
if (typeof value !== "string" || !FILE_TYPES.has(value)) {
|
|
55
|
+
throw new Error(`fileType must be ANDROID_APP or IOS_APP (got ${String(value)})`);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
export function parseTags(value) {
|
|
60
|
+
return parseStringList("tags", value);
|
|
61
|
+
}
|
|
62
|
+
export const OPENAPI_URL = "https://aximo.autify.com/openapi.yaml";
|
|
63
|
+
// Sentinel error used by handlers so the envelope can attach the OpenAPI hint
|
|
64
|
+
// without losing the original parser message.
|
|
65
|
+
export class JsonBodyError extends Error {
|
|
66
|
+
constructor(message) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = "JsonBodyError";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function parseJsonBody(value) {
|
|
72
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
73
|
+
throw new JsonBodyError("--json must be a non-empty JSON string");
|
|
74
|
+
}
|
|
75
|
+
let parsed;
|
|
76
|
+
try {
|
|
77
|
+
parsed = JSON.parse(value);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
throw new JsonBodyError(`--json is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
+
}
|
|
82
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
83
|
+
throw new JsonBodyError("--json must be a JSON object");
|
|
84
|
+
}
|
|
85
|
+
return parsed;
|
|
86
|
+
}
|
|
87
|
+
export function parseJsonObject(name, value) {
|
|
88
|
+
if (value === undefined || value === "")
|
|
89
|
+
return undefined;
|
|
90
|
+
if (typeof value !== "string")
|
|
91
|
+
throw new Error(`${name} must be a JSON string`);
|
|
92
|
+
let parsed;
|
|
93
|
+
try {
|
|
94
|
+
parsed = JSON.parse(value);
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
throw new Error(`${name} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
98
|
+
}
|
|
99
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
100
|
+
throw new Error(`${name} must be a JSON object`);
|
|
101
|
+
}
|
|
102
|
+
return parsed;
|
|
103
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { requireString, requireId, parsePlatform, parseFileType, parseTags, parseJsonObject, parseJsonBody, JsonBodyError, } from "./validate.js";
|
|
3
|
+
describe("requireId", () => {
|
|
4
|
+
it("accepts plain IDs", () => {
|
|
5
|
+
expect(requireId("sessionId", "abc123_-")).toBe("abc123_-");
|
|
6
|
+
});
|
|
7
|
+
it.each([
|
|
8
|
+
["caseId?fields=x"],
|
|
9
|
+
["caseId#frag"],
|
|
10
|
+
["caseId%20enc"],
|
|
11
|
+
["foo/bar"],
|
|
12
|
+
["foo\\bar"],
|
|
13
|
+
["../etc"],
|
|
14
|
+
["with space"],
|
|
15
|
+
])("rejects %s", (value) => {
|
|
16
|
+
expect(() => requireId("id", value)).toThrow(/forbidden/);
|
|
17
|
+
});
|
|
18
|
+
it("rejects tab via control-char check", () => {
|
|
19
|
+
expect(() => requireId("id", "tab\there")).toThrow();
|
|
20
|
+
});
|
|
21
|
+
it("still requires non-empty", () => {
|
|
22
|
+
expect(() => requireId("id", "")).toThrow(/required/);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("parseJsonBody", () => {
|
|
26
|
+
it("parses object", () => {
|
|
27
|
+
expect(parseJsonBody('{"a":1}')).toEqual({ a: 1 });
|
|
28
|
+
});
|
|
29
|
+
it("rejects invalid JSON with JsonBodyError", () => {
|
|
30
|
+
expect(() => parseJsonBody("{bad")).toThrow(JsonBodyError);
|
|
31
|
+
});
|
|
32
|
+
it("rejects arrays", () => {
|
|
33
|
+
expect(() => parseJsonBody("[1]")).toThrow(/JSON object/);
|
|
34
|
+
});
|
|
35
|
+
it("rejects empty", () => {
|
|
36
|
+
expect(() => parseJsonBody("")).toThrow(JsonBodyError);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("requireString", () => {
|
|
40
|
+
it("returns the value when non-empty string", () => {
|
|
41
|
+
expect(requireString("x", "hello")).toBe("hello");
|
|
42
|
+
});
|
|
43
|
+
it("throws on empty", () => {
|
|
44
|
+
expect(() => requireString("x", "")).toThrow("x is required");
|
|
45
|
+
});
|
|
46
|
+
it("throws on non-string", () => {
|
|
47
|
+
expect(() => requireString("x", 42)).toThrow();
|
|
48
|
+
});
|
|
49
|
+
it("rejects control characters", () => {
|
|
50
|
+
expect(() => requireString("x", "a\u0000b")).toThrow("control");
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe("parsePlatform", () => {
|
|
54
|
+
it("accepts ANDROID / IOS", () => {
|
|
55
|
+
expect(parsePlatform("ANDROID")).toBe("ANDROID");
|
|
56
|
+
expect(parsePlatform("IOS")).toBe("IOS");
|
|
57
|
+
});
|
|
58
|
+
it("returns undefined for undefined or empty", () => {
|
|
59
|
+
expect(parsePlatform(undefined)).toBeUndefined();
|
|
60
|
+
expect(parsePlatform("")).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
it("rejects invalid", () => {
|
|
63
|
+
expect(() => parsePlatform("WINDOWS")).toThrow();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("parseFileType", () => {
|
|
67
|
+
it("accepts valid values", () => {
|
|
68
|
+
expect(parseFileType("IOS_APP")).toBe("IOS_APP");
|
|
69
|
+
});
|
|
70
|
+
it("rejects invalid", () => {
|
|
71
|
+
expect(() => parseFileType("APK")).toThrow();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe("parseTags", () => {
|
|
75
|
+
it("splits and trims", () => {
|
|
76
|
+
expect(parseTags("a, b ,c")).toEqual(["a", "b", "c"]);
|
|
77
|
+
});
|
|
78
|
+
it("returns undefined for empty", () => {
|
|
79
|
+
expect(parseTags("")).toBeUndefined();
|
|
80
|
+
expect(parseTags(",,")).toBeUndefined();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("parseJsonObject", () => {
|
|
84
|
+
it("parses object", () => {
|
|
85
|
+
expect(parseJsonObject("mobileConfig", '{"a":1}')).toEqual({ a: 1 });
|
|
86
|
+
});
|
|
87
|
+
it("rejects arrays", () => {
|
|
88
|
+
expect(() => parseJsonObject("x", "[1]")).toThrow("must be a JSON object");
|
|
89
|
+
});
|
|
90
|
+
it("rejects invalid JSON", () => {
|
|
91
|
+
expect(() => parseJsonObject("x", "{bad")).toThrow("not valid JSON");
|
|
92
|
+
});
|
|
93
|
+
it("returns undefined for empty", () => {
|
|
94
|
+
expect(parseJsonObject("x", "")).toBeUndefined();
|
|
95
|
+
});
|
|
96
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autifyhq/aximo-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Autify Aximo Command Line Interface (CLI)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"autify",
|
|
7
|
+
"aximo",
|
|
8
|
+
"cli"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/autifyhq/aximo-cli#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/autifyhq/aximo-cli/issues"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"author": "Autify",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/autifyhq/aximo-cli.git"
|
|
19
|
+
},
|
|
20
|
+
"bin": {
|
|
21
|
+
"aximo": "./dist/cli.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"type": "module",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"citty": "0.2.2",
|
|
40
|
+
"ws": "^8.18.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@commitlint/cli": "20.5.0",
|
|
44
|
+
"@commitlint/config-conventional": "20.5.0",
|
|
45
|
+
"@secretlint/secretlint-rule-preset-recommend": "11.7.1",
|
|
46
|
+
"@types/node": "^25.6.0",
|
|
47
|
+
"@types/ws": "^8.18.0",
|
|
48
|
+
"@vitest/coverage-v8": "4.1.4",
|
|
49
|
+
"husky": "9.1.7",
|
|
50
|
+
"msw": "2.13.2",
|
|
51
|
+
"nano-staged": "1.0.2",
|
|
52
|
+
"oxfmt": "0.45.0",
|
|
53
|
+
"oxlint": "1.60.0",
|
|
54
|
+
"secretlint": "11.7.1",
|
|
55
|
+
"tsx": "4.21.0",
|
|
56
|
+
"typescript": "6.0.2",
|
|
57
|
+
"vitest": "4.1.4"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=20"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"build": "tsc",
|
|
64
|
+
"cli": "tsx src/cli.ts",
|
|
65
|
+
"format": "oxfmt --write .",
|
|
66
|
+
"format:check": "oxfmt --check .",
|
|
67
|
+
"lint": "oxlint --deny-warnings --report-unused-disable-directives",
|
|
68
|
+
"lint:fix": "oxlint --fix --report-unused-disable-directives",
|
|
69
|
+
"test": "vitest run --coverage",
|
|
70
|
+
"typecheck": "tsc --noEmit"
|
|
71
|
+
}
|
|
72
|
+
}
|