@amxts/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/README.ru.md +162 -0
  4. package/amxmodx/base/include/amxconst.inc +594 -0
  5. package/amxmodx/base/include/amxmisc.inc +902 -0
  6. package/amxmodx/base/include/amxmodx.inc +3447 -0
  7. package/amxmodx/base/include/amxmodx_version.inc +20 -0
  8. package/amxmodx/base/include/cellarray.inc +525 -0
  9. package/amxmodx/base/include/cellstack.inc +166 -0
  10. package/amxmodx/base/include/celltrie.inc +412 -0
  11. package/amxmodx/base/include/core.inc +202 -0
  12. package/amxmodx/base/include/csstats.inc +298 -0
  13. package/amxmodx/base/include/csstats_const.inc +29 -0
  14. package/amxmodx/base/include/cstrike.inc +1287 -0
  15. package/amxmodx/base/include/cstrike_const.inc +521 -0
  16. package/amxmodx/base/include/csx.inc +259 -0
  17. package/amxmodx/base/include/cvars.inc +547 -0
  18. package/amxmodx/base/include/datapack.inc +161 -0
  19. package/amxmodx/base/include/dbi.inc +154 -0
  20. package/amxmodx/base/include/dodconst.inc +152 -0
  21. package/amxmodx/base/include/dodfun.inc +152 -0
  22. package/amxmodx/base/include/dodstats.inc +69 -0
  23. package/amxmodx/base/include/dodx.inc +161 -0
  24. package/amxmodx/base/include/engine.inc +1343 -0
  25. package/amxmodx/base/include/engine_const.inc +310 -0
  26. package/amxmodx/base/include/engine_stocks.inc +248 -0
  27. package/amxmodx/base/include/esf.inc +70 -0
  28. package/amxmodx/base/include/esf_const.inc +74 -0
  29. package/amxmodx/base/include/fakemeta.inc +1127 -0
  30. package/amxmodx/base/include/fakemeta_const.inc +793 -0
  31. package/amxmodx/base/include/fakemeta_stocks.inc +395 -0
  32. package/amxmodx/base/include/fakemeta_util.inc +882 -0
  33. package/amxmodx/base/include/file.inc +666 -0
  34. package/amxmodx/base/include/float.inc +422 -0
  35. package/amxmodx/base/include/fun.inc +333 -0
  36. package/amxmodx/base/include/gameconfig.inc +93 -0
  37. package/amxmodx/base/include/geoip.inc +264 -0
  38. package/amxmodx/base/include/ham_const.inc +4352 -0
  39. package/amxmodx/base/include/hamsandwich.inc +439 -0
  40. package/amxmodx/base/include/hlsdk_const.inc +808 -0
  41. package/amxmodx/base/include/json.inc +777 -0
  42. package/amxmodx/base/include/lang.inc +119 -0
  43. package/amxmodx/base/include/message_const.inc +1130 -0
  44. package/amxmodx/base/include/message_stocks.inc +161 -0
  45. package/amxmodx/base/include/messages.inc +604 -0
  46. package/amxmodx/base/include/newmenus.inc +387 -0
  47. package/amxmodx/base/include/ns.inc +754 -0
  48. package/amxmodx/base/include/ns_const.inc +196 -0
  49. package/amxmodx/base/include/nvault.inc +154 -0
  50. package/amxmodx/base/include/regex.inc +348 -0
  51. package/amxmodx/base/include/sockets.inc +183 -0
  52. package/amxmodx/base/include/sorting.inc +107 -0
  53. package/amxmodx/base/include/sqlx.inc +582 -0
  54. package/amxmodx/base/include/string.inc +786 -0
  55. package/amxmodx/base/include/string_const.inc +156 -0
  56. package/amxmodx/base/include/string_stocks.inc +325 -0
  57. package/amxmodx/base/include/textparse_ini.inc +214 -0
  58. package/amxmodx/base/include/textparse_smc.inc +261 -0
  59. package/amxmodx/base/include/tfcconst.inc +84 -0
  60. package/amxmodx/base/include/tfcstats.inc +62 -0
  61. package/amxmodx/base/include/tfcx.inc +148 -0
  62. package/amxmodx/base/include/time.inc +118 -0
  63. package/amxmodx/base/include/tsconst.inc +154 -0
  64. package/amxmodx/base/include/tsfun.inc +198 -0
  65. package/amxmodx/base/include/tsstats.inc +65 -0
  66. package/amxmodx/base/include/tsx.inc +88 -0
  67. package/amxmodx/base/include/vault.inc +60 -0
  68. package/amxmodx/base/include/vector.inc +131 -0
  69. package/amxmodx/base/include/xs.inc +1570 -0
  70. package/as/amxts.d.ts +153 -0
  71. package/as/constants.ts +4730 -0
  72. package/as/effects.ts +1449 -0
  73. package/as/entities.ts +5482 -0
  74. package/as/events.ts +3054 -0
  75. package/as/facade.ts +4639 -0
  76. package/as/flags.ts +299 -0
  77. package/as/fs.ts +287 -0
  78. package/as/hooks.ts +18536 -0
  79. package/as/kit.ts +25 -0
  80. package/as/lib/check.ts +86 -0
  81. package/as/modules/http.ts +184 -0
  82. package/as/natives.ts +11845 -0
  83. package/as/os.ts +30 -0
  84. package/as/promise.ts +1392 -0
  85. package/as/promise.types.d.ts +82 -0
  86. package/as/remote.ts +288 -0
  87. package/as/tsconfig.json +22 -0
  88. package/as/vector.ts +65 -0
  89. package/bin/amxts.mjs +10 -0
  90. package/includes/menu_core.inc +355 -0
  91. package/includes/order.txt +54 -0
  92. package/includes/sources.json +27 -0
  93. package/includes/universal_config.inc +355 -0
  94. package/lint/oxlint-plugin.mjs +77 -0
  95. package/node_modules/assemblyscript/LICENSE +201 -0
  96. package/node_modules/assemblyscript/NOTICE +93 -0
  97. package/node_modules/assemblyscript/package.json +63 -0
  98. package/node_modules/assemblyscript/std/README.md +6 -0
  99. package/node_modules/assemblyscript/std/assembly/array.ts +526 -0
  100. package/node_modules/assemblyscript/std/assembly/arraybuffer.ts +77 -0
  101. package/node_modules/assemblyscript/std/assembly/atomics.ts +127 -0
  102. package/node_modules/assemblyscript/std/assembly/bindings/asyncify.ts +16 -0
  103. package/node_modules/assemblyscript/std/assembly/bindings/dom.ts +291 -0
  104. package/node_modules/assemblyscript/std/assembly/bindings/node.ts +6 -0
  105. package/node_modules/assemblyscript/std/assembly/builtins.ts +2631 -0
  106. package/node_modules/assemblyscript/std/assembly/compat.ts +2 -0
  107. package/node_modules/assemblyscript/std/assembly/console.ts +42 -0
  108. package/node_modules/assemblyscript/std/assembly/crypto.ts +9 -0
  109. package/node_modules/assemblyscript/std/assembly/dataview.ts +181 -0
  110. package/node_modules/assemblyscript/std/assembly/date.ts +373 -0
  111. package/node_modules/assemblyscript/std/assembly/diagnostics.ts +11 -0
  112. package/node_modules/assemblyscript/std/assembly/error.ts +44 -0
  113. package/node_modules/assemblyscript/std/assembly/function.ts +38 -0
  114. package/node_modules/assemblyscript/std/assembly/index.d.ts +2822 -0
  115. package/node_modules/assemblyscript/std/assembly/iterator.ts +35 -0
  116. package/node_modules/assemblyscript/std/assembly/map.ts +260 -0
  117. package/node_modules/assemblyscript/std/assembly/math.ts +3289 -0
  118. package/node_modules/assemblyscript/std/assembly/memory.ts +123 -0
  119. package/node_modules/assemblyscript/std/assembly/number.ts +388 -0
  120. package/node_modules/assemblyscript/std/assembly/object.ts +36 -0
  121. package/node_modules/assemblyscript/std/assembly/performance.ts +9 -0
  122. package/node_modules/assemblyscript/std/assembly/polyfills.ts +27 -0
  123. package/node_modules/assemblyscript/std/assembly/process.ts +50 -0
  124. package/node_modules/assemblyscript/std/assembly/reference.ts +48 -0
  125. package/node_modules/assemblyscript/std/assembly/regexp.ts +12 -0
  126. package/node_modules/assemblyscript/std/assembly/rt/README.md +83 -0
  127. package/node_modules/assemblyscript/std/assembly/rt/common.ts +81 -0
  128. package/node_modules/assemblyscript/std/assembly/rt/index-incremental.ts +2 -0
  129. package/node_modules/assemblyscript/std/assembly/rt/index-minimal.ts +2 -0
  130. package/node_modules/assemblyscript/std/assembly/rt/index-stub.ts +1 -0
  131. package/node_modules/assemblyscript/std/assembly/rt/index.d.ts +37 -0
  132. package/node_modules/assemblyscript/std/assembly/rt/itcms.ts +419 -0
  133. package/node_modules/assemblyscript/std/assembly/rt/rtrace.ts +15 -0
  134. package/node_modules/assemblyscript/std/assembly/rt/stub.ts +133 -0
  135. package/node_modules/assemblyscript/std/assembly/rt/tcms.ts +254 -0
  136. package/node_modules/assemblyscript/std/assembly/rt/tlsf.ts +592 -0
  137. package/node_modules/assemblyscript/std/assembly/rt.ts +87 -0
  138. package/node_modules/assemblyscript/std/assembly/set.ts +220 -0
  139. package/node_modules/assemblyscript/std/assembly/shared/feature.ts +65 -0
  140. package/node_modules/assemblyscript/std/assembly/shared/runtime.ts +11 -0
  141. package/node_modules/assemblyscript/std/assembly/shared/target.ts +11 -0
  142. package/node_modules/assemblyscript/std/assembly/shared/tsconfig.json +11 -0
  143. package/node_modules/assemblyscript/std/assembly/shared/typeinfo.ts +72 -0
  144. package/node_modules/assemblyscript/std/assembly/staticarray.ts +401 -0
  145. package/node_modules/assemblyscript/std/assembly/string.ts +847 -0
  146. package/node_modules/assemblyscript/std/assembly/symbol.ts +114 -0
  147. package/node_modules/assemblyscript/std/assembly/table.ts +16 -0
  148. package/node_modules/assemblyscript/std/assembly/tsconfig.json +6 -0
  149. package/node_modules/assemblyscript/std/assembly/typedarray.ts +1945 -0
  150. package/node_modules/assemblyscript/std/assembly/uri.ts +17 -0
  151. package/node_modules/assemblyscript/std/assembly/util/bytes.ts +107 -0
  152. package/node_modules/assemblyscript/std/assembly/util/casemap.ts +497 -0
  153. package/node_modules/assemblyscript/std/assembly/util/error.ts +54 -0
  154. package/node_modules/assemblyscript/std/assembly/util/hash.ts +117 -0
  155. package/node_modules/assemblyscript/std/assembly/util/math.ts +1922 -0
  156. package/node_modules/assemblyscript/std/assembly/util/memory.ts +290 -0
  157. package/node_modules/assemblyscript/std/assembly/util/number.ts +873 -0
  158. package/node_modules/assemblyscript/std/assembly/util/sort.ts +313 -0
  159. package/node_modules/assemblyscript/std/assembly/util/string.ts +1202 -0
  160. package/node_modules/assemblyscript/std/assembly/util/uri.ts +275 -0
  161. package/node_modules/assemblyscript/std/assembly/vector.ts +4 -0
  162. package/node_modules/assemblyscript/std/assembly.json +16 -0
  163. package/node_modules/assemblyscript/std/portable/index.d.ts +462 -0
  164. package/node_modules/assemblyscript/std/portable/index.js +416 -0
  165. package/node_modules/assemblyscript/std/portable.json +11 -0
  166. package/node_modules/assemblyscript/std/types/assembly/index.d.ts +1 -0
  167. package/node_modules/assemblyscript/std/types/assembly/package.json +3 -0
  168. package/node_modules/assemblyscript/std/types/portable/index.d.ts +1 -0
  169. package/node_modules/assemblyscript/std/types/portable/package.json +3 -0
  170. package/node_modules/assemblyscript/tsconfig-base.json +13 -0
  171. package/package.json +112 -0
  172. package/runtime/deps/assemblyscript/LICENSE +201 -0
  173. package/runtime/deps/assemblyscript/NOTICE +93 -0
  174. package/runtime/deps/assemblyscript/bin/asc.js +35 -0
  175. package/runtime/deps/assemblyscript/dist/asc.js +25035 -0
  176. package/runtime/deps/assemblyscript/dist/assemblyscript.js +337 -0
  177. package/runtime/deps/assemblyscript/node_modules/binaryen/LICENSE +201 -0
  178. package/runtime/deps/assemblyscript/node_modules/binaryen/index.js +28905 -0
  179. package/runtime/deps/assemblyscript/node_modules/binaryen/package.json +50 -0
  180. package/runtime/deps/assemblyscript/node_modules/long/LICENSE +202 -0
  181. package/runtime/deps/assemblyscript/node_modules/long/index.js +1581 -0
  182. package/runtime/deps/assemblyscript/node_modules/long/package.json +58 -0
  183. package/runtime/deps/assemblyscript/package.json +114 -0
  184. package/runtime/host/amxts.inc +85 -0
  185. package/runtime/licenses/AMXX-LICENSE.txt +34 -0
  186. package/runtime/licenses/AssemblyScript-LICENSE +201 -0
  187. package/runtime/licenses/AssemblyScript-NOTICE +93 -0
  188. package/runtime/licenses/Binaryen-LICENSE +201 -0
  189. package/runtime/licenses/Bun-LICENSE.md +84 -0
  190. package/runtime/licenses/GPL-3.0.txt +674 -0
  191. package/runtime/licenses/LLVM-LICENSE.TXT +279 -0
  192. package/runtime/licenses/README.md +25 -0
  193. package/runtime/licenses/WAMR-LICENSE +219 -0
  194. package/runtime/natives.txt +1095 -0
  195. package/runtime/patches/README.md +59 -0
  196. package/runtime/patches/assemblyscript-0.28.20-amxts.patch +14174 -0
  197. package/runtime/patches/wamr-2.4.5-amxts.patch +364 -0
  198. package/scripts/apply-docs.ts +508 -0
  199. package/scripts/asc.ts +27 -0
  200. package/scripts/auto-imports.ts +258 -0
  201. package/scripts/build-wasm.ts +595 -0
  202. package/scripts/check.ts +93 -0
  203. package/scripts/compile-cache.ts +179 -0
  204. package/scripts/compile.ts +401 -0
  205. package/scripts/docker-server.ts +73 -0
  206. package/scripts/docs/as/amxts.ts +210 -0
  207. package/scripts/docs/as/effects.ts +1684 -0
  208. package/scripts/docs/as/facade.ts +3302 -0
  209. package/scripts/docs/as/fs.ts +173 -0
  210. package/scripts/docs/as/lib/check.ts +68 -0
  211. package/scripts/docs/as/modules/http.ts +66 -0
  212. package/scripts/docs/as/os.ts +16 -0
  213. package/scripts/docs/as/promise.ts +132 -0
  214. package/scripts/docs/as/promise.types.ts +63 -0
  215. package/scripts/docs/as/vector.ts +48 -0
  216. package/scripts/docs/entities.ts +2338 -0
  217. package/scripts/docs/events.ts +245 -0
  218. package/scripts/docs/game.ts +497 -0
  219. package/scripts/docs/messages.ts +148 -0
  220. package/scripts/file-contents.ts +74 -0
  221. package/scripts/includes.ts +134 -0
  222. package/scripts/player-fields.ts +866 -0
  223. package/scripts/plugin-cache.ts +92 -0
  224. package/scripts/plugin-natives.ts +1157 -0
  225. package/scripts/prebuilt.ts +268 -0
  226. package/scripts/prepare.ts +134 -0
  227. package/scripts/project.ts +973 -0
  228. package/scripts/run.ts +28 -0
  229. package/scripts/shared-modules.ts +906 -0
  230. package/scripts/system.ts +33 -0
  231. package/scripts/tracked-fs.ts +115 -0
  232. package/scripts/typed-configs.ts +788 -0
  233. package/scripts/ui.ts +77 -0
  234. package/src/cli-api.mjs +175 -0
  235. package/src/parser/include-parser.ts +506 -0
  236. package/src/system.mjs +155 -0
  237. package/src/testing/compile-cache.ts +31 -0
  238. package/src/testing/compile.ts +222 -0
  239. package/src/testing/coroutines.ts +191 -0
  240. package/src/testing/index.ts +39 -0
  241. package/src/testing/kits.ts +55 -0
  242. package/src/testing/memory.ts +125 -0
  243. package/src/testing/natives.ts +925 -0
  244. package/src/testing/server.ts +1874 -0
  245. package/src/testing/setup.ts +63 -0
  246. package/src/testing/tables.ts +139 -0
  247. package/src/types.ts +51 -0
