@amxts/core 0.2.3 → 0.2.4
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/package.json +3 -3
- package/scripts/build-wasm.ts +5 -1
- package/scripts/prebuilt.ts +1 -1
- package/scripts/project.ts +64 -4
- package/scripts/upgrade.ts +21 -23
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amxts/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.4",
|
|
5
5
|
"description": "Counter-Strike 1.6 plugins in TypeScript: compiled ahead of time and run inside AMX Mod X, next to Pawn plugins.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "kukson777",
|
|
@@ -104,8 +104,8 @@
|
|
|
104
104
|
"assemblyscript": "0.28.20"
|
|
105
105
|
},
|
|
106
106
|
"optionalDependencies": {
|
|
107
|
-
"@amxts/wamrc-linux-x64": "^0.2.
|
|
108
|
-
"@amxts/wamrc-win32-x64": "^0.2.
|
|
107
|
+
"@amxts/wamrc-linux-x64": "^0.2.4",
|
|
108
|
+
"@amxts/wamrc-win32-x64": "^0.2.4"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@amxts/config-core": "^0.1.2",
|
package/scripts/build-wasm.ts
CHANGED
|
@@ -45,7 +45,7 @@ import { serverIncludes } from './includes';
|
|
|
45
45
|
import { pluginCache } from './plugin-cache';
|
|
46
46
|
import { includeName } from './plugin-natives';
|
|
47
47
|
import { fromRegistry, prebuiltOf, prebuiltSurface } from './prebuilt';
|
|
48
|
-
import { CORE_DIR, CORE_PLUGINS, loadProject, modulesInUse, pluginList, projectPlugins, sourcesFor } from './project';
|
|
48
|
+
import { CORE_DIR, CORE_PLUGINS, loadProject, modulesInUse, pluginList, projectPlugins, sourcesFor, staleCopies } from './project';
|
|
49
49
|
import { sharedModulesBuild } from './shared-modules';
|
|
50
50
|
import { describeSystem, serverFolder, serverSystem, SYSTEM_NAME, WAMRC_PACKAGE, wamrcPath } from './system';
|
|
51
51
|
import { c, live, log, progress, since } from './ui';
|
|
@@ -162,6 +162,10 @@ function ownPlugins(): Target[] {
|
|
|
162
162
|
return projectPlugins(project).map(source => ({ source, name: basename(source).replace(/\.ts$/, '') }));
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
for (const copy of staleCopies(project)) {
|
|
166
|
+
log.warn(`${shown(copy)} is a copy of amxts's own API from an older version, not a plugin: delete it (npx amxts upgrade does)`);
|
|
167
|
+
}
|
|
168
|
+
|
|
165
169
|
for (const plugin of ownPlugins()) {
|
|
166
170
|
if (project.modules.some(pkg => pkg.short === plugin.name)) {
|
|
167
171
|
fail(`${shown(plugin.source)}: a module in amxts.config.ts is called ${plugin.name} too`, 'Rename the plugin.');
|
package/scripts/prebuilt.ts
CHANGED
|
@@ -235,7 +235,7 @@ function mismatch(manifest: PrebuiltManifest, pkg: ModulePackage, sources: Sourc
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
const own = resolve(sources.project.pluginsDir) !== resolve(CORE_PLUGINS);
|
|
238
|
-
const shadow = own ? manifest.places.find(place =>
|
|
238
|
+
const shadow = own ? manifest.places.find(place => sources.ownFile(place)) : undefined;
|
|
239
239
|
if (shadow) return `${posix(relative(sources.project.dir, join(sources.project.pluginsDir, shadow)))} takes the place of a file ${named} was built from`;
|
|
240
240
|
return null;
|
|
241
241
|
}
|
package/scripts/project.ts
CHANGED
|
@@ -53,6 +53,7 @@ import { createRequire } from 'node:module';
|
|
|
53
53
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
54
54
|
import { fileURLToPath } from 'node:url';
|
|
55
55
|
import ts from 'typescript';
|
|
56
|
+
import { serverFolder } from '../src/system.mjs';
|
|
56
57
|
import { coreImports, importedName, importTable, withAutoImports } from './auto-imports';
|
|
57
58
|
import { includeDirs } from './includes';
|
|
58
59
|
import { existsSync, readdirSync, readFileSync, statSync } from './tracked-fs';
|
|
@@ -667,9 +668,57 @@ export function coreEntryOf(place: string): string {
|
|
|
667
668
|
export function projectPlugins(project: Project): string[] {
|
|
668
669
|
const core = resolve(project.pluginsDir) === resolve(CORE_PLUGINS);
|
|
669
670
|
if (core && resolve(project.dir) !== resolve(CORE_DIR)) return [];
|
|
671
|
+
const stale = new Set(staleCopies(project));
|
|
670
672
|
return readdirSync(project.pluginsDir)
|
|
671
673
|
.filter(f => f.endsWith('.ts') && !f.endsWith('.d.ts') && !(core && NOT_PLUGINS.has(f)))
|
|
672
|
-
.map(f => join(project.pluginsDir, f))
|
|
674
|
+
.map(f => join(project.pluginsDir, f))
|
|
675
|
+
.filter(f => !stale.has(f));
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/** A server's addons/amxts: the module's files, written over on every start. */
|
|
679
|
+
export const SERVER_FOLDER = /[\\/]addons[\\/]amxts$/i;
|
|
680
|
+
|
|
681
|
+
/** The server's addons/amxts that AMXTS_SERVER names, or '' when it names none. */
|
|
682
|
+
export function serverDir(): string {
|
|
683
|
+
try {
|
|
684
|
+
const dir = serverFolder(process.env.AMXTS_SERVER ?? '');
|
|
685
|
+
return dir && resolve(dir);
|
|
686
|
+
} catch {
|
|
687
|
+
return '';
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Copies of the core's own API at the top of the project's plugins folder,
|
|
693
|
+
* left there by an older amxts: a file named as one of the core's as/ (or
|
|
694
|
+
* the editor's imports.d.ts) whose first line is the core's - a generator's
|
|
695
|
+
* header or that file's own first line. An author's file of the same name
|
|
696
|
+
* starts otherwise and stays a plugin. A server's addons/amxts/plugins holds
|
|
697
|
+
* these files on purpose: the module writes them there for the plugins
|
|
698
|
+
* compiled on the server.
|
|
699
|
+
*/
|
|
700
|
+
export function staleCopies(project: Project): string[] {
|
|
701
|
+
const dir = resolve(project.pluginsDir);
|
|
702
|
+
const parent = dirname(dir);
|
|
703
|
+
if (!existsSync(dir) || dir === resolve(CORE_PLUGINS) || SERVER_FOLDER.test(parent) || parent === serverDir()) return [];
|
|
704
|
+
coreFirstLines ??= new Map([...readdirSync(CORE_PLUGINS).filter(f => f.endsWith('.ts')).map(f => [f, firstLine(join(CORE_PLUGINS, f))] as const), ['imports.d.ts', '// GENERATED by ']]);
|
|
705
|
+
const core = coreFirstLines;
|
|
706
|
+
return readdirSync(dir)
|
|
707
|
+
.filter((f) => {
|
|
708
|
+
const header = core.get(f);
|
|
709
|
+
if (header === undefined) return false;
|
|
710
|
+
const line = firstLine(join(dir, f));
|
|
711
|
+
return line.startsWith('// GENERATED by ') || line === header;
|
|
712
|
+
})
|
|
713
|
+
.sort()
|
|
714
|
+
.map(f => join(dir, f));
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/** The first line of each file at the top of the core's as/, read once. */
|
|
718
|
+
let coreFirstLines: Map<string, string> | undefined;
|
|
719
|
+
|
|
720
|
+
function firstLine(path: string): string {
|
|
721
|
+
return readFileSync(path, 'utf8').split('\n', 1)[0].trimEnd();
|
|
673
722
|
}
|
|
674
723
|
|
|
675
724
|
/** The modules that run on the server - each in its owner plugin: every one but a library. */
|
|
@@ -747,7 +796,12 @@ export class Sources {
|
|
|
747
796
|
/** A plugin that imports a module package the config does not list. */
|
|
748
797
|
readonly problems: string[] = [];
|
|
749
798
|
|
|
750
|
-
|
|
799
|
+
/** Copies of the core's API an older amxts left in the plugins folder: the core's files are under them. */
|
|
800
|
+
private readonly stale: Set<string>;
|
|
801
|
+
|
|
802
|
+
constructor(readonly root: string, readonly project: Project) {
|
|
803
|
+
this.stale = new Set(staleCopies(project));
|
|
804
|
+
}
|
|
751
805
|
|
|
752
806
|
/**
|
|
753
807
|
* Whether a file is a plugin's code, which auto-imports reach: the
|
|
@@ -792,14 +846,20 @@ export class Sources {
|
|
|
792
846
|
return this.project.modules.find(pkg => path === pkg.module || path === pkg.natives || ofPackage(pkg, path)) ?? null;
|
|
793
847
|
}
|
|
794
848
|
|
|
849
|
+
/** The project's own file at this place under its plugins folder, or null: an old copy of the core's API is not one. */
|
|
850
|
+
ownFile(place: string): string | null {
|
|
851
|
+
const own = join(this.project.pluginsDir, place);
|
|
852
|
+
return existsSync(own) && !this.stale.has(own) ? own : null;
|
|
853
|
+
}
|
|
854
|
+
|
|
795
855
|
/** The file on disk at this place in the tree, or null. */
|
|
796
856
|
real(path: string): string | null {
|
|
797
857
|
const rel = this.rel(path);
|
|
798
858
|
if (!inside(this.root, resolve(path))) return existsSync(path) ? resolve(path) : null;
|
|
799
859
|
|
|
800
860
|
if (this.project.pluginsDir !== resolve(this.root)) {
|
|
801
|
-
const own =
|
|
802
|
-
if (
|
|
861
|
+
const own = this.ownFile(rel);
|
|
862
|
+
if (own) return own;
|
|
803
863
|
}
|
|
804
864
|
const core = resolve(this.root, rel);
|
|
805
865
|
if (existsSync(core)) return core;
|
package/scripts/upgrade.ts
CHANGED
|
@@ -29,13 +29,13 @@ import type { Kind } from './upgrade-names';
|
|
|
29
29
|
// functions take one object, the menu's context, and an item is one object
|
|
30
30
|
// with its title (scripts/upgrade-menus.ts). What is rewritten no longer
|
|
31
31
|
// matches, so a second run changes nothing.
|
|
32
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
32
|
+
import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
33
33
|
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
34
34
|
import { fileURLToPath } from 'node:url';
|
|
35
35
|
import ts from 'typescript';
|
|
36
36
|
import { MESSAGE_NAMES } from './client-messages';
|
|
37
|
-
import { CORE_ENTRIES, CORE_PLUGINS, loadProject } from './project';
|
|
38
|
-
import { apiFiles
|
|
37
|
+
import { CORE_ENTRIES, CORE_PLUGINS, loadProject, SERVER_FOLDER, serverDir, staleCopies } from './project';
|
|
38
|
+
import { apiFiles } from './system';
|
|
39
39
|
import { c, log } from './ui';
|
|
40
40
|
import { upgradeMenus } from './upgrade-menus';
|
|
41
41
|
import { COMMON, EVENTS, FLAG_NAMES, GAME_EVENT_FIELDS, HIDDEN, HIDDEN_EVENTS, JOIN_OPTIONS, RENAMED, SERVER_EVENT_CLASSES, SERVER_EVENT_FIELDS, SERVER_EVENTS, SERVER_EVENTS_BY_HAND, SERVER_FIELD_CLASSES, SERVER_GAME_EVENTS } from './upgrade-names';
|
|
@@ -775,9 +775,6 @@ export function upgradeFlags(file: string, text: string): { text: string; change
|
|
|
775
775
|
/** Folders that are not the project's code: what is installed, built or generated. */
|
|
776
776
|
const SKIP = new Set(['node_modules', 'dist', '.amxts', '.git']);
|
|
777
777
|
|
|
778
|
-
/** A server's addons/amxts: the module's files, written over on every start. */
|
|
779
|
-
const SERVER_FOLDER = /[\\/]addons[\\/]amxts$/i;
|
|
780
|
-
|
|
781
778
|
/** The project's TypeScript files: its plugins, its tests and fixtures, a module's sources. */
|
|
782
779
|
function codeFiles(dir: string, skip: Set<string>): string[] {
|
|
783
780
|
return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
|
|
@@ -787,16 +784,6 @@ function codeFiles(dir: string, skip: Set<string>): string[] {
|
|
|
787
784
|
});
|
|
788
785
|
}
|
|
789
786
|
|
|
790
|
-
/** The server's addons/amxts that AMXTS_SERVER names, or '' when it names none. */
|
|
791
|
-
function serverDir(): string {
|
|
792
|
-
try {
|
|
793
|
-
const dir = serverFolder(process.env.AMXTS_SERVER ?? '');
|
|
794
|
-
return dir && resolve(dir);
|
|
795
|
-
} catch {
|
|
796
|
-
return '';
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
|
|
800
787
|
/**
|
|
801
788
|
* The project's code to upgrade. The module's own files - the API a server
|
|
802
789
|
* writes beside its plugins, at the core's version it runs - are not, in the
|
|
@@ -810,14 +797,20 @@ function projectFiles(dir: string, pluginsDir: string, outDir: string): string[]
|
|
|
810
797
|
return codeFiles(dir, new Set([outDir, serverDir()])).filter(file => !theirs.has(basename(file)) || dirname(file) === pluginsDir);
|
|
811
798
|
}
|
|
812
799
|
|
|
813
|
-
/**
|
|
814
|
-
|
|
800
|
+
/**
|
|
801
|
+
* Rewrites the project in `dir`: every change, in the order of the files, and
|
|
802
|
+
* what is left to do by hand. Then removes the copies of the core's API an
|
|
803
|
+
* older amxts left in the plugins folder - after the rewrite, so nothing
|
|
804
|
+
* still imports them by `~/`. `write: false` only lists them.
|
|
805
|
+
*/
|
|
806
|
+
export function upgradeProject(dir: string, { write = true } = {}): { changes: Change[]; left: Left[]; removed: string[] } {
|
|
815
807
|
const project = loadProject(dir);
|
|
816
808
|
const ownFolder = resolve(project.pluginsDir) !== resolve(CORE_PLUGINS);
|
|
817
|
-
const
|
|
809
|
+
const stale = staleCopies(project);
|
|
810
|
+
const renames = renamesFor(project.modules, place => ownFolder && existsSync(join(project.pluginsDir, place)) && !stale.includes(join(project.pluginsDir, place)));
|
|
818
811
|
const changes: Change[] = [];
|
|
819
812
|
const left: Left[] = [];
|
|
820
|
-
for (const file of projectFiles(project.dir, resolve(project.pluginsDir), project.outDir)) {
|
|
813
|
+
for (const file of projectFiles(project.dir, resolve(project.pluginsDir), project.outDir).filter(file => !stale.includes(file))) {
|
|
821
814
|
const text = readFileSync(file, 'utf8');
|
|
822
815
|
const name = relative(project.dir, file).replace(/\\/g, '/');
|
|
823
816
|
const http = dropHttpImports(name, text);
|
|
@@ -835,7 +828,10 @@ export function upgradeProject(dir: string, { write = true } = {}): { changes: C
|
|
|
835
828
|
if (write) writeFileSync(file, flags.text);
|
|
836
829
|
changes.push(...http.changes, ...imports.changes, ...handlers.changes, ...menus.changes, ...names.changes, ...events.changes, ...messages.changes, ...flags.changes);
|
|
837
830
|
}
|
|
838
|
-
|
|
831
|
+
if (write) {
|
|
832
|
+
for (const file of stale) rmSync(file);
|
|
833
|
+
}
|
|
834
|
+
return { changes, left, removed: stale.map(file => basename(file)) };
|
|
839
835
|
}
|
|
840
836
|
|
|
841
837
|
// Run as a task (scripts/run.ts names it in argv) or by itself.
|
|
@@ -844,14 +840,16 @@ if (import.meta.main || resolve(process.argv[1] ?? '') === fileURLToPath(import.
|
|
|
844
840
|
// amxts command as JSON, which prints what is left to do in its summary.
|
|
845
841
|
const args = process.argv.slice(2);
|
|
846
842
|
const report = args.includes('--report') ? args[args.indexOf('--report') + 1] : undefined;
|
|
847
|
-
const
|
|
843
|
+
const write = !args.includes('--dry-run');
|
|
844
|
+
const { changes, left, removed } = upgradeProject(process.cwd(), { write });
|
|
845
|
+
if (removed.length) log.success(`${write ? 'removed' : 'would remove'} amxts's old API copies from plugins/: ${removed.join(', ')}`);
|
|
848
846
|
for (const change of changes) console.log(` ${c.dim(`${change.file}:${change.line}`)} ${change.from} ${c.dim('→')} ${change.to}`);
|
|
849
847
|
if (report) {
|
|
850
848
|
writeFileSync(report, JSON.stringify({ changes, left }));
|
|
851
849
|
} else {
|
|
852
850
|
const files = new Set(changes.map(change => change.file)).size;
|
|
853
851
|
if (changes.length) log.success(`upgraded ${changes.length} place(s) in ${files} file(s)`);
|
|
854
|
-
else if (!left.length) log.success('nothing to upgrade: the code already uses this core\'s API');
|
|
852
|
+
else if (!left.length && !removed.length) log.success('nothing to upgrade: the code already uses this core\'s API');
|
|
855
853
|
for (const each of left) log.warn(`${each.file}:${each.line} ${each.why}`);
|
|
856
854
|
}
|
|
857
855
|
}
|