overpy 9.4.21
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 +674 -0
- package/README.md +1132 -0
- package/cli.js +207 -0
- package/overpy.d.ts +73 -0
- package/overpy.js +200899 -0
- package/package.json +34 -0
package/cli.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var import_promises = require("node:fs/promises");
|
|
4
|
+
var import_node_path = require("node:path");
|
|
5
|
+
function loadOverpy() {
|
|
6
|
+
try {
|
|
7
|
+
return require("./overpy_standalone");
|
|
8
|
+
} catch {
|
|
9
|
+
try {
|
|
10
|
+
return require("./overpy");
|
|
11
|
+
} catch {
|
|
12
|
+
throw new Error("Unable to load OverPy runtime module. Expected './overpy_standalone' or './overpy'.");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function printHelp() {
|
|
17
|
+
const helpText = `OverPy CLI
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
overpy <command> [inputPath] [options]
|
|
21
|
+
|
|
22
|
+
Commands:
|
|
23
|
+
compile Compile OverPy code to Workshop code
|
|
24
|
+
decompile Decompile Workshop code to OverPy code
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
-i, --input <path> Input file path
|
|
28
|
+
-o, --output <path> Output file path
|
|
29
|
+
-l, --language <lang> Workshop language (default: en-US)
|
|
30
|
+
--root <path> Root path for compile imports
|
|
31
|
+
--main-file <name> Main file name for compile
|
|
32
|
+
--ignore-variable-index Omit variable indexes in decompile output
|
|
33
|
+
--ignore-subroutine-index Omit subroutine indexes in decompile output
|
|
34
|
+
-h, --help Show help
|
|
35
|
+
-V, --version Show package version
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
overpy compile -i script.opy -o script.txt
|
|
39
|
+
cat script.opy | overpy compile > script.txt
|
|
40
|
+
overpy decompile -i workshop.txt -o script.opy
|
|
41
|
+
cat workshop.txt | overpy decompile --ignore-variable-index > script.opy
|
|
42
|
+
`;
|
|
43
|
+
process.stdout.write(helpText);
|
|
44
|
+
}
|
|
45
|
+
function getVersion() {
|
|
46
|
+
const pkg = require("../package.json");
|
|
47
|
+
return pkg.version;
|
|
48
|
+
}
|
|
49
|
+
function isOption(value) {
|
|
50
|
+
return value.startsWith("-");
|
|
51
|
+
}
|
|
52
|
+
function consumeValue(args, index, optionName) {
|
|
53
|
+
const value = args[index + 1];
|
|
54
|
+
if (!value || isOption(value)) {
|
|
55
|
+
throw new Error(`Missing value for ${optionName}`);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
function parseArgs(argv) {
|
|
60
|
+
const parsed = {
|
|
61
|
+
command: null,
|
|
62
|
+
help: false,
|
|
63
|
+
version: false,
|
|
64
|
+
language: "en-US",
|
|
65
|
+
ignoreVariableIndex: false,
|
|
66
|
+
ignoreSubroutineIndex: false
|
|
67
|
+
};
|
|
68
|
+
const args = [...argv];
|
|
69
|
+
if (args.length === 0) {
|
|
70
|
+
parsed.help = true;
|
|
71
|
+
return parsed;
|
|
72
|
+
}
|
|
73
|
+
for (const flag of args) {
|
|
74
|
+
if (flag === "-h" || flag === "--help") {
|
|
75
|
+
parsed.help = true;
|
|
76
|
+
}
|
|
77
|
+
if (flag === "-V" || flag === "--version") {
|
|
78
|
+
parsed.version = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (parsed.help || parsed.version) {
|
|
82
|
+
return parsed;
|
|
83
|
+
}
|
|
84
|
+
const command = args.shift();
|
|
85
|
+
if (command !== "compile" && command !== "decompile") {
|
|
86
|
+
throw new Error(`Unknown command '${command}'. Expected 'compile' or 'decompile'.`);
|
|
87
|
+
}
|
|
88
|
+
parsed.command = command;
|
|
89
|
+
for (let i = 0; i < args.length; i++) {
|
|
90
|
+
const arg = args[i];
|
|
91
|
+
if (arg === "-i" || arg === "--input") {
|
|
92
|
+
parsed.inputPath = consumeValue(args, i, arg);
|
|
93
|
+
i++;
|
|
94
|
+
} else if (arg === "-o" || arg === "--output") {
|
|
95
|
+
parsed.outputPath = consumeValue(args, i, arg);
|
|
96
|
+
i++;
|
|
97
|
+
} else if (arg === "-l" || arg === "--language") {
|
|
98
|
+
parsed.language = consumeValue(args, i, arg);
|
|
99
|
+
i++;
|
|
100
|
+
} else if (arg === "--root") {
|
|
101
|
+
parsed.rootPath = consumeValue(args, i, arg);
|
|
102
|
+
i++;
|
|
103
|
+
} else if (arg === "--main-file") {
|
|
104
|
+
parsed.mainFileName = consumeValue(args, i, arg);
|
|
105
|
+
i++;
|
|
106
|
+
} else if (arg === "--ignore-variable-index") {
|
|
107
|
+
parsed.ignoreVariableIndex = true;
|
|
108
|
+
} else if (arg === "--ignore-subroutine-index") {
|
|
109
|
+
parsed.ignoreSubroutineIndex = true;
|
|
110
|
+
} else if (!isOption(arg) && !parsed.inputPath) {
|
|
111
|
+
parsed.inputPath = arg;
|
|
112
|
+
} else if (!isOption(arg) && parsed.inputPath) {
|
|
113
|
+
throw new Error(`Unexpected extra positional argument '${arg}'.`);
|
|
114
|
+
} else {
|
|
115
|
+
throw new Error(`Unknown option '${arg}'.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return parsed;
|
|
119
|
+
}
|
|
120
|
+
async function readStdin() {
|
|
121
|
+
const chunks = [];
|
|
122
|
+
for await (const chunk of process.stdin) {
|
|
123
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
124
|
+
}
|
|
125
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
126
|
+
}
|
|
127
|
+
async function loadInput(inputPath) {
|
|
128
|
+
if (inputPath) {
|
|
129
|
+
const absolute = (0, import_node_path.resolve)(inputPath);
|
|
130
|
+
const content = await (0, import_promises.readFile)(absolute, "utf8");
|
|
131
|
+
return { content, absolutePath: absolute, fromFile: true };
|
|
132
|
+
}
|
|
133
|
+
if (!process.stdin.isTTY) {
|
|
134
|
+
const content = await readStdin();
|
|
135
|
+
return { content, absolutePath: "", fromFile: false };
|
|
136
|
+
}
|
|
137
|
+
return { content: "", absolutePath: "", fromFile: false };
|
|
138
|
+
}
|
|
139
|
+
function formatError(error) {
|
|
140
|
+
if (error instanceof Error) {
|
|
141
|
+
return error.message;
|
|
142
|
+
}
|
|
143
|
+
return String(error);
|
|
144
|
+
}
|
|
145
|
+
function formatWarning(warning) {
|
|
146
|
+
if (warning && typeof warning === "object" && "message" in warning) {
|
|
147
|
+
return String(warning.message);
|
|
148
|
+
}
|
|
149
|
+
return String(warning);
|
|
150
|
+
}
|
|
151
|
+
async function writeOutput(content, outputPath) {
|
|
152
|
+
if (outputPath) {
|
|
153
|
+
await (0, import_promises.writeFile)((0, import_node_path.resolve)(outputPath), content, "utf8");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
process.stdout.write(content);
|
|
157
|
+
}
|
|
158
|
+
async function run() {
|
|
159
|
+
const overpy = loadOverpy();
|
|
160
|
+
const parsed = parseArgs(process.argv.slice(2));
|
|
161
|
+
if (parsed.version) {
|
|
162
|
+
process.stdout.write(`${getVersion()}
|
|
163
|
+
`);
|
|
164
|
+
return 0;
|
|
165
|
+
}
|
|
166
|
+
if (parsed.help || !parsed.command) {
|
|
167
|
+
printHelp();
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
const input = await loadInput(parsed.inputPath);
|
|
171
|
+
if (!input.content) {
|
|
172
|
+
process.stderr.write("No input provided. Use --input/-i, positional inputPath, or pipe via stdin.\n\n");
|
|
173
|
+
printHelp();
|
|
174
|
+
return 2;
|
|
175
|
+
}
|
|
176
|
+
await overpy.readyPromise;
|
|
177
|
+
if (parsed.command === "compile") {
|
|
178
|
+
const rootPath = parsed.rootPath ?? (input.fromFile ? (0, import_node_path.dirname)(input.absolutePath) : process.cwd());
|
|
179
|
+
const mainFileName = parsed.mainFileName ?? (input.fromFile ? (0, import_node_path.basename)(input.absolutePath) : "stdin.opy");
|
|
180
|
+
const result = await overpy.compile(
|
|
181
|
+
input.content,
|
|
182
|
+
parsed.language,
|
|
183
|
+
rootPath,
|
|
184
|
+
mainFileName
|
|
185
|
+
);
|
|
186
|
+
for (const warning of result.encounteredWarnings) {
|
|
187
|
+
process.stderr.write(`Warning: ${formatWarning(warning)}
|
|
188
|
+
`);
|
|
189
|
+
}
|
|
190
|
+
await writeOutput(result.result, parsed.outputPath);
|
|
191
|
+
return 0;
|
|
192
|
+
}
|
|
193
|
+
const decompiled = overpy.decompileAllRules(input.content, parsed.language, {
|
|
194
|
+
ignoreVariableIndex: parsed.ignoreVariableIndex,
|
|
195
|
+
ignoreSubroutineIndex: parsed.ignoreSubroutineIndex
|
|
196
|
+
});
|
|
197
|
+
await writeOutput(decompiled, parsed.outputPath);
|
|
198
|
+
return 0;
|
|
199
|
+
}
|
|
200
|
+
run().then((exitCode) => {
|
|
201
|
+
process.exitCode = exitCode;
|
|
202
|
+
}).catch((error) => {
|
|
203
|
+
process.stderr.write(`Error: ${formatError(error)}
|
|
204
|
+
`);
|
|
205
|
+
process.exitCode = 1;
|
|
206
|
+
});
|
|
207
|
+
//# sourceMappingURL=overpy_cli.js.map
|
package/overpy.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
declare namespace overpy {
|
|
2
|
+
type UnknownRecord = Record<string, unknown>;
|
|
3
|
+
|
|
4
|
+
interface CompileResult {
|
|
5
|
+
result: string;
|
|
6
|
+
macros: unknown[];
|
|
7
|
+
astMacros: UnknownRecord;
|
|
8
|
+
astConstants: UnknownRecord;
|
|
9
|
+
globalVariables: unknown[];
|
|
10
|
+
playerVariables: unknown[];
|
|
11
|
+
subroutines: unknown[];
|
|
12
|
+
encounteredWarnings: unknown[];
|
|
13
|
+
hiddenWarnings: string[];
|
|
14
|
+
enumMembers: UnknownRecord;
|
|
15
|
+
nbElements: number;
|
|
16
|
+
activatedExtensions: string[];
|
|
17
|
+
spentExtensionPoints: number;
|
|
18
|
+
availableExtensionPoints: number;
|
|
19
|
+
translationLanguages: string[];
|
|
20
|
+
translatedStrings: unknown[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function compile(
|
|
24
|
+
content: string,
|
|
25
|
+
language?: string,
|
|
26
|
+
rootPath?: string,
|
|
27
|
+
mainFileName?: string
|
|
28
|
+
): Promise<CompileResult>;
|
|
29
|
+
|
|
30
|
+
function decompileAllRules(
|
|
31
|
+
content: string,
|
|
32
|
+
language?: string,
|
|
33
|
+
options?: {
|
|
34
|
+
ignoreVariableIndex?: boolean;
|
|
35
|
+
ignoreSubroutineIndex?: boolean;
|
|
36
|
+
}
|
|
37
|
+
): string;
|
|
38
|
+
|
|
39
|
+
function decompileActions(content: string): unknown[];
|
|
40
|
+
function decompileConditions(content: string): unknown[];
|
|
41
|
+
function astToOpy(content: unknown): string;
|
|
42
|
+
function resetGlobalVariables(language?: string): void;
|
|
43
|
+
function typeToString(type: unknown): string;
|
|
44
|
+
function computeCustomGameSettingsSchema(): unknown;
|
|
45
|
+
|
|
46
|
+
const readyPromise: Promise<void>;
|
|
47
|
+
const actionKw: UnknownRecord;
|
|
48
|
+
const valueFuncKw: UnknownRecord;
|
|
49
|
+
const constantValues: UnknownRecord;
|
|
50
|
+
const annotations: UnknownRecord;
|
|
51
|
+
const eventKw: UnknownRecord;
|
|
52
|
+
const eventTeamKw: UnknownRecord;
|
|
53
|
+
const eventSlotKw: UnknownRecord;
|
|
54
|
+
const eventPlayerKw: UnknownRecord;
|
|
55
|
+
const ruleKw: UnknownRecord;
|
|
56
|
+
const stringKw: UnknownRecord;
|
|
57
|
+
const heroKw: UnknownRecord;
|
|
58
|
+
const mapKw: UnknownRecord;
|
|
59
|
+
const opyFuncs: UnknownRecord;
|
|
60
|
+
const opyMemberFuncs: UnknownRecord;
|
|
61
|
+
const opyKeywords: UnknownRecord;
|
|
62
|
+
const opyConstants: UnknownRecord;
|
|
63
|
+
const opyModules: UnknownRecord;
|
|
64
|
+
const opyMacros: UnknownRecord;
|
|
65
|
+
const currentLanguage: string;
|
|
66
|
+
const macros: unknown[];
|
|
67
|
+
const preprocessingDirectives: UnknownRecord;
|
|
68
|
+
const opyStringEntities: UnknownRecord;
|
|
69
|
+
const customGameSettingsSchema: UnknownRecord;
|
|
70
|
+
const overpyTemplate: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export = overpy;
|