@meru454545/nexus-modscript-composer 2.0.12
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/README.md +179 -0
- package/dist/composer.d.ts +83 -0
- package/dist/composer.d.ts.map +1 -0
- package/dist/composer.js +367 -0
- package/dist/composer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/l0-parser.d.ts +22 -0
- package/dist/l0-parser.d.ts.map +1 -0
- package/dist/l0-parser.js +209 -0
- package/dist/l0-parser.js.map +1 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +54 -0
- package/dist/logger.js.map +1 -0
- package/dist/orchestrator.d.ts +41 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +198 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/script-validator.d.ts +22 -0
- package/dist/script-validator.d.ts.map +1 -0
- package/dist/script-validator.js +1029 -0
- package/dist/script-validator.js.map +1 -0
- package/dist/shellcheck-bin.d.ts +2 -0
- package/dist/shellcheck-bin.d.ts.map +1 -0
- package/dist/shellcheck-bin.js +42 -0
- package/dist/shellcheck-bin.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @meru2802/nexus-modscript-composer
|
|
2
|
+
|
|
3
|
+
Compose multi-layer deployment scripts for NexusEPM agents. Takes individual L0 monitoring/collection scripts and produces a composed L1 collection script + L2 deployment wrapper (systemd service on Linux, Scheduled Task on Windows).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @meru2802/nexus-modscript-composer
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { generateFinalScript } from "@meru2802/nexus-modscript-composer";
|
|
15
|
+
|
|
16
|
+
const l0Bodies = [tomcatScript, postgresqlScript]; // raw L0 script strings with metadata headers
|
|
17
|
+
|
|
18
|
+
const result = await generateFinalScript(l0Bodies, {
|
|
19
|
+
platform: "windows",
|
|
20
|
+
templateUrls: {
|
|
21
|
+
l1: "https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l1-windows.ps1.tmpl",
|
|
22
|
+
l2: "https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l2-windows.ps1.tmpl",
|
|
23
|
+
},
|
|
24
|
+
orgId: "acme-corp",
|
|
25
|
+
icebergEndpoint: "https://iceberg.example.com/api/v1/collect",
|
|
26
|
+
agentId: "agent-001",
|
|
27
|
+
authToken: "bearer-token",
|
|
28
|
+
bufferTime: "5m",
|
|
29
|
+
timeout: "10m",
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(result.l1Script); // composed L1 collection script
|
|
33
|
+
console.log(result.l2Script); // L2 deployment wrapper
|
|
34
|
+
console.log(result.modules); // ["tomcat", "postgresql"]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## The L0 output contract (`OUTPUT_SCHEMA_VERSION: 2`)
|
|
38
|
+
|
|
39
|
+
An L0 collector writes a stream of **single-line JSON records** to stdout — nothing else. There are exactly two shapes:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
{"log":"probing for tomcat via ps"}
|
|
43
|
+
{"log":"found 2 catalina processes"}
|
|
44
|
+
{"result":{"module":"tomcat","category":"app_monitoring","status":"ok","timestamp":"...","error":null,"data":{}}}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Any number of `{"log":...}` records, then exactly one `{"result":...}` as the last line.
|
|
48
|
+
|
|
49
|
+
L1 captures each module's stream, folds it into one envelope, and sends **one POST per module**. Your records travel **byte-for-byte** — L1 never unwraps or reshapes them:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"agent_id": "agent-001",
|
|
54
|
+
"org_id": "acme-corp",
|
|
55
|
+
"module": "tomcat",
|
|
56
|
+
"timestamp": "2026-07-29T10:00:00Z",
|
|
57
|
+
"logs": [ {"log":"probing for tomcat via ps"}, {"log":"found 2 catalina processes"} ],
|
|
58
|
+
"result": { "result": { "module": "tomcat", "status": "ok", "data": {} } }
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Because nothing is unwrapped, the collector payload sits at `envelope.result.result`.
|
|
63
|
+
|
|
64
|
+
If a collector errors or reaches the L1 timeout, L1 preserves every valid
|
|
65
|
+
`{"log":...}` record emitted before the failure, appends a synthetic error
|
|
66
|
+
result when needed, and still attempts the module POST before exiting.
|
|
67
|
+
|
|
68
|
+
Collectors get two helpers, defined inside the collector function:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
_nexus_log "method 3 (process): running=true score=5" # → {"log":"..."}
|
|
72
|
+
cat <<EOF | _nexus_result # → {"result":{...}} on one line
|
|
73
|
+
{ "module": "tomcat", ... }
|
|
74
|
+
EOF
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Verify any collector against the contract with:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
./scripts/verify-l0-contract.sh # all scripts in l0-scripts/
|
|
81
|
+
./scripts/verify-l0-contract.sh l0-scripts/mine.sh # one script
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See `AIX-L0-AUTHORING-GUIDE.md` §4 for the full contract, including the PowerShell equivalents.
|
|
85
|
+
|
|
86
|
+
## Template URLs
|
|
87
|
+
|
|
88
|
+
| Platform | Layer | URL |
|
|
89
|
+
|----------|-------|-----|
|
|
90
|
+
| Linux | L1 | `https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l1-linux.sh.tmpl` |
|
|
91
|
+
| Linux | L2 | `https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l2-linux.sh.tmpl` |
|
|
92
|
+
| Windows | L1 | `https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l1-windows.ps1.tmpl` |
|
|
93
|
+
| Windows | L2 | `https://nexus-endpoint-desktop-app.s3.ap-south-1.amazonaws.com/l1-l2-templates/l2-windows.ps1.tmpl` |
|
|
94
|
+
|
|
95
|
+
## `generateFinalScript(l0ScriptBodies, options)`
|
|
96
|
+
|
|
97
|
+
### Parameters
|
|
98
|
+
|
|
99
|
+
**`l0ScriptBodies`** `string[]` -- Array of raw L0 script contents. Each string must include the full metadata header (`# ==== NEXUS MODSCRIPT L0 ====` ... `# ==== END METADATA ====`) followed by the function body. All L0 scripts must target the same `OS_FAMILY` as the `platform` option.
|
|
100
|
+
|
|
101
|
+
**`options`** `GenerateOptions`:
|
|
102
|
+
|
|
103
|
+
| Field | Type | Required | Default | Description |
|
|
104
|
+
|-------|------|----------|---------|-------------|
|
|
105
|
+
| `platform` | `"linux" \| "windows"` | Yes | -- | Target OS. Must match the `OS_FAMILY` in all L0 scripts. |
|
|
106
|
+
| `templateUrls` | `{ l1: string, l2: string }` | Yes | -- | URLs to fetch the L1 and L2 template files. See table above. |
|
|
107
|
+
| `orgId` | `string` | No | `"test-client"` | Organization ID baked into L1 for Iceberg payloads. |
|
|
108
|
+
| `icebergEndpoint` | `string` | No | `"https://iceberg.example.com/api/v1/collect"` | URL where L1 POSTs collected data. Written to the L2 env file. |
|
|
109
|
+
| `agentId` | `string` | No | `"test-agent-001"` | Agent identifier included in Iceberg payloads. |
|
|
110
|
+
| `authToken` | `string` | No | `"test-bearer-token"` | Bearer token for Iceberg API authentication. |
|
|
111
|
+
| `bufferTime` | `string` | No | `"5m"` | Wait time after L1 completes before next run. Accepts `"30s"`, `"5m"`, `"1h"`. Linux: `OnUnitInactiveSec`. Windows: `Start-Sleep` in wrapper loop. |
|
|
112
|
+
| `timeout` | `string` | No | `"10m"` | L0 collection deadline. At the deadline L1 stops unfinished collectors and posts their partial logs; L2 retains a bounded hard-kill grace period. Same format as `bufferTime`. |
|
|
113
|
+
| `maxParallel` | `number` | No | `5` | Max parallel L0 modules. Linux: background jobs. Windows: runspace pool size. |
|
|
114
|
+
| `previousServiceId` | `string` | No | `""` | Service ID of a previous deployment to tear down before installing the new one. |
|
|
115
|
+
| `writeToDisk` | `boolean` | No | `false` | Write the composed scripts to timestamped files on disk. |
|
|
116
|
+
| `outputDir` | `string` | No | `"./final-scripts"` | Directory for `writeToDisk` output. Resolved relative to `process.cwd()`. |
|
|
117
|
+
|
|
118
|
+
### Return Value
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
{
|
|
122
|
+
l1Script: string; // Composed L1 collection script (all L0 modules merged)
|
|
123
|
+
l2Script: string; // L2 deployment wrapper (installs L1 as systemd service or Scheduled Task)
|
|
124
|
+
platform: "linux" | "windows";
|
|
125
|
+
modules: string[]; // Names of L0 modules included, e.g. ["tomcat", "postgresql"]
|
|
126
|
+
l1Path?: string; // File path if writeToDisk was true
|
|
127
|
+
l2Path?: string; // File path if writeToDisk was true
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The function validates the composed scripts (structural checks, syntax via `bash -n`/`shellcheck`/`pwsh`, and a dry-run extraction test) before returning. It throws if validation fails.
|
|
132
|
+
|
|
133
|
+
## Windows deletion verifier lifecycle
|
|
134
|
+
|
|
135
|
+
Use the `deletion-verifier` lifecycle only for a Windows Nexus Endpoint removal job. It requires exactly one L0: [`l0-scripts/nexus_endpoint_deletion.ps1`](l0-scripts/nexus_endpoint_deletion.ps1). The collector is read-only and reports the remaining owned artifacts; it never deletes them.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
const result = await generateFinalScript([nexusDeletionL0], {
|
|
139
|
+
platform: "windows",
|
|
140
|
+
templateUrls,
|
|
141
|
+
orgId: "org-1",
|
|
142
|
+
icebergEndpoint: "https://iceberg.example.com/v1/nexus-deletion/events",
|
|
143
|
+
agentId: "agent-1",
|
|
144
|
+
bufferTime: "30s",
|
|
145
|
+
timeout: "60s",
|
|
146
|
+
lifecycle: {
|
|
147
|
+
kind: "deletion-verifier",
|
|
148
|
+
jobId: "delete-2026-09-25-agent-1",
|
|
149
|
+
callbackToken: "one-job-scoped-token",
|
|
150
|
+
expectedWindowsUpdateAuOptions: null, // value recorded before installation; null = absent
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
This produces the isolated task `\NexusDeletionVerifier\NexusDeletionVerifier-<jobId>` and only uses `C:\ProgramData\NexusDeletionVerifier\<jobId>`. It does not share the normal `NexusModScripts` root. L1 writes `completion.ack` only when all three conditions hold: the L0 result has `data.complete: true`, its `data.job_id` matches the configured job, and Iceberg returned a 2xx response for that exact envelope. L2 then unregisters the verifier task and deletes only its isolated root.
|
|
156
|
+
|
|
157
|
+
The normal bulk cleanup helper is [`scripts/purge-nexus-modscripts.ps1`](scripts/purge-nexus-modscripts.ps1). It removes regular `\NexusModScripts\` deployments and deliberately never removes a deletion verifier.
|
|
158
|
+
|
|
159
|
+
### Iceberg controller contract
|
|
160
|
+
|
|
161
|
+
The controller must create a unique job ID and callback token, deploy the verifier **before** issuing the RMM uninstall command, and accept idempotent callback events. Treat completion as valid only when the authenticated callback has:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"module": "nexus_endpoint_deletion",
|
|
166
|
+
"result": {
|
|
167
|
+
"result": {
|
|
168
|
+
"data": {
|
|
169
|
+
"job_id": "the-controller-job-id",
|
|
170
|
+
"manifest_version": 1,
|
|
171
|
+
"complete": true,
|
|
172
|
+
"remaining": []
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Require the scoped token plus `X-Nexus-Deletion-Job` to match the job. Deduplicate `X-Nexus-Event-Id`; persist every non-complete scan as progress; and mark the job complete only after receiving this complete event. Record `AUOptions` before installation and pass that original value (or `null` when absent) as `expectedWindowsUpdateAuOptions`; restore it before accepting completion. For existing machines that lack this installation-time journal, require an explicit administrator-selected baseline and keep the job pending until one is supplied. Do not rely on the TacticalRMM DELETE HTTP response as proof of endpoint cleanup: it removes the management record before the agent-side uninstall has necessarily finished. Start the verifier after all ordinary modular scripts have been purged and before the first endpoint/RMM removal action, so it remains available to observe the final state.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { L0Script, ModScriptLifecycle, OsFamily } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize all line endings to CRLF for Windows PowerShell 5.1 compatibility.
|
|
4
|
+
* Strips all bare \r first (handles \r\n→\n and stray \r→nothing),
|
|
5
|
+
* then converts every \n to \r\n.
|
|
6
|
+
* Guarantees no bare \r survives before here-string terminators ("@, '@).
|
|
7
|
+
*
|
|
8
|
+
* Also replaces non-ASCII characters (box-drawing, em/en dashes) with ASCII
|
|
9
|
+
* equivalents. PowerShell 5.1 reads files without a BOM using the system's
|
|
10
|
+
* ANSI code page (usually Windows-1252). Multi-byte UTF-8 sequences like
|
|
11
|
+
* ─ (U+2500, box-drawing) decode as â"€, where byte 0x94 is a RIGHT DOUBLE
|
|
12
|
+
* QUOTATION MARK — this can corrupt the tokenizer's string-tracking state
|
|
13
|
+
* and cause spurious "Missing closing '}'" parse errors.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeWindowsLineEndings(content: string): string;
|
|
16
|
+
export interface ComposeL1Params {
|
|
17
|
+
orgId: string;
|
|
18
|
+
l0Scripts: L0Script[];
|
|
19
|
+
osFamily: OsFamily;
|
|
20
|
+
template: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compose an L1 script from multiple L0 scripts.
|
|
24
|
+
*
|
|
25
|
+
* For Linux: L0 functions run in parallel as background jobs (&),
|
|
26
|
+
* each writes to a temp file, results are pushed individually.
|
|
27
|
+
* For Windows: L0 functions run in parallel using PowerShell runspace pool,
|
|
28
|
+
* results are pushed individually.
|
|
29
|
+
*/
|
|
30
|
+
export declare function composeL1(params: ComposeL1Params): string;
|
|
31
|
+
export interface ComposeL2Params {
|
|
32
|
+
l1Script: string;
|
|
33
|
+
serviceName?: string;
|
|
34
|
+
osFamily: OsFamily;
|
|
35
|
+
template: string;
|
|
36
|
+
bufferTime?: string;
|
|
37
|
+
bufferTimeSeconds?: number;
|
|
38
|
+
timeout?: string;
|
|
39
|
+
timeoutSeconds?: number;
|
|
40
|
+
icebergEndpoint?: string;
|
|
41
|
+
agentId?: string;
|
|
42
|
+
authToken?: string;
|
|
43
|
+
orgId?: string;
|
|
44
|
+
maxParallel?: number;
|
|
45
|
+
previousServiceId?: string;
|
|
46
|
+
lifecycle?: ModScriptLifecycle;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Wrap an L1 script inside an L2 deployment wrapper.
|
|
50
|
+
*
|
|
51
|
+
* For Linux: L2 creates systemd service+timer, writes L1 to disk,
|
|
52
|
+
* creates env file, enables and starts the timer.
|
|
53
|
+
* Parameters are baked into the script (not passed as args)
|
|
54
|
+
* because TacticalRMM runs the L2 once to install.
|
|
55
|
+
*
|
|
56
|
+
* For Windows: L2 creates a Scheduled Task running as SYSTEM,
|
|
57
|
+
* writes L1 + env + wrapper to disk, registers the task.
|
|
58
|
+
*/
|
|
59
|
+
export declare function composeL2(params: ComposeL2Params): {
|
|
60
|
+
script: string;
|
|
61
|
+
args: string[];
|
|
62
|
+
shell: "shell" | "powershell";
|
|
63
|
+
requiredRuntimeArgs: string[];
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Parse a human-readable interval string into seconds, minutes, and systemd format.
|
|
67
|
+
* Examples: "5m" → { seconds: 300, minutes: 5, systemd: "5min" }
|
|
68
|
+
*/
|
|
69
|
+
export declare function parseInterval(interval: string): {
|
|
70
|
+
seconds: number;
|
|
71
|
+
minutes: number;
|
|
72
|
+
systemd: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Validate that every here-string terminator ('@ or "@) in a PowerShell script
|
|
76
|
+
* conforms to PowerShell 5.1 rules:
|
|
77
|
+
* - Must be at column 0 (no leading whitespace)
|
|
78
|
+
* - No bare \r anywhere in the script
|
|
79
|
+
*
|
|
80
|
+
* Returns an array of error messages (empty = valid).
|
|
81
|
+
*/
|
|
82
|
+
export declare function validateHereStringTerminators(script: string): string[];
|
|
83
|
+
//# sourceMappingURL=composer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../src/composer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKzE;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CASnE;AAqBD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAgFzD;AAID,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9B,mBAAmB,EAAE,MAAM,EAAE,CAAC;CAC/B,CAkBA;AAwMD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB,CAuCA;AAID;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBtE"}
|
package/dist/composer.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { createLogger } from "./logger.js";
|
|
2
|
+
const log = createLogger("composer");
|
|
3
|
+
/**
|
|
4
|
+
* Normalize all line endings to CRLF for Windows PowerShell 5.1 compatibility.
|
|
5
|
+
* Strips all bare \r first (handles \r\n→\n and stray \r→nothing),
|
|
6
|
+
* then converts every \n to \r\n.
|
|
7
|
+
* Guarantees no bare \r survives before here-string terminators ("@, '@).
|
|
8
|
+
*
|
|
9
|
+
* Also replaces non-ASCII characters (box-drawing, em/en dashes) with ASCII
|
|
10
|
+
* equivalents. PowerShell 5.1 reads files without a BOM using the system's
|
|
11
|
+
* ANSI code page (usually Windows-1252). Multi-byte UTF-8 sequences like
|
|
12
|
+
* ─ (U+2500, box-drawing) decode as â"€, where byte 0x94 is a RIGHT DOUBLE
|
|
13
|
+
* QUOTATION MARK — this can corrupt the tokenizer's string-tracking state
|
|
14
|
+
* and cause spurious "Missing closing '}'" parse errors.
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeWindowsLineEndings(content) {
|
|
17
|
+
return content
|
|
18
|
+
.replace(/\r/g, "")
|
|
19
|
+
.replace(/[─━┄┅┈┉╌╍═]/g, "-") // box-drawing horizontals → ASCII dash
|
|
20
|
+
.replace(/[│┃┆┇┊┋╎╏║]/g, "|") // box-drawing verticals → ASCII pipe
|
|
21
|
+
.replace(/—/g, "--") // em dash -> double dash
|
|
22
|
+
.replace(/–/g, "-") // en dash -> single dash
|
|
23
|
+
.replace(/[→←↑↓↔↕]/g, "->") // arrows -> ASCII arrow
|
|
24
|
+
.replace(/\n/g, "\r\n");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Safe template placeholder replacement that avoids special $ patterns.
|
|
28
|
+
* String.prototype.replace treats $', $`, $&, $1 etc. as special in the
|
|
29
|
+
* replacement string. Using a function callback avoids this entirely.
|
|
30
|
+
*/
|
|
31
|
+
function templateReplace(template, placeholder, value) {
|
|
32
|
+
const pattern = new RegExp(placeholder.replace(/[{}]/g, (c) => `\\${c}`), "g");
|
|
33
|
+
return template.replace(pattern, () => value);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Compose an L1 script from multiple L0 scripts.
|
|
37
|
+
*
|
|
38
|
+
* For Linux: L0 functions run in parallel as background jobs (&),
|
|
39
|
+
* each writes to a temp file, results are pushed individually.
|
|
40
|
+
* For Windows: L0 functions run in parallel using PowerShell runspace pool,
|
|
41
|
+
* results are pushed individually.
|
|
42
|
+
*/
|
|
43
|
+
export function composeL1(params) {
|
|
44
|
+
const { orgId, l0Scripts, osFamily } = params;
|
|
45
|
+
log.info("Composing L1 script", {
|
|
46
|
+
orgId,
|
|
47
|
+
osFamily,
|
|
48
|
+
moduleCount: l0Scripts.length,
|
|
49
|
+
modules: l0Scripts.map((l0) => l0.meta.name),
|
|
50
|
+
});
|
|
51
|
+
// Validate all L0 scripts match the target OS
|
|
52
|
+
for (const l0 of l0Scripts) {
|
|
53
|
+
if (l0.meta.osFamily !== osFamily) {
|
|
54
|
+
log.error("OS family mismatch in L0 script", {
|
|
55
|
+
scriptName: l0.meta.name,
|
|
56
|
+
scriptOs: l0.meta.osFamily,
|
|
57
|
+
targetOs: osFamily,
|
|
58
|
+
});
|
|
59
|
+
throw new Error(`L0 "${l0.meta.name}" is for ${l0.meta.osFamily}, but target OS is ${osFamily}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const template = params.template;
|
|
63
|
+
log.debug("L1 template received", { templateLength: template.length });
|
|
64
|
+
// Extract module names and versions
|
|
65
|
+
const moduleNames = l0Scripts.map((l0) => l0.meta.name);
|
|
66
|
+
const versionList = l0Scripts
|
|
67
|
+
.map((l0) => `${l0.meta.name}@${l0.meta.version}`)
|
|
68
|
+
.join(", ");
|
|
69
|
+
// Build module names array string for the target language.
|
|
70
|
+
// Linux (bash `arr=(...)`) and AIX (ksh `set -A arr ...`) both want
|
|
71
|
+
// space-separated quoted names; Windows (PowerShell `@(...)`) wants commas.
|
|
72
|
+
const moduleNamesArray = osFamily === "windows"
|
|
73
|
+
? moduleNames.map((n) => `"${n}"`).join(", ")
|
|
74
|
+
: moduleNames.map((n) => `"${n}"`).join(" ");
|
|
75
|
+
// Concatenate all L0 function bodies
|
|
76
|
+
const l0Bodies = l0Scripts
|
|
77
|
+
.map((l0) => `# ── L0: ${l0.meta.name} v${l0.meta.version} (${l0.meta.category}) ──\n${l0.functionBody}`)
|
|
78
|
+
.join("\n\n");
|
|
79
|
+
log.trace("L0 bodies concatenated", { totalLength: l0Bodies.length });
|
|
80
|
+
// Replace template placeholders — use templateReplace for values that may
|
|
81
|
+
// contain $ characters (L0 bodies, module arrays) to avoid JS replace() $-patterns
|
|
82
|
+
let composed = template;
|
|
83
|
+
composed = templateReplace(composed, "{{ORG_ID}}", orgId);
|
|
84
|
+
composed = templateReplace(composed, "{{GENERATED_AT}}", new Date().toISOString());
|
|
85
|
+
composed = templateReplace(composed, "{{MODULE_LIST}}", moduleNames.join(", "));
|
|
86
|
+
composed = templateReplace(composed, "{{L0_VERSION_LIST}}", versionList);
|
|
87
|
+
composed = templateReplace(composed, "{{L0_FUNCTION_BODIES}}", l0Bodies);
|
|
88
|
+
composed = templateReplace(composed, "{{MODULE_NAMES_ARRAY}}", moduleNamesArray);
|
|
89
|
+
// Normalize line endings: Windows PowerShell 5.1 fails on mixed \r\n and \n,
|
|
90
|
+
// and bare \r before here-string terminators ("@, '@) breaks parsing.
|
|
91
|
+
if (osFamily === "windows") {
|
|
92
|
+
composed = normalizeWindowsLineEndings(composed);
|
|
93
|
+
const terminatorErrors = validateHereStringTerminators(composed);
|
|
94
|
+
if (terminatorErrors.length > 0) {
|
|
95
|
+
throw new Error(`L1 here-string terminator corruption after normalization: ${terminatorErrors.join("; ")}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
log.info("L1 composition complete", {
|
|
99
|
+
outputLength: composed.length,
|
|
100
|
+
versionList,
|
|
101
|
+
});
|
|
102
|
+
return composed;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Wrap an L1 script inside an L2 deployment wrapper.
|
|
106
|
+
*
|
|
107
|
+
* For Linux: L2 creates systemd service+timer, writes L1 to disk,
|
|
108
|
+
* creates env file, enables and starts the timer.
|
|
109
|
+
* Parameters are baked into the script (not passed as args)
|
|
110
|
+
* because TacticalRMM runs the L2 once to install.
|
|
111
|
+
*
|
|
112
|
+
* For Windows: L2 creates a Scheduled Task running as SYSTEM,
|
|
113
|
+
* writes L1 + env + wrapper to disk, registers the task.
|
|
114
|
+
*/
|
|
115
|
+
export function composeL2(params) {
|
|
116
|
+
const { osFamily } = params;
|
|
117
|
+
log.info("Composing L2 deployment wrapper", {
|
|
118
|
+
osFamily,
|
|
119
|
+
serviceName: params.serviceName,
|
|
120
|
+
bufferTime: params.bufferTime,
|
|
121
|
+
timeout: params.timeout,
|
|
122
|
+
orgId: params.orgId,
|
|
123
|
+
});
|
|
124
|
+
if (osFamily === "linux") {
|
|
125
|
+
return composeL2Linux(params);
|
|
126
|
+
}
|
|
127
|
+
else if (osFamily === "aix") {
|
|
128
|
+
return composeL2Aix(params);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return composeL2Windows(params);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function composeL2Linux(params) {
|
|
135
|
+
const template = params.template;
|
|
136
|
+
log.debug("Composing L2 Linux (systemd service+timer)", {
|
|
137
|
+
serviceName: params.serviceName,
|
|
138
|
+
bufferTime: params.bufferTime,
|
|
139
|
+
timeout: params.timeout,
|
|
140
|
+
l1Length: params.l1Script.length,
|
|
141
|
+
});
|
|
142
|
+
// Replace all placeholders — must use templateReplace because L1
|
|
143
|
+
// contains L0 bodies with $ patterns that JS replace() misinterprets.
|
|
144
|
+
// Missing params get empty string (script validates at runtime).
|
|
145
|
+
let script = templateReplace(template, "{{L1_SCRIPT_BODY}}", params.l1Script);
|
|
146
|
+
script = templateReplace(script, "{{SERVICE_NAME}}", params.serviceName ?? "");
|
|
147
|
+
script = templateReplace(script, "{{PREVIOUS_SERVICE_ID}}", params.previousServiceId ?? "");
|
|
148
|
+
script = templateReplace(script, "{{BUFFER_TIME}}", params.bufferTime ?? "");
|
|
149
|
+
script = templateReplace(script, "{{ICEBERG_ENDPOINT}}", params.icebergEndpoint ?? "");
|
|
150
|
+
script = templateReplace(script, "{{AGENT_ID}}", params.agentId ?? "");
|
|
151
|
+
script = templateReplace(script, "{{AUTH_TOKEN}}", params.authToken ?? "");
|
|
152
|
+
script = templateReplace(script, "{{ORG_ID}}", params.orgId ?? "");
|
|
153
|
+
script = templateReplace(script, "{{MAX_PARALLEL}}", String(params.maxParallel ?? 5));
|
|
154
|
+
script = templateReplace(script, "{{TIMEOUT}}", params.timeout ?? "");
|
|
155
|
+
const args = [params.serviceName ?? "", params.previousServiceId ?? ""];
|
|
156
|
+
// Track which params were NOT provided at composition time
|
|
157
|
+
const requiredRuntimeArgs = [];
|
|
158
|
+
if (!params.serviceName)
|
|
159
|
+
requiredRuntimeArgs.push("--service-name");
|
|
160
|
+
if (!params.bufferTime)
|
|
161
|
+
requiredRuntimeArgs.push("--buffer-time");
|
|
162
|
+
if (!params.icebergEndpoint)
|
|
163
|
+
requiredRuntimeArgs.push("--iceberg-endpoint");
|
|
164
|
+
if (!params.agentId)
|
|
165
|
+
requiredRuntimeArgs.push("--agent-id");
|
|
166
|
+
if (!params.authToken)
|
|
167
|
+
requiredRuntimeArgs.push("--auth-token");
|
|
168
|
+
if (!params.orgId)
|
|
169
|
+
requiredRuntimeArgs.push("--org-id");
|
|
170
|
+
if (!params.timeout)
|
|
171
|
+
requiredRuntimeArgs.push("--timeout");
|
|
172
|
+
log.debug("L2 Linux composed", {
|
|
173
|
+
outputLength: script.length,
|
|
174
|
+
argCount: args.length,
|
|
175
|
+
requiredRuntimeArgs,
|
|
176
|
+
});
|
|
177
|
+
return { script, args, shell: "shell", requiredRuntimeArgs };
|
|
178
|
+
}
|
|
179
|
+
function composeL2Aix(params) {
|
|
180
|
+
const template = params.template;
|
|
181
|
+
log.debug("Composing L2 AIX (SRC subsystem + ksh wrapper daemon)", {
|
|
182
|
+
serviceName: params.serviceName,
|
|
183
|
+
bufferTimeSeconds: params.bufferTimeSeconds,
|
|
184
|
+
timeoutSeconds: params.timeoutSeconds,
|
|
185
|
+
l1Length: params.l1Script.length,
|
|
186
|
+
});
|
|
187
|
+
// Replace all placeholders — must use templateReplace because L1
|
|
188
|
+
// contains L0 bodies with $ patterns that JS replace() misinterprets.
|
|
189
|
+
// The SRC wrapper daemon uses integer-seconds timing (sleep N / watchdog),
|
|
190
|
+
// like the Windows wrapper. The human-readable forms are kept for the
|
|
191
|
+
// JSON service_id output only.
|
|
192
|
+
let script = templateReplace(template, "{{L1_SCRIPT_BODY}}", params.l1Script);
|
|
193
|
+
script = templateReplace(script, "{{SERVICE_NAME}}", params.serviceName ?? "");
|
|
194
|
+
script = templateReplace(script, "{{PREVIOUS_SERVICE_ID}}", params.previousServiceId ?? "");
|
|
195
|
+
script = templateReplace(script, "{{BUFFER_TIME}}", params.bufferTime ?? "");
|
|
196
|
+
script = templateReplace(script, "{{BUFFER_TIME_SECONDS}}", String(params.bufferTimeSeconds ?? 0));
|
|
197
|
+
script = templateReplace(script, "{{TIMEOUT}}", params.timeout ?? "");
|
|
198
|
+
script = templateReplace(script, "{{TIMEOUT_SECONDS}}", String(params.timeoutSeconds ?? 0));
|
|
199
|
+
script = templateReplace(script, "{{ICEBERG_ENDPOINT}}", params.icebergEndpoint ?? "");
|
|
200
|
+
script = templateReplace(script, "{{AGENT_ID}}", params.agentId ?? "");
|
|
201
|
+
script = templateReplace(script, "{{AUTH_TOKEN}}", params.authToken ?? "");
|
|
202
|
+
script = templateReplace(script, "{{ORG_ID}}", params.orgId ?? "");
|
|
203
|
+
script = templateReplace(script, "{{MAX_PARALLEL}}", String(params.maxParallel ?? 5));
|
|
204
|
+
const args = [params.serviceName ?? "", params.previousServiceId ?? ""];
|
|
205
|
+
// Track which params were NOT provided at composition time
|
|
206
|
+
const requiredRuntimeArgs = [];
|
|
207
|
+
if (!params.serviceName)
|
|
208
|
+
requiredRuntimeArgs.push("--service-name");
|
|
209
|
+
if (!params.bufferTimeSeconds)
|
|
210
|
+
requiredRuntimeArgs.push("--buffer-time");
|
|
211
|
+
if (!params.icebergEndpoint)
|
|
212
|
+
requiredRuntimeArgs.push("--iceberg-endpoint");
|
|
213
|
+
if (!params.agentId)
|
|
214
|
+
requiredRuntimeArgs.push("--agent-id");
|
|
215
|
+
if (!params.authToken)
|
|
216
|
+
requiredRuntimeArgs.push("--auth-token");
|
|
217
|
+
if (!params.orgId)
|
|
218
|
+
requiredRuntimeArgs.push("--org-id");
|
|
219
|
+
if (!params.timeoutSeconds)
|
|
220
|
+
requiredRuntimeArgs.push("--timeout");
|
|
221
|
+
log.debug("L2 AIX composed", {
|
|
222
|
+
outputLength: script.length,
|
|
223
|
+
argCount: args.length,
|
|
224
|
+
requiredRuntimeArgs,
|
|
225
|
+
});
|
|
226
|
+
return { script, args, shell: "shell", requiredRuntimeArgs };
|
|
227
|
+
}
|
|
228
|
+
function composeL2Windows(params) {
|
|
229
|
+
const template = params.template;
|
|
230
|
+
const lifecycle = params.lifecycle ?? { kind: "continuous" };
|
|
231
|
+
const effectiveAuthToken = lifecycle.kind === "deletion-verifier"
|
|
232
|
+
? lifecycle.callbackToken
|
|
233
|
+
: (params.authToken ?? "");
|
|
234
|
+
log.debug("Composing L2 Windows (Scheduled Task)", {
|
|
235
|
+
serviceName: params.serviceName,
|
|
236
|
+
bufferTimeSeconds: params.bufferTimeSeconds,
|
|
237
|
+
timeoutSeconds: params.timeoutSeconds,
|
|
238
|
+
l1Length: params.l1Script.length,
|
|
239
|
+
});
|
|
240
|
+
// Replace all placeholders — must use templateReplace because L1
|
|
241
|
+
// contains L0 bodies with $ patterns that JS replace() misinterprets.
|
|
242
|
+
// Missing int params get 0 (sentinel), strings get empty.
|
|
243
|
+
let script = templateReplace(template, "{{L1_SCRIPT_BODY}}", params.l1Script);
|
|
244
|
+
script = templateReplace(script, "{{SERVICE_NAME}}", params.serviceName ?? "");
|
|
245
|
+
script = templateReplace(script, "{{PREVIOUS_SERVICE_ID}}", params.previousServiceId ?? "");
|
|
246
|
+
script = templateReplace(script, "{{BUFFER_TIME_SECONDS}}", String(params.bufferTimeSeconds ?? 0));
|
|
247
|
+
script = templateReplace(script, "{{TIMEOUT_SECONDS}}", String(params.timeoutSeconds ?? 0));
|
|
248
|
+
script = templateReplace(script, "{{ICEBERG_ENDPOINT}}", params.icebergEndpoint ?? "");
|
|
249
|
+
script = templateReplace(script, "{{AGENT_ID}}", params.agentId ?? "");
|
|
250
|
+
script = templateReplace(script, "{{AUTH_TOKEN}}", effectiveAuthToken);
|
|
251
|
+
script = templateReplace(script, "{{ORG_ID}}", params.orgId ?? "");
|
|
252
|
+
script = templateReplace(script, "{{MAX_PARALLEL}}", String(params.maxParallel ?? 5));
|
|
253
|
+
script = templateReplace(script, "{{LIFECYCLE_KIND}}", lifecycle.kind);
|
|
254
|
+
script = templateReplace(script, "{{DELETION_JOB_ID}}", lifecycle.kind === "deletion-verifier" ? lifecycle.jobId : "");
|
|
255
|
+
script = templateReplace(script, "{{EXPECTED_WINDOWS_UPDATE_AU_OPTIONS}}", lifecycle.kind === "deletion-verifier"
|
|
256
|
+
? (lifecycle.expectedWindowsUpdateAuOptions === null
|
|
257
|
+
? "absent"
|
|
258
|
+
: String(lifecycle.expectedWindowsUpdateAuOptions))
|
|
259
|
+
: "");
|
|
260
|
+
const moduleListMatch = params.l1Script.match(/^# MODULES:\s*(.+)$/m);
|
|
261
|
+
const moduleCount = moduleListMatch?.[1]
|
|
262
|
+
?.split(",")
|
|
263
|
+
.map((name) => name.trim())
|
|
264
|
+
.filter(Boolean).length ?? 1;
|
|
265
|
+
script = templateReplace(script, "{{MODULE_COUNT}}", String(Math.max(1, moduleCount)));
|
|
266
|
+
// Template has LF, injected L1 has CRLF → mixed endings.
|
|
267
|
+
// Normalize entire L2 to CRLF for PowerShell 5.1 here-string compatibility.
|
|
268
|
+
script = normalizeWindowsLineEndings(script);
|
|
269
|
+
const terminatorErrors = validateHereStringTerminators(script);
|
|
270
|
+
if (terminatorErrors.length > 0) {
|
|
271
|
+
throw new Error(`L2 here-string terminator corruption after normalization: ${terminatorErrors.join("; ")}`);
|
|
272
|
+
}
|
|
273
|
+
const args = [`-ServiceName`, params.serviceName ?? ""];
|
|
274
|
+
if (params.previousServiceId) {
|
|
275
|
+
args.push(`-PreviousServiceId`, params.previousServiceId);
|
|
276
|
+
}
|
|
277
|
+
// Track which params were NOT provided at composition time
|
|
278
|
+
const requiredRuntimeArgs = [];
|
|
279
|
+
if (!params.serviceName)
|
|
280
|
+
requiredRuntimeArgs.push("-ServiceName");
|
|
281
|
+
if (!params.bufferTimeSeconds)
|
|
282
|
+
requiredRuntimeArgs.push("-BufferTimeSeconds");
|
|
283
|
+
if (!params.timeoutSeconds)
|
|
284
|
+
requiredRuntimeArgs.push("-TimeoutSeconds");
|
|
285
|
+
if (!params.icebergEndpoint)
|
|
286
|
+
requiredRuntimeArgs.push("-IcebergEndpoint");
|
|
287
|
+
if (!params.agentId)
|
|
288
|
+
requiredRuntimeArgs.push("-AgentId");
|
|
289
|
+
if (!effectiveAuthToken)
|
|
290
|
+
requiredRuntimeArgs.push("-AuthToken");
|
|
291
|
+
if (!params.orgId)
|
|
292
|
+
requiredRuntimeArgs.push("-OrgId");
|
|
293
|
+
if (lifecycle.kind === "deletion-verifier" && !lifecycle.jobId) {
|
|
294
|
+
requiredRuntimeArgs.push("deletion lifecycle jobId");
|
|
295
|
+
}
|
|
296
|
+
log.debug("L2 Windows composed", {
|
|
297
|
+
outputLength: script.length,
|
|
298
|
+
argCount: args.length,
|
|
299
|
+
requiredRuntimeArgs,
|
|
300
|
+
});
|
|
301
|
+
return { script, args, shell: "powershell", requiredRuntimeArgs };
|
|
302
|
+
}
|
|
303
|
+
// INTERVAL PARSING
|
|
304
|
+
/**
|
|
305
|
+
* Parse a human-readable interval string into seconds, minutes, and systemd format.
|
|
306
|
+
* Examples: "5m" → { seconds: 300, minutes: 5, systemd: "5min" }
|
|
307
|
+
*/
|
|
308
|
+
export function parseInterval(interval) {
|
|
309
|
+
log.debug("Parsing interval", { interval });
|
|
310
|
+
const match = interval.match(/^(\d+)\s*(s|sec|seconds?|m|min|minutes?|h|hr|hours?)$/i);
|
|
311
|
+
if (!match) {
|
|
312
|
+
log.error("Invalid interval format", { interval });
|
|
313
|
+
throw new Error(`Invalid interval: "${interval}". Use format like "5m", "1h", "30s".`);
|
|
314
|
+
}
|
|
315
|
+
const value = parseInt(match[1], 10);
|
|
316
|
+
const unit = match[2].toLowerCase();
|
|
317
|
+
let result;
|
|
318
|
+
if (unit.startsWith("s")) {
|
|
319
|
+
result = {
|
|
320
|
+
seconds: value,
|
|
321
|
+
minutes: Math.max(1, Math.ceil(value / 60)),
|
|
322
|
+
systemd: `${value}s`,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
else if (unit.startsWith("h")) {
|
|
326
|
+
result = { seconds: value * 3600, minutes: value * 60, systemd: `${value}h` };
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
// minutes
|
|
330
|
+
result = { seconds: value * 60, minutes: value, systemd: `${value}min` };
|
|
331
|
+
}
|
|
332
|
+
log.debug("Interval parsed", {
|
|
333
|
+
input: interval,
|
|
334
|
+
seconds: result.seconds,
|
|
335
|
+
minutes: result.minutes,
|
|
336
|
+
systemd: result.systemd,
|
|
337
|
+
});
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
// HERE-STRING TERMINATOR VALIDATION
|
|
341
|
+
/**
|
|
342
|
+
* Validate that every here-string terminator ('@ or "@) in a PowerShell script
|
|
343
|
+
* conforms to PowerShell 5.1 rules:
|
|
344
|
+
* - Must be at column 0 (no leading whitespace)
|
|
345
|
+
* - No bare \r anywhere in the script
|
|
346
|
+
*
|
|
347
|
+
* Returns an array of error messages (empty = valid).
|
|
348
|
+
*/
|
|
349
|
+
export function validateHereStringTerminators(script) {
|
|
350
|
+
const errors = [];
|
|
351
|
+
const lines = script.split(/\r?\n/);
|
|
352
|
+
for (let i = 0; i < lines.length; i++) {
|
|
353
|
+
const line = lines[i];
|
|
354
|
+
// Detect MISPLACED terminators: leading whitespace before '@ or "@
|
|
355
|
+
if (/^\s+['"]@\s*$/.test(line)) {
|
|
356
|
+
errors.push(`Line ${i + 1}: here-string terminator has leading whitespace — ` +
|
|
357
|
+
`PowerShell 5.1 will not recognize it`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Check for bare \r (not followed by \n) — corrupts here-string parsing
|
|
361
|
+
const bareCR = script.match(/\r(?!\n)/g);
|
|
362
|
+
if (bareCR) {
|
|
363
|
+
errors.push(`${bareCR.length} bare \\r character(s) found — will corrupt here-string parsing`);
|
|
364
|
+
}
|
|
365
|
+
return errors;
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../src/composer.ts"],"names":[],"mappings":"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"}
|