@peekling/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/AUTHORS +8 -0
- package/LICENSE +202 -0
- package/LICENSING.md +20 -0
- package/NOTICE +6 -0
- package/README.md +264 -0
- package/dist/atomic-directory.d.ts +2 -0
- package/dist/atomic-directory.d.ts.map +1 -0
- package/dist/atomic-directory.js +28 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +100 -0
- package/dist/doctor.d.ts +12 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +121 -0
- package/dist/image.d.ts +4 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +7 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +569 -0
- package/dist/png.d.ts +7 -0
- package/dist/png.d.ts.map +1 -0
- package/dist/png.js +169 -0
- package/dist/zip.d.ts +2 -0
- package/dist/zip.d.ts.map +1 -0
- package/dist/zip.js +119 -0
- package/package.json +63 -0
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { preflight } from "@peekling/preflight";
|
|
2
|
+
import { parseDataText } from "@peekling/runtime/pack";
|
|
3
|
+
import { lstat, open } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
const MAX_DOCTOR_INPUT_BYTES = 64 * 1024;
|
|
6
|
+
export async function runDoctor(configPath, options = {}) {
|
|
7
|
+
let configuration;
|
|
8
|
+
try {
|
|
9
|
+
configuration = await readJsonData(configPath, "configuration");
|
|
10
|
+
}
|
|
11
|
+
catch (cause) {
|
|
12
|
+
return inputFailure("$input.configuration", cause, "Pass a readable JSON Configuration file", options.json);
|
|
13
|
+
}
|
|
14
|
+
let pack;
|
|
15
|
+
if (options.packPath) {
|
|
16
|
+
try {
|
|
17
|
+
pack = await readJsonData(options.packPath, "Pack");
|
|
18
|
+
}
|
|
19
|
+
catch (cause) {
|
|
20
|
+
return inputFailure("$input.pack", cause, "Pass a readable JSON Pack file", options.json);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const report = preflight(configuration, {
|
|
24
|
+
...(pack !== undefined ? { pack } : {}),
|
|
25
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
report,
|
|
29
|
+
output: options.json ? formatJson(report) : formatHuman(report),
|
|
30
|
+
exitCode: report.valid ? 0 : 1,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function inputFailure(path, cause, fix, json = false) {
|
|
34
|
+
const report = {
|
|
35
|
+
valid: false,
|
|
36
|
+
errors: [
|
|
37
|
+
{
|
|
38
|
+
code: "invalid-input",
|
|
39
|
+
path,
|
|
40
|
+
message: cause instanceof Error ? cause.message : "Input is invalid",
|
|
41
|
+
fix,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
warnings: [],
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
report,
|
|
48
|
+
output: json ? formatJson(report) : formatHuman(report),
|
|
49
|
+
exitCode: 1,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function readJsonData(target, label) {
|
|
53
|
+
if (path.extname(target).toLowerCase() !== ".json") {
|
|
54
|
+
throw new Error(`${label} input must be a JSON data file. Doctor never imports project code.`);
|
|
55
|
+
}
|
|
56
|
+
const initial = await lstat(target);
|
|
57
|
+
if (initial.isSymbolicLink())
|
|
58
|
+
throw new Error(`${label} input must not be a symbolic link`);
|
|
59
|
+
if (!initial.isFile())
|
|
60
|
+
throw new Error(`${label} input must be a regular file`);
|
|
61
|
+
if (initial.size > MAX_DOCTOR_INPUT_BYTES) {
|
|
62
|
+
throw new Error(`${label} input exceeds 65536 bytes`);
|
|
63
|
+
}
|
|
64
|
+
const handle = await open(target, "r");
|
|
65
|
+
try {
|
|
66
|
+
const opened = await handle.stat();
|
|
67
|
+
if (!opened.isFile()) {
|
|
68
|
+
throw new Error(`${label} input must be a regular file`);
|
|
69
|
+
}
|
|
70
|
+
if (opened.dev !== initial.dev || opened.ino !== initial.ino) {
|
|
71
|
+
throw new Error(`${label} input changed before it could be read`);
|
|
72
|
+
}
|
|
73
|
+
if (opened.size > MAX_DOCTOR_INPUT_BYTES) {
|
|
74
|
+
throw new Error(`${label} input exceeds 65536 bytes`);
|
|
75
|
+
}
|
|
76
|
+
const bytes = Buffer.alloc(MAX_DOCTOR_INPUT_BYTES + 1);
|
|
77
|
+
let offset = 0;
|
|
78
|
+
while (offset < bytes.byteLength) {
|
|
79
|
+
const result = await handle.read(bytes, offset, bytes.byteLength - offset, offset);
|
|
80
|
+
if (result.bytesRead === 0)
|
|
81
|
+
break;
|
|
82
|
+
offset += result.bytesRead;
|
|
83
|
+
}
|
|
84
|
+
if (offset > MAX_DOCTOR_INPUT_BYTES) {
|
|
85
|
+
throw new Error(`${label} input exceeds 65536 bytes`);
|
|
86
|
+
}
|
|
87
|
+
let text;
|
|
88
|
+
try {
|
|
89
|
+
text = new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, offset));
|
|
90
|
+
}
|
|
91
|
+
catch (cause) {
|
|
92
|
+
throw new Error(`${label} input must be valid UTF-8`, { cause });
|
|
93
|
+
}
|
|
94
|
+
return parseDataText(text, `${label} ${target}`);
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
await handle.close();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function formatJson(report) {
|
|
101
|
+
return `${JSON.stringify(report, null, 2)}\n`;
|
|
102
|
+
}
|
|
103
|
+
function formatHuman(report) {
|
|
104
|
+
const lines = [
|
|
105
|
+
report.valid
|
|
106
|
+
? "Peekling Doctor found no configuration errors."
|
|
107
|
+
: `Peekling Doctor found ${report.errors.length} configuration error${report.errors.length === 1 ? "" : "s"}.`,
|
|
108
|
+
];
|
|
109
|
+
for (const [label, issues] of [
|
|
110
|
+
["ERROR", report.errors],
|
|
111
|
+
["WARNING", report.warnings],
|
|
112
|
+
]) {
|
|
113
|
+
for (const issue of issues) {
|
|
114
|
+
lines.push("", `${label} ${issue.code} at ${issue.path}`, ` ${issue.message}`, ` Fix: ${issue.fix}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (report.warnings.length > 0) {
|
|
118
|
+
lines.push("", `${report.warnings.length} warning${report.warnings.length === 1 ? "" : "s"} need review.`);
|
|
119
|
+
}
|
|
120
|
+
return `${lines.join("\n")}\n`;
|
|
121
|
+
}
|
package/dist/image.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,MAAM,SAAS,GAAG,cAAc,CAAC;AAEvC,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CAIxE"}
|
package/dist/image.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { inspectImageStructure } from "@peekling/runtime/pack";
|
|
2
|
+
import { inspectPng } from "./png.js";
|
|
3
|
+
export function inspectImage(buffer, fileName) {
|
|
4
|
+
if (fileName.toLowerCase().endsWith(".png"))
|
|
5
|
+
return { ...inspectPng(buffer), mimeType: "image/png" };
|
|
6
|
+
return inspectImageStructure(buffer, "image/webp");
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ValidationResult {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
atlas: {
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
bytes: number;
|
|
8
|
+
};
|
|
9
|
+
states: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function packAuthoringSource(sourceDirectory: string, output: string): Promise<void>;
|
|
12
|
+
export declare function createPack(target: string, name: string): Promise<void>;
|
|
13
|
+
export declare function validatePackDirectory(target: string): Promise<ValidationResult>;
|
|
14
|
+
export interface CodexImportMetadata {
|
|
15
|
+
license: string;
|
|
16
|
+
author: string;
|
|
17
|
+
source: string;
|
|
18
|
+
rights: string;
|
|
19
|
+
allowPng?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function importCodexPet(input: string, output: string, metadata: CodexImportMetadata): Promise<void>;
|
|
22
|
+
export { createFixtureAtlas } from "./png.js";
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB;AA2FD,wBAAsB,mBAAmB,CACvC,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmSf;AA+CD,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B5E;AAkHD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAyE3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA4DD,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAsDf;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC"}
|