rs3-api-ts 0.0.0-stage → 0.1.1
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 +27 -2
- package/data/modio-libraries.json +21 -0
- package/dist/build.js +130 -0
- package/dist/checks.js +335 -0
- package/dist/dev.js +81 -0
- package/dist/errors.js +13 -0
- package/dist/index.js +194 -0
- package/dist/init.js +427 -0
- package/dist/libraries.js +99 -0
- package/dist/permissions.js +59 -0
- package/dist/postprocess.js +36 -0
- package/dist/project.js +98 -0
- package/dist/prompt.js +160 -0
- package/dist/report.js +87 -0
- package/package.json +53 -4
- package/templates/_gitignore +2 -0
- package/templates/_tsconfig.json +8 -0
- package/templates/src/main.ts +9 -0
- package/templates/src/modules/xp.ts +16 -0
- package/tsconfig.base.json +18 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.catalogPath = catalogPath;
|
|
37
|
+
exports.loadCatalog = loadCatalog;
|
|
38
|
+
exports.findLibrary = findLibrary;
|
|
39
|
+
exports.parseDependencies = parseDependencies;
|
|
40
|
+
exports.toManifestDependencies = toManifestDependencies;
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const errors_1 = require("./errors");
|
|
44
|
+
const project_1 = require("./project");
|
|
45
|
+
let cached;
|
|
46
|
+
function catalogPath() {
|
|
47
|
+
return path.join((0, project_1.sdkRoot)(), "data", "modio-libraries.json");
|
|
48
|
+
}
|
|
49
|
+
function loadCatalog() {
|
|
50
|
+
if (cached === undefined) {
|
|
51
|
+
cached = JSON.parse(fs.readFileSync(catalogPath(), "utf8"));
|
|
52
|
+
}
|
|
53
|
+
return cached;
|
|
54
|
+
}
|
|
55
|
+
function findLibrary(nameId) {
|
|
56
|
+
return loadCatalog().libraries.find((lib) => lib.name_id === nameId);
|
|
57
|
+
}
|
|
58
|
+
/** A bare name has to be in the catalog; `name=id` takes any mod.io id. */
|
|
59
|
+
function parseDependencies(input) {
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const raw of input.split(",")) {
|
|
62
|
+
const entry = raw.trim();
|
|
63
|
+
if (entry === "") {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const eq = entry.indexOf("=");
|
|
67
|
+
if (eq > 0) {
|
|
68
|
+
const name = entry.slice(0, eq).trim();
|
|
69
|
+
const id = Number(entry.slice(eq + 1).trim());
|
|
70
|
+
if (!Number.isInteger(id) || id <= 0) {
|
|
71
|
+
throw new errors_1.CliError(`"${entry}" does not end in a mod.io id`, [
|
|
72
|
+
"the part after = is the numeric id from the plugin's mod.io page",
|
|
73
|
+
`for example: ${name}=6398181`,
|
|
74
|
+
]);
|
|
75
|
+
}
|
|
76
|
+
out.push({ name, id });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const known = findLibrary(entry);
|
|
80
|
+
if (known === undefined) {
|
|
81
|
+
const names = loadCatalog().libraries.map((l) => l.name_id);
|
|
82
|
+
throw new errors_1.CliError(`"${entry}" is not in the known library list`, [
|
|
83
|
+
names.length > 0 ? `known libraries: ${names.join(", ")}` : "the known library list is empty",
|
|
84
|
+
`if it is not listed, give its mod.io id: ${entry}=123456`,
|
|
85
|
+
"or refresh the list with: npm run deps:dump",
|
|
86
|
+
]);
|
|
87
|
+
}
|
|
88
|
+
out.push({ name: known.name_id, id: known.id });
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
/** The client wants identifier -> mod.io id, and `{}` for none. */
|
|
93
|
+
function toManifestDependencies(entries) {
|
|
94
|
+
const out = {};
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
out[entry.name] = entry.id;
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.permissionsPath = permissionsPath;
|
|
37
|
+
exports.loadPermissions = loadPermissions;
|
|
38
|
+
exports.findPermission = findPermission;
|
|
39
|
+
exports.permissionNames = permissionNames;
|
|
40
|
+
const fs = __importStar(require("node:fs"));
|
|
41
|
+
const path = __importStar(require("node:path"));
|
|
42
|
+
let cached;
|
|
43
|
+
function permissionsPath() {
|
|
44
|
+
const corePackage = require.resolve("rs3-api-core/package.json");
|
|
45
|
+
return path.join(path.dirname(corePackage), "data", "permissions.json");
|
|
46
|
+
}
|
|
47
|
+
function loadPermissions() {
|
|
48
|
+
if (cached === undefined) {
|
|
49
|
+
const file = JSON.parse(fs.readFileSync(permissionsPath(), "utf8"));
|
|
50
|
+
cached = file.permissions.map((p) => ({ ...p, gates: p.gates.map((g) => new RegExp(g)) }));
|
|
51
|
+
}
|
|
52
|
+
return cached;
|
|
53
|
+
}
|
|
54
|
+
function findPermission(name) {
|
|
55
|
+
return loadPermissions().find((p) => p.name === name);
|
|
56
|
+
}
|
|
57
|
+
function permissionNames() {
|
|
58
|
+
return loadPermissions().map((p) => p.name);
|
|
59
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeReadable = makeReadable;
|
|
4
|
+
const LUA_KEYWORDS = new Set([
|
|
5
|
+
"and", "break", "do", "else", "elseif", "end", "false", "for", "function", "goto", "if", "in",
|
|
6
|
+
"local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while",
|
|
7
|
+
]);
|
|
8
|
+
/** Tidies TypeScriptToLua output for release builds. Dev bundles are left alone. */
|
|
9
|
+
function makeReadable(code) {
|
|
10
|
+
let out = code;
|
|
11
|
+
if (!/\bM\b/.test(out.replace(/____exports/g, ""))) {
|
|
12
|
+
out = out.replace(/____exports/g, "M");
|
|
13
|
+
}
|
|
14
|
+
out = out.replace(/\bfor ____, /g, "for _, ");
|
|
15
|
+
// @noSelf tags are copied through from the TypeScript but only mean something to the compiler.
|
|
16
|
+
out = out.replace(/^-- ?\n(?=-- @noSelf)/gm, "").replace(/^-- @noSelf\w*\n/gm, "");
|
|
17
|
+
// local ____rs3_2Dapi_2Dextended = require(...) -> local ext = require(...)
|
|
18
|
+
for (const match of out.matchAll(/^local (____[A-Za-z][A-Za-z0-9_]*) = require\("([^"]+)"\)$/gm)) {
|
|
19
|
+
const mangled = match[1];
|
|
20
|
+
const modulePath = match[2];
|
|
21
|
+
const candidate = /rs3-api-extended/.test(modulePath) ? "ext" : mangled.slice(4).replace(/_2D/g, "_");
|
|
22
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(candidate) || LUA_KEYWORDS.has(candidate)) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const taken = new RegExp(`\\b${candidate}\\b`).test(out.split(mangled).join(""));
|
|
26
|
+
if (!taken) {
|
|
27
|
+
out = out.split(mangled).join(candidate);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// The client turns require("a.b") into the path a.b.lua, so module paths need slashes.
|
|
31
|
+
out = out.replace(/require\("([^"]+)"\)/g, (_match, modulePath) => {
|
|
32
|
+
return `require("${modulePath.replace(/\./g, "/")}")`;
|
|
33
|
+
});
|
|
34
|
+
out = out.replace(/[ \t]+$/gm, "");
|
|
35
|
+
return out.endsWith("\n") ? out : `${out}\n`;
|
|
36
|
+
}
|
package/dist/project.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadProject = loadProject;
|
|
37
|
+
exports.sdkRoot = sdkRoot;
|
|
38
|
+
exports.sdkVersion = sdkVersion;
|
|
39
|
+
const fs = __importStar(require("node:fs"));
|
|
40
|
+
const path = __importStar(require("node:path"));
|
|
41
|
+
const tstl = __importStar(require("typescript-to-lua"));
|
|
42
|
+
const errors_1 = require("./errors");
|
|
43
|
+
function loadProject(cwd) {
|
|
44
|
+
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
45
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
46
|
+
throw new errors_1.CliError("no tsconfig.json here, so there is no plugin to build", [
|
|
47
|
+
`looked in ${cwd}`,
|
|
48
|
+
"run this from the plugin folder, or scaffold one with: rs3-plugin init my-plugin",
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
const parsed = tstl.parseConfigFileWithSystem(tsconfigPath);
|
|
52
|
+
const srcDir = parsed.options.rootDir ?? path.join(cwd, "src");
|
|
53
|
+
const outDir = parsed.options.outDir ?? path.join(cwd, "dist");
|
|
54
|
+
const manifestPath = path.join(cwd, "plugin.json");
|
|
55
|
+
let manifest;
|
|
56
|
+
let manifestError;
|
|
57
|
+
if (!fs.existsSync(manifestPath)) {
|
|
58
|
+
manifestError = "plugin.json is missing";
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
try {
|
|
62
|
+
manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
manifestError = `plugin.json is not valid JSON: ${error instanceof Error ? error.message : String(error)}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
let packageJson;
|
|
69
|
+
const packageJsonPath = path.join(cwd, "package.json");
|
|
70
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
71
|
+
try {
|
|
72
|
+
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
packageJson = undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
cwd,
|
|
80
|
+
tsconfigPath,
|
|
81
|
+
manifestPath,
|
|
82
|
+
manifest,
|
|
83
|
+
manifestError,
|
|
84
|
+
srcDir,
|
|
85
|
+
outDir,
|
|
86
|
+
entryFile: path.join(srcDir, "main.ts"),
|
|
87
|
+
parsed,
|
|
88
|
+
packageJson,
|
|
89
|
+
syncVersion: packageJson?.rs3?.syncVersion === true,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function sdkRoot() {
|
|
93
|
+
return path.resolve(__dirname, "..");
|
|
94
|
+
}
|
|
95
|
+
function sdkVersion() {
|
|
96
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(sdkRoot(), "package.json"), "utf8"));
|
|
97
|
+
return pkg.version;
|
|
98
|
+
}
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.text = text;
|
|
37
|
+
exports.confirm = confirm;
|
|
38
|
+
exports.multiSelect = multiSelect;
|
|
39
|
+
const readline = __importStar(require("node:readline"));
|
|
40
|
+
const node_process_1 = require("node:process");
|
|
41
|
+
/** Re-asks until the validator is happy. */
|
|
42
|
+
async function text(question, fallback, validate) {
|
|
43
|
+
for (;;) {
|
|
44
|
+
const raw = (await ask(fallback !== undefined ? `${question} (${fallback}): ` : `${question}: `)).trim();
|
|
45
|
+
const value = raw === "" && fallback !== undefined ? fallback : raw;
|
|
46
|
+
const error = validate(value);
|
|
47
|
+
if (error === undefined) {
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
node_process_1.stdout.write(` ${error}\n`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function confirm(question, fallback) {
|
|
54
|
+
for (;;) {
|
|
55
|
+
const raw = (await ask(`${question} [${fallback ? "Y/n" : "y/N"}]: `)).trim().toLowerCase();
|
|
56
|
+
if (raw === "") {
|
|
57
|
+
return fallback;
|
|
58
|
+
}
|
|
59
|
+
if (raw === "y" || raw === "yes") {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (raw === "n" || raw === "no") {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
node_process_1.stdout.write(" answer y or n\n");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Up and down move, space toggles, `a` toggles all, enter confirms. One boolean per item. */
|
|
69
|
+
function multiSelect(question, items, preselected = []) {
|
|
70
|
+
if (items.length === 0) {
|
|
71
|
+
return Promise.resolve([]);
|
|
72
|
+
}
|
|
73
|
+
return new Promise((resolve) => {
|
|
74
|
+
const selected = items.map((_, i) => preselected[i] === true);
|
|
75
|
+
let cursor = 0;
|
|
76
|
+
let drawn = false;
|
|
77
|
+
const frame = () => {
|
|
78
|
+
const lines = [`${question} (up/down move, space toggles, a toggles all, enter confirms)`];
|
|
79
|
+
items.forEach((item, i) => {
|
|
80
|
+
const pointer = i === cursor ? ">" : " ";
|
|
81
|
+
const box = selected[i] ? "[x]" : "[ ]";
|
|
82
|
+
const hint = item.hint !== undefined ? ` ${dim(item.hint)}` : "";
|
|
83
|
+
lines.push(`${pointer} ${box} ${item.label}${hint}`);
|
|
84
|
+
});
|
|
85
|
+
return lines;
|
|
86
|
+
};
|
|
87
|
+
const draw = () => {
|
|
88
|
+
if (drawn) {
|
|
89
|
+
node_process_1.stdout.write(`\x1b[${items.length + 1}A\x1b[J`);
|
|
90
|
+
}
|
|
91
|
+
node_process_1.stdout.write(`${frame().join("\n")}\n`);
|
|
92
|
+
drawn = true;
|
|
93
|
+
};
|
|
94
|
+
const finish = () => {
|
|
95
|
+
node_process_1.stdin.removeListener("keypress", onKeypress);
|
|
96
|
+
if (node_process_1.stdin.isTTY) {
|
|
97
|
+
node_process_1.stdin.setRawMode(false);
|
|
98
|
+
}
|
|
99
|
+
node_process_1.stdin.pause();
|
|
100
|
+
node_process_1.stdout.write("\x1b[?25h");
|
|
101
|
+
const chosen = items.filter((_, i) => selected[i]).map((item) => item.label);
|
|
102
|
+
node_process_1.stdout.write(`${question}: ${chosen.length > 0 ? chosen.join(", ") : "none"}\n`);
|
|
103
|
+
resolve(selected);
|
|
104
|
+
};
|
|
105
|
+
const onKeypress = (_str, key) => {
|
|
106
|
+
if (key.ctrl === true && key.name === "c") {
|
|
107
|
+
node_process_1.stdout.write("\x1b[?25h\n");
|
|
108
|
+
process.exit(130);
|
|
109
|
+
}
|
|
110
|
+
switch (key.name) {
|
|
111
|
+
case "up":
|
|
112
|
+
case "k":
|
|
113
|
+
cursor = (cursor - 1 + items.length) % items.length;
|
|
114
|
+
break;
|
|
115
|
+
case "down":
|
|
116
|
+
case "j":
|
|
117
|
+
cursor = (cursor + 1) % items.length;
|
|
118
|
+
break;
|
|
119
|
+
case "space":
|
|
120
|
+
selected[cursor] = !selected[cursor];
|
|
121
|
+
break;
|
|
122
|
+
case "a":
|
|
123
|
+
{
|
|
124
|
+
const all = selected.every(Boolean);
|
|
125
|
+
selected.fill(!all);
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case "return":
|
|
129
|
+
case "enter":
|
|
130
|
+
// wipe the list so only the summary line is left behind
|
|
131
|
+
node_process_1.stdout.write(`\x1b[${items.length + 1}A\x1b[J`);
|
|
132
|
+
finish();
|
|
133
|
+
return;
|
|
134
|
+
default:
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
draw();
|
|
138
|
+
};
|
|
139
|
+
readline.emitKeypressEvents(node_process_1.stdin);
|
|
140
|
+
if (node_process_1.stdin.isTTY) {
|
|
141
|
+
node_process_1.stdin.setRawMode(true);
|
|
142
|
+
}
|
|
143
|
+
node_process_1.stdin.resume();
|
|
144
|
+
node_process_1.stdout.write("\x1b[?25l");
|
|
145
|
+
node_process_1.stdin.on("keypress", onKeypress);
|
|
146
|
+
draw();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
function ask(prompt) {
|
|
150
|
+
const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
|
|
151
|
+
return new Promise((resolve) => {
|
|
152
|
+
rl.question(prompt, (answer) => {
|
|
153
|
+
rl.close();
|
|
154
|
+
resolve(answer);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function dim(text) {
|
|
159
|
+
return node_process_1.stdout.isTTY ? `\x1b[2m${text}\x1b[22m` : text;
|
|
160
|
+
}
|
package/dist/report.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.printError = printError;
|
|
37
|
+
exports.printProblems = printProblems;
|
|
38
|
+
exports.printSummary = printSummary;
|
|
39
|
+
const path = __importStar(require("node:path"));
|
|
40
|
+
const errors_1 = require("./errors");
|
|
41
|
+
/** Prints a thrown error the same way a build problem is printed, hint included. */
|
|
42
|
+
function printError(error) {
|
|
43
|
+
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
+
if (error instanceof errors_1.CliError && error.hint !== undefined) {
|
|
45
|
+
for (const line of error.hint.split("\n")) {
|
|
46
|
+
console.error(line === "" ? "" : ` ${line}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function location(problem) {
|
|
51
|
+
if (problem.file === undefined) {
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
const file = path.relative(process.cwd(), problem.file);
|
|
55
|
+
return problem.line !== undefined ? `${file}:${problem.line}: ` : `${file}: `;
|
|
56
|
+
}
|
|
57
|
+
function printProblems(problems) {
|
|
58
|
+
const ordered = [...problems].sort((a, b) => (a.level === b.level ? 0 : a.level === "error" ? -1 : 1));
|
|
59
|
+
for (const problem of ordered) {
|
|
60
|
+
const out = problem.level === "error" ? console.error : console.warn;
|
|
61
|
+
out(`${problem.level}: ${location(problem)}${problem.message}`);
|
|
62
|
+
if (problem.hint !== undefined) {
|
|
63
|
+
const lines = Array.isArray(problem.hint) ? problem.hint : problem.hint.split("\n");
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
out(line === "" ? "" : ` ${line}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function printSummary(result) {
|
|
71
|
+
const errors = result.problems.filter((p) => p.level === "error").length;
|
|
72
|
+
const warnings = result.problems.filter((p) => p.level === "warning").length;
|
|
73
|
+
const name = result.project.manifest?.name ?? "plugin";
|
|
74
|
+
const mode = result.dev ? "dev bundle" : "release";
|
|
75
|
+
for (const note of result.notes) {
|
|
76
|
+
console.log(`note: ${note}`);
|
|
77
|
+
}
|
|
78
|
+
if (result.ok) {
|
|
79
|
+
console.log(`built ${name} (${mode}) -> ${path.relative(process.cwd(), result.outDir) || "."} (${result.files.length} lua file${result.files.length === 1 ? "" : "s"}${warnings > 0 ? `, ${warnings} warning${warnings === 1 ? "" : "s"}` : ""})`);
|
|
80
|
+
if (result.deployedTo !== undefined) {
|
|
81
|
+
console.log(`copied to ${result.deployedTo}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.error(`build failed: ${errors} error${errors === 1 ? "" : "s"}${warnings > 0 ? `, ${warnings} warning${warnings === 1 ? "" : "s"}` : ""}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rs3-api-ts",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "rs3-plugin: scaffold, build and check RuneScape 3 plugins written in TypeScript. Emits readable Lua and validates plugin.json against the client's rules.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Mark7625",
|
|
7
|
+
"homepage": "https://github.com/Rs3-Plugins/rs3-api-ts#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/Rs3-Plugins/rs3-api-ts.git",
|
|
11
|
+
"directory": "packages/cli"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Rs3-Plugins/rs3-api-ts/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"runescape",
|
|
18
|
+
"rs3",
|
|
19
|
+
"plugin",
|
|
20
|
+
"lua",
|
|
21
|
+
"typescript-to-lua",
|
|
22
|
+
"tstl",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"bin": {
|
|
26
|
+
"rs3-plugin": "dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"templates",
|
|
31
|
+
"data",
|
|
32
|
+
"tsconfig.base.json",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -p tsconfig.json",
|
|
41
|
+
"prepack": "npm run build"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"rs3-api-core": "^0.1.1",
|
|
45
|
+
"rs3-api-extended": "^0.1.1",
|
|
46
|
+
"typescript": "6.0.2",
|
|
47
|
+
"typescript-to-lua": "^1.37.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^26.6.5"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { on } from "rs3-api-extended";
|
|
2
|
+
|
|
3
|
+
let unsubscribe = () => {};
|
|
4
|
+
|
|
5
|
+
export function init() {
|
|
6
|
+
unsubscribe = on(Event.SkillTransmit, (e) => {
|
|
7
|
+
const gained = e.newXP - e.oldXP;
|
|
8
|
+
if (gained > 0) {
|
|
9
|
+
print(`[${Plugin.Name}] +${gained} xp (level ${e.newGameplayLevel})`);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function shutdown() {
|
|
15
|
+
unsubscribe();
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "bundler",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"types": ["rs3-api-core"],
|
|
9
|
+
"skipLibCheck": true
|
|
10
|
+
},
|
|
11
|
+
"tstl": {
|
|
12
|
+
"luaTarget": "5.4",
|
|
13
|
+
"luaLibImport": "none",
|
|
14
|
+
"noImplicitSelf": true,
|
|
15
|
+
"noHeader": true,
|
|
16
|
+
"sourceMapTraceback": false
|
|
17
|
+
}
|
|
18
|
+
}
|