@@ -0,0 +1,258 @@
1
+ // Auto-imports: a plugin uses `Player`, `server` or a module's namespace
2
+ // without an import line, and the build adds the import.
3
+ //
4
+ // server.addEventListener("init", () => menus.show(player, "MAIN"));
5
+ //
6
+ // What can be used so is a table of names (autoImports): the facade's public
7
+ // exports - everything `@amxts/core` exports but its hood (HOOD) - and what
8
+ // each module amxts.config.ts lists gives in its definition:
9
+ //
10
+ // export default defineModule({
11
+ // meta: { name: "menu-core" },
12
+ // imports: [{ from: "@amxts/menu-core", as: "menus" }],
13
+ // });
14
+ //
15
+ // - the module as a namespace, `menus.create(...)` - or one of its exports
16
+ // by its own name, `{ from, name: "semiclip" }`: an object whose properties a
17
+ // plugin assigns, `semiclip.rule = ...`, which a namespace's cannot be.
18
+ //
19
+ // Before a plugin's file is compiled (Sources.read in scripts/project.ts),
20
+ // withAutoImports reads it with the TypeScript parser and finds the names it
21
+ // uses without declaring or importing them - a local of the same name wins,
22
+ // in its own scope - and adds an import for each one the table has, on one
23
+ // line after the file's last: the lines above keep their numbers, so an
24
+ // error points where it did. A name the file does not use is not imported,
25
+ // so a module no plugin uses is not compiled into any of them.
26
+ //
27
+ // asc compiles an imported file where its import statement stands, and ES
28
+ // modules run an import before the file that imports it; scripts/compile.ts
29
+ // moves every import to the top of its file after parsing (hoistImports),
30
+ // so the one at the end runs first too.
31
+ //
32
+ // `.amxts/imports.d.ts` (scripts/prepare.ts, importsDeclaration) gives the
33
+ // editor the same names as globals.
34
+ import { dirname, join } from 'node:path';
35
+ import ts from 'typescript';
36
+ import { existsSync, readFileSync, statSync } from './tracked-fs';
37
+
38
+ /** One name a plugin can use without importing it. */
39
+ export interface AutoImport {
40
+ /** What the plugin writes: `Player`, `semiclip`. */
41
+ name: string;
42
+ /** Where it comes from, as an import line writes it: `@amxts/core`, `@amxts/resemiclip`. */
43
+ from: string;
44
+ /** `import * as semiclip from "..."` rather than `import { Player } from "..."`. */
45
+ namespace: boolean;
46
+ }
47
+
48
+ /**
49
+ * What a module gives in `defineModule({ imports })`: its API as a namespace
50
+ * under `as`, or its export `name` under that name.
51
+ */
52
+ export type ModuleImport = { from: string; as: string } | { from: string; name: string };
53
+
54
+ /** The name a plugin uses what a module gives by. */
55
+ export function importedName(each: ModuleImport): string {
56
+ return 'as' in each ? each.as : each.name;
57
+ }
58
+
59
+ export const CORE = '@amxts/core';
60
+
61
+ /**
62
+ * The facade's exports that are the hood, not the plugin API: what the
63
+ * facade and the generated files are built from - cells, raw handlers and
64
+ * the listener tables - and what a module's natives call through the kit
65
+ * (as/kit.ts). A plugin that needs one imports it by name. Every other
66
+ * export of the facade is auto-imported, a new one included; so is none
67
+ * whose name starts with `_`.
68
+ */
69
+ export const HOOD = new Set([
70
+ // Cells and raw handlers.
71
+ 'Call CellArray CellBuffer Handler WideHandler NoArgument arg argc argString argText cell cellFloat cells cellsToString cmd cmdWide floatCell handled hook hostIndex nativeFn noOrigin out paint playerIds publicFor putCell readText ret setArg setArgText stringToCells swapTeam text TEXT_MAX',
72
+ // The kit's.
73
+ 'caller cellArrayRows cellsText colorTags createCellArray defineModule destroyCellArray menuColors PawnCall PawnFunction pushCellArrayRow showMenu textCells',
74
+ // The generated listener and flag tables.
75
+ 'addGameListener addServerListener removeGameListener removeServerListener GameAnswerMap GameEventMap ServerEventMap HookEntry HookEvent EntvarFlags FlagFamily FlagList flagList FlagStore MemberFlags ACCESS BUTTON DAMAGE EFFECT ENTITY_FLAG HIDE_HUD PHYSICS_FLAG WEAPON_STATE',
76
+ ].flatMap(group => group.split(' ')));
77
+
78
+ // ---------------------------------------------------------------- the table
79
+
80
+ /** The names a file exports, following `export *` and `export { ... } from` into the files beside it. */
81
+ function exportsOf(file: string, seen = new Set<string>()): string[] {
82
+ if (seen.has(file) || !existsSync(file)) return [];
83
+ seen.add(file);
84
+ const source = ts.createSourceFile(file, readFileSync(file, 'utf8'), ts.ScriptTarget.Latest, false);
85
+ return source.statements.flatMap((statement) => {
86
+ if (ts.isExportDeclaration(statement)) {
87
+ const from = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? join(dirname(file), `${statement.moduleSpecifier.text}.ts`) : null;
88
+ if (!statement.exportClause) return from ? exportsOf(from, seen) : [];
89
+ return ts.isNamedExports(statement.exportClause) ? statement.exportClause.elements.map(each => each.name.text) : [];
90
+ }
91
+ const exported = ts.canHaveModifiers(statement) && ts.getModifiers(statement)?.some(m => m.kind === ts.SyntaxKind.ExportKeyword);
92
+ if (!exported) return [];
93
+ if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.flatMap(each => (ts.isIdentifier(each.name) ? [each.name.text] : []));
94
+ const name = (statement as { name?: ts.Node }).name;
95
+ return name && ts.isIdentifier(name) ? [name.text] : [];
96
+ });
97
+ }
98
+
99
+ let facade: { stamp: string; names: string[] } | null = null;
100
+
101
+ /** Everything the facade exports, the hood included. */
102
+ export function facadeExports(facadeFile: string): string[] {
103
+ // The facade's own files change only in the core's checkout; a stamp of
104
+ // the entry is enough to notice an edit there during `amxts dev`.
105
+ const stamp = existsSync(facadeFile) ? String(statSync(facadeFile).mtimeMs) : 'none';
106
+ if (facade?.stamp !== stamp) facade = { stamp, names: [...new Set(exportsOf(facadeFile))].sort() };
107
+ return facade.names;
108
+ }
109
+
110
+ /** The facade's public exports: what a plugin uses from `@amxts/core` without an import. */
111
+ export function coreImports(facadeFile: string): AutoImport[] {
112
+ return facadeExports(facadeFile).filter(name => !name.startsWith('_') && !HOOD.has(name)).map(name => ({ name, from: CORE, namespace: false }));
113
+ }
114
+
115
+ /**
116
+ * The project's table: the facade's names, then each module's. Two sources
117
+ * of one name are a problem, naming both - the plugin could not tell which
118
+ * it gets.
119
+ */
120
+ export function importTable(core: AutoImport[], modules: { name: string; imports: ModuleImport[] }[], problems: string[]): Map<string, AutoImport> {
121
+ const table = new Map<string, AutoImport>();
122
+ const give = (entry: AutoImport, by: string) => {
123
+ const taken = table.get(entry.name);
124
+ if (taken) problems.push(`auto-imports: ${entry.name} is given by ${taken.from} and by ${by} - rename one of them (imports in ${by}'s defineModule)`);
125
+ else table.set(entry.name, entry);
126
+ };
127
+ for (const entry of core) give(entry, CORE);
128
+ for (const pkg of modules) {
129
+ for (const each of pkg.imports) give({ name: importedName(each), from: each.from, namespace: 'as' in each }, pkg.name);
130
+ }
131
+ return table;
132
+ }
133
+
134
+ // ---------------------------------------------------------------- a file
135
+
136
+ /** The names a binding declares: `x`, `{ a, b: c }`, `[d, ...e]`. */
137
+ function bound(name: ts.BindingName): string[] {
138
+ if (ts.isIdentifier(name)) return [name.text];
139
+ return name.elements.flatMap(element => (ts.isOmittedExpression(element) ? [] : bound(element.name)));
140
+ }
141
+
142
+ /** What these statements declare in the scope they are in. */
143
+ function declaredBy(statements: readonly ts.Statement[]): string[] {
144
+ return statements.flatMap((statement): string[] => {
145
+ if (ts.isVariableStatement(statement)) return statement.declarationList.declarations.flatMap(each => bound(each.name));
146
+ if (ts.isImportDeclaration(statement)) {
147
+ const clause = statement.importClause;
148
+ const bindings = clause?.namedBindings;
149
+ return [
150
+ ...(clause?.name ? [clause.name.text] : []),
151
+ ...(bindings && ts.isNamespaceImport(bindings) ? [bindings.name.text] : []),
152
+ ...(bindings && ts.isNamedImports(bindings) ? bindings.elements.map(each => each.name.text) : []),
153
+ ];
154
+ }
155
+ if (ts.isImportEqualsDeclaration(statement)) return [statement.name.text];
156
+ if (ts.isModuleDeclaration(statement)) return ts.isIdentifier(statement.name) ? [statement.name.text] : [];
157
+ const name = (statement as { name?: ts.Node }).name;
158
+ return name && ts.isIdentifier(name) ? [name.text] : [];
159
+ });
160
+ }
161
+
162
+ /** The names a node declares for what is inside it: parameters, type parameters, a loop's variable, a function expression's own name. */
163
+ function declaredInside(node: ts.Node): string[] {
164
+ const names: string[] = [];
165
+ const typeParameters = (node as { typeParameters?: ts.NodeArray<ts.TypeParameterDeclaration> }).typeParameters;
166
+ for (const each of typeParameters ?? []) names.push(each.name.text);
167
+ if (ts.isFunctionLike(node)) names.push(...node.parameters.flatMap(parameter => bound(parameter.name)));
168
+ if ((ts.isFunctionExpression(node) || ts.isClassExpression(node)) && node.name) names.push(node.name.text);
169
+ if (ts.isBlock(node) || ts.isModuleBlock(node) || ts.isSourceFile(node)) names.push(...declaredBy(node.statements));
170
+ if (ts.isCaseBlock(node)) names.push(...declaredBy(node.clauses.flatMap(clause => clause.statements)));
171
+ if ((ts.isForStatement(node) || ts.isForOfStatement(node) || ts.isForInStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer)) {
172
+ for (const each of node.initializer.declarations) names.push(...bound(each.name));
173
+ }
174
+ if (ts.isCatchClause(node) && node.variableDeclaration) names.push(...bound(node.variableDeclaration.name));
175
+ if (ts.isMappedTypeNode(node)) names.push(node.typeParameter.name.text);
176
+ if (ts.isInferTypeNode(node)) names.push(node.typeParameter.name.text);
177
+ return names;
178
+ }
179
+
180
+ /** Whether an identifier names something in scope, rather than a property, a label or what a declaration declares. */
181
+ function isReference(id: ts.Identifier): boolean {
182
+ const parent = id.parent;
183
+ if (ts.isShorthandPropertyAssignment(parent)) return parent.name === id;
184
+ if ((parent as { name?: ts.Node }).name === id) return false;
185
+ if (ts.isQualifiedName(parent)) return parent.left === id;
186
+ if (ts.isBindingElement(parent)) return parent.initializer === id;
187
+ if (ts.isImportSpecifier(parent) || ts.isExportSpecifier(parent)) return false;
188
+ return !(ts.isLabeledStatement(parent) || ts.isBreakOrContinueStatement(parent) || ts.isMetaProperty(parent));
189
+ }
190
+
191
+ /**
192
+ * The names a file uses without declaring them in a scope that reaches the
193
+ * use, and without importing them: what it expects from outside.
194
+ */
195
+ export function freeNames(file: ts.SourceFile): Set<string> {
196
+ const free = new Set<string>();
197
+ const visit = (node: ts.Node, scopes: Set<string>[]) => {
198
+ const own = declaredInside(node);
199
+ // `infer U` declares U for the whole conditional type it is in.
200
+ if (ts.isConditionalTypeNode(node)) {
201
+ node.extendsType.forEachChild(function infers(child): void {
202
+ if (ts.isInferTypeNode(child)) own.push(child.typeParameter.name.text);
203
+ child.forEachChild(infers);
204
+ });
205
+ }
206
+ const inner = own.length ? [...scopes, new Set(own)] : scopes;
207
+ if (ts.isIdentifier(node) && isReference(node) && !inner.some(scope => scope.has(node.text))) free.add(node.text);
208
+ node.forEachChild(child => visit(child, inner));
209
+ };
210
+ visit(file, []);
211
+ return free;
212
+ }
213
+
214
+ /**
215
+ * The file with an import line after its last for every name of the table
216
+ * it uses and does not declare - or as it is, when it uses none.
217
+ */
218
+ export function withAutoImports(path: string, text: string, table: Map<string, AutoImport>): string {
219
+ if (table.size === 0) return text;
220
+ const file = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
221
+ const wanted = [...freeNames(file)].map(name => table.get(name)).filter((entry): entry is AutoImport => entry !== undefined);
222
+ if (wanted.length === 0) return text;
223
+
224
+ const named = new Map<string, string[]>();
225
+ const lines: string[] = [];
226
+ for (const entry of wanted.sort((a, b) => a.name.localeCompare(b.name))) {
227
+ if (entry.namespace) lines.push(`import * as ${entry.name} from "${entry.from}";`);
228
+ else named.set(entry.from, [...(named.get(entry.from) ?? []), entry.name]);
229
+ }
230
+ for (const [from, names] of named) lines.unshift(`import { ${names.join(', ')} } from "${from}";`);
231
+ return `${text.replace(/\s*$/, '')}\n${lines.join(' ')}\n`;
232
+ }
233
+
234
+ // ---------------------------------------------------------------- the editor
235
+
236
+ /**
237
+ * `.amxts/imports.d.ts`: the table as globals, so that the editor completes,
238
+ * checks and goes to the definition of what a plugin uses without an import.
239
+ * An alias, not a copy: a class is its type and its value, a namespace its
240
+ * types too (`menus.Menu`).
241
+ */
242
+ export function importsDeclaration(table: AutoImport[]): string {
243
+ const sources = [...new Set(table.map(entry => entry.from))];
244
+ const alias = (from: string) => `__${sources.indexOf(from)}`;
245
+ return [
246
+ '// GENERATED by amxts prepare: what the plugins use without an import - the',
247
+ '// facade\'s API and what the modules in amxts.config.ts give. The build adds',
248
+ '// the imports; this file tells the editor.',
249
+ ...sources.map(from => `import * as ${alias(from)} from "${from}";`),
250
+ '',
251
+ 'declare global {',
252
+ ...table.map(entry => `\texport import ${entry.name} = ${alias(entry.from)}${entry.namespace ? '' : `.${entry.name}`};`),
253
+ '}',
254
+ '',
255
+ 'export {};',
256
+ '',
257
+ ].join('\n');
258
+ }