suitescript-verify 0.0.0-stage → 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 +54 -2
- package/dist/bin/suitescript-verify.js +3 -0
- package/dist/certificate.js +116 -0
- package/dist/cli.js +196 -0
- package/dist/config.js +141 -0
- package/dist/doctor.js +97 -0
- package/dist/envfile.js +56 -0
- package/dist/init.js +35 -0
- package/dist/netsuite.js +65 -0
- package/dist/probes.js +93 -0
- package/dist/results.js +33 -0
- package/dist/run.js +184 -0
- package/dist/sdf.js +53 -0
- package/dist/shared.js +132 -0
- package/package.json +75 -4
- package/templates/runner.template.js +64 -0
- package/templates/sdf/deploy.xml +8 -0
- package/templates/sdf/manifest.xml +12 -0
- package/templates/sdf/package.json +5 -0
- package/templates/sdf/runner.xml +17 -0
- package/templates/sdf/suitecloud.config.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,77 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "suitescript-verify",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Run probes in a NetSuite sandbox to verify what SuiteScript modules do, with guardrails for agents.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"suitescript",
|
|
7
|
+
"netsuite",
|
|
8
|
+
"verification",
|
|
9
|
+
"probe",
|
|
10
|
+
"suitecloud"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/nemchik/suitescript-verify#readme",
|
|
13
|
+
"bugs": "https://github.com/nemchik/suitescript-verify/issues",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/nemchik/suitescript-verify.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Eric Nemchik",
|
|
20
|
+
"type": "module",
|
|
21
|
+
"bin": {
|
|
22
|
+
"suitescript-verify": "./dist/bin/suitescript-verify.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"templates",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"prebuild": "node -e \"require(\\\"node:fs\\\").rmSync(\\\"dist\\\",{recursive:true,force:true})\"",
|
|
32
|
+
"build": "tsc -p tsconfig.build.json",
|
|
33
|
+
"check": "biome check",
|
|
34
|
+
"preformat": "npm run typecheck",
|
|
35
|
+
"format": "biome check --write",
|
|
36
|
+
"lint": "biome lint",
|
|
37
|
+
"prepack": "npm run build",
|
|
38
|
+
"skills": "node scripts/skills.ts",
|
|
39
|
+
"skills:add": "node scripts/skills.ts add --skill \"*\" --agent universal --agent claude-code --yes",
|
|
40
|
+
"skills:check": "node scripts/skills.ts check",
|
|
41
|
+
"skills:install": "node scripts/skills.ts experimental_install && node scripts/link-claude-skills.ts",
|
|
42
|
+
"skills:list": "node scripts/skills.ts list",
|
|
43
|
+
"skills:update": "node scripts/skills.ts update --project --yes && node scripts/link-claude-skills.ts",
|
|
44
|
+
"pretest": "npm run build",
|
|
45
|
+
"test": "node --test test/*.test.ts",
|
|
46
|
+
"typecheck": "tsc"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@biomejs/biome": "2.6.6",
|
|
50
|
+
"@types/node": "24.19.2",
|
|
51
|
+
"git-pull-run": "2.1.0",
|
|
52
|
+
"lefthook": "2.2.2",
|
|
53
|
+
"skills": "1.7.6",
|
|
54
|
+
"typescript": "7.0.2"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@oracle/suitecloud-cli": "^4.1.1"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=24"
|
|
61
|
+
},
|
|
62
|
+
"devEngines": {
|
|
63
|
+
"runtime": {
|
|
64
|
+
"name": "node",
|
|
65
|
+
"version": "24.22.3",
|
|
66
|
+
"onFail": "error"
|
|
67
|
+
},
|
|
68
|
+
"packageManager": {
|
|
69
|
+
"name": "npm",
|
|
70
|
+
"version": "12.2.2",
|
|
71
|
+
"onFail": "warn"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"allowScripts": {
|
|
75
|
+
"lefthook": true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The verification runner: a RESTlet that runs one probe by name and returns
|
|
3
|
+
* what it found. It never runs code from the request: the probes below are
|
|
4
|
+
* the only code it can run, and they are generated from the probes folder
|
|
5
|
+
* into this file's dependency list by `suitescript-verify deploy`.
|
|
6
|
+
*
|
|
7
|
+
* It refuses to run unless the account is a sandbox.
|
|
8
|
+
*
|
|
9
|
+
* @NApiVersion 2.1
|
|
10
|
+
* @NScriptType Restlet
|
|
11
|
+
*/
|
|
12
|
+
define(["N/runtime" /*PROBE_PATHS*/], (runtime /*PROBE_NAMES*/) => {
|
|
13
|
+
const probes = new Map([
|
|
14
|
+
/*PROBE_ENTRIES*/
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
post(body) {
|
|
19
|
+
if (runtime.envType !== runtime.EnvType.SANDBOX) {
|
|
20
|
+
return { error: "refused: the runner only runs in a sandbox" };
|
|
21
|
+
}
|
|
22
|
+
const name = body && typeof body.probe === "string" ? body.probe : "";
|
|
23
|
+
const entry = probes.get(name);
|
|
24
|
+
if (!entry) {
|
|
25
|
+
return { error: "unknown probe", known: [...probes.keys()] };
|
|
26
|
+
}
|
|
27
|
+
const [probe, declared] = entry;
|
|
28
|
+
// Parameters are data: only declared names, only strings that match the
|
|
29
|
+
// declared pattern in full, and never evaluated.
|
|
30
|
+
const sent = body.params === undefined ? {} : body.params;
|
|
31
|
+
if (!sent || typeof sent !== "object" || Array.isArray(sent)) {
|
|
32
|
+
return { error: "invalid params: expected an object" };
|
|
33
|
+
}
|
|
34
|
+
const params = {};
|
|
35
|
+
for (const key of Object.keys(sent)) {
|
|
36
|
+
if (!declared.some((param) => param.name === key)) {
|
|
37
|
+
return { error: `undeclared param: ${key}` };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const { name: key, pattern } of declared) {
|
|
41
|
+
const value = sent[key];
|
|
42
|
+
if (typeof value !== "string") {
|
|
43
|
+
return { error: `missing or non-string param: ${key}` };
|
|
44
|
+
}
|
|
45
|
+
if (!new RegExp(`^(?:${pattern})$`, "u").test(value)) {
|
|
46
|
+
return { error: `param does not match its pattern: ${key}` };
|
|
47
|
+
}
|
|
48
|
+
params[key] = value;
|
|
49
|
+
}
|
|
50
|
+
let result;
|
|
51
|
+
try {
|
|
52
|
+
result = probe.run(params);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
result = `THROWS: ${e.name}: ${e.message}`;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
probe: name,
|
|
58
|
+
result,
|
|
59
|
+
scriptType: "RESTlet",
|
|
60
|
+
version: String(runtime.version),
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<manifest projecttype="ACCOUNTCUSTOMIZATION">
|
|
2
|
+
<projectname>suitescript-verify</projectname>
|
|
3
|
+
<frameworkversion>1.0</frameworkversion>
|
|
4
|
+
<dependencies>
|
|
5
|
+
<features>
|
|
6
|
+
<feature required="true">SERVERSIDESCRIPTING</feature>
|
|
7
|
+
</features>
|
|
8
|
+
<objects>
|
|
9
|
+
<object>customrole_suitescript_verify</object>
|
|
10
|
+
</objects>
|
|
11
|
+
</dependencies>
|
|
12
|
+
</manifest>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<restlet scriptid="customscript_suitescript_verify_runner">
|
|
2
|
+
<description>Runs one version-controlled probe by name in a sandbox. Source: the project's verification folder, through suitescript-verify.</description>
|
|
3
|
+
<isinactive>F</isinactive>
|
|
4
|
+
<name>suitescript-verify runner</name>
|
|
5
|
+
<notifyowner>F</notifyowner>
|
|
6
|
+
<scriptfile>[/SuiteScripts/suitescript-verify/runner.js]</scriptfile>
|
|
7
|
+
<scriptdeployments>
|
|
8
|
+
<scriptdeployment scriptid="customdeploy_suitescript_verify_runner">
|
|
9
|
+
<allroles>F</allroles>
|
|
10
|
+
<audslctrole>[customrole_suitescript_verify]</audslctrole>
|
|
11
|
+
<isdeployed>%%DEPLOYED%%</isdeployed>
|
|
12
|
+
<loglevel>DEBUG</loglevel>
|
|
13
|
+
<status>RELEASED</status>
|
|
14
|
+
<title>suitescript-verify runner</title>
|
|
15
|
+
</scriptdeployment>
|
|
16
|
+
</scriptdeployments>
|
|
17
|
+
</restlet>
|