@s2script/sdk 0.4.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/chat.d.ts +0 -7
- package/clients.d.ts +0 -18
- package/commands.d.ts +1 -4
- package/config.d.ts +0 -2
- package/cookies.d.ts +0 -3
- package/damage.d.ts +0 -5
- package/dist/cli.js +305 -126
- package/entity.d.ts +21 -36
- package/events.d.ts +0 -13
- package/interfaces.d.ts +1 -24
- package/package.json +7 -5
- package/plugin.d.ts +112 -0
- package/plugins.d.ts +11 -1
- package/server.d.ts +0 -7
- package/sound.d.ts +0 -4
- package/topmenu.d.ts +0 -4
- package/usercmd.d.ts +5 -18
- package/frame.d.ts +0 -13
package/dist/cli.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
import * as esbuild from "esbuild";
|
|
5
5
|
import AdmZip from "adm-zip";
|
|
6
6
|
import { readFileSync as readFileSync4, mkdirSync } from "node:fs";
|
|
7
|
-
import { resolve as
|
|
7
|
+
import { resolve as resolve5, join as join6 } from "node:path";
|
|
8
8
|
|
|
9
9
|
// src/typecheck/typecheck.ts
|
|
10
10
|
import ts from "typescript";
|
|
11
|
-
import { existsSync as
|
|
12
|
-
import { join as
|
|
11
|
+
import { existsSync as existsSync3, readdirSync, readFileSync, writeFileSync, rmSync, mkdtempSync } from "node:fs";
|
|
12
|
+
import { join as join3, resolve as resolve2 } from "node:path";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
|
|
15
15
|
// src/packages-resolve.ts
|
|
@@ -55,11 +55,47 @@ function resolvePackagesDir(opts) {
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// src/tsconfig-shared.ts
|
|
59
|
+
var sharedCompilerOptionsJson = {
|
|
60
|
+
strict: true,
|
|
61
|
+
noEmit: true,
|
|
62
|
+
moduleResolution: "bundler",
|
|
63
|
+
module: "ESNext",
|
|
64
|
+
target: "ES2020",
|
|
65
|
+
lib: ["ES2020"],
|
|
66
|
+
types: [],
|
|
67
|
+
skipLibCheck: true,
|
|
68
|
+
allowImportingTsExtensions: true
|
|
69
|
+
};
|
|
70
|
+
function sharedProgramOptions(tsMod) {
|
|
71
|
+
return {
|
|
72
|
+
strict: sharedCompilerOptionsJson.strict,
|
|
73
|
+
noEmit: sharedCompilerOptionsJson.noEmit,
|
|
74
|
+
allowImportingTsExtensions: sharedCompilerOptionsJson.allowImportingTsExtensions,
|
|
75
|
+
moduleResolution: tsMod.ModuleResolutionKind.Bundler,
|
|
76
|
+
module: tsMod.ModuleKind.ESNext,
|
|
77
|
+
target: tsMod.ScriptTarget.ES2020,
|
|
78
|
+
lib: sharedCompilerOptionsJson.lib.map((l) => `lib.${l.toLowerCase()}.d.ts`),
|
|
79
|
+
types: [...sharedCompilerOptionsJson.types],
|
|
80
|
+
skipLibCheck: sharedCompilerOptionsJson.skipLibCheck
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/contracts.ts
|
|
85
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
86
|
+
import { join as join2 } from "node:path";
|
|
87
|
+
function localContractPath(pluginDir, dep) {
|
|
88
|
+
const segs = dep.split("/");
|
|
89
|
+
if (segs.some((s) => s === "" || s === "." || s === "..")) return null;
|
|
90
|
+
const p = join2(pluginDir, ".s2script", "types", ...segs, "index.d.ts");
|
|
91
|
+
return existsSync2(p) ? p : null;
|
|
92
|
+
}
|
|
93
|
+
|
|
58
94
|
// src/typecheck/typecheck.ts
|
|
59
95
|
function localDeclarationFiles(pluginDir) {
|
|
60
|
-
const srcDir =
|
|
61
|
-
if (!
|
|
62
|
-
return readdirSync(srcDir).filter((f) => f.endsWith(".d.ts")).map((f) =>
|
|
96
|
+
const srcDir = join3(pluginDir, "src");
|
|
97
|
+
if (!existsSync3(srcDir)) return [];
|
|
98
|
+
return readdirSync(srcDir).filter((f) => f.endsWith(".d.ts")).map((f) => join3(srcDir, f));
|
|
63
99
|
}
|
|
64
100
|
function declaredModules(dtsFiles) {
|
|
65
101
|
const out = /* @__PURE__ */ new Set();
|
|
@@ -72,31 +108,33 @@ function declaredModules(dtsFiles) {
|
|
|
72
108
|
function typecheckPlugin(pluginDir, opts) {
|
|
73
109
|
const absDir = resolve2(pluginDir);
|
|
74
110
|
const packagesDir = opts?.packagesDir ? resolve2(opts.packagesDir) : resolvePackagesDir({ pluginDir: absDir });
|
|
75
|
-
const pkg = JSON.parse(readFileSync(
|
|
111
|
+
const pkg = JSON.parse(readFileSync(join3(absDir, "package.json"), "utf8"));
|
|
76
112
|
const s2 = pkg.s2script ?? {};
|
|
77
113
|
const entryRel = s2.main ?? pkg.main;
|
|
78
|
-
if (!entryRel) throw new Error(`typecheckPlugin: no entry point in ${
|
|
114
|
+
if (!entryRel) throw new Error(`typecheckPlugin: no entry point in ${join3(absDir, "package.json")}`);
|
|
79
115
|
const entry = resolve2(absDir, entryRel);
|
|
80
116
|
const isAlwaysResolved = (d) => d.startsWith("@s2script/sdk/") || d === "@s2script/cs2" || d.startsWith("@s2script/cs2/");
|
|
81
117
|
const localDts = localDeclarationFiles(absDir);
|
|
82
118
|
const locallyDeclared = declaredModules(localDts);
|
|
119
|
+
const allDeclaredDeps = [
|
|
120
|
+
...Object.keys(s2.pluginDependencies ?? {}),
|
|
121
|
+
...Object.keys(s2.optionalPluginDependencies ?? {})
|
|
122
|
+
];
|
|
123
|
+
const contractPaths = {};
|
|
124
|
+
for (const d of allDeclaredDeps) {
|
|
125
|
+
const p = localContractPath(absDir, d);
|
|
126
|
+
if (p !== null) contractPaths[d] = [p];
|
|
127
|
+
}
|
|
83
128
|
const deps = [
|
|
84
129
|
...Object.keys(s2.pluginDependencies ?? {}),
|
|
85
130
|
...Object.keys(s2.optionalPluginDependencies ?? {})
|
|
86
131
|
// Never stub a module the plugin declares itself — a shorthand `declare module "X";` and a
|
|
87
132
|
// full `declare module "X" { … }` for the same X collide.
|
|
88
|
-
].filter((d) => !isAlwaysResolved(d) && !locallyDeclared.has(d));
|
|
133
|
+
].filter((d) => !isAlwaysResolved(d) && !locallyDeclared.has(d) && contractPaths[d] === void 0);
|
|
89
134
|
const options = {
|
|
90
|
-
strict: true,
|
|
91
|
-
noEmit: true,
|
|
92
135
|
// Accept explicit `.ts` import extensions (node type-stripping requires them for source-to-source
|
|
93
136
|
// imports; esbuild strips them at bundle time). Backward-compatible — extensionless imports still resolve.
|
|
94
|
-
|
|
95
|
-
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
96
|
-
module: ts.ModuleKind.ESNext,
|
|
97
|
-
target: ts.ScriptTarget.ES2020,
|
|
98
|
-
lib: ["lib.es2020.d.ts"],
|
|
99
|
-
types: [],
|
|
137
|
+
...sharedProgramOptions(ts),
|
|
100
138
|
baseUrl: packagesDir,
|
|
101
139
|
paths: {
|
|
102
140
|
// Builtins are `@s2script/sdk/<cap>` → packages/sdk/<cap>.d.ts. The `@s2script/*` fallback
|
|
@@ -104,15 +142,15 @@ function typecheckPlugin(pluginDir, opts) {
|
|
|
104
142
|
// dirs are deleted). tsc picks the longest matching prefix, so `@s2script/sdk/*` wins for
|
|
105
143
|
// sdk imports.
|
|
106
144
|
"@s2script/sdk/*": ["sdk/*.d.ts"],
|
|
107
|
-
"@s2script/*": ["*/index.d.ts"]
|
|
108
|
-
|
|
109
|
-
|
|
145
|
+
"@s2script/*": ["*/index.d.ts"],
|
|
146
|
+
...contractPaths
|
|
147
|
+
}
|
|
110
148
|
};
|
|
111
|
-
const rootNames = [entry,
|
|
112
|
-
const tmp = mkdtempSync(
|
|
149
|
+
const rootNames = [entry, join3(packagesDir, "sdk", "globals.d.ts"), ...localDts];
|
|
150
|
+
const tmp = mkdtempSync(join3(tmpdir(), "s2tc-"));
|
|
113
151
|
try {
|
|
114
152
|
if (deps.length) {
|
|
115
|
-
const stub =
|
|
153
|
+
const stub = join3(tmp, "ambient.d.ts");
|
|
116
154
|
writeFileSync(stub, deps.map((d) => `declare module ${JSON.stringify(d)};`).join("\n") + "\n");
|
|
117
155
|
rootNames.push(stub);
|
|
118
156
|
}
|
|
@@ -132,7 +170,7 @@ function typecheckPlugin(pluginDir, opts) {
|
|
|
132
170
|
}
|
|
133
171
|
return { file, line, col, code: d.code, message: ts.flattenDiagnosticMessageText(d.messageText, "\n") };
|
|
134
172
|
});
|
|
135
|
-
return { ok: out.length === 0, diagnostics: out };
|
|
173
|
+
return { ok: out.length === 0, diagnostics: out, program };
|
|
136
174
|
} finally {
|
|
137
175
|
rmSync(tmp, { recursive: true, force: true });
|
|
138
176
|
}
|
|
@@ -239,8 +277,8 @@ function validateDecl(full, decl, typeStr, errs) {
|
|
|
239
277
|
}
|
|
240
278
|
|
|
241
279
|
// src/publish-gate.ts
|
|
242
|
-
import { existsSync as
|
|
243
|
-
import { join as
|
|
280
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
281
|
+
import { join as join4, resolve as resolve3 } from "node:path";
|
|
244
282
|
function hasPublishes(publishes) {
|
|
245
283
|
if (publishes == null) return false;
|
|
246
284
|
if (typeof publishes === "string") return publishes.trim().length > 0;
|
|
@@ -266,7 +304,7 @@ function assertPublishesTypes(pkg, pluginDir) {
|
|
|
266
304
|
};
|
|
267
305
|
}
|
|
268
306
|
const typesPath = resolve3(pluginDir, typesRel);
|
|
269
|
-
if (!
|
|
307
|
+
if (!existsSync4(typesPath)) {
|
|
270
308
|
return { ok: false, error: `types file not found: ${typesRel}` };
|
|
271
309
|
}
|
|
272
310
|
const st = statSync(typesPath);
|
|
@@ -341,32 +379,160 @@ function derivePublishes(authored, pkgName, pkgVersion, typesPath) {
|
|
|
341
379
|
return out;
|
|
342
380
|
}
|
|
343
381
|
|
|
382
|
+
// src/api-version.ts
|
|
383
|
+
var HOST_API_VERSION_MAJOR = 2;
|
|
384
|
+
var STAMPED_API_VERSION = `${HOST_API_VERSION_MAJOR}.x`;
|
|
385
|
+
|
|
386
|
+
// src/publish-scan.ts
|
|
387
|
+
import ts2 from "typescript";
|
|
388
|
+
function isPluginContext(type) {
|
|
389
|
+
const sym = type.getSymbol() ?? type.aliasSymbol;
|
|
390
|
+
return sym?.getName() === "PluginContext";
|
|
391
|
+
}
|
|
392
|
+
function scanPluginProgram(program, pluginDir) {
|
|
393
|
+
const checker = program.getTypeChecker();
|
|
394
|
+
const out = { publishNames: [], dynamicPublishSites: [], useNames: [] };
|
|
395
|
+
const dirPrefix = pluginDir.replace(/\\/g, "/").replace(/\/+$/, "") + "/";
|
|
396
|
+
for (const sf of program.getSourceFiles()) {
|
|
397
|
+
if (sf.isDeclarationFile) continue;
|
|
398
|
+
if (!sf.fileName.replace(/\\/g, "/").startsWith(dirPrefix)) continue;
|
|
399
|
+
const visit = (node) => {
|
|
400
|
+
if (ts2.isCallExpression(node) && ts2.isPropertyAccessExpression(node.expression)) {
|
|
401
|
+
const method = node.expression.name.text;
|
|
402
|
+
if (method === "publish" || method === "use" || method === "tryUse") {
|
|
403
|
+
const recv = checker.getTypeAtLocation(node.expression.expression);
|
|
404
|
+
if (isPluginContext(recv)) {
|
|
405
|
+
const arg0 = node.arguments[0];
|
|
406
|
+
if (method === "publish") {
|
|
407
|
+
if (arg0 !== void 0 && ts2.isStringLiteralLike(arg0)) {
|
|
408
|
+
out.publishNames.push(arg0.text);
|
|
409
|
+
} else {
|
|
410
|
+
const { line } = sf.getLineAndCharacterOfPosition(node.getStart());
|
|
411
|
+
out.dynamicPublishSites.push(`${sf.fileName}:${line + 1}`);
|
|
412
|
+
}
|
|
413
|
+
} else if (arg0 !== void 0 && ts2.isStringLiteralLike(arg0)) {
|
|
414
|
+
out.useNames.push(arg0.text);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
ts2.forEachChild(node, visit);
|
|
420
|
+
};
|
|
421
|
+
visit(sf);
|
|
422
|
+
}
|
|
423
|
+
out.publishNames = [...new Set(out.publishNames)];
|
|
424
|
+
out.useNames = [...new Set(out.useNames)];
|
|
425
|
+
return out;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/lint/lint.ts
|
|
429
|
+
import { ESLint } from "eslint";
|
|
430
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
431
|
+
import { join as join5, resolve as resolve4 } from "node:path";
|
|
432
|
+
import s2lint from "@s2script/eslint-plugin";
|
|
433
|
+
var CONFIG_FILES = ["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", "eslint.config.ts"];
|
|
434
|
+
async function lintPlugin(pluginDir, program) {
|
|
435
|
+
const absDir = resolve4(pluginDir);
|
|
436
|
+
const hasOwnConfig = CONFIG_FILES.some((f) => existsSync5(join5(absDir, f)));
|
|
437
|
+
const eslint = hasOwnConfig ? new ESLint({ cwd: absDir, errorOnUnmatchedPattern: false }) : new ESLint({
|
|
438
|
+
cwd: absDir,
|
|
439
|
+
overrideConfigFile: true,
|
|
440
|
+
overrideConfig: s2lint.configs.build([program]),
|
|
441
|
+
errorOnUnmatchedPattern: false
|
|
442
|
+
});
|
|
443
|
+
const dirPrefix = absDir.replace(/\\/g, "/").replace(/\/+$/, "") + "/";
|
|
444
|
+
const targets = hasOwnConfig ? ["**/*.ts"] : program.getSourceFiles().filter((sf) => !sf.isDeclarationFile && sf.fileName.replace(/\\/g, "/").startsWith(dirPrefix)).map((sf) => sf.fileName);
|
|
445
|
+
if (targets.length === 0) return { ok: true, output: "", errorCount: 0 };
|
|
446
|
+
const results = await eslint.lintFiles(targets);
|
|
447
|
+
const errorCount = results.reduce((n, r) => n + r.errorCount, 0);
|
|
448
|
+
const formatter = await eslint.loadFormatter("stylish");
|
|
449
|
+
const output2 = String(await formatter.format(results));
|
|
450
|
+
return { ok: errorCount === 0, output: output2, errorCount };
|
|
451
|
+
}
|
|
452
|
+
|
|
344
453
|
// src/build.ts
|
|
345
454
|
async function buildPlugin(dir, packagesDir) {
|
|
346
|
-
const absDir =
|
|
347
|
-
const pkgPath =
|
|
455
|
+
const absDir = resolve5(dir);
|
|
456
|
+
const pkgPath = join6(absDir, "package.json");
|
|
348
457
|
const pkg = JSON.parse(readFileSync4(pkgPath, "utf8"));
|
|
349
|
-
const gate = assertPublishesTypes(pkg, absDir);
|
|
350
|
-
if (!gate.ok) {
|
|
351
|
-
throw new Error(`publish gate failed: ${gate.error}`);
|
|
352
|
-
}
|
|
353
458
|
const s2 = pkg.s2script ?? {};
|
|
354
|
-
const
|
|
459
|
+
const config = s2.config ?? void 0;
|
|
460
|
+
if (config !== void 0) {
|
|
461
|
+
const cfgErrs = validateConfigBlock(config);
|
|
462
|
+
if (cfgErrs.length) throw new Error(`invalid s2script.config:
|
|
463
|
+
${cfgErrs.join("\n ")}`);
|
|
464
|
+
}
|
|
355
465
|
const tc = typecheckPlugin(absDir, packagesDir !== void 0 ? { packagesDir } : void 0);
|
|
356
466
|
if (!tc.ok) {
|
|
357
467
|
throw new Error(`typecheck failed (${tc.diagnostics.length} error(s)):
|
|
358
468
|
${formatDiagnostics(tc.diagnostics)}`);
|
|
359
469
|
}
|
|
360
|
-
const
|
|
361
|
-
const
|
|
470
|
+
const scan = scanPluginProgram(tc.program, absDir);
|
|
471
|
+
const lint = await lintPlugin(absDir, tc.program);
|
|
472
|
+
if (!lint.ok) {
|
|
473
|
+
throw new Error(`lint failed (${lint.errorCount} error(s)):
|
|
474
|
+
${lint.output}`);
|
|
475
|
+
}
|
|
476
|
+
if (lint.output.trim().length > 0) console.warn(lint.output);
|
|
477
|
+
if (scan.dynamicPublishSites.length > 0) {
|
|
478
|
+
throw new Error(
|
|
479
|
+
`ctx.publish name must be a string literal (the manifest publishes block is derived from code):
|
|
480
|
+
` + scan.dynamicPublishSites.join("\n ")
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
let effectivePublishes = s2.publishes;
|
|
484
|
+
if (!hasPublishes(effectivePublishes)) {
|
|
485
|
+
if (scan.publishNames.length === 1 && scan.publishNames[0] === pkg.name) {
|
|
486
|
+
effectivePublishes = "self";
|
|
487
|
+
} else if (scan.publishNames.length > 0) {
|
|
488
|
+
throw new Error(
|
|
489
|
+
`code publishes ${JSON.stringify(scan.publishNames)} but s2script.publishes is missing \u2014 a contract named differently from the package needs an authored entry with a concrete version`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
} else {
|
|
493
|
+
const authoredNames = Object.keys(expandPublishes(effectivePublishes, pkg.name, pkg.version)).sort();
|
|
494
|
+
const codeNames = [...scan.publishNames].sort();
|
|
495
|
+
if (JSON.stringify(authoredNames) !== JSON.stringify(codeNames)) {
|
|
496
|
+
throw new Error(
|
|
497
|
+
`publishes drift: package.json declares ${JSON.stringify(authoredNames)} but the code's ctx.publish calls are ${JSON.stringify(codeNames)} \u2014 fix whichever is wrong (the manifest is generated from code; the loader re-verifies at Active)`
|
|
498
|
+
);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const gate = assertPublishesTypes({ ...pkg, s2script: { ...s2, publishes: effectivePublishes } }, absDir);
|
|
502
|
+
if (!gate.ok) {
|
|
503
|
+
throw new Error(`publish gate failed: ${gate.error}`);
|
|
504
|
+
}
|
|
505
|
+
const derivedPublishes = derivePublishes(
|
|
506
|
+
effectivePublishes,
|
|
507
|
+
pkg.name,
|
|
508
|
+
pkg.version,
|
|
509
|
+
gate.typesPath
|
|
510
|
+
);
|
|
362
511
|
const pluginDependencies = s2.pluginDependencies ?? {};
|
|
363
512
|
const optionalPluginDependencies = s2.optionalPluginDependencies ?? {};
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
513
|
+
const declaredDeps = /* @__PURE__ */ new Set([
|
|
514
|
+
...Object.keys(pluginDependencies),
|
|
515
|
+
...Object.keys(optionalPluginDependencies)
|
|
516
|
+
]);
|
|
517
|
+
for (const used of scan.useNames) {
|
|
518
|
+
if (!declaredDeps.has(used)) {
|
|
519
|
+
console.warn(
|
|
520
|
+
`WARN: ctx.use/tryUse(${JSON.stringify(used)}) is not declared under s2script.pluginDependencies/optionalPluginDependencies \u2014 it will throw at runtime`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
for (const dep of declaredDeps) {
|
|
525
|
+
if (!scan.useNames.includes(dep)) {
|
|
526
|
+
console.warn(`WARN: dependency ${JSON.stringify(dep)} is declared but never ctx.use()d`);
|
|
527
|
+
}
|
|
369
528
|
}
|
|
529
|
+
const { name, version } = pkg;
|
|
530
|
+
if (s2.apiVersion !== void 0) {
|
|
531
|
+
console.warn(
|
|
532
|
+
`WARN: ${pkgPath}: s2script.apiVersion is ignored \u2014 s2s build derives apiVersion from the SDK (stamping ${JSON.stringify(STAMPED_API_VERSION)}). Remove the field.`
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
const apiVersion = STAMPED_API_VERSION;
|
|
370
536
|
const external = Array.from(/* @__PURE__ */ new Set([
|
|
371
537
|
"@s2script/*",
|
|
372
538
|
...Object.keys(pluginDependencies),
|
|
@@ -378,7 +544,7 @@ ${formatDiagnostics(tc.diagnostics)}`);
|
|
|
378
544
|
`buildPlugin: no entry point found in ${pkgPath} (set s2script.main or main)`
|
|
379
545
|
);
|
|
380
546
|
}
|
|
381
|
-
const entryPoint =
|
|
547
|
+
const entryPoint = join6(absDir, entryRelative);
|
|
382
548
|
const result = await esbuild.build({
|
|
383
549
|
entryPoints: [entryPoint],
|
|
384
550
|
bundle: true,
|
|
@@ -401,6 +567,15 @@ ${formatDiagnostics(tc.diagnostics)}`);
|
|
|
401
567
|
manifest.publishes = derivedPublishes;
|
|
402
568
|
}
|
|
403
569
|
if (config !== void 0) manifest.config = config;
|
|
570
|
+
const compiledAgainst = {};
|
|
571
|
+
for (const dep of [
|
|
572
|
+
...Object.keys(pluginDependencies),
|
|
573
|
+
...Object.keys(optionalPluginDependencies)
|
|
574
|
+
]) {
|
|
575
|
+
const contractPath = localContractPath(absDir, dep);
|
|
576
|
+
if (contractPath !== null) compiledAgainst[dep] = hashContract(contractPath);
|
|
577
|
+
}
|
|
578
|
+
if (Object.keys(compiledAgainst).length > 0) manifest.compiledAgainst = compiledAgainst;
|
|
404
579
|
const zip = new AdmZip();
|
|
405
580
|
zip.addFile("manifest.json", Buffer.from(JSON.stringify(manifest, null, 2)));
|
|
406
581
|
zip.addFile("plugin.js", Buffer.from(pluginJs));
|
|
@@ -412,16 +587,16 @@ ${formatDiagnostics(tc.diagnostics)}`);
|
|
|
412
587
|
}
|
|
413
588
|
}
|
|
414
589
|
const sanitizedId = name.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
415
|
-
const outDir =
|
|
590
|
+
const outDir = join6(absDir, "dist");
|
|
416
591
|
mkdirSync(outDir, { recursive: true });
|
|
417
|
-
const outPath =
|
|
592
|
+
const outPath = join6(outDir, `${sanitizedId}.s2sp`);
|
|
418
593
|
zip.writeZip(outPath);
|
|
419
594
|
return outPath;
|
|
420
595
|
}
|
|
421
596
|
|
|
422
597
|
// src/schemagen/gen.ts
|
|
423
598
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
|
|
424
|
-
import { join as
|
|
599
|
+
import { join as join7 } from "node:path";
|
|
425
600
|
|
|
426
601
|
// src/schemagen/model.ts
|
|
427
602
|
var READ = {
|
|
@@ -613,21 +788,21 @@ function emitJs(model) {
|
|
|
613
788
|
for (const c of model.classes) {
|
|
614
789
|
out.push(` A[${S(c.className)}] = {`);
|
|
615
790
|
for (const f of flattenedFields(model, c.className)) {
|
|
616
|
-
const
|
|
791
|
+
const resolve8 = `off(${S(f.declaringClass)},${S(f.rawName)})`;
|
|
617
792
|
let entry;
|
|
618
793
|
if (f.accessorKind === "str") {
|
|
619
|
-
entry = `get: function () { return this.ref.readString(${
|
|
794
|
+
entry = `get: function () { return this.ref.readString(${resolve8}, ${f.strLen}); }`;
|
|
620
795
|
} else if (f.accessorKind === "u64" || f.accessorKind === "i64") {
|
|
621
|
-
entry = `get: function () { var v = this.ref.${READ[f.accessorKind]}(${
|
|
796
|
+
entry = `get: function () { var v = this.ref.${READ[f.accessorKind]}(${resolve8}); return v === null ? null : v.toString(); }`;
|
|
622
797
|
} else if (VEC_INFO[f.accessorKind]) {
|
|
623
798
|
const vi = VEC_INFO[f.accessorKind];
|
|
624
|
-
entry = `get: function () { var a = this.ref.readFloats(${
|
|
799
|
+
entry = `get: function () { var a = this.ref.readFloats(${resolve8}, ${vi.count}); return a === null ? null : new ${vi.cls}(a[0], a[1], a[2]); }`;
|
|
625
800
|
} else {
|
|
626
|
-
entry = `get: function () { return this.ref.${READ[f.accessorKind]}(${
|
|
801
|
+
entry = `get: function () { return this.ref.${READ[f.accessorKind]}(${resolve8}); }`;
|
|
627
802
|
}
|
|
628
803
|
if (f.writable) {
|
|
629
804
|
const wm = WRITE[f.accessorKind];
|
|
630
|
-
entry += `, set: function (v) { var o = ${
|
|
805
|
+
entry += `, set: function (v) { var o = ${resolve8}; if (this.ref.${wm}(o, v)) this.ref.notifyStateChanged(o); }`;
|
|
631
806
|
}
|
|
632
807
|
out.push(` ${S(f.propName)}: { ${entry} },`);
|
|
633
808
|
}
|
|
@@ -653,8 +828,8 @@ var LIST_PATH = "games/cs2/codegen-classes.json";
|
|
|
653
828
|
var JS_OUT = "games/cs2/js/schema.generated.js";
|
|
654
829
|
var DTS_OUT = "packages/cs2/schema.generated.d.ts";
|
|
655
830
|
function runGenSchema(repoRoot, opts) {
|
|
656
|
-
const catalog = JSON.parse(readFileSync5(
|
|
657
|
-
const list = JSON.parse(readFileSync5(
|
|
831
|
+
const catalog = JSON.parse(readFileSync5(join7(repoRoot, CATALOG_PATH), "utf8"));
|
|
832
|
+
const list = JSON.parse(readFileSync5(join7(repoRoot, LIST_PATH), "utf8"));
|
|
658
833
|
const model = buildModel(catalog, list);
|
|
659
834
|
const dts = emitDts(model);
|
|
660
835
|
const js = emitJs(model);
|
|
@@ -663,7 +838,7 @@ function runGenSchema(repoRoot, opts) {
|
|
|
663
838
|
const drift = [];
|
|
664
839
|
const files = [[JS_OUT, js], [DTS_OUT, dts]];
|
|
665
840
|
for (const [rel, content] of files) {
|
|
666
|
-
const abs =
|
|
841
|
+
const abs = join7(repoRoot, rel);
|
|
667
842
|
if (opts.check) {
|
|
668
843
|
let cur = "";
|
|
669
844
|
try {
|
|
@@ -683,7 +858,7 @@ function runGenSchema(repoRoot, opts) {
|
|
|
683
858
|
|
|
684
859
|
// src/eventgen/gen.ts
|
|
685
860
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync3 } from "node:fs";
|
|
686
|
-
import { join as
|
|
861
|
+
import { join as join8 } from "node:path";
|
|
687
862
|
|
|
688
863
|
// src/eventgen/model.ts
|
|
689
864
|
var TYPE_TO_GETTER = {
|
|
@@ -768,11 +943,11 @@ function emitEventDts(model) {
|
|
|
768
943
|
var CATALOG_PATH2 = "games/cs2/gamedata/event-catalog.json";
|
|
769
944
|
var DTS_OUT2 = "packages/cs2/events.generated.d.ts";
|
|
770
945
|
function runGenEvents(repoRoot, opts) {
|
|
771
|
-
const catalog = JSON.parse(readFileSync6(
|
|
946
|
+
const catalog = JSON.parse(readFileSync6(join8(repoRoot, CATALOG_PATH2), "utf8"));
|
|
772
947
|
const model = buildEventModel(catalog);
|
|
773
948
|
const dts = emitEventDts(model);
|
|
774
949
|
const drift = [];
|
|
775
|
-
const abs =
|
|
950
|
+
const abs = join8(repoRoot, DTS_OUT2);
|
|
776
951
|
if (opts.check) {
|
|
777
952
|
let cur = "";
|
|
778
953
|
try {
|
|
@@ -788,7 +963,7 @@ function runGenEvents(repoRoot, opts) {
|
|
|
788
963
|
|
|
789
964
|
// src/navgen/gen.ts
|
|
790
965
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
|
|
791
|
-
import { join as
|
|
966
|
+
import { join as join9 } from "node:path";
|
|
792
967
|
|
|
793
968
|
// src/navgen/model.ts
|
|
794
969
|
var SUPPORTED_NAV_KINDS = /* @__PURE__ */ new Set([
|
|
@@ -863,22 +1038,22 @@ function emitNavJs(model) {
|
|
|
863
1038
|
out.push(` function ${w.wrapper}(root, path) { this.root = root; this.path = path; }`);
|
|
864
1039
|
out.push(` Object.defineProperties(${w.wrapper}.prototype, {`);
|
|
865
1040
|
for (const f of w.fields) {
|
|
866
|
-
const
|
|
1041
|
+
const resolve8 = `off(${S2(f.declaringClass)},${S2(f.rawName)})`;
|
|
867
1042
|
let getter;
|
|
868
1043
|
const kind = f.accessorKind;
|
|
869
1044
|
if (kind === "u64") {
|
|
870
|
-
getter = `get: function () { var v = this.root.readUInt64Via(this.path, ${
|
|
1045
|
+
getter = `get: function () { var v = this.root.readUInt64Via(this.path, ${resolve8}); return v === null ? null : v.toString(); }`;
|
|
871
1046
|
} else if (kind === "i64") {
|
|
872
|
-
getter = `get: function () { var v = this.root.readInt64Via(this.path, ${
|
|
1047
|
+
getter = `get: function () { var v = this.root.readInt64Via(this.path, ${resolve8}); return v === null ? null : v.toString(); }`;
|
|
873
1048
|
} else if (VEC_INFO[kind]) {
|
|
874
1049
|
const vi = VEC_INFO[kind];
|
|
875
|
-
getter = `get: function () { var a = this.root.readFloatsChain(this.path, ${
|
|
1050
|
+
getter = `get: function () { var a = this.root.readFloatsChain(this.path, ${resolve8}, ${vi.count}); return a === null ? null : new ${vi.cls}(a[0], a[1], a[2]); }`;
|
|
876
1051
|
} else if (kind === "handle") {
|
|
877
|
-
getter = `get: function () { return this.root.readHandleVia(this.path, ${
|
|
1052
|
+
getter = `get: function () { return this.root.readHandleVia(this.path, ${resolve8}); }`;
|
|
878
1053
|
} else {
|
|
879
1054
|
const method = READ_VIA[kind];
|
|
880
1055
|
if (!method) continue;
|
|
881
|
-
getter = `get: function () { return this.root.${method}(this.path, ${
|
|
1056
|
+
getter = `get: function () { return this.root.${method}(this.path, ${resolve8}); }`;
|
|
882
1057
|
}
|
|
883
1058
|
out.push(` ${S2(f.propName)}: { ${getter} },`);
|
|
884
1059
|
}
|
|
@@ -950,8 +1125,8 @@ var CATALOG_PATH3 = "games/cs2/gamedata/schema-catalog.json";
|
|
|
950
1125
|
var JS_OUT2 = "games/cs2/js/nav.generated.js";
|
|
951
1126
|
var DTS_OUT3 = "packages/cs2/nav.generated.d.ts";
|
|
952
1127
|
function runGenNav(repoRoot, opts) {
|
|
953
|
-
const config = JSON.parse(readFileSync7(
|
|
954
|
-
const catalog = JSON.parse(readFileSync7(
|
|
1128
|
+
const config = JSON.parse(readFileSync7(join9(repoRoot, TARGETS_PATH), "utf8"));
|
|
1129
|
+
const catalog = JSON.parse(readFileSync7(join9(repoRoot, CATALOG_PATH3), "utf8"));
|
|
955
1130
|
const model = buildNavModel(config, catalog);
|
|
956
1131
|
const js = emitNavJs(model);
|
|
957
1132
|
const dts = emitNavDts(model);
|
|
@@ -959,7 +1134,7 @@ function runGenNav(repoRoot, opts) {
|
|
|
959
1134
|
const drift = [];
|
|
960
1135
|
const files = [[JS_OUT2, js], [DTS_OUT3, dts]];
|
|
961
1136
|
for (const [rel, content] of files) {
|
|
962
|
-
const abs =
|
|
1137
|
+
const abs = join9(repoRoot, rel);
|
|
963
1138
|
if (opts.check) {
|
|
964
1139
|
let cur = "";
|
|
965
1140
|
try {
|
|
@@ -978,11 +1153,12 @@ function runGenNav(repoRoot, opts) {
|
|
|
978
1153
|
import {
|
|
979
1154
|
mkdirSync as mkdirSync2,
|
|
980
1155
|
writeFileSync as writeFileSync5,
|
|
981
|
-
existsSync as
|
|
1156
|
+
existsSync as existsSync6,
|
|
982
1157
|
readdirSync as readdirSync2,
|
|
983
|
-
readFileSync as readFileSync8
|
|
1158
|
+
readFileSync as readFileSync8,
|
|
1159
|
+
symlinkSync
|
|
984
1160
|
} from "node:fs";
|
|
985
|
-
import { dirname as dirname2, join as
|
|
1161
|
+
import { dirname as dirname2, join as join10, resolve as resolve6, basename } from "node:path";
|
|
986
1162
|
import { createInterface } from "node:readline/promises";
|
|
987
1163
|
import { stdin as input, stdout as output } from "node:process";
|
|
988
1164
|
import { spawnSync } from "node:child_process";
|
|
@@ -990,13 +1166,13 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
990
1166
|
function readCliVersion() {
|
|
991
1167
|
const here = dirname2(fileURLToPath2(import.meta.url));
|
|
992
1168
|
const candidates = [
|
|
993
|
-
|
|
1169
|
+
join10(here, "..", "package.json"),
|
|
994
1170
|
// dist/cli.js → packages/sdk/package.json
|
|
995
|
-
|
|
1171
|
+
join10(here, "..", "..", "package.json")
|
|
996
1172
|
// src/create → packages/sdk/package.json
|
|
997
1173
|
];
|
|
998
1174
|
for (const p of candidates) {
|
|
999
|
-
if (!
|
|
1175
|
+
if (!existsSync6(p)) continue;
|
|
1000
1176
|
try {
|
|
1001
1177
|
const pkg = JSON.parse(readFileSync8(p, "utf8"));
|
|
1002
1178
|
if (pkg.name === "@s2script/sdk" && pkg.version) return pkg.version;
|
|
@@ -1008,18 +1184,18 @@ function readCliVersion() {
|
|
|
1008
1184
|
function findLocalPackagesDir() {
|
|
1009
1185
|
const here = dirname2(fileURLToPath2(import.meta.url));
|
|
1010
1186
|
const candidates = [
|
|
1011
|
-
|
|
1187
|
+
join10(here, "..", ".."),
|
|
1012
1188
|
// dist/cli.js → packages
|
|
1013
|
-
|
|
1189
|
+
join10(here, "..", "..", "..")
|
|
1014
1190
|
// src/create → packages
|
|
1015
1191
|
];
|
|
1016
1192
|
for (const c of candidates) {
|
|
1017
|
-
if (isPackagesDir(c)) return
|
|
1193
|
+
if (isPackagesDir(c)) return resolve6(c);
|
|
1018
1194
|
}
|
|
1019
1195
|
return void 0;
|
|
1020
1196
|
}
|
|
1021
1197
|
function defaultNameFromPath(dir) {
|
|
1022
|
-
const base = basename(
|
|
1198
|
+
const base = basename(resolve6(dir));
|
|
1023
1199
|
const slug = base.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() || "plugin";
|
|
1024
1200
|
return `@plugin/${slug}`;
|
|
1025
1201
|
}
|
|
@@ -1056,9 +1232,9 @@ function assertInstall(v) {
|
|
|
1056
1232
|
}
|
|
1057
1233
|
function createPackageNames(game) {
|
|
1058
1234
|
if (game === "cs2") {
|
|
1059
|
-
return ["sdk", "cs2"];
|
|
1235
|
+
return ["sdk", "cs2", "eslint-plugin"];
|
|
1060
1236
|
}
|
|
1061
|
-
return ["sdk"];
|
|
1237
|
+
return ["sdk", "eslint-plugin"];
|
|
1062
1238
|
}
|
|
1063
1239
|
function resolvePublishedVersion(pkg) {
|
|
1064
1240
|
const r = spawnSync("npm", ["view", pkg, "version"], { encoding: "utf8", timeout: 5e3 });
|
|
@@ -1068,68 +1244,62 @@ function versionSpecFrom(status, stdout) {
|
|
|
1068
1244
|
const v = (stdout ?? "").trim();
|
|
1069
1245
|
return status === 0 && /^\d+\.\d+\.\d+/.test(v) ? `^${v}` : "latest";
|
|
1070
1246
|
}
|
|
1071
|
-
function registryDevDeps(game, sdkVersion,
|
|
1247
|
+
function registryDevDeps(game, sdkVersion, resolve8 = resolvePublishedVersion) {
|
|
1072
1248
|
const deps = {};
|
|
1073
1249
|
for (const n of createPackageNames(game)) {
|
|
1074
|
-
deps[`@s2script/${n}`] = n === "sdk" ? `^${sdkVersion}` :
|
|
1250
|
+
deps[`@s2script/${n}`] = n === "sdk" ? `^${sdkVersion}` : resolve8(`@s2script/${n}`);
|
|
1075
1251
|
}
|
|
1076
1252
|
return deps;
|
|
1077
1253
|
}
|
|
1078
1254
|
function fileDevDeps(packagesDir, game) {
|
|
1079
1255
|
const deps = {};
|
|
1080
1256
|
for (const n of createPackageNames(game)) {
|
|
1081
|
-
const abs =
|
|
1082
|
-
if (!
|
|
1257
|
+
const abs = join10(packagesDir, n);
|
|
1258
|
+
if (!existsSync6(join10(abs, "package.json"))) return void 0;
|
|
1083
1259
|
deps[`@s2script/${n}`] = `file:${abs}`;
|
|
1084
1260
|
}
|
|
1085
1261
|
return deps;
|
|
1086
1262
|
}
|
|
1087
1263
|
function pluginSource(game) {
|
|
1088
1264
|
if (game === "cs2") {
|
|
1089
|
-
return `import {
|
|
1265
|
+
return `import { plugin } from "@s2script/sdk/plugin";
|
|
1090
1266
|
import { Chat } from "@s2script/sdk/chat";
|
|
1091
1267
|
|
|
1092
|
-
export
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
if (
|
|
1096
|
-
Chat.toSlot(
|
|
1268
|
+
export default plugin((ctx) => {
|
|
1269
|
+
ctx.commands.register("hello", (cmd) => {
|
|
1270
|
+
cmd.reply("hello from s2script");
|
|
1271
|
+
if (cmd.callerSlot >= 0) {
|
|
1272
|
+
Chat.toSlot(cmd.callerSlot, "hello from s2script");
|
|
1097
1273
|
}
|
|
1098
1274
|
});
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
export function onUnload(): void {}
|
|
1275
|
+
});
|
|
1102
1276
|
`;
|
|
1103
1277
|
}
|
|
1104
|
-
return `import {
|
|
1278
|
+
return `import { plugin } from "@s2script/sdk/plugin";
|
|
1105
1279
|
import { delay } from "@s2script/sdk/timers";
|
|
1106
1280
|
|
|
1107
|
-
export
|
|
1281
|
+
export default plugin((ctx) => {
|
|
1108
1282
|
let n = 0;
|
|
1109
|
-
|
|
1283
|
+
ctx.server.onGameFrame(() => {
|
|
1110
1284
|
n += 1;
|
|
1111
1285
|
});
|
|
1112
|
-
void delay(1000).then(() =>
|
|
1113
|
-
|
|
1114
|
-
|
|
1286
|
+
void delay(1000).then(() => console.log("s2script plugin alive; frames so far:", n));
|
|
1287
|
+
});
|
|
1288
|
+
`;
|
|
1115
1289
|
}
|
|
1290
|
+
var ESLINT_RANGE = "^10.7.0";
|
|
1291
|
+
function eslintConfig() {
|
|
1292
|
+
return `import s2script from "@s2script/eslint-plugin";
|
|
1116
1293
|
|
|
1117
|
-
|
|
1294
|
+
// The SAME pinned rules \`s2s build\` enforces \u2014 the editor's ESLint extension picks this up,
|
|
1295
|
+
// so a violation is a red squiggle before you ever build (green editor => green build).
|
|
1296
|
+
export default s2script.configs.recommended({ tsconfigRootDir: import.meta.dirname });
|
|
1118
1297
|
`;
|
|
1119
1298
|
}
|
|
1120
1299
|
function tsconfigJson() {
|
|
1121
1300
|
return JSON.stringify(
|
|
1122
1301
|
{
|
|
1123
|
-
compilerOptions:
|
|
1124
|
-
strict: true,
|
|
1125
|
-
noEmit: true,
|
|
1126
|
-
moduleResolution: "bundler",
|
|
1127
|
-
module: "ESNext",
|
|
1128
|
-
target: "ES2020",
|
|
1129
|
-
lib: ["ES2020"],
|
|
1130
|
-
types: [],
|
|
1131
|
-
skipLibCheck: true
|
|
1132
|
-
},
|
|
1302
|
+
compilerOptions: sharedCompilerOptionsJson,
|
|
1133
1303
|
include: ["src", "node_modules/@s2script/sdk/globals.d.ts"]
|
|
1134
1304
|
},
|
|
1135
1305
|
null,
|
|
@@ -1138,7 +1308,10 @@ function tsconfigJson() {
|
|
|
1138
1308
|
}
|
|
1139
1309
|
function packageJsonContent(name, game, version, localPackagesDir) {
|
|
1140
1310
|
const fileDeps = localPackagesDir ? fileDevDeps(localPackagesDir, game) : void 0;
|
|
1141
|
-
const devDependencies =
|
|
1311
|
+
const devDependencies = {
|
|
1312
|
+
...fileDeps ?? registryDevDeps(game, version),
|
|
1313
|
+
eslint: ESLINT_RANGE
|
|
1314
|
+
};
|
|
1142
1315
|
return JSON.stringify(
|
|
1143
1316
|
{
|
|
1144
1317
|
name,
|
|
@@ -1148,10 +1321,7 @@ function packageJsonContent(name, game, version, localPackagesDir) {
|
|
|
1148
1321
|
scripts: {
|
|
1149
1322
|
build: "s2s build ."
|
|
1150
1323
|
},
|
|
1151
|
-
devDependencies
|
|
1152
|
-
s2script: {
|
|
1153
|
-
apiVersion: "1.x"
|
|
1154
|
-
}
|
|
1324
|
+
devDependencies
|
|
1155
1325
|
},
|
|
1156
1326
|
null,
|
|
1157
1327
|
2
|
|
@@ -1164,6 +1334,12 @@ dist/
|
|
|
1164
1334
|
.DS_Store
|
|
1165
1335
|
`;
|
|
1166
1336
|
}
|
|
1337
|
+
function linkLocalPackagesForNoInstall(targetPath, localPackagesDir) {
|
|
1338
|
+
const nm = join10(targetPath, "node_modules");
|
|
1339
|
+
mkdirSync2(nm, { recursive: true });
|
|
1340
|
+
const dest = join10(nm, "@s2script");
|
|
1341
|
+
if (!existsSync6(dest)) symlinkSync(localPackagesDir, dest);
|
|
1342
|
+
}
|
|
1167
1343
|
function runInstall(dir, pm) {
|
|
1168
1344
|
if (pm === "none") return;
|
|
1169
1345
|
const r = spawnSync(pm, ["install"], {
|
|
@@ -1175,7 +1351,7 @@ function runInstall(dir, pm) {
|
|
|
1175
1351
|
if (r.status !== 0) throw new Error(`${pm} install failed (exit ${r.status})`);
|
|
1176
1352
|
}
|
|
1177
1353
|
async function createPlugin(opts = {}) {
|
|
1178
|
-
const targetPath =
|
|
1354
|
+
const targetPath = resolve6(opts.path ?? ".");
|
|
1179
1355
|
const interactive = Boolean(input.isTTY && output.isTTY && !opts.yes);
|
|
1180
1356
|
let game = assertGame(opts.game);
|
|
1181
1357
|
let name = opts.name;
|
|
@@ -1184,7 +1360,7 @@ async function createPlugin(opts = {}) {
|
|
|
1184
1360
|
if (template !== "minimal") {
|
|
1185
1361
|
throw new Error(`unknown template ${JSON.stringify(template)} (v1 supports: minimal)`);
|
|
1186
1362
|
}
|
|
1187
|
-
if (
|
|
1363
|
+
if (existsSync6(targetPath)) {
|
|
1188
1364
|
const kids = readdirSync2(targetPath);
|
|
1189
1365
|
const meaningful = kids.filter((k) => k !== ".git");
|
|
1190
1366
|
if (meaningful.length) {
|
|
@@ -1231,18 +1407,21 @@ async function createPlugin(opts = {}) {
|
|
|
1231
1407
|
install = install ?? (opts.noInstall ? "none" : "npm");
|
|
1232
1408
|
const version = readCliVersion();
|
|
1233
1409
|
const localPackagesDir = findLocalPackagesDir();
|
|
1234
|
-
mkdirSync2(
|
|
1410
|
+
mkdirSync2(join10(targetPath, "src"), { recursive: true });
|
|
1235
1411
|
writeFileSync5(
|
|
1236
|
-
|
|
1412
|
+
join10(targetPath, "package.json"),
|
|
1237
1413
|
packageJsonContent(name, game, version, localPackagesDir)
|
|
1238
1414
|
);
|
|
1239
|
-
writeFileSync5(
|
|
1240
|
-
writeFileSync5(
|
|
1241
|
-
writeFileSync5(
|
|
1415
|
+
writeFileSync5(join10(targetPath, "tsconfig.json"), tsconfigJson());
|
|
1416
|
+
writeFileSync5(join10(targetPath, "eslint.config.mjs"), eslintConfig());
|
|
1417
|
+
writeFileSync5(join10(targetPath, "src", "plugin.ts"), pluginSource(game));
|
|
1418
|
+
writeFileSync5(join10(targetPath, ".gitignore"), gitignore());
|
|
1242
1419
|
let installed = false;
|
|
1243
1420
|
if (install !== "none") {
|
|
1244
1421
|
runInstall(targetPath, install);
|
|
1245
1422
|
installed = true;
|
|
1423
|
+
} else if (localPackagesDir) {
|
|
1424
|
+
linkLocalPackagesForNoInstall(targetPath, localPackagesDir);
|
|
1246
1425
|
}
|
|
1247
1426
|
return {
|
|
1248
1427
|
dir: targetPath,
|
|
@@ -1257,7 +1436,7 @@ async function createPlugin(opts = {}) {
|
|
|
1257
1436
|
// src/config/gen.ts
|
|
1258
1437
|
import AdmZip2 from "adm-zip";
|
|
1259
1438
|
import { writeFileSync as writeFileSync6, mkdirSync as mkdirSync3 } from "node:fs";
|
|
1260
|
-
import { join as
|
|
1439
|
+
import { join as join11 } from "node:path";
|
|
1261
1440
|
|
|
1262
1441
|
// src/config/config-path.ts
|
|
1263
1442
|
function configFileName(id) {
|
|
@@ -1304,7 +1483,7 @@ function genConfigFromManifest(manifest, outDir) {
|
|
|
1304
1483
|
const id = typeof manifest.id === "string" ? manifest.id : "";
|
|
1305
1484
|
if (!id) throw new Error("config gen: manifest declares config but has no id");
|
|
1306
1485
|
mkdirSync3(outDir, { recursive: true });
|
|
1307
|
-
const path =
|
|
1486
|
+
const path = join11(outDir, configFileName(id));
|
|
1308
1487
|
writeFileSync6(path, generateDefaultJsonc(config));
|
|
1309
1488
|
return path;
|
|
1310
1489
|
}
|
|
@@ -1328,11 +1507,11 @@ function runConfigGen(s2sps, outDir) {
|
|
|
1328
1507
|
|
|
1329
1508
|
// src/cli.ts
|
|
1330
1509
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
1331
|
-
import { dirname as dirname3, join as
|
|
1510
|
+
import { dirname as dirname3, join as join12, resolve as resolve7 } from "node:path";
|
|
1332
1511
|
var argv = process.argv.slice(2);
|
|
1333
1512
|
var command = argv[0];
|
|
1334
1513
|
function repoRootFromCli() {
|
|
1335
|
-
return
|
|
1514
|
+
return join12(dirname3(fileURLToPath3(import.meta.url)), "..", "..", "..");
|
|
1336
1515
|
}
|
|
1337
1516
|
function parseFlag(args, name) {
|
|
1338
1517
|
const eq = args.find((a) => a.startsWith(`${name}=`));
|
|
@@ -1444,7 +1623,7 @@ if (command === "gen-schema") {
|
|
|
1444
1623
|
try {
|
|
1445
1624
|
const packagesDir = resolvePackagesDir({
|
|
1446
1625
|
explicit: packagesDirFlag,
|
|
1447
|
-
pluginDir:
|
|
1626
|
+
pluginDir: resolve7(dir),
|
|
1448
1627
|
fromCliUrl: import.meta.url
|
|
1449
1628
|
});
|
|
1450
1629
|
console.log(await buildPlugin(dir, packagesDir));
|