amxxpack 1.5.0-beta.2 → 1.5.0-beta.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.
Files changed (105) hide show
  1. package/README.md +278 -29
  2. package/lib/index.js +5 -23
  3. package/package.json +20 -17
  4. package/resources/project-types/amxmodx-legacy.json +21 -0
  5. package/resources/project-types/amxmodx.json +21 -0
  6. package/resources/project-types/sourcemod.json +21 -0
  7. package/resources/templates/amxmodx/include.txt +1 -0
  8. package/resources/templates/sourcemod/include.txt +1 -0
  9. package/lib/builder/amxxpc.d.ts +0 -33
  10. package/lib/builder/amxxpc.js +0 -116
  11. package/lib/builder/builder.d.ts +0 -36
  12. package/lib/builder/builder.js +0 -375
  13. package/lib/builder/compiler.d.ts +0 -33
  14. package/lib/builder/compiler.js +0 -112
  15. package/lib/builder/constants.d.ts +0 -1
  16. package/lib/builder/constants.js +0 -10
  17. package/lib/builder/index.d.ts +0 -1
  18. package/lib/builder/index.js +0 -8
  19. package/lib/builder/plugins-cache.d.ts +0 -41
  20. package/lib/builder/plugins-cache.js +0 -243
  21. package/lib/builder/plugins-dependencies.d.ts +0 -7
  22. package/lib/builder/plugins-dependencies.js +0 -34
  23. package/lib/cli/constants/index.d.ts +0 -5
  24. package/lib/cli/constants/index.js +0 -10
  25. package/lib/cli/controller.d.ts +0 -32
  26. package/lib/cli/controller.js +0 -130
  27. package/lib/cli/helpers/command-action.d.ts +0 -1
  28. package/lib/cli/helpers/command-action.js +0 -27
  29. package/lib/cli/helpers/handle-error.d.ts +0 -1
  30. package/lib/cli/helpers/handle-error.js +0 -40
  31. package/lib/cli/index.d.ts +0 -3
  32. package/lib/cli/index.js +0 -19
  33. package/lib/cli/program.d.ts +0 -4
  34. package/lib/cli/program.js +0 -112
  35. package/lib/cli/services/project-creator.d.ts +0 -21
  36. package/lib/cli/services/project-creator.js +0 -160
  37. package/lib/cli/services/template-builder.d.ts +0 -11
  38. package/lib/cli/services/template-builder.js +0 -48
  39. package/lib/cli/types.d.ts +0 -13
  40. package/lib/cli/types.js +0 -2
  41. package/lib/common/cli-error.d.ts +0 -3
  42. package/lib/common/cli-error.js +0 -9
  43. package/lib/config/amxmodx.d.ts +0 -10
  44. package/lib/config/amxmodx.js +0 -11
  45. package/lib/config/index.d.ts +0 -7
  46. package/lib/config/index.js +0 -16
  47. package/lib/config/sourcemod.d.ts +0 -11
  48. package/lib/config/sourcemod.js +0 -12
  49. package/lib/constants/index.d.ts +0 -0
  50. package/lib/constants/index.js +0 -5
  51. package/lib/downloaders/compiler/constants.d.ts +0 -5
  52. package/lib/downloaders/compiler/constants.js +0 -9
  53. package/lib/downloaders/compiler/downloader.d.ts +0 -13
  54. package/lib/downloaders/compiler/downloader.js +0 -135
  55. package/lib/downloaders/compiler/index.d.ts +0 -17
  56. package/lib/downloaders/compiler/index.js +0 -152
  57. package/lib/downloaders/compiler/resolvers.d.ts +0 -6
  58. package/lib/downloaders/compiler/resolvers.js +0 -31
  59. package/lib/downloaders/compiler/types.d.ts +0 -17
  60. package/lib/downloaders/compiler/types.js +0 -2
  61. package/lib/downloaders/index.d.ts +0 -8
  62. package/lib/downloaders/index.js +0 -33
  63. package/lib/downloaders/thirdparty/downloader.d.ts +0 -7
  64. package/lib/downloaders/thirdparty/downloader.js +0 -63
  65. package/lib/downloaders/thirdparty/index.d.ts +0 -7
  66. package/lib/downloaders/thirdparty/index.js +0 -63
  67. package/lib/downloaders/thirdparty/types.d.ts +0 -7
  68. package/lib/downloaders/thirdparty/types.js +0 -2
  69. package/lib/downloaders/types/index.d.ts +0 -3
  70. package/lib/downloaders/types/index.js +0 -2
  71. package/lib/index.d.ts +0 -2
  72. package/lib/logger/constants.d.ts +0 -7
  73. package/lib/logger/constants.js +0 -11
  74. package/lib/logger/logger.d.ts +0 -16
  75. package/lib/logger/logger.js +0 -60
  76. package/lib/logger/types.d.ts +0 -3
  77. package/lib/logger/types.js +0 -2
  78. package/lib/project-config/configs/amxmodx.d.ts +0 -3
  79. package/lib/project-config/configs/amxmodx.js +0 -13
  80. package/lib/project-config/configs/sourcemod.d.ts +0 -3
  81. package/lib/project-config/configs/sourcemod.js +0 -13
  82. package/lib/project-config/defaults.d.ts +0 -3
  83. package/lib/project-config/defaults.js +0 -43
  84. package/lib/project-config/index.d.ts +0 -8
  85. package/lib/project-config/index.js +0 -115
  86. package/lib/project-config/load.d.ts +0 -3
  87. package/lib/project-config/load.js +0 -55
  88. package/lib/project-config/resolve.d.ts +0 -4
  89. package/lib/project-config/resolve.js +0 -39
  90. package/lib/project-config/types/index.d.ts +0 -24
  91. package/lib/project-config/types/index.js +0 -2
  92. package/lib/types/index.d.ts +0 -94
  93. package/lib/types/index.js +0 -2
  94. package/lib/utils/accumulator.d.ts +0 -2
  95. package/lib/utils/accumulator.js +0 -10
  96. package/lib/utils/copy-file.d.ts +0 -8
  97. package/lib/utils/copy-file.js +0 -36
  98. package/lib/utils/download.d.ts +0 -6
  99. package/lib/utils/download.js +0 -28
  100. package/lib/utils/parse-includes.d.ts +0 -9
  101. package/lib/utils/parse-includes.js +0 -39
  102. package/lib/utils/setup-watch.d.ts +0 -2
  103. package/lib/utils/setup-watch.js +0 -27
  104. package/lib/utils/string-accumulator.d.ts +0 -2
  105. package/lib/utils/string-accumulator.js +0 -10
