@arcadialdev/arcality 2.4.23 → 2.4.25
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/.agents/skills/e2e-testing-expert/SKILL.md +28 -28
- package/.agents/skills/security-qa/SKILL.md +254 -0
- package/README.md +95 -95
- package/bin/arcality.mjs +55 -93
- package/package.json +68 -68
- package/playwright.config.js +33 -33
- package/scripts/gen-and-run.mjs +24 -13
- package/scripts/init.mjs +297 -296
- package/scripts/postinstall.mjs +77 -77
- package/scripts/setup.mjs +166 -166
- package/src/configLoader.mjs +179 -185
- package/src/configManager.mjs +172 -172
- package/src/envSetup.ts +205 -205
- package/src/index.ts +25 -25
- package/src/services/collectiveMemoryService.ts +1 -1
- package/src/services/securityScanner.ts +128 -0
- package/tests/_helpers/ArcalityReporter.js +632 -229
- package/tests/_helpers/ArcalityReporter.ts +262 -27
- package/tests/_helpers/agentic-runner.bundle.spec.js +366 -8
- package/tests/_helpers/agentic-runner.spec.ts +46 -4
- package/tests/_helpers/ai-agent-helper.ts +128 -6
- package/tests/_helpers/qa-security-tools.ts +265 -0
package/src/configManager.mjs
CHANGED
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
// src/configManager.mjs
|
|
2
|
-
// Manages the local arcality.config file — single configuration per project.
|
|
3
|
-
// Replaces multi-config .env approach.
|
|
4
|
-
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
|
|
8
|
-
const CONFIG_FILENAME = 'arcality.config';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Resolves the path to arcality.config in the project root.
|
|
12
|
-
* @param {string} [projectRoot] - Override project root. Defaults to cwd.
|
|
13
|
-
* @returns {string}
|
|
14
|
-
*/
|
|
15
|
-
export function getConfigPath(projectRoot) {
|
|
16
|
-
return path.join(projectRoot || process.cwd(), CONFIG_FILENAME);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Checks if arcality.config exists in the project.
|
|
21
|
-
* @param {string} [projectRoot]
|
|
22
|
-
* @returns {boolean}
|
|
23
|
-
*/
|
|
24
|
-
export function configExists(projectRoot) {
|
|
25
|
-
return fs.existsSync(getConfigPath(projectRoot));
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Reads and parses the arcality.config file.
|
|
30
|
-
* @param {string} [projectRoot]
|
|
31
|
-
* @returns {ArcalityConfig | null}
|
|
32
|
-
*/
|
|
33
|
-
export function loadProjectConfig(projectRoot) {
|
|
34
|
-
const configPath = getConfigPath(projectRoot);
|
|
35
|
-
try {
|
|
36
|
-
if (!fs.existsSync(configPath)) return null;
|
|
37
|
-
let raw = fs.readFileSync(configPath, 'utf8');
|
|
38
|
-
// Strip BOM if present
|
|
39
|
-
if (raw.charCodeAt(0) === 0xFEFF) raw = raw.slice(1);
|
|
40
|
-
return JSON.parse(raw);
|
|
41
|
-
} catch (err) {
|
|
42
|
-
console.error(`⚠️ Error reading ${CONFIG_FILENAME}: ${err.message}`);
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Writes the arcality.config file.
|
|
49
|
-
* @param {ArcalityConfig} config
|
|
50
|
-
* @param {string} [projectRoot]
|
|
51
|
-
*/
|
|
52
|
-
export function saveProjectConfig(config, projectRoot) {
|
|
53
|
-
const configPath = getConfigPath(projectRoot);
|
|
54
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Validates that the config has all required fields for running.
|
|
59
|
-
* @param {ArcalityConfig} config
|
|
60
|
-
* @returns {{ valid: boolean, missing: string[] }}
|
|
61
|
-
*/
|
|
62
|
-
export function validateConfig(config) {
|
|
63
|
-
const missing = [];
|
|
64
|
-
|
|
65
|
-
if (!config) {
|
|
66
|
-
return { valid: false, missing: ['arcality.config file'] };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!config.apiKey) missing.push('apiKey');
|
|
70
|
-
if (!config.projectId) missing.push('projectId');
|
|
71
|
-
if (!config.project?.baseUrl) missing.push('project.baseUrl');
|
|
72
|
-
if (!config.auth?.username) missing.push('auth.username');
|
|
73
|
-
if (!config.auth?.password) missing.push('auth.password');
|
|
74
|
-
|
|
75
|
-
return { valid: missing.length === 0, missing };
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Creates a fresh arcality.config structure.
|
|
80
|
-
* @param {object} params
|
|
81
|
-
* @returns {ArcalityConfig}
|
|
82
|
-
*/
|
|
83
|
-
export function createConfig({
|
|
84
|
-
apiKey,
|
|
85
|
-
organizationId,
|
|
86
|
-
projectId,
|
|
87
|
-
projectName,
|
|
88
|
-
baseUrl,
|
|
89
|
-
frameworkDetected,
|
|
90
|
-
username,
|
|
91
|
-
password,
|
|
92
|
-
arcalityVersion,
|
|
93
|
-
yamlOutputDir = './arcality',
|
|
94
|
-
}) {
|
|
95
|
-
return {
|
|
96
|
-
version: '1',
|
|
97
|
-
apiKey,
|
|
98
|
-
organizationId: organizationId || null,
|
|
99
|
-
projectId,
|
|
100
|
-
project: {
|
|
101
|
-
name: projectName,
|
|
102
|
-
baseUrl,
|
|
103
|
-
frameworkDetected: frameworkDetected || null,
|
|
104
|
-
},
|
|
105
|
-
auth: {
|
|
106
|
-
username,
|
|
107
|
-
password,
|
|
108
|
-
},
|
|
109
|
-
runtime: {
|
|
110
|
-
yamlOutputDir,
|
|
111
|
-
reuseSuccessfulYamls: true,
|
|
112
|
-
singleConfigurationMode: true,
|
|
113
|
-
},
|
|
114
|
-
meta: {
|
|
115
|
-
arcalityVersion: arcalityVersion || 'unknown',
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Injects arcality.config values into process.env for backward compat
|
|
122
|
-
* with existing modules that read from process.env.
|
|
123
|
-
* @param {ArcalityConfig} config
|
|
124
|
-
*/
|
|
125
|
-
export function injectConfigToEnv(config) {
|
|
126
|
-
if (!config) return;
|
|
127
|
-
|
|
128
|
-
if (config.apiKey) process.env.ARCALITY_API_KEY = config.apiKey;
|
|
129
|
-
if (config.projectId) process.env.ARCALITY_PROJECT_ID = config.projectId;
|
|
130
|
-
if (config.project?.baseUrl) {
|
|
131
|
-
process.env.BASE_URL = config.project.baseUrl;
|
|
132
|
-
}
|
|
133
|
-
if (config.auth?.username) process.env.LOGIN_USER = config.auth.username;
|
|
134
|
-
if (config.auth?.password) process.env.LOGIN_PASSWORD = config.auth.password;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Gets the YAML output directory from config, falling back to default.
|
|
139
|
-
* @param {ArcalityConfig} config
|
|
140
|
-
* @param {string} [projectRoot]
|
|
141
|
-
* @returns {string} absolute path
|
|
142
|
-
*/
|
|
143
|
-
export function getYamlOutputDir(config, projectRoot) {
|
|
144
|
-
const dir = config?.runtime?.yamlOutputDir || './arcality';
|
|
145
|
-
return path.resolve(projectRoot || process.cwd(), dir);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Ensures the YAML output directory exists.
|
|
150
|
-
* @param {ArcalityConfig} config
|
|
151
|
-
* @param {string} [projectRoot]
|
|
152
|
-
* @returns {string} absolute path to the directory
|
|
153
|
-
*/
|
|
154
|
-
export function ensureYamlOutputDir(config, projectRoot) {
|
|
155
|
-
const dir = getYamlOutputDir(config, projectRoot);
|
|
156
|
-
if (!fs.existsSync(dir)) {
|
|
157
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
158
|
-
}
|
|
159
|
-
return dir;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @typedef {object} ArcalityConfig
|
|
164
|
-
* @property {string} version
|
|
165
|
-
* @property {string} apiKey
|
|
166
|
-
* @property {string|null} organizationId
|
|
167
|
-
* @property {string} projectId
|
|
168
|
-
* @property {{ name: string, baseUrl: string, frameworkDetected: string|null }} project
|
|
169
|
-
* @property {{ username: string, password: string }} auth
|
|
170
|
-
* @property {{ yamlOutputDir: string, reuseSuccessfulYamls: boolean, singleConfigurationMode: boolean }} runtime
|
|
171
|
-
* @property {{ arcalityVersion: string }} meta
|
|
172
|
-
*/
|
|
1
|
+
// src/configManager.mjs
|
|
2
|
+
// Manages the local arcality.config file — single configuration per project.
|
|
3
|
+
// Replaces multi-config .env approach.
|
|
4
|
+
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
|
|
8
|
+
const CONFIG_FILENAME = 'arcality.config';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the path to arcality.config in the project root.
|
|
12
|
+
* @param {string} [projectRoot] - Override project root. Defaults to cwd.
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
export function getConfigPath(projectRoot) {
|
|
16
|
+
return path.join(projectRoot || process.cwd(), CONFIG_FILENAME);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Checks if arcality.config exists in the project.
|
|
21
|
+
* @param {string} [projectRoot]
|
|
22
|
+
* @returns {boolean}
|
|
23
|
+
*/
|
|
24
|
+
export function configExists(projectRoot) {
|
|
25
|
+
return fs.existsSync(getConfigPath(projectRoot));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Reads and parses the arcality.config file.
|
|
30
|
+
* @param {string} [projectRoot]
|
|
31
|
+
* @returns {ArcalityConfig | null}
|
|
32
|
+
*/
|
|
33
|
+
export function loadProjectConfig(projectRoot) {
|
|
34
|
+
const configPath = getConfigPath(projectRoot);
|
|
35
|
+
try {
|
|
36
|
+
if (!fs.existsSync(configPath)) return null;
|
|
37
|
+
let raw = fs.readFileSync(configPath, 'utf8');
|
|
38
|
+
// Strip BOM if present
|
|
39
|
+
if (raw.charCodeAt(0) === 0xFEFF) raw = raw.slice(1);
|
|
40
|
+
return JSON.parse(raw);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(`⚠️ Error reading ${CONFIG_FILENAME}: ${err.message}`);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Writes the arcality.config file.
|
|
49
|
+
* @param {ArcalityConfig} config
|
|
50
|
+
* @param {string} [projectRoot]
|
|
51
|
+
*/
|
|
52
|
+
export function saveProjectConfig(config, projectRoot) {
|
|
53
|
+
const configPath = getConfigPath(projectRoot);
|
|
54
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Validates that the config has all required fields for running.
|
|
59
|
+
* @param {ArcalityConfig} config
|
|
60
|
+
* @returns {{ valid: boolean, missing: string[] }}
|
|
61
|
+
*/
|
|
62
|
+
export function validateConfig(config) {
|
|
63
|
+
const missing = [];
|
|
64
|
+
|
|
65
|
+
if (!config) {
|
|
66
|
+
return { valid: false, missing: ['arcality.config file'] };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!config.apiKey) missing.push('apiKey');
|
|
70
|
+
if (!config.projectId) missing.push('projectId');
|
|
71
|
+
if (!config.project?.baseUrl) missing.push('project.baseUrl');
|
|
72
|
+
if (!config.auth?.username) missing.push('auth.username');
|
|
73
|
+
if (!config.auth?.password) missing.push('auth.password');
|
|
74
|
+
|
|
75
|
+
return { valid: missing.length === 0, missing };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates a fresh arcality.config structure.
|
|
80
|
+
* @param {object} params
|
|
81
|
+
* @returns {ArcalityConfig}
|
|
82
|
+
*/
|
|
83
|
+
export function createConfig({
|
|
84
|
+
apiKey,
|
|
85
|
+
organizationId,
|
|
86
|
+
projectId,
|
|
87
|
+
projectName,
|
|
88
|
+
baseUrl,
|
|
89
|
+
frameworkDetected,
|
|
90
|
+
username,
|
|
91
|
+
password,
|
|
92
|
+
arcalityVersion,
|
|
93
|
+
yamlOutputDir = './arcality',
|
|
94
|
+
}) {
|
|
95
|
+
return {
|
|
96
|
+
version: '1',
|
|
97
|
+
apiKey,
|
|
98
|
+
organizationId: organizationId || null,
|
|
99
|
+
projectId,
|
|
100
|
+
project: {
|
|
101
|
+
name: projectName,
|
|
102
|
+
baseUrl,
|
|
103
|
+
frameworkDetected: frameworkDetected || null,
|
|
104
|
+
},
|
|
105
|
+
auth: {
|
|
106
|
+
username,
|
|
107
|
+
password,
|
|
108
|
+
},
|
|
109
|
+
runtime: {
|
|
110
|
+
yamlOutputDir,
|
|
111
|
+
reuseSuccessfulYamls: true,
|
|
112
|
+
singleConfigurationMode: true,
|
|
113
|
+
},
|
|
114
|
+
meta: {
|
|
115
|
+
arcalityVersion: arcalityVersion || 'unknown',
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Injects arcality.config values into process.env for backward compat
|
|
122
|
+
* with existing modules that read from process.env.
|
|
123
|
+
* @param {ArcalityConfig} config
|
|
124
|
+
*/
|
|
125
|
+
export function injectConfigToEnv(config) {
|
|
126
|
+
if (!config) return;
|
|
127
|
+
|
|
128
|
+
if (config.apiKey) process.env.ARCALITY_API_KEY = config.apiKey;
|
|
129
|
+
if (config.projectId) process.env.ARCALITY_PROJECT_ID = config.projectId;
|
|
130
|
+
if (config.project?.baseUrl) {
|
|
131
|
+
process.env.BASE_URL = config.project.baseUrl;
|
|
132
|
+
}
|
|
133
|
+
if (config.auth?.username) process.env.LOGIN_USER = config.auth.username;
|
|
134
|
+
if (config.auth?.password) process.env.LOGIN_PASSWORD = config.auth.password;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Gets the YAML output directory from config, falling back to default.
|
|
139
|
+
* @param {ArcalityConfig} config
|
|
140
|
+
* @param {string} [projectRoot]
|
|
141
|
+
* @returns {string} absolute path
|
|
142
|
+
*/
|
|
143
|
+
export function getYamlOutputDir(config, projectRoot) {
|
|
144
|
+
const dir = config?.runtime?.yamlOutputDir || './arcality';
|
|
145
|
+
return path.resolve(projectRoot || process.cwd(), dir);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Ensures the YAML output directory exists.
|
|
150
|
+
* @param {ArcalityConfig} config
|
|
151
|
+
* @param {string} [projectRoot]
|
|
152
|
+
* @returns {string} absolute path to the directory
|
|
153
|
+
*/
|
|
154
|
+
export function ensureYamlOutputDir(config, projectRoot) {
|
|
155
|
+
const dir = getYamlOutputDir(config, projectRoot);
|
|
156
|
+
if (!fs.existsSync(dir)) {
|
|
157
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
158
|
+
}
|
|
159
|
+
return dir;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @typedef {object} ArcalityConfig
|
|
164
|
+
* @property {string} version
|
|
165
|
+
* @property {string} apiKey
|
|
166
|
+
* @property {string|null} organizationId
|
|
167
|
+
* @property {string} projectId
|
|
168
|
+
* @property {{ name: string, baseUrl: string, frameworkDetected: string|null }} project
|
|
169
|
+
* @property {{ username: string, password: string }} auth
|
|
170
|
+
* @property {{ yamlOutputDir: string, reuseSuccessfulYamls: boolean, singleConfigurationMode: boolean }} runtime
|
|
171
|
+
* @property {{ arcalityVersion: string }} meta
|
|
172
|
+
*/
|