@eighty4/c2 0.0.3 → 0.0.5-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/CHANGELOG.md +8 -1
- package/README.md +0 -3
- package/lib/attachments.ts +5 -5
- package/lib/{c2.bin.ts → bin.ts} +17 -6
- package/lib/cli.ts +1 -5
- package/lib/expression.ts +2 -2
- package/lib/fs.testing.ts +2 -2
- package/lib_js/attachments.js +6 -6
- package/lib_js/{c2.bin.js → bin.js} +16 -6
- package/lib_js/cli.js +1 -5
- package/lib_js/expression.js +2 -2
- package/lib_js/fs.testing.js +2 -2
- package/lib_types/{c2.api.d.ts → api.d.ts} +1 -1
- package/lib_types/api.d.ts.map +1 -0
- package/lib_types/bin.d.ts +3 -0
- package/lib_types/bin.d.ts.map +1 -0
- package/lib_types/cli.d.ts.map +1 -1
- package/package.json +14 -15
- package/lib/fs.ts +0 -17
- package/lib_js/fs.js +0 -15
- package/lib_types/c2.api.d.ts.map +0 -1
- package/lib_types/c2.bin.d.ts +0 -3
- package/lib_types/c2.bin.d.ts.map +0 -1
- package/lib_types/fs.d.ts +0 -4
- package/lib_types/fs.d.ts.map +0 -1
- /package/lib/{c2.api.ts → api.ts} +0 -0
- /package/lib_js/{c2.api.js → api.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
- ???
|
|
6
6
|
|
|
7
|
+
## [v0.0.4] - 2025-06-30
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Cleaning up console output of errors and CLI usage
|
|
12
|
+
|
|
7
13
|
## [v0.0.3] - 2025-06-26
|
|
8
14
|
|
|
9
15
|
### Fixed
|
|
@@ -22,6 +28,7 @@
|
|
|
22
28
|
- Evaluate env() and file() expressions in user data
|
|
23
29
|
- Merge multiple user data into a MIME multipart message
|
|
24
30
|
|
|
25
|
-
[Unreleased]: https://github.com/eighty4/c2/compare/v0.0.
|
|
31
|
+
[Unreleased]: https://github.com/eighty4/c2/compare/v0.0.4...HEAD
|
|
32
|
+
[v0.0.4]: https://github.com/eighty4/c2/compare/v0.0.3...v0.0.4
|
|
26
33
|
[v0.0.3]: https://github.com/eighty4/c2/compare/v0.0.2...v0.0.3
|
|
27
34
|
[v0.0.2]: https://github.com/eighty4/c2/releases/tag/v0.0.2
|
package/README.md
CHANGED
package/lib/attachments.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises'
|
|
1
2
|
import { evalTemplateExpressions } from './expression.ts'
|
|
2
|
-
import { readDirListing, readToString } from './fs.ts'
|
|
3
3
|
|
|
4
4
|
export type AttachmentType = 'cloud-config' | 'x-shellscript'
|
|
5
5
|
|
|
@@ -14,11 +14,11 @@ export interface Attachment {
|
|
|
14
14
|
export async function collectAttachments(
|
|
15
15
|
dir: string,
|
|
16
16
|
): Promise<Array<Attachment>> {
|
|
17
|
-
const filenames = await
|
|
17
|
+
const filenames = await readdir(dir)
|
|
18
18
|
const attachments = await Promise.all(
|
|
19
19
|
filenames.map(async filename => {
|
|
20
20
|
const path = `${dir}/${filename}`
|
|
21
|
-
const source = await
|
|
21
|
+
const source = await readFile(path, 'utf-8')
|
|
22
22
|
const type = resolveAttachmentType(filename, source)
|
|
23
23
|
const content = await evalTemplateExpressions(source)
|
|
24
24
|
return { content, filename, path, type, source }
|
|
@@ -31,9 +31,9 @@ function compareAttachmentFilenames(
|
|
|
31
31
|
a1: Attachment,
|
|
32
32
|
a2: Attachment,
|
|
33
33
|
): 1 | 0 | -1 {
|
|
34
|
-
if (a1.filename
|
|
34
|
+
if (a1.filename < a2.filename) return -1
|
|
35
35
|
if (a1.filename > a2.filename) return 1
|
|
36
|
-
return
|
|
36
|
+
return 0
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export function resolveAttachmentType(
|
package/lib/{c2.bin.ts → bin.ts}
RENAMED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { stat } from 'node:fs/promises'
|
|
3
4
|
import { buildUserData } from './build.ts'
|
|
4
5
|
import { parseArgs, type ParsedArgs } from './cli.ts'
|
|
5
|
-
import { doesDirExist } from './fs.ts'
|
|
6
6
|
import { startUserDataHttp } from './http.ts'
|
|
7
7
|
|
|
8
8
|
let args: ParsedArgs | undefined
|
|
9
9
|
try {
|
|
10
10
|
args = parseArgs()
|
|
11
11
|
} catch (e: any) {
|
|
12
|
-
|
|
13
|
-
console.error(e.message)
|
|
14
|
-
}
|
|
12
|
+
errorExit(e.message)
|
|
15
13
|
}
|
|
16
14
|
|
|
17
15
|
if (!args || args.help) {
|
|
18
16
|
const optional = (s: string) => `\u001b[90m${s}\u001b[0m`
|
|
19
17
|
const required = (s: string) => `\u001b[1m${s}\u001b[0m`
|
|
20
|
-
|
|
18
|
+
console.error(
|
|
21
19
|
`c2 ${optional('[[--base64] | [--http PORT]]')} ${required('USER_DATA_DIR')}`,
|
|
22
20
|
)
|
|
21
|
+
process.exit(1)
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
if (!(await doesDirExist(args.userDataDir))) {
|
|
@@ -46,6 +45,18 @@ try {
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
function errorExit(msg: string): never {
|
|
49
|
-
console.error(msg)
|
|
48
|
+
console.error(errorText('error:'), msg)
|
|
50
49
|
process.exit(1)
|
|
51
50
|
}
|
|
51
|
+
|
|
52
|
+
function errorText(s: string): string {
|
|
53
|
+
return `\u001b[1;31m${s}\u001b[0m`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function doesDirExist(p: string): Promise<boolean> {
|
|
57
|
+
try {
|
|
58
|
+
return (await stat(p)).isDirectory()
|
|
59
|
+
} catch (ignore) {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
}
|
package/lib/cli.ts
CHANGED
|
@@ -7,11 +7,7 @@ export type ParsedArgs =
|
|
|
7
7
|
userDataDir: string
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const SCRIPT_SUFFIXES = Object.freeze([
|
|
11
|
-
'/c2',
|
|
12
|
-
'/lib_js/c2.bin.js',
|
|
13
|
-
'/lib/c2.bin.ts',
|
|
14
|
-
])
|
|
10
|
+
const SCRIPT_SUFFIXES = Object.freeze(['/c2', '/lib_js/bin.js', '/lib/bin.ts'])
|
|
15
11
|
|
|
16
12
|
export function parseArgs(input?: Array<string>): ParsedArgs {
|
|
17
13
|
if (!input) {
|
package/lib/expression.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
1
2
|
import MagicString from 'magic-string'
|
|
2
|
-
import { readToString } from './fs.ts'
|
|
3
3
|
|
|
4
4
|
type TemplateExpression = {
|
|
5
5
|
index: number
|
|
@@ -56,7 +56,7 @@ async function evaluate(expression: string): Promise<string> {
|
|
|
56
56
|
}
|
|
57
57
|
path = `${process.env.HOME}${path.substring(1)}`
|
|
58
58
|
}
|
|
59
|
-
return
|
|
59
|
+
return await readFile(path, 'utf-8')
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
throw new Error(`unsupported expression: ${expression}`)
|
package/lib/fs.testing.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
1
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
2
2
|
import { tmpdir } from 'node:os'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@ export async function makeFile(
|
|
|
8
8
|
pathPrefix?: string,
|
|
9
9
|
): Promise<string> {
|
|
10
10
|
const p = !!pathPrefix ? join(pathPrefix, path) : path
|
|
11
|
-
await
|
|
11
|
+
await writeFile(p, content)
|
|
12
12
|
return p
|
|
13
13
|
}
|
|
14
14
|
|
package/lib_js/attachments.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
1
2
|
import { evalTemplateExpressions } from "./expression.js";
|
|
2
|
-
import { readDirListing, readToString } from "./fs.js";
|
|
3
3
|
export async function collectAttachments(dir) {
|
|
4
|
-
const filenames = await
|
|
4
|
+
const filenames = await readdir(dir);
|
|
5
5
|
const attachments = await Promise.all(filenames.map(async (filename) => {
|
|
6
6
|
const path = `${dir}/${filename}`;
|
|
7
|
-
const source = await
|
|
7
|
+
const source = await readFile(path, 'utf-8');
|
|
8
8
|
const type = resolveAttachmentType(filename, source);
|
|
9
9
|
const content = await evalTemplateExpressions(source);
|
|
10
10
|
return { content, filename, path, type, source };
|
|
@@ -12,11 +12,11 @@ export async function collectAttachments(dir) {
|
|
|
12
12
|
return attachments.sort(compareAttachmentFilenames);
|
|
13
13
|
}
|
|
14
14
|
function compareAttachmentFilenames(a1, a2) {
|
|
15
|
-
if (a1.filename
|
|
16
|
-
return
|
|
15
|
+
if (a1.filename < a2.filename)
|
|
16
|
+
return -1;
|
|
17
17
|
if (a1.filename > a2.filename)
|
|
18
18
|
return 1;
|
|
19
|
-
return
|
|
19
|
+
return 0;
|
|
20
20
|
}
|
|
21
21
|
export function resolveAttachmentType(filename, source) {
|
|
22
22
|
if (filename.endsWith('.yml') || filename.endsWith('.yaml')) {
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { stat } from 'node:fs/promises';
|
|
2
3
|
import { buildUserData } from "./build.js";
|
|
3
4
|
import { parseArgs } from "./cli.js";
|
|
4
|
-
import { doesDirExist } from "./fs.js";
|
|
5
5
|
import { startUserDataHttp } from "./http.js";
|
|
6
6
|
let args;
|
|
7
7
|
try {
|
|
8
8
|
args = parseArgs();
|
|
9
9
|
}
|
|
10
10
|
catch (e) {
|
|
11
|
-
|
|
12
|
-
console.error(e.message);
|
|
13
|
-
}
|
|
11
|
+
errorExit(e.message);
|
|
14
12
|
}
|
|
15
13
|
if (!args || args.help) {
|
|
16
14
|
const optional = (s) => `\u001b[90m${s}\u001b[0m`;
|
|
17
15
|
const required = (s) => `\u001b[1m${s}\u001b[0m`;
|
|
18
|
-
|
|
16
|
+
console.error(`c2 ${optional('[[--base64] | [--http PORT]]')} ${required('USER_DATA_DIR')}`);
|
|
17
|
+
process.exit(1);
|
|
19
18
|
}
|
|
20
19
|
if (!(await doesDirExist(args.userDataDir))) {
|
|
21
20
|
errorExit(`${args.userDataDir} directory does not exist`);
|
|
@@ -39,6 +38,17 @@ catch (e) {
|
|
|
39
38
|
errorExit(e.message);
|
|
40
39
|
}
|
|
41
40
|
function errorExit(msg) {
|
|
42
|
-
console.error(msg);
|
|
41
|
+
console.error(errorText('error:'), msg);
|
|
43
42
|
process.exit(1);
|
|
44
43
|
}
|
|
44
|
+
function errorText(s) {
|
|
45
|
+
return `\u001b[1;31m${s}\u001b[0m`;
|
|
46
|
+
}
|
|
47
|
+
async function doesDirExist(p) {
|
|
48
|
+
try {
|
|
49
|
+
return (await stat(p)).isDirectory();
|
|
50
|
+
}
|
|
51
|
+
catch (ignore) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
package/lib_js/cli.js
CHANGED
package/lib_js/expression.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
1
2
|
import MagicString from 'magic-string';
|
|
2
|
-
import { readToString } from "./fs.js";
|
|
3
3
|
export async function evalTemplateExpressions(content) {
|
|
4
4
|
const regex = new RegExp(/\${{\s*(.*)\s*}}/g);
|
|
5
5
|
let match;
|
|
@@ -41,7 +41,7 @@ async function evaluate(expression) {
|
|
|
41
41
|
}
|
|
42
42
|
path = `${process.env.HOME}${path.substring(1)}`;
|
|
43
43
|
}
|
|
44
|
-
return
|
|
44
|
+
return await readFile(path, 'utf-8');
|
|
45
45
|
}
|
|
46
46
|
throw new Error(`unsupported expression: ${expression}`);
|
|
47
47
|
}
|
package/lib_js/fs.testing.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { mkdtemp, rm } from 'node:fs/promises';
|
|
1
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
export async function makeFile(path, content, pathPrefix) {
|
|
5
5
|
const p = !!pathPrefix ? join(pathPrefix, path) : path;
|
|
6
|
-
await
|
|
6
|
+
await writeFile(p, content);
|
|
7
7
|
return p;
|
|
8
8
|
}
|
|
9
9
|
export async function makeTempDir() {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { type BuildUserDataOpts, buildUserData } from './build.ts';
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../lib/bin.ts"],"names":[],"mappings":""}
|
package/lib_types/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../lib/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAChB;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IACI,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACtB,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../lib/cli.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAChB;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,GACd;IACI,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACtB,CAAA;AAIP,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,UAAU,CAqD3D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eighty4/c2",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5-0",
|
|
4
4
|
"author": "Adam McKee <adam.be.g84d@gmail.com>",
|
|
5
5
|
"repository": "https://github.com/eighty4/c2",
|
|
6
6
|
"homepage": "https://github.com/eighty4/c2",
|
|
@@ -20,27 +20,19 @@
|
|
|
20
20
|
"node": ">=23"
|
|
21
21
|
},
|
|
22
22
|
"bin": {
|
|
23
|
-
"c2": "./lib_js/
|
|
23
|
+
"c2": "./lib_js/bin.js"
|
|
24
24
|
},
|
|
25
25
|
"exports": {
|
|
26
26
|
".": {
|
|
27
|
-
"bun": "./lib/
|
|
28
|
-
"node": "./lib_js/
|
|
29
|
-
"types": "./lib_types/
|
|
27
|
+
"bun": "./lib/api.ts",
|
|
28
|
+
"node": "./lib_js/api.js",
|
|
29
|
+
"types": "./lib_types/api.d.ts"
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "tsc",
|
|
34
|
-
"fmt": "prettier --write .",
|
|
35
|
-
"fmtcheck": "prettier --check .",
|
|
36
|
-
"test": "bun test",
|
|
37
|
-
"typecheck": "tsc --noEmit"
|
|
38
|
-
},
|
|
39
32
|
"dependencies": {
|
|
40
33
|
"magic-string": "0.30.17"
|
|
41
34
|
},
|
|
42
35
|
"devDependencies": {
|
|
43
|
-
"@types/bun": "1.2.5",
|
|
44
36
|
"@types/node": "^22.14.1",
|
|
45
37
|
"prettier": "^3.5.3",
|
|
46
38
|
"typescript": "5.8.2"
|
|
@@ -51,5 +43,12 @@
|
|
|
51
43
|
"lib_js/*",
|
|
52
44
|
"lib_types/*",
|
|
53
45
|
"CHANGELOG.md"
|
|
54
|
-
]
|
|
55
|
-
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc",
|
|
49
|
+
"fmt": "prettier --write .",
|
|
50
|
+
"fmtcheck": "prettier --check .",
|
|
51
|
+
"test": "node --test \"lib/**/*.spec.ts\"",
|
|
52
|
+
"typecheck": "tsc --noEmit"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/lib/fs.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { readdir, readFile, stat } from 'node:fs/promises'
|
|
2
|
-
|
|
3
|
-
export async function doesDirExist(p: string): Promise<boolean> {
|
|
4
|
-
try {
|
|
5
|
-
return (await stat(p)).isDirectory()
|
|
6
|
-
} catch (ignore) {
|
|
7
|
-
return false
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export async function readDirListing(p: string): Promise<Array<string>> {
|
|
12
|
-
return readdir(p)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export async function readToString(p: string): Promise<string> {
|
|
16
|
-
return readFile(p, 'utf8')
|
|
17
|
-
}
|
package/lib_js/fs.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
2
|
-
export async function doesDirExist(p) {
|
|
3
|
-
try {
|
|
4
|
-
return (await stat(p)).isDirectory();
|
|
5
|
-
}
|
|
6
|
-
catch (ignore) {
|
|
7
|
-
return false;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export async function readDirListing(p) {
|
|
11
|
-
return readdir(p);
|
|
12
|
-
}
|
|
13
|
-
export async function readToString(p) {
|
|
14
|
-
return readFile(p, 'utf8');
|
|
15
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"c2.api.d.ts","sourceRoot":"","sources":["../lib/c2.api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA"}
|
package/lib_types/c2.bin.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"c2.bin.d.ts","sourceRoot":"","sources":["../lib/c2.bin.ts"],"names":[],"mappings":""}
|
package/lib_types/fs.d.ts
DELETED
package/lib_types/fs.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../lib/fs.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAM9D;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAEtE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7D"}
|
|
File without changes
|
|
File without changes
|