package/README.md CHANGED
@@ -1,5 +1,13 @@
1
- # 📦 AMXXPack 🇺🇦 [![npm](https://img.shields.io/npm/v/amxxpack/beta.svg)](https://www.npmjs.com/package/amxxpack/v/beta)
2
- Simple build system and **CLI** for **AMX Mod X** projects.
1
+ # 📦 AMXXPack 🇺🇦
2
+
3
+ [![npm version](https://img.shields.io/npm/v/amxxpack/beta.svg)](https://www.npmjs.com/package/amxxpack/v/beta)
4
+ [![License](https://img.shields.io/github/license/Hedgefog/node-amxxpack)](https://github.com/Hedgefog/node-amxxpack/blob/master/LICENSE)
5
+ [![npm downloads](https://img.shields.io/npm/dm/amxxpack)](https://www.npmjs.com/package/amxxpack/v/beta)
6
+ [![GitHub issues](https://img.shields.io/github/issues/Hedgefog/node-amxxpack)](https://github.com/Hedgefog/node-amxxpack/issues)
7
+ [![Dependencies Status](https://img.shields.io/librariesio/release/npm/amxxpack)](https://libraries.io/npm/amxxpack)
8
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Hedgefog/node-amxxpack/pulls)
9
+
10
+ Build system and **CLI** for **AMX Mod X** and **SourceMod** projects.
3
11
 
4
12
  ---
5
13
 
@@ -9,9 +17,16 @@ Simple build system and **CLI** for **AMX Mod X** projects.
9
17
  - [Requirements](#-requirements)
10
18
  - [Installation](#-installation)
11
19
  - [Quick start](#-quick-start)
20
+ - [Examples](#-examples)
21
+ - [Basic Project Structure](#basic-project-structure)
22
+ - [Configuration Examples](#configuration-examples)
23
+ - [Development Workflow](#development-workflow-examples)
24
+ - [Integration Examples](#integration-examples)
12
25
  - [Commands](#-commands)
13
26
  - [Advanced configuration](#-advanced-configuration)
14
27
  - [Using with SourceMod](#using-with-sourcemod)
28
+ - [Troubleshooting](#-troubleshooting)
29
+ - [Contributing](#-contributing)
15
30
  - [License](#-license)
16
31
 
17
32
  ---
@@ -20,47 +35,66 @@ Simple build system and **CLI** for **AMX Mod X** projects.
20
35
 
21
36
  This system will be useful for projects with multiple plugins and assets. Using the command-line interface you can build an entire project with a single command. It also supports hot rebuild to keep your plugins and assets up to date during the work.
22
37
 
38
+ Check out projects [built with **AMXXPack**](https://github.com/search?q=path%3A.amxxpack*.json&type=code)
39
+
23
40
  ---
24
41
 
25
42
  ## 📚 Features
26
- - ⚙ Flexible configuration
27
- - 🔥 Hot reload
28
- - 🧸 Assets builder
43
+
44
+ ### 🛠 Build System
45
+ - Flexible JSON-based configuration
46
+ - 🗃️ Multi-plugin project support
47
+ - 🔄 Incremental builds with caching
48
+ - 🎯 Selective plugin compilation
49
+ - 📁 Support for multiple input directories
50
+ - 🔧 Customizable output structure
51
+ - 🔥 Hot reload for rapid development
52
+
53
+ ### 🧩 Plugin Development
54
+ - 🔗 Third-party dependencies management
55
+ - 📥 Automatic compiler downloads
56
+ - 📚 Generating new files using CLI commands
57
+ - ⛓️ Support for both **AMX Mod X** and **SourceMod**
58
+
59
+ ### 🧸 Asset Management
60
+ - 🔍 Glob pattern filtering
29
61
 
30
62
  ---
31
63
 
32
- ## 🔄Requirements
33
- - Node.js 10.0.0+
64
+ ## 🔄 Requirements
65
+ - Node.js 16.0.0 or higher
34
66
 
35
67
  ---
36
68
 
37
69
  ## 🔧 Installation
38
70
  **AMXXPack** is available through the npm registry.
39
- Installation can be done using the `npm i amxxpack@1.5.0-beta.2` command:
71
+ Installation can be done using the `npm i amxxpack@beta` command:
40
72
  ```
41
- npm install amxxpack
73
+ npm install amxxpack@beta
42
74
  ```
43
75
 
44
76
  or install it globally to use as a system command
45
77
  ```
46
- npm install -g amxxpack
78
+ npm install -g amxxpack@beta
47
79
  ```
48
80
 
49
81
  ---
50
82
 
51
-
52
83
  ## ▶ Quick start
53
84
  - Open a terminal inside the project directory (existing or create a new one)
54
- - Execute `npm install amxxpack@1.5.0-beta.2 -g` command to install `amxxpack` globally
85
+ - Execute `npm install amxxpack@beta -g` command to install `amxxpack` globally
55
86
  - Execute `amxxpack create .` command to create a new config
56
87
  - Execute `amxxpack install` to download project dependencies (compiler, thirdparty etc.)
57
88
  - Use `amxxpack build` command to build the project
58
89
  - Use `amxxpack watch` command to build the project and watch changes
59
90
 
91
+ ---
92
+
60
93
  ## 📋 Commands
61
94
  - `amxxpack create <name>` - create new project
62
95
  - `--git` - initialize git
63
- - `--nonpm` - don't initialize the npm package
96
+ - `--no-npm` - don't initialize the npm package
97
+ - `--no-install` - don't install compiler
64
98
  - `--version` - project version
65
99
  - `--author` - project author
66
100
  - `--description` - project name
@@ -68,31 +102,216 @@ npm install -g amxxpack
68
102
  - `amxxpack config` - initialize project config in the current workspace
69
103
  - `--type` - project type (e.g. `amxmodx`, `amxmodx-legacy`, `sourcemod`)
70
104
  - `amxxpack install` - install project dependencies
105
+ - `--compiler` - install compiler
106
+ - `--thirdparty` - install third-party dependencies
71
107
  - `--config` - config file
72
108
  - `amxxpack build` - command to build the project
73
109
  - `--watch` - flag to watch changes
74
110
  - `--config` - config file
75
111
  - `--ignore` - ignore build errors
76
112
  - `--no-cache` - disable caching
113
+ - `--assets` - build assets
114
+ - `--includes` - build includes
115
+ - `--scripts` - build scripts
116
+ - `--plugins` - build plugins
77
117
  - `amxxpack compile <path|glob>` - compile specific plugin in the project
78
118
  - `--config` - config file
79
119
  - `--no-cache` - disable caching
80
- - `amxxpack generate <script|lib|include> [name]` - create a new file in the project workspace
81
- - `--config` - config file
82
- - `--name` - plugin name
83
- - `--version` - plugin version
84
- - `--author` - plugin author
85
- - `--lib` - library name
86
- - `--include` - include list separated by a comma
87
- - `--overwrite` - overwrite the file if it already exists
88
- - `amxxpack cache clean` - clean amxxpack cache
120
+ - `amxxpack generate <type>` - create a new file in the project workspace
121
+ - `script` - create a new script file
122
+ - `--title` - plugin title
123
+ - `--version` - plugin version
124
+ - `--author` - plugin author
125
+ - `--include` - include list separated by a comma
126
+ - `--overwrite` - overwrite the file if it already exists
127
+ - `--config` - config file
128
+ - `include` - create a new include file
129
+ - `--include` - include list separated by a comma
130
+ - `--overwrite` - overwrite the file if it already exists
131
+ - `--config` - config file
132
+ - `library` - create a new library file
133
+ - `--name` - library name
134
+ - `--title` - library title
135
+ - `--version` - library version
136
+ - `--author` - library author
137
+ - `--include` - include list separated by a comma
138
+ - `--overwrite` - overwrite the file if it already exists
139
+ - `--config` - config file
140
+ - `amxxpack dependency <command>` - third-party dependencies
141
+ - `list` - list all third-party dependencies
142
+ - `add <name> <url>` - add a new third-party dependency
143
+ - `--strip <value>` - number of directories to strip from the archive structure
144
+ - `--filter <value>` - glob patterns separated by a comma
145
+ - `remove <name>` - remove a third-party dependency
146
+ - `amxxpack cache` - clean amxxpack cache
147
+ - `clean` - clean amxxpack cache
148
+ - `size` - show amxxpack cache size
89
149
  - `amxxpack i` - alias to `install` command
90
150
  - `amxxpack g` - alias to `generate` command
91
151
  - `amxxpack b` - alias to `build` command
92
152
  - `amxxpack c` - alias to `compile` command
153
+ - `amxxpack d` - alias to `dependency` command
154
+ - `amxxpack dep` - alias to `dependency` command
155
+ - `amxxpack thirdparty` - alias to `dependency` command
156
+ - `amxxpack t` - alias to `dependency` command
93
157
 
94
158
  ---
95
159
 
160
+ ## 📋 Examples
161
+
162
+ ### Basic Project Structure
163
+
164
+ Here's a typical **AMXXPack** project structure:
165
+
166
+ ```
167
+ myproject/
168
+ ├── .thirdparty/ # Third-party dependencies
169
+
170
+ ├── assets/ # Game assets
171
+ │ ├── models/
172
+ │ └── sounds/
173
+
174
+ ├── src/
175
+ │ ├── scripts/ # Plugin source files
176
+ │ │ ├── plugin1.sma
177
+ │ │ └── plugin2.sma
178
+ │ └── include/ # Include files
179
+ │ ├── constants.inc
180
+ │ └── stocks.inc
181
+
182
+ ├── .amxxpack.json # Project configuration
183
+ └── package.json # NPM configuration
184
+ ```
185
+
186
+ ### Configuration Examples
187
+
188
+ #### Basic Configuration
189
+ ```json
190
+ {
191
+ "type": "amxmodx",
192
+ "compiler": {
193
+ "version": "1.9",
194
+ "addons": ["cstrike"]
195
+ },
196
+ "input": {
197
+ "scripts": "./src/scripts",
198
+ "include": "./src/include",
199
+ "assets": "./assets"
200
+ },
201
+ "output": {
202
+ "base": "./dist",
203
+ "plugins": "./addons/amxmodx/plugins",
204
+ "scripts": "./addons/amxmodx/scripting",
205
+ "include": "./addons/amxmodx/scripting/include",
206
+ "assets": "."
207
+ }
208
+ }
209
+ ```
210
+
211
+ #### Advanced Configuration with Third-party Dependencies
212
+ ```json
213
+ {
214
+ "type": "amxmodx",
215
+ "compiler": {
216
+ "version": "1.9",
217
+ "addons": ["cstrike"]
218
+ },
219
+ "thirdparty": {
220
+ "dependencies": [
221
+ { "name": "somemodule", "url": "https://website/somemodule-v100.zip" }
222
+ ]
223
+ },
224
+ "include": [
225
+ "./.compiler/include",
226
+ "./.thirdparty/somemodule/include"
227
+ ],
228
+ "input": {
229
+ "scripts": [
230
+ { "dir": "./src/scripts", "output": { "prefix": "mymod_" } },
231
+ { "dir": "./somemodule/scripts" }
232
+ ],
233
+ "include": ["./src/include"],
234
+ "assets": [
235
+ { "dir": "./assets" },
236
+ { "dir": "./somemodule/models", "output": { "dest": "./models" } }
237
+ ]
238
+ },
239
+ "output": {
240
+ "base": "./dist",
241
+ "plugins": "./addons/amxmodx/plugins",
242
+ "scripts": "./addons/amxmodx/scripting",
243
+ "include": "./addons/amxmodx/scripting/include",
244
+ "assets": "."
245
+ }
246
+ }
247
+ ```
248
+
249
+ ### Development Workflow Examples
250
+
251
+ 1. **Starting a New Project**
252
+ ```bash
253
+ # Create a new directory
254
+ mkdir myproject
255
+ cd myproject
256
+
257
+ # Initialize the project
258
+ amxxpack create . --git --type amxmodx
259
+
260
+ # Install dependencies
261
+ amxxpack install
262
+
263
+ # Generate a new plugin
264
+ amxxpack generate script mymod_core --author "Your Name" --version "1.0.0"
265
+
266
+ # Start development with hot reload
267
+ amxxpack build --watch
268
+ ```
269
+
270
+ 2. **Working with Multiple Plugins**
271
+ ```bash
272
+ # Compile specific plugins
273
+ amxxpack compile "mymod_core.sma"
274
+ amxxpack compile "mymod_*.sma"
275
+ amxxpack compile "features/*.sma"
276
+
277
+ # Build entire project
278
+ amxxpack build
279
+
280
+ # Watch for changes
281
+ amxxpack build --watch
282
+ ```
283
+
284
+ 3. **Using with Version Control**
285
+ ```bash
286
+ # Typical .gitignore entries
287
+ node_modules/
288
+ .compiler/
289
+ .thirdparty/
290
+ dist/
291
+ *.amxx
292
+ ```
293
+
294
+ ### Integration Examples
295
+
296
+ 1. **CI/CD Pipeline (GitHub Actions)**
297
+ ```yaml
298
+ name: Build
299
+
300
+ on: [push, pull_request]
301
+
302
+ jobs:
303
+ build:
304
+ runs-on: ubuntu-latest
305
+ steps:
306
+ - uses: actions/checkout@v5
307
+ - uses: actions/setup-node@v5
308
+ with:
309
+ node-version: '20'
310
+ - run: npm install -g amxxpack@beta
311
+ - run: amxxpack install
312
+ - run: amxxpack build
313
+ ```
314
+
96
315
  ## 🦸 Advanced configuration
97
316
 
98
317
  ### Third-party dependencies
@@ -174,16 +393,28 @@ You can use multiple directories as builder inputs, just specify an array of dir
174
393
  }
175
394
  ```
176
395
 
177
- ### Input options
178
- You can specify additional options for the input directories.
396
+ ### Configuring input and output
397
+ You can specify additional output options for the input directories.
398
+ Output options can be specified in the input configuration or in the output configuration. Specifying options in the input configuration will override output configuration for specific input.
179
399
 
180
400
  #### Flat compilation
181
- `flat` option is used to specify if the scripts should be compiled in a flat directory structure even if `rules.flatCompilation` is disabled.
401
+ `flat` option is used to specify if the input directory should be copied using a flat directory structure.
402
+ By default only `assets` are compiled without a flat directory structure.
182
403
 
183
404
  ```json
184
405
  {
185
406
  "input": {
186
- "scripts": ["./src/scripts", { "dir": "./src/scripts", "flat": false }]
407
+ "scripts": ["./src/scripts", { "dir": "./src/scripts", "output": { "flat": false } }]
408
+ }
409
+ }
410
+ ```
411
+
412
+ Same option can be specified for the output directories:
413
+
414
+ ```json
415
+ {
416
+ "output": {
417
+ "scripts": { "dir": "./dist/scripts", "flat": false }
187
418
  }
188
419
  }
189
420
  ```
@@ -194,7 +425,16 @@ You can specify additional options for the input directories.
194
425
  ```json
195
426
  {
196
427
  "input": {
197
- "scripts": ["./src/scripts", { "dir": "./src/scripts", "prefix": "test_" }]
428
+ "scripts": ["./src/scripts", { "dir": "./src/scripts", "output": { "prefix": "test_" } }]
429
+ }
430
+ }
431
+ ```
432
+
433
+ For output directories:
434
+ ```json
435
+ {
436
+ "output": {
437
+ "scripts": { "dir": "./dist/scripts", "prefix": "test_" }
198
438
  }
199
439
  }
200
440
  ```
@@ -206,7 +446,16 @@ You can specify additional options for the input directories.
206
446
  ```json
207
447
  {
208
448
  "input": {
209
- "scripts": ["./src/scripts", { "dir": "./src/scripts", "dest": "sub" }]
449
+ "scripts": ["./src/scripts", { "dir": "./src/scripts", "output": { "dest": "sub" } }]
450
+ }
451
+ }
452
+ ```
453
+
454
+ For output directories:
455
+ ```json
456
+ {
457
+ "output": {
458
+ "scripts": { "dir": "./dist/scripts", "dest": "sub" }
210
459
  }
211
460
  }
212
461
  ```
@@ -292,7 +541,7 @@ If you use **SourceMod** with **AMXXPack** you should set `type` to `sourcemod`
292
541
  {
293
542
  "type": "sourcemod",
294
543
  "compiler": {
295
- "version": "1.12.0",
544
+ "version": "1.12",
296
545
  }
297
546
  }
298
547
  ```
package/lib/index.js CHANGED
@@ -1,23 +1,5 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- var __importDefault = (this && this.__importDefault) || function (mod) {
17
- return (mod && mod.__esModule) ? mod : { "default": mod };
18
- };
19
- Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.default = void 0;
21
- var builder_1 = require("./builder");
22
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(builder_1).default; } });
23
- __exportStar(require("./builder"), exports);
1
+ #!/usr/bin/env node
2
+ "use strict";var wt=Object.create;var Oe=Object.defineProperty;var vt=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var Ct=Object.getPrototypeOf,jt=Object.prototype.hasOwnProperty;var It=(o,e)=>()=>(e||o((e={exports:{}}).exports,e),e.exports);var xt=(o,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of yt(e))!jt.call(o,r)&&r!==t&&Oe(o,r,{get:()=>e[r],enumerable:!(i=vt(e,r))||i.enumerable});return o};var p=(o,e,t)=>(t=o!=null?wt(Ct(o)):{},xt(e||!o||!o.__esModule?Oe(t,"default",{value:o,enumerable:!0}):t,o));var ke=It((Kt,bt)=>{bt.exports={name:"amxxpack",description:"AMXXPack",author:"Hedgehog Fog",version:"1.5.0-beta.4",license:"MIT",scripts:{test:"jest",build:"tsc && tsup",lint:"eslint",prepare:"npm run build"},main:"lib/index.js",bin:{amxxpack:"./lib/index.js"},files:["lib/**/*","resources/**/*"],repository:{type:"git",url:"https://github.com/Hedgefog/node-amxxpack"},bugs:{url:"https://github.com/Hedgefog/node-amxxpack/issues"},homepage:"https://github.com/Hedgefog/node-amxxpack",keywords:["amx","amxx","amxmodx","sourcemod","smx","cli","pawn","compiler","build","watch"],dependencies:{chokidar:"^4.0.3",colors:"^1.4.0",commander:"^14.0.0",decompress:"^4.2.1",download:"^8.0.0",globule:"^1.3.4",lodash:"^4.17.21","node-cache":"^5.1.2","normalize-path":"^3.0.0"},devDependencies:{"@eslint/js":"^9.34.0","@stylistic/eslint-plugin":"^5.3.1","@types/chance":"^1.1.3","@types/chokidar":"^2.1.3","@types/colors":"^1.2.1","@types/commander":"^2.12.2","@types/decompress":"^4.2.4","@types/download":"^8.0.1","@types/globule":"^1.1.4","@types/jest":"^27.4.1","@types/lodash":"^4.17.20","@types/node":"^24.3.0","@types/normalize-path":"^3.0.0",chance:"^1.1.9",eslint:"^9.34.0",jest:"^27.5.1","ts-jest":"^27.1.3","tsconfig-paths":"^4.2.0",tsup:"^8.5.0","type-fest":"^3.13.1",typescript:"^4.8.4","typescript-eslint":"^8.41.0"}}});var He=require("commander");var m=class extends Error{constructor(e){super(e),this.name="CLIError"}};var N=p(require("path")),Ae=p(require("os")),Le=p(require("fs")),we=N.default.join(Ae.default.tmpdir(),".amxxpack");Le.default.mkdirSync(we,{recursive:!0});var ge=process.env.RESOURCES_DIR||N.default.resolve(require.main.path,"..","resources"),c={title:"AMXXPack",command:"amxxpack",downloadDir:N.default.join(we,"downloads"),cacheFile:N.default.join(we,".cache.json"),resourcesDir:ge,templatesDir:N.default.join(ge,"templates"),projectTypesDir:N.default.resolve(ge,"project-types"),version:ke().version,project:{defaultVersion:"0.1.0",configFile:".amxxpack.json",defaultType:"amxmodx"}};var I=p(require("colors/safe"));var ve=class{constructor(e={}){this.debugMode=e.debug||process.env.NODE_ENV==="development"}debug(...e){this.out("debug",...e)}success(...e){this.out("success",...e)}info(...e){this.out("info",...e)}warn(...e){this.out("warning",...e)}error(...e){this.out("error",...e)}out(e,...t){if(e==="debug"&&!this.debugMode)return;let i=t.map(a=>a instanceof Object?JSON.stringify(a):String(a)).join(" "),r=this.getLevelLabel(e),s=this.colorifyMessageByLevel(e,i),n=new Date().toLocaleTimeString();console.log(`[${n}]`,r,s)}colorifyMessageByLevel(e,t){switch(e){case"debug":return I.default.grey(t);case"success":return I.default.white(t);case"info":return I.default.grey(t);case"warning":return I.default.white(t);case"error":return I.default.white(t)}return t}getLevelLabel(e){switch(e){case"debug":return I.default.grey("[DEBUG]");case"success":return I.default.green("[SUCCESS]");case"info":return I.default.cyan("[INFO]");case"warning":return I.default.yellow("[WARNING]");case"error":return I.default.red("[ERROR]")}return""}},l=new ve;function Dt(o){switch(o.code){case"commander.help":return l.info(`Use '${c.command} --help' to see all available commands`),!0;case"commander.version":return l.info(`${c.title} CLI v${o.message}`),!0}return!1}function H(o){if(o instanceof He.CommanderError){if(Dt(o)){process.exit(0);return}l.error(o.message)}else o instanceof Error?l.error(o.message):l.error("Unknown error");if(process.env.NODE_ENV==="development")throw o;process.exit(1)}var ht=require("commander");var ct=require("commander");function w(o){return async(...e)=>{try{await o(...e)}catch(t){H(t)}}}var Ye=require("commander");var P=p(require("path")),S=require("lodash");var g=require("lodash"),G=p(require("path")),V=p(require("fs"));var Pt=(o,e)=>({type:o,input:{scripts:"./src/scripts",include:"./src/include",assets:"./assets"},output:{base:"./dist",scripts:`./addons/${e.addonName}/scripting`,plugins:`./addons/${e.addonName}/plugins`,include:`./addons/${e.addonName}/scripting/include`,assets:"./"},compiler:{dir:"./.compiler",version:e.defaultVersion,dev:!1,addons:[],executable:e.executable},thirdparty:{dir:"./.thirdparty",dependencies:[]},include:[],rules:{flatCompilation:!0,rebuildDependents:!0},cli:{templates:{context:{PLUGIN_VERSION:"1.0.0",PLUGIN_AUTHOR:c.title}}}});function St(o){let e=G.default.resolve(c.projectTypesDir,`${o}.json`);if(!V.default.existsSync(e))throw new m(`Unsupported project type: ${o}`);return JSON.parse(V.default.readFileSync(e,"utf8"))}function ye(o,e,t){var h,v;t=t?G.default.resolve(t):process.cwd();let i=St(o),r=Pt(o,i),s=(0,g.defaultsDeep)({},e,r),n=(v=(h=e.rules)==null?void 0:h.flatCompilation)!=null?v:!0,a=y=>G.default.resolve(t,y),d=(y,$,he)=>{var $e,Te,Re,Ne;let b=(0,g.isObject)(y)?y:{dir:y},L=(0,g.isObject)($)?$:{dir:$};return(0,g.defaults)({src:a(b.dir),dest:G.default.resolve(t,s.output.base,L.dir,(($e=b.output)==null?void 0:$e.dir)||"."),prefix:[L.prefix,(Te=b.output)==null?void 0:Te.prefix].join(""),filter:b.filter?(0,g.castArray)(b.filter):[],flat:(0,g.isNil)((Re=b.output)==null?void 0:Re.flat)&&(0,g.isNil)(L.flat)?void 0:!!((Ne=b.output)!=null&&Ne.flat||L.flat)},he)},f=(y,$,he)=>{var b;return(0,g.isNull)((b=e.output)==null?void 0:b[y])?[]:(0,g.map)((0,g.castArray)(s.input[$]),L=>d(L,s.output[y],he))};return{type:o,path:t,defaults:{...(0,g.pick)(r,["type","input","output","thirdparty","include","cli"]),compiler:(0,g.pick)(r.compiler,["dir","version","addons","executable"])},cli:s.cli,targets:{assets:f("assets","assets",{flat:!1}),include:f("include","include",{flat:!0}),scripts:f("scripts","scripts",{flat:!0}),plugins:f("plugins","scripts",{flat:n})},include:(0,g.map)(s.include,a),compiler:{...s.compiler,dir:a(s.compiler.dir),config:i},thirdparty:{dir:a(s.thirdparty.dir),dependencies:(0,g.map)(s.thirdparty.dependencies,y=>({...y,strip:y.strip||0,filter:y.filter||[],type:y.type||null}))},rules:{flatCompilation:s.rules.flatCompilation,rebuildDependents:s.rules.rebuildDependents}}}function oe(o,e){if(!V.default.existsSync(o))throw new m(`Cannot find config file: ${o}`);try{let t=V.default.readFileSync(o,"utf8"),i=JSON.parse(t);return ye(i.type||c.project.defaultType,i,e)}catch(t){throw new m(`Failed to read config file: ${o}! ${t instanceof Error?t.message:t}`)}}var q=p(require("path")),Ce=p(require("fs")),je=p(require("normalize-path")),Ue=p(require("decompress")),Ie=require("lodash"),_e=p(require("os"));var Be=p(require("path")),Me=p(require("fs")),ze=p(require("download"));async function Ft(o,e){let{dir:t,base:i}=Be.default.parse(e);return await Me.default.promises.mkdir(t,{recursive:!0}),await(0,ze.default)(o,t,{filename:i}),{url:o,path:e}}var J=Ft;var X=class{constructor(e){this.projectConfig=e}async download(){let{compiler:e}=this.projectConfig,t=e.dir,i=[...e.addons],r=this.projectConfig.compiler.config.downloader.baseDist;i.includes(r)||i.unshift(r);let s=(0,Ie.map)(i,a=>this.resolveDist({type:this.projectConfig.type,name:a,version:e.version,dev:e.dev}));l.info("\u{1F53D} Downloading compiler...");let n=await Promise.all((0,Ie.map)(s,a=>this.downloadDist(a)));l.info("\u{1F4E4} Extracting compiler files...");for(let a of n)await this.extractDist(a.path,t)}async downloadDist(e){let t=await this.getDistFileName(e);if(!t)throw new m("Failed to fetch dist file meta!");let i=this.resolveDownloadDistOpts(t,e),r=await this.downloadFile(i);return{dist:e,path:r.path}}async extractDist(e,t){let{fileExtensions:i}=this.projectConfig.compiler.config;l.info(`\u{1F4E4} Extracting "${q.default.parse(e).base}"...`),await Ce.default.promises.mkdir(t,{recursive:!0}),await(0,Ue.default)(e,t,{map:r=>{let s={...r};return(0,je.default)(s.path).startsWith(this.projectConfig.compiler.config.downloader.compilerDir)&&(s.path=q.default.relative(this.projectConfig.compiler.config.downloader.compilerDir,s.path)),s},filter:r=>(0,je.default)(r.path).startsWith(this.projectConfig.compiler.config.downloader.compilerDir)?i.script!==q.default.extname(r.path).slice(1):!1})}async getDistFileName(e){if(e.dev)return this.resolveFileName(e);if(!this.projectConfig.compiler.config.downloader.useMetaFile)return this.resolveFileName({...e,version:this.projectConfig.compiler.version});let t=this.resolveMetaFileName(e),i=this.resolveDownloadDistOpts(t,e),r=await this.downloadFile(i);return(await Ce.default.promises.readFile(r.path,"utf8")).trim()}resolveDist(e){let t=this.projectConfig.compiler.config.downloader.baseDist,{type:i,name:r=t,dev:s=!1}=e,n=s?e.version:this.resolveReleaseVersion(e.version||this.projectConfig.compiler.config.defaultVersion);e.version!==n&&r===t&&l.warn(`The "${e.version}" version format is redundant. Change the compiler version to "${n}" in the project configuration to remove this warning.`);let a=this.resolvePlatform();return{type:i,name:r,version:n,platform:a,dev:s}}resolveSource(e){let t=[this.projectConfig.compiler.config.downloader.distSource],i=this.resolveReleaseVersion(e.version);return t.push(i),t.join("/")}resolveDownloadDistOpts(e,t){let i=q.default.join(c.downloadDir,e),r=this.resolveSource(t);return{url:this.resolveUrl(r,e),path:i}}resolveUrl(e,t){return`${this.projectConfig.compiler.config.downloader.downloadHost}/${e}/${t}`}resolveReleaseVersion(e){return e.split(".").slice(0,2).join(".")}resolveFileName({type:e,name:t,version:i,platform:r}){return[e,i,t,`${r}${r==="linux"?".tar.gz":".zip"}`].filter(Boolean).join("-")}resolveMetaFileName({type:e,name:t,platform:i}){return[e,"latest",t,`${i}`].filter(Boolean).join("-")}resolvePlatform(){let e=_e.default.platform();switch(e){case"win32":return"windows";case"linux":return"linux";case"darwin":return"mac"}throw new m(`Unable to resolve platform for ${e}`)}async downloadFile(e){return l.debug(`Downloading file from "${e.url}" to "${e.path}"`),await J(e.url,e.path)}};var k=p(require("path")),Ve=p(require("decompress")),Je=p(require("globule")),qe=p(require("fs")),Xe=require("url");var T=p(require("fs"));async function Et(o,e){await T.default.promises.access(o,T.default.constants.W_OK|T.default.constants.R_OK);try{await T.default.promises.access(e,T.default.constants.W_OK|T.default.constants.R_OK)}catch(t){if(t.code!=="ENOENT")throw t}await T.default.promises.copyFile(o,e)}var O=Et;var Ke=p(require("chokidar"));function $t(o){let e=Ke.default.watch(o,{persistent:!0,ignoreInitial:!0,interval:300,awaitWriteFinish:{stabilityThreshold:50,pollInterval:10}});return process.on("SIGINT",async()=>{await e.close(),process.exit(0)}),e.on("error",t=>{console.error("Watcher failure",t),process.exit(1)}),e}var xe=$t;var We=p(require("fs"));async function se(o){let e=await We.default.promises.readFile(o,"utf8"),t=/^\s*#(tryinclude|include)\s+(?:(?:"([^"]+)")|(?:<([^>]+)>))/gm,i=[],r;for(;r=t.exec(e);){let s=r[2]!=="tryinclude";r[2]?i.push({name:r[2],type:"relative",required:s}):r[3]&&i.push({name:r[3],type:"native",required:s})}return i}function Tt(){let o="";return e=>(o+=(e==null?void 0:e.toString())||"",o)}var be=Tt;var Ge=["zip","tar","tar.gz","tar.bz2"];var Y=class{constructor(e){this.projectConfig=e}async download(){for(let e of this.projectConfig.thirdparty.dependencies)l.info(`\u{1F53D} Downloading "${e.name}" thirdparty...`),await this.downloadDependency(e)}async downloadDependency(e){let t=k.default.join(c.downloadDir,e.name),i=new Xe.URL(e.url).pathname,{base:r}=k.default.parse(i)||{},s=r||k.default.parse(t).base;await J(e.url,t);let n=k.default.join(this.projectConfig.path,this.projectConfig.thirdparty.dir,e.name);if(await qe.default.promises.mkdir(n,{recursive:!0}),e.type==="archive"||Ge.includes(k.default.extname(s).slice(1))){l.info(`\u{1F4E4} Extracting "${e.name}" thirdparty...`),await(0,Ve.default)(t,n,{strip:e.strip,filter:e.filter&&(a=>Je.default.isMatch(e.filter,a.path,{dot:!0,nocase:!0,matchBase:!0}))});return}l.info(`\u27A1\uFE0F Copying "${e.name}" thirdparty...`),await O(t,k.default.join(n,s))}};var ne=class{constructor(e){this.compilerDownloader=new X(e),this.thirdpartyDownloader=new Y(e)}async downloadCompiler(){await this.compilerDownloader.download()}async downloadThirdparty(){await this.thirdpartyDownloader.download()}};var ae=p(require("fs")),De=p(require("path")),D=require("lodash");var B=class{constructor(e,t,i){this.projectConfig=e;this.context=null;this.rawIncludes=null;this.context=(0,D.defaults)((0,D.merge)({},this.projectConfig.cli.templates.context,t),i)}async buildTemplate(e,t){let{templateDir:i}=this.projectConfig.compiler.config.cli,r=(0,D.get)(this.projectConfig.cli.templates.files,e,De.default.join(c.templatesDir,`${i}/${e}.txt`));return(await ae.default.promises.readFile(r,"utf8")).replace(/\{\{([a-zA-Z0-9_]+)\}\}/gm,(a,...d)=>{let[f]=d;return(0,D.get)(t,f,(0,D.get)(this.context,f,a))})}async createFile(e,t,i){let{dir:r}=De.default.parse(e);await ae.default.promises.mkdir(r,{recursive:!0});let s=(await Promise.all((0,D.map)(this.context.INCLUDES,n=>this.buildTemplate("include-directive",{FILE:n})))).join(`
3
+ `);await ae.default.promises.writeFile(e,await this.buildTemplate(t,{INCLUDES:s}),{flag:i?"w":"wx"}),l.info("\u{1F4C4} New file created:",e)}};var F=class{constructor(e){this.projectConfig=oe(e)}async install(e){let t=new ne(this.projectConfig);e.compiler&&await t.downloadCompiler(),e.thirdparty&&await t.downloadThirdparty()}async createScript(e,t){let{config:{fileExtensions:i,cli:{defaultIncludes:r}}}=this.projectConfig.compiler,s=(0,S.first)(this.projectConfig.targets.scripts),{name:n,dir:a}=P.default.parse(e);await this.createTemplateService(e,{FILE_NAME:e,PLUGIN_NAME:t.title,PLUGIN_VERSION:t.version,PLUGIN_AUTHOR:t.author,INCLUDES:(0,S.uniq)([...r,...t.include||[]])}).createFile(P.default.join(s.src,a,`${n}.${i.script}`),"script",t.overwrite||!1)}async createInclude(e,t={}){let{config:{fileExtensions:i,cli:{defaultIncludes:r}}}=this.projectConfig.compiler,s=(0,S.first)(this.projectConfig.targets.include),{name:n,dir:a}=P.default.parse(e);await this.createTemplateService(e,{FILE_NAME:e,INCLUDES:(0,S.uniq)([...r,...t.include||[]])}).createFile(P.default.join(s.src,a,`${n}.${i.include}`),"include",t.overwrite||!1)}async createLibrary(e,t){let{config:{fileExtensions:i,cli:{defaultIncludes:r}}}=this.projectConfig.compiler,s=(0,S.first)(this.projectConfig.targets.scripts),n=(0,S.first)(this.projectConfig.targets.include),{name:a,dir:d}=P.default.parse(e),f=this.createTemplateService(e,{FILE_NAME:e,PLUGIN_NAME:t.title,PLUGIN_VERSION:t.version,PLUGIN_AUTHOR:t.author,LIBRARY_NAME:t.name||a.replace(/-/g,"_"),INCLUDES:(0,S.uniq)([...r,...t.include||[]]),INCLUDE_NAME:a});await f.createFile(P.default.join(s.src,d,`${a}.${i.script}`),"library-script",t.overwrite||!1),await f.createFile(P.default.join(n.src,`${a}.${i.include}`),"library-include",t.overwrite||!1)}createTemplateService(e,t){let{name:i}=P.default.parse(e);return new B(this.projectConfig,t,{PLUGIN_NAME:i})}};var ce=new Ye.Command;ce.command("script").alias("s").arguments("<filename>").option("--title, -n <title>","Plugin title").option("--version, -v <version>","Plugin version").option("--author, -a <author>","Plugin author").option("--include, -i <include>","Add include",o=>o.split(/[\s|,]/),[]).option("--overwrite","Overwrite file if it already exists",!1).option("--config, -c <path>","Config file",c.project.configFile).action(w(async(o,e)=>{let{title:t,version:i,author:r,include:s,overwrite:n,config:a}=e;await new F(a).createScript(o,{title:t,version:i,author:r,include:s,overwrite:n})}));ce.command("include").alias("i").arguments("<filename>").option("--include, -i <include>","Add include",o=>o.split(/[\s|,]/),[]).option("--overwrite","Overwrite file if it already exists",!1).option("--config, -c <path>","Config file",c.project.configFile).action(w(async(o,e)=>{let{include:t,overwrite:i,config:r}=e;await new F(r).createInclude(o,{include:t,overwrite:i})}));ce.command("library").alias("lib").alias("l").arguments("<filename>").option("--title, -t <title>","Library title").option("--version, -v <version>","Library version").option("--author, -a <author>","Library author").option("--name, -n <name>","Library name").option("--include, -i <include>","Add include",o=>o.split(/[\s|,]/),[]).option("--overwrite","Overwrite file if it already exists",!1).option("--config, -c <path>","Config file",c.project.configFile).action(w(async(o,e)=>{let{name:t,title:i,version:r,author:s,include:n,overwrite:a,config:d}=e;await new F(d).createLibrary(o,{name:t,title:i,version:r,author:s,include:n,overwrite:a})}));var Ze=ce;var u=p(require("path")),pe=p(require("globule")),j=p(require("normalize-path")),U=require("lodash"),z=p(require("fs"));var le=p(require("path")),et=p(require("child_process")),tt=p(require("fs"));var it=require("lodash");var Qe={filename:/([a-zA-Z0-9.\-_/:\\\s]+)/,line:/\(([0-9]+)(?:\s--\s([0-9]+))?\)/,type:/((?:fatal\s)?error|warning)/,code:/([0-9]+)/,text:/(.*)/};function Ot(){let{filename:o,line:e,type:t,code:i,text:r}=Qe,s=[o,e,/\s:\s/,t,/\s/,i,/:\s/,r].map(n=>n.toString().slice(1,-1)).join("");return new RegExp(s)}var kt=Ot();function At(o){let e=o.match(kt);if(!e)return{type:"echo",text:o};let[,t,i,r,s,n,a]=e;return{filename:t,startLine:+i,endLine:r?+r:-1,type:s,code:+n,text:a}}function Lt(o){return o.startsWith("Compilation aborted.")||o.startsWith("Could not locate output file")}function Ht(o){let e={messages:[],aborted:!1,error:!1};return o.split(`
4
+ `).forEach(t=>{let i=At(t),{type:r}=i;r==="error"||r==="fatal error"?e.error=!0:r==="echo"&&Lt(t)&&(e.error=!0,e.aborted=!0),e.messages.push(i)}),e}function Bt(o,e){return[o.path,`-o${e}`,...(0,it.castArray)(o.includeDir).map(t=>`-i${t}`)]}function Mt(o){let e=o.dest,t=le.default.parse(e),i=le.default.parse(e).base;return tt.default.mkdirSync(t.dir,{recursive:!0}),new Promise(r=>{let s=be(),n=d=>{let f=s(),h=Ht(f),v=d&&d.message;!v&&h.error&&(v="Compilation error"),r({error:v,plugin:i,success:!v,output:h})},a=et.default.spawn(o.compiler,Bt(o,e),{env:process.env,cwd:le.default.parse(o.compiler).dir});a.on("error",n),a.on("close",n),a.stdout.on("data",s),a.stderr.on("data",d=>console.error(d))})}var Pe=Mt;var M=p(require("fs")),Z=p(require("path")),Fe=p(require("crypto")),rt=p(require("node-cache")),ot=p(require("normalize-path")),st=p(require("globule"));var Se=(r=>(r.Hash="hash",r.Dependencies="dependencies",r.DependenciesHash="dependencies-hash",r.Dependents="dependents",r))(Se||{});var Q=class{constructor(e,t,i,r=[]){this.projectDir=e;this.includeDirs=t;this.fileExtensions=i;this.cache=new rt.default,this.ignoredIncludesSet=new Set(r)}clear(){this.cache.data={}}save(e){M.default.writeFileSync(e,JSON.stringify(this.cache.data))}load(e){if(!M.default.existsSync(e))return;let t=M.default.readFileSync(e,"utf8");this.cache.data=JSON.parse(t)}async isRelevantSrc(e){let t=this.cache.get(this.getFileCacheKey(e,"hash"));if(!t||await this.createFileHash(e)!==t)return!1;let r=this.getDependencies(e),s=await this.getFilesHash(r.items);return r.hash===s}async isRelevantFile(e){let t=await this.createFileHash(e);if(!t)return!1;let i=this.cache.get(this.getFileCacheKey(e,"hash"));return t===i}async updateSrc(e){let t=this.cache.get(this.getFileCacheKey(e,"hash")),i=await this.updateFileHash(e),r=await this.updateDependencies(e);return t!==i||r}async updateFile(e){let t=this.cache.get(this.getFileCacheKey(e,"hash")),i=await this.updateFileHash(e);return t!==i}async deleteFile(e){let t=this.getDependencies(e);for(let i of t.items)this.removeDependent(i,e);for(let i of Object.values(Se))this.cache.del(this.getFileCacheKey(e,i))}isDependenciesInitialized(e){return this.cache.has(this.getFileCacheKey(e,"dependencies"))}getDependencies(e){let t=this.cache.get(this.getFileCacheKey(e,"dependencies")),i=this.cache.get(this.getFileCacheKey(e,"dependencies-hash"));return i?{items:t||[],hash:i}:{items:[],hash:null}}async updateDependencies(e){let t=this.getFileCacheKey(e,"dependencies"),i=this.getFileCacheKey(e,"dependencies-hash"),r=this.cache.has(t)?this.cache.get(t):[],s=this.cache.has(i)?this.cache.get(i):null,n=new Set(await this.parseDependencies(e));for(let h of n.values()){this.isDependenciesInitialized(h)||await this.updateDependencies(h);for(let v of this.getDependencies(h).items)n.add(v)}let a=Array.from(n);this.cache.set(t,a);let d=await this.getFilesHash(a);if(this.cache.set(i,d),s===d)return!1;for(let h of r)n.has(h)||this.removeDependent(h,e);let f=this.getDependents(e);for(let h of a){this.addDependent(h,e);for(let v of f)this.addDependent(h,v)}return!0}getDependents(e){let t=this.getFileCacheKey(e,"dependents");return this.cache.has(t)?this.cache.get(t):[]}addDependent(e,t){let i=this.getFileCacheKey(e,"dependents"),r=this.cache.has(i)?this.cache.get(i):[],s=new Set(r);s.has(t)||(s.add(t),this.cache.set(i,Array.from(s)),l.debug(`Added dependent: ${e} <- ${t}`))}removeDependent(e,t){let i=this.getFileCacheKey(e,"dependents");if(!this.cache.has(i))return;let r=this.cache.get(i),s=new Set(r);s.delete(t),this.cache.set(this.getFileCacheKey(e,"dependents"),Array.from(s)),l.debug(`Remove dependent: ${e} <- ${t}`)}async parseDependencies(e){let t=new Set,i=await se(e);for(let r of i)if(r.type=="native"){if(this.ignoredIncludesSet.has(r.name))continue;for(let s of this.includeDirs){let n=`${r.name}.${this.fileExtensions.include}`,[a]=st.default.find(Z.default.join(s,"**",`${n}`),{nodir:!0});if(a){t.add(a);break}}}else{let n=Z.default.extname(r.name).slice(1)?r.name:`${r.name}.${this.fileExtensions.include}`;t.add(Z.default.resolve(Z.default.dirname(e),n))}return Array.from(t)}async getFilesHash(e){let t=Fe.default.createHash("sha256");for(let i of e){let r=this.getFileCacheKey(i,"hash"),s=this.cache.has(r)?this.cache.get(r):await this.updateFileHash(i);t.update(s)}return t.digest("hex")}async updateFileHash(e){let t=await this.createFileHash(e);return this.cache.set(this.getFileCacheKey(e,"hash"),t),t}async createFileHash(e){if(!M.default.existsSync(e))return null;let t=await M.default.promises.readFile(e);return this.createHash(t)}getFileCacheKey(e,t){return this.createHash(`${this.projectDir}:${(0,ot.default)(e)}?${t}`)}createHash(e){let t=Fe.default.createHash("sha256");return t.update(e),t.digest("hex")}};var ee=class{constructor(e,t={}){this.projectConfig=e;this.options=t;this.cache=null;this.options.noCache||this.initCache(),this.fileTargetsMap=new Map,this.scriptsPathPattern=`**/*.${e.compiler.config.fileExtensions.script}`,this.includePathPattern=`**/*.${e.compiler.config.fileExtensions.include}`,this.assetsPathPattern="**/*.*"}async buildInclude(){for(let e of this.projectConfig.targets.include)await this.buildDir(e,this.includePathPattern,t=>this.updateInclude(t))}async buildAssets(){for(let e of this.projectConfig.targets.assets)await this.buildDir(e,this.assetsPathPattern,t=>this.updateAsset(t))}async buildScripts(e={}){let{fileExtensions:t}=this.projectConfig.compiler.config,i=!0;for(let r of this.projectConfig.targets.scripts)await this.buildDir(r,e.pattern?u.default.join("**",e.pattern):this.scriptsPathPattern,async s=>{t.script===u.default.extname(s).slice(1)&&(e.skipCompilation?i&&(i=await this.updateScript(s)):i&&(i=await this.updateScriptAndPlugin(s)))});return i}async watchAssets(){for(let e of this.projectConfig.targets.assets)await this.watchDir(e,this.assetsPathPattern,t=>this.updateAsset(t))}async watchInclude(){for(let e of this.projectConfig.targets.include)await this.watchDir(e,this.includePathPattern,async t=>{await this.updateInclude(t)&&await this.rebuildDependents(t)})}async watchScripts(){for(let e of this.projectConfig.targets.scripts)await this.watchDir(e,this.scriptsPathPattern,t=>this.updateScriptAndPlugin(t))}async updateScript(e){let t=!0;this.cache&&(t=await this.cache.updateSrc(e));let i=this.getFileTarget(e);if(i.dest){let r=this.resolveDestPath(e,i);if(this.cache&&!t&&await this.cache.isRelevantFile(r))return!1;await z.default.promises.mkdir(u.default.dirname(r),{recursive:!0}),await O(e,r),this.cache&&await this.cache.updateFile(r),l.info("\u{1F4C4} Script updated:",(0,j.default)(r))}return!0}async updateAsset(e){let t=!0;this.cache&&(t=await this.cache.updateFile(e));let i=this.getFileTarget(e);if(i.dest){let r=this.resolveDestPath(e,i);if(this.cache&&!t&&await this.cache.isRelevantFile(r))return!1;await z.default.promises.mkdir(u.default.dirname(r),{recursive:!0}),await O(e,r),this.cache&&await this.cache.updateFile(r),l.info("\u{1F9F8} Asset updated:",(0,j.default)(r))}}async updateInclude(e){if(this.cache&&!await this.cache.updateSrc(e))return!1;let t=this.getFileTarget(e);if(t.dest){let i=this.resolveDestPath(e,t);await z.default.promises.mkdir(u.default.dirname(i),{recursive:!0}),await O(e,i),l.info("\u{1F4C4} Include updated:",(0,j.default)(i))}return!0}async updatePlugin(e){try{if(!await this.compileScript(e))return!1}catch(t){if(!this.options.ignoreErrors)throw t;return!1}return!0}async updateScriptAndPlugin(e){return await this.updatePlugin(e)?(await this.updateScript(e),!0):!1}async compileScript(e){let t=this.getPluginTarget(e);if(!t)return!0;let i=u.default.relative(process.cwd(),e),r=this.resolvePluginDestPath(e,t);if(this.cache){let a=await this.cache.isRelevantSrc(e),d=await this.cache.isRelevantFile(r);if(a&&d)return l.info("\u{1F4C4} Script is already up to date:",(0,j.default)(i),"Skipped!"),!0}let s=u.default.join(this.projectConfig.compiler.dir,this.projectConfig.compiler.executable);await z.default.promises.mkdir(u.default.dirname(r),{recursive:!0});let n=await Pe({path:e,dest:r,compiler:s,includeDir:[u.default.join(this.projectConfig.compiler.dir,"include"),...this.projectConfig.include,...(0,U.map)(pe.default.find((0,U.map)(this.projectConfig.targets.include,a=>u.default.join(a.src,"**/"))),a=>u.default.resolve(a))]});if(this.cache&&(n.error?await this.cache.deleteFile(r):await this.cache.updateFile(r)),n.output.messages.forEach(a=>{let{startLine:d,type:f,code:h,text:v,filename:y}=a,$=y?u.default.relative(process.cwd(),y):i;f==="error"||f==="fatal error"?l.error(`${(0,j.default)($)}:${d}`,"-",f,h,":",v):f==="warning"?l.warn(`${(0,j.default)($)}:${d}`,"-",f,h,":",v):f==="echo"&&l.debug(v)}),n.success)l.success("Script compiled successfully:",(0,j.default)(i)),l.info("\u{1F9E9} Plugin updated:",(0,j.default)(r));else throw new m(`Failed to compile ${(0,j.default)(i)} : "${n.error}"`);return n.success}async rebuildDependents(e){if(!this.cache||!this.projectConfig.rules.rebuildDependents)return;let{fileExtensions:t}=this.projectConfig.compiler.config,i=this.cache.getDependents(e);for(let r of i)t.script===u.default.extname(r).slice(1)&&await this.updateScriptAndPlugin(r)}async buildDir(e,t,i){await pe.default.find(u.default.join(e.src,t),{nodir:!0}).reduce((s,n)=>s.then(async()=>{if(e.filter){let a=u.default.relative(e.src,n);if(!this.execPathFilter(a,e.filter))return}this.setFileTarget(n,e),await i(u.default.normalize(n)),this.cache&&this.cache.save(c.cacheFile)}),Promise.resolve())}async watchDir(e,t,i){let r=async n=>{if(this.execPathFilter(n,t)){if(e.filter){let a=u.default.relative(e.src,n);if(!this.execPathFilter(a,e.filter))return}l.info("\u{1F539} File change detected. Starting incremental compilation..."),this.setFileTarget(n,e),await i(u.default.normalize(n)).catch(a=>l.error(a.message)),l.info("\u{1F539} Compilation complete. Watching for file changes."),this.cache&&this.cache.save(c.cacheFile)}},s=async n=>{this.cache&&await this.cache.deleteFile(n)};xe(e.src).on("add",r).on("change",r).on("unlink",s)}initCache(){let e=this.getNativeIncludes();this.cache=new Q(this.projectConfig.path,(0,U.map)(this.projectConfig.targets.include,"src"),this.projectConfig.compiler.config.fileExtensions,e),this.cache.load(c.cacheFile)}getNativeIncludes(){let{fileExtensions:e}=this.projectConfig.compiler.config,t=[];for(let i of this.projectConfig.include)for(let r of z.default.readdirSync(i)){let{name:s,ext:n}=u.default.parse(r);n.slice(1)==e.include&&t.push(s)}return t}setFileTarget(e,t){this.fileTargetsMap.set((0,j.default)(e),t)}getFileTarget(e){return this.fileTargetsMap.get((0,j.default)(e))}getPluginTarget(e){let t=(0,j.default)(e),i=`plugin:${t}`;if(!this.fileTargetsMap.has(i)){let r=this.fileTargetsMap.get(t);if(!r)throw new m(`Source file ${t} not found in any target`);this.fileTargetsMap.set(`plugin:${t}`,(0,U.find)(this.projectConfig.targets.plugins,{src:r.src}))}return this.fileTargetsMap.get(i)}execPathFilter(e,t){return!t||Array.isArray(t)&&!t.length?!0:pe.default.isMatch(t,e,{dot:!0,nocase:!0,matchBase:!0})}resolveDestPath(e,t){let{dir:i,base:r}=u.default.parse(e),s=t.flat?".":u.default.relative(t.src,i);return u.default.join(t.dest,s,`${t.prefix}${r}`)}resolvePluginDestPath(e,t){let{fileExtensions:i}=this.projectConfig.compiler.config,r=this.getFileTarget(e),s=t.flat?".":u.default.relative(r.src,u.default.dirname(e)),{name:n}=u.default.parse(e);return u.default.join(t.dest,s,`${t.prefix}${n}.${i.plugin}`)}};function nt(o,e){return new ee(o,e)}var _=class{constructor(e,t){this.projectConfig=oe(e),this.builder=nt(this.projectConfig,t)}async compile(e){await this.builder.buildScripts({pattern:e})}async build(e){e.watch&&(e.assets&&await this.builder.watchAssets(),e.includes&&await this.builder.watchInclude(),e.scripts&&await this.builder.watchScripts());try{let t=!0;return e.assets&&await this.builder.buildAssets(),e.includes&&await this.builder.buildInclude(),(e.plugins||e.scripts)&&(t=await this.builder.buildScripts({skipCompilation:!e.plugins})),t}catch(t){throw new m(`Build failed! Error: ${t instanceof Error?t.message:"Unknown error"}`)}}};var x=p(require("path")),C=p(require("fs")),at=require("child_process"),R=require("lodash");var K=class{constructor(e){let t=e.cwd||process.cwd(),i=e.name||x.default.basename(t);this.isCurrentDir=!!e.name&&e.name===".",this.projectDir=this.isCurrentDir?t:x.default.join(t,i),this.options={...e,name:i,cwd:t},this.projectConfig=ye(e.type,{},this.projectDir)}async createProject(){if(!this.isCurrentDir&&C.default.existsSync(this.projectDir))throw new m(`Project ${this.options.name} is already exists!`);if(this.isCurrentDir&&this.isInitialized())throw new m("Cannot create a project! The directory is not empty!");await this.createConfig(),await this.createDirectories(),this.options.npm&&await this.updatePackage(),this.options.git&&!this.isGitInitialized()&&await this.initGit(),this.isGitInitialized()&&await this.updateGitignore(),this.isNpmPackageInitialized()&&await this.installDependencies(),this.options.install&&await this.execCommand(`npx ${c.command} install`)}async updatePackage(){l.info("\u{1F4E6} Initializing npm package...");let e=x.default.join(this.projectDir,"package.json"),t={name:this.options.name,version:(0,R.get)(this.options,"version","0.1.0"),author:(0,R.get)(this.options,"author",c.title),description:(0,R.get)(this.options,"description",`This project was generated by ${c.title} CLI`)};C.default.existsSync(e)&&(0,R.merge)(t,JSON.parse(await C.default.promises.readFile(e,"utf8"))),(0,R.merge)(t,{scripts:{build:`${c.command} build`,watch:`${c.command} build --watch`,postinstall:`${c.command} install`}}),await C.default.promises.writeFile(e,JSON.stringify(t,null,2))}async createConfig(){l.info("\u{1F527} Creating project configuration file..."),await C.default.promises.mkdir(this.projectDir,{recursive:!0});let e=x.default.join(this.projectDir,c.project.configFile),t=(0,R.merge)({},this.projectConfig.defaults);await C.default.promises.writeFile(e,JSON.stringify(t,null,2))}async createDirectories(){l.info("\u{1F4C1} Creating project directories...");for(let e of this.projectConfig.targets.assets)await C.default.promises.mkdir(e.src,{recursive:!0});for(let e of this.projectConfig.targets.include)await C.default.promises.mkdir(e.src,{recursive:!0});for(let e of this.projectConfig.targets.scripts)await C.default.promises.mkdir(e.src,{recursive:!0})}async installDependencies(){l.info("\u{1F504} Installing dependencies..."),await this.execCommand(`npm install ${c.command}@${c.version} --save-dev`)}async initGit(){l.info("\u{1F33F} Initializing git..."),await this.execCommand("git init")}async updateGitignore(){l.info("\u2754 Updating .gitignore file...");let e=x.default.join(this.projectDir,".gitignore"),t=[`*.${this.projectConfig.compiler.config.fileExtensions.plugin}`],i=r=>!x.default.isAbsolute(r)&&t.push(`npx ${x.default.relative(this.projectDir,r)}/`);i("node_modules"),i(this.projectConfig.compiler.dir),i(this.projectConfig.thirdparty.dir);for(let r of this.projectConfig.targets.assets)i(r.src);C.default.existsSync(e)&&t.unshift(""),t.push(""),await C.default.promises.appendFile(e,t.join(`
5
+ `))}isInitialized(){return C.default.existsSync(x.default.join(this.projectDir,c.project.configFile))}isGitInitialized(){return C.default.existsSync(x.default.join(this.projectDir,".git"))}isNpmPackageInitialized(){return C.default.existsSync(x.default.join(this.projectDir,"package.json"))}execCommand(e){return new Promise(t=>{let i=(0,at.exec)(e,{cwd:this.projectDir});i.on("error",t),i.on("close",t)})}};var A=new ct.Command;A.command("config").option("--type, -t <type>","Project type",c.project.defaultType).action(w(async o=>{let{type:e}=o;await new K({type:e}).createConfig()}));A.command("create").argument("<name>","Project name").option("--type, -t <type>","Project type",c.project.defaultType).option("--version, -v <version>","Project version").option("--author, -a <author>","Project author").option("--description, -d <author>","Project description").option("--no-npm","Don't initialize npm package",!0).option("--no-install","Don't install dependencies",!0).option("--git","Initialize git",!1).action(w(async(o,e)=>{let{version:t,author:i,description:r,npm:s,install:n,git:a,type:d}=e;if(!o)throw new m("Project name cannot be empty!");await new K({name:o,version:t,author:i,description:r,npm:s,install:n,git:a,type:d}).createProject(),l.success(`Your project is ready! Thanks for using ${c.title} CLI! \u{1F917}`)}));A.command("install").alias("i").option("--config, -c <path>","Config file",c.project.configFile).option("--compiler","Install compiler").option("--thirdparty","Install thirdparty dependencies").action(w(async(o,e)=>{let{config:t,compiler:i,thirdparty:r}=e.opts(),s=!i&&!r;await new F(t).install({compiler:s||!!i,thirdparty:s||!!r})}));A.command("compile").alias("c").argument("<pattern>","Script path or glob").option("--config, -c <path>","Config file",c.project.configFile).option("--no-cache","Disable caching").action(w(async(o,e)=>{let{config:t,cache:i}=e;await new _(t,{noCache:!i}).compile(o)}));A.command("build").alias("b").option("--config, -c <path>","Config file",c.project.configFile).option("--watch, -w","Watch project").option("--ignore, -i","Ignore build errors").option("--no-cache","Disable caching").option("--assets","Build assets").option("--scripts","Build scripts").option("--plugins","Build plugins").option("--includes","Build includes").action(w(async(o,e)=>{let{config:t,watch:i,ignore:r,cache:s,assets:n,scripts:a,plugins:d,includes:f}=e.opts(),h=!n&&!a&&!d&&!f,v=new _(t,{noCache:!s});l.info("\u2692\uFE0F Building..."),await v.build({watch:i,ignoreErrors:r,noCache:!s,assets:h||n,scripts:h||a,plugins:h||d,includes:h||f})?l.success("\u2705 Build completed successfully!"):l.error("\u26A0\uFE0F Build completed with errors!")}));A.addCommand(Ze.name("generate").alias("new").alias("n").alias("g"));var lt=A;var dt=require("commander");var E=p(require("fs"));var pt=p(require("path")),te=class{getCacheSize(){let e=0;if(E.default.existsSync(c.cacheFile)&&(e+=E.default.statSync(c.cacheFile).size),E.default.existsSync(c.downloadDir)){let t=E.default.readdirSync(c.downloadDir);for(let i of t)e+=E.default.statSync(pt.default.join(c.downloadDir,i)).size}return e}clearCache(){E.default.existsSync(c.cacheFile)&&E.default.rmSync(c.cacheFile),E.default.rmSync(c.downloadDir,{recursive:!0,force:!0})}};var de=new dt.Command,Ee;de.hook("preAction",()=>{Ee=new te});de.command("clean").action(w(()=>{Ee.clearCache(),l.info("\u{1F9F9} Cache cleaned!")}));de.command("size").action(w(()=>{let o=Ee.getCacheSize();l.info(`\u{1F4BE} Cache size: ${o} bytes`)}));var ut=de;var ft=require("commander");var ue=p(require("fs")),fe=require("lodash");var ie=class{async getDependencies(){return(await this.readProjectConfig()).thirdparty.dependencies}async addDependency(e,t,i,r){let s=await this.readProjectConfig();if((0,fe.find)(s.thirdparty.dependencies,{name:e}))throw new m(`Dependency "${e}" already exists!`);s.thirdparty.dependencies.push({name:e,url:t,strip:i,filter:r}),await ue.default.promises.writeFile(c.project.configFile,JSON.stringify(s,null,2))}async removeDependency(e){let t=await this.readProjectConfig(),i=(0,fe.findIndex)(t.thirdparty.dependencies,{name:e});if(i===-1)throw new m(`Dependency "${e}" not found!`);t.thirdparty.dependencies.splice(i,1),await ue.default.promises.writeFile(c.project.configFile,JSON.stringify(t,null,2))}async readProjectConfig(){try{return JSON.parse(await ue.default.promises.readFile(c.project.configFile,"utf8"))}catch{throw new m(`Failed to read project config ${c.project.configFile}`)}}};var re=new ft.Command,me;re.hook("preAction",()=>{me=new ie});re.command("list").alias("l").action(w(async()=>{let o=await me.getDependencies();if(!o.length){l.info("\u{1F50D} No thirdparty dependencies found!");return}l.info("\u{1F50D} Thirdparty dependencies:");for(let e of o)l.info(`- ${e.name} "${e.url}"`)}));re.command("add").alias("a").argument("<name>","Thirdparty name").argument("<url>","Thirdparty URL").option("--strip [strip]","Strip",o=>parseInt(o,10)).option("--filter [filter]","Filter",o=>o.split(",")).action(w(async(o,e,t)=>{let{strip:i,filter:r}=t;await me.addDependency(o,e,i,r),l.success(`\u2795 Dependency "${o}" added successfully!`)}));re.command("remove").alias("r").argument("<name>","Thirdparty name").action(w(async o=>{await me.removeDependency(o),l.success(`\u{1F5D1}\uFE0F Dependency "${o}" removed successfully!`)}));var mt=re;var W=new ht.Command;W.name(`${c.title} CLI`).description(`${c.title} CLI - Building tools for pawn projects`);W.version(c.version);lt.commands.forEach(o=>W.addCommand(o));W.addCommand(ut.name("cache"));W.addCommand(mt.name("dependency").alias("dep").alias("d").alias("thirdparty").alias("t"));var gt=W;try{gt.exitOverride(H).parse()}catch(o){H(o)}
package/package.json CHANGED
@@ -2,23 +2,22 @@
2
2
  "name": "amxxpack",
3
3
  "description": "AMXXPack",
4
4
  "author": "Hedgehog Fog",
5
- "version": "1.5.0-beta.2",
5
+ "version": "1.5.0-beta.4",
6
6
  "license": "MIT",
7
- "main": "lib/builder/index.js",
8
- "types": "lib/builder/index.d.ts",
9
- "files": [
10
- "lib/**/*",
11
- "resources/**/*"
12
- ],
13
7
  "scripts": {
14
8
  "test": "jest",
15
- "build": "tsc",
9
+ "build": "tsc && tsup",
16
10
  "lint": "eslint",
17
11
  "prepare": "npm run build"
18
12
  },
13
+ "main": "lib/index.js",
19
14
  "bin": {
20
- "amxxpack": "./lib/cli/index.js"
15
+ "amxxpack": "./lib/index.js"
21
16
  },
17
+ "files": [
18
+ "lib/**/*",
19
+ "resources/**/*"
20
+ ],
22
21
  "repository": {
23
22
  "type": "git",
24
23
  "url": "https://github.com/Hedgefog/node-amxxpack"
@@ -31,23 +30,28 @@
31
30
  "amx",
32
31
  "amxx",
33
32
  "amxmodx",
33
+ "sourcemod",
34
+ "smx",
34
35
  "cli",
35
- "pawn"
36
+ "pawn",
37
+ "compiler",
38
+ "build",
39
+ "watch"
36
40
  ],
37
41
  "dependencies": {
38
- "chokidar": "^4.0.1",
42
+ "chokidar": "^4.0.3",
39
43
  "colors": "^1.4.0",
40
44
  "commander": "^14.0.0",
41
45
  "decompress": "^4.2.1",
42
46
  "download": "^8.0.0",
43
47
  "globule": "^1.3.4",
44
48
  "lodash": "^4.17.21",
45
- "mkdirp": "^3.0.1",
46
49
  "node-cache": "^5.1.2",
47
50
  "normalize-path": "^3.0.0"
48
51
  },
49
52
  "devDependencies": {
50
53
  "@eslint/js": "^9.34.0",
54
+ "@stylistic/eslint-plugin": "^5.3.1",
51
55
  "@types/chance": "^1.1.3",
52
56
  "@types/chokidar": "^2.1.3",
53
57
  "@types/colors": "^1.2.1",
@@ -56,17 +60,16 @@
56
60
  "@types/download": "^8.0.1",
57
61
  "@types/globule": "^1.1.4",
58
62
  "@types/jest": "^27.4.1",
59
- "@types/lodash": "^4.14.178",
60
- "@types/mkdirp": "^1.0.2",
63
+ "@types/lodash": "^4.17.20",
61
64
  "@types/node": "^24.3.0",
62
65
  "@types/normalize-path": "^3.0.0",
63
- "@types/rimraf": "^3.0.2",
64
66
  "chance": "^1.1.9",
65
67
  "eslint": "^9.34.0",
66
68
  "jest": "^27.5.1",
67
- "rimraf": "^3.0.2",
68
69
  "ts-jest": "^27.1.3",
69
- "type-fest": "^3.2.0",
70
+ "tsconfig-paths": "^4.2.0",
71
+ "tsup": "^8.5.0",
72
+ "type-fest": "^3.13.1",
70
73
  "typescript": "^4.8.4",
71
74
  "typescript-eslint": "^8.41.0"
72
75
  }
@@ -0,0 +1,21 @@
1
+ {
2
+ "executable": "amxxpc",
3
+ "defaultVersion": "1.8.2",
4
+ "addonName": "amxmodx",
5
+ "fileExtensions": {
6
+ "script": "sma",
7
+ "include": "inc",
8
+ "plugin": "amxx"
9
+ },
10
+ "cli": {
11
+ "defaultIncludes": ["amxmodx"],
12
+ "templateDir": "amxmodx"
13
+ },
14
+ "downloader": {
15
+ "downloadHost": "https://www.amxmodx.org",
16
+ "useMetaFile": false,
17
+ "baseDist": "base",
18
+ "distSource": "release",
19
+ "compilerDir": "addons/amxmodx/scripting"
20
+ }
21
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "executable": "amxxpc",
3
+ "defaultVersion": "1.9",
4
+ "addonName": "amxmodx",
5
+ "fileExtensions": {
6
+ "script": "sma",
7
+ "include": "inc",
8
+ "plugin": "amxx"
9
+ },
10
+ "cli": {
11
+ "defaultIncludes": ["amxmodx"],
12
+ "templateDir": "amxmodx"
13
+ },
14
+ "downloader": {
15
+ "downloadHost": "https://www.amxmodx.org",
16
+ "useMetaFile": true,
17
+ "baseDist": "base",
18
+ "distSource": "amxxdrop",
19
+ "compilerDir": "addons/amxmodx/scripting"
20
+ }
21
+ }