@evitcastudio/kit 3.3.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -127
- package/lib/bundle/cli/cli.js +1101 -984
- package/lib/bundle/cli/kit-game-templates/multi/dist/src/client/index.js +286 -0
- package/lib/bundle/cli/kit-game-templates/multi/src/client/index.ts +1 -1
- package/lib/cli/app-bundler.d.ts.map +1 -1
- package/lib/cli/app-bundler.js +60 -8
- package/lib/cli/create.d.ts.map +1 -1
- package/lib/cli/create.js +7 -6
- package/lib/cli/doctor.d.ts.map +1 -1
- package/lib/cli/doctor.js +57 -30
- package/lib/cli/host.d.ts.map +1 -1
- package/lib/cli/host.js +19 -12
- package/lib/cli/init.d.ts.map +1 -1
- package/lib/cli/init.js +20 -17
- package/lib/cli/resource-builder.d.ts.map +1 -1
- package/lib/cli/resource-builder.js +11 -8
- package/lib/cli/theme.d.ts +36 -0
- package/lib/cli/theme.d.ts.map +1 -0
- package/lib/cli/theme.js +41 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/plugins/camera/index.d.ts +3 -0
- package/lib/plugins/camera/index.d.ts.map +1 -0
- package/lib/plugins/camera/index.js +2 -0
- package/package.json +6 -1
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// node_modules/@evitcastudio/kit/lib/events/event-system.js
|
|
2
|
+
class EventEmitter {
|
|
3
|
+
listener;
|
|
4
|
+
plugin;
|
|
5
|
+
constructor(pListener, pPlugin) {
|
|
6
|
+
this.listener = pListener;
|
|
7
|
+
this.plugin = pPlugin;
|
|
8
|
+
}
|
|
9
|
+
emit(pEvent) {
|
|
10
|
+
if (pEvent.plugin && pEvent.plugin !== this.plugin.name) {
|
|
11
|
+
throw new Error(`Event mismatch: ${this.plugin.name} tried to emit an event from the ${pEvent.plugin} namespace.`);
|
|
12
|
+
}
|
|
13
|
+
const event = {
|
|
14
|
+
plugin: this.plugin.name,
|
|
15
|
+
event: pEvent.event,
|
|
16
|
+
data: pEvent?.data,
|
|
17
|
+
timestamp: Date.now()
|
|
18
|
+
};
|
|
19
|
+
Object.freeze(event);
|
|
20
|
+
this.listener(event);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// node_modules/@evitcastudio/kit/lib/kit.js
|
|
25
|
+
var extensionToPath = {
|
|
26
|
+
".vyint": "interface",
|
|
27
|
+
".vym": "map",
|
|
28
|
+
".vyi": "icon",
|
|
29
|
+
".vymac": "macros",
|
|
30
|
+
".aac": "sound",
|
|
31
|
+
".mp3": "sound",
|
|
32
|
+
".wav": "sound",
|
|
33
|
+
".m4a": "sound",
|
|
34
|
+
".ogg": "sound",
|
|
35
|
+
".flac": "sound"
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
class Kit {
|
|
39
|
+
static plugins = {};
|
|
40
|
+
static emitters = new Map;
|
|
41
|
+
static events = {};
|
|
42
|
+
constructor() {
|
|
43
|
+
throw new Error("[Kit] is not to be instantiated.");
|
|
44
|
+
}
|
|
45
|
+
static init(pPlugins) {
|
|
46
|
+
pPlugins.forEach((pPlugin) => {
|
|
47
|
+
this.registerPlugin(pPlugin);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
static registerPlugin(pPlugin) {
|
|
51
|
+
if (Array.isArray(pPlugin)) {
|
|
52
|
+
const plugins = [];
|
|
53
|
+
pPlugin.forEach((pPlugin2) => {
|
|
54
|
+
const plugin = this.registerPlugin(pPlugin2);
|
|
55
|
+
if (plugin && !Array.isArray(plugin)) {
|
|
56
|
+
plugins.push(plugin);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return plugins;
|
|
60
|
+
} else {
|
|
61
|
+
const plugin = new pPlugin;
|
|
62
|
+
const pluginName = plugin.name;
|
|
63
|
+
if (!pluginName || typeof pluginName !== "string" || !/^[a-zA-Z0-9-_]+$/.test(pluginName)) {
|
|
64
|
+
throw new Error(`[Kit] Invalid plugin name: '${pluginName}'. The name must be a non-empty string containing only alphanumeric characters, dashes, or underscores.`);
|
|
65
|
+
}
|
|
66
|
+
if (Kit.plugins[pluginName]) {
|
|
67
|
+
throw new Error(`[Kit] plugin with name '${pluginName}' is already registered.`);
|
|
68
|
+
}
|
|
69
|
+
const listener = function(pEvent) {
|
|
70
|
+
Kit.emit(pEvent);
|
|
71
|
+
};
|
|
72
|
+
const emitter = new EventEmitter(listener, plugin);
|
|
73
|
+
Kit.emitters.set(pluginName, emitter);
|
|
74
|
+
Kit.plugins[pluginName] = plugin;
|
|
75
|
+
plugin._register(emitter);
|
|
76
|
+
plugin.onRegistered();
|
|
77
|
+
return plugin;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
static getPlugin(pName) {
|
|
81
|
+
const plugin = Kit.plugins[pName];
|
|
82
|
+
if (!plugin) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
return plugin;
|
|
86
|
+
}
|
|
87
|
+
static getPlugins() {
|
|
88
|
+
return Object.keys(Kit.plugins);
|
|
89
|
+
}
|
|
90
|
+
static emit(pEvent) {
|
|
91
|
+
const { plugin, event } = pEvent;
|
|
92
|
+
const eventScope = `${plugin}-${event}`;
|
|
93
|
+
if (!Kit.events[eventScope]) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
Kit.events[eventScope].forEach((pListener) => pListener(pEvent));
|
|
97
|
+
}
|
|
98
|
+
static on(pPluginName, pEventName, pListener) {
|
|
99
|
+
const eventScope = `${pPluginName}-${pEventName}`;
|
|
100
|
+
if (!Kit.events[eventScope]) {
|
|
101
|
+
Kit.events[eventScope] = [];
|
|
102
|
+
}
|
|
103
|
+
Kit.events[eventScope].push(pListener);
|
|
104
|
+
}
|
|
105
|
+
static off(pPluginName, pEventName, pListener) {
|
|
106
|
+
const eventScope = `${pPluginName}-${pEventName}`;
|
|
107
|
+
if (Kit.events[eventScope].includes(pListener)) {
|
|
108
|
+
Kit.events[eventScope].splice(Kit.events[eventScope].indexOf(pListener), 1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
static setResource(pData) {
|
|
112
|
+
pData.forEach((pResource) => {
|
|
113
|
+
const extensionMatch = pResource.fileName.match(/\.[^.]+$/);
|
|
114
|
+
const fileNameWithoutExtensionMatch = pResource.fileName.match(/(.+?)(?=\.[^.]+$|$)/);
|
|
115
|
+
if (extensionMatch && fileNameWithoutExtensionMatch) {
|
|
116
|
+
const extension = extensionMatch[0];
|
|
117
|
+
const fileNameWithoutExtension = fileNameWithoutExtensionMatch[0];
|
|
118
|
+
const resourceType = extensionToPath[extension];
|
|
119
|
+
if (resourceType) {
|
|
120
|
+
globalThis.VYLO.Resource.setResource(resourceType, fileNameWithoutExtension, `${pResource.resourceIdentifier}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
static async setResources(pResourceJson) {
|
|
126
|
+
if (!globalThis.VYLO) {
|
|
127
|
+
throw new Error("[Kit] VYLO is not defined. Please ensure the VYLO variable is available in the global namespace.");
|
|
128
|
+
}
|
|
129
|
+
if (pResourceJson) {
|
|
130
|
+
const resources = Object.values(pResourceJson);
|
|
131
|
+
const consolidatedData = resources.flat();
|
|
132
|
+
this.setResource(consolidatedData);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// node_modules/@evitcastudio/kit/lib/plugins/kit-plugin.js
|
|
137
|
+
class KitPlugin {
|
|
138
|
+
_emitter = null;
|
|
139
|
+
_register(pEmitter) {
|
|
140
|
+
this._emitter = pEmitter;
|
|
141
|
+
}
|
|
142
|
+
emit(pEvent) {
|
|
143
|
+
if (!this._emitter) {
|
|
144
|
+
console.error("[Kit Plugin] emitter not set. This is an indication that the plugin is not registered.");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
this._emitter.emit(pEvent);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// node_modules/@evitcastudio/kit/lib/plugins/network/index.js
|
|
151
|
+
class Network extends KitPlugin {
|
|
152
|
+
name = "Network";
|
|
153
|
+
initiated = false;
|
|
154
|
+
packets = new Map;
|
|
155
|
+
reversedPacketMap = new Map;
|
|
156
|
+
onRegistered() {
|
|
157
|
+
this.initiated = true;
|
|
158
|
+
}
|
|
159
|
+
listeners = new Map;
|
|
160
|
+
onPacket(pPacketName, pListener) {
|
|
161
|
+
if (!this.packets.has(pPacketName)) {
|
|
162
|
+
throw new Error(`Packet name '${pPacketName}' is not registered.`);
|
|
163
|
+
}
|
|
164
|
+
this.listeners.set(pPacketName, pListener);
|
|
165
|
+
}
|
|
166
|
+
on(pPacketName, pListener) {
|
|
167
|
+
this.onPacket(pPacketName, pListener);
|
|
168
|
+
}
|
|
169
|
+
onNetwork(pClient, pPacketName, pData = [], pVerbose) {
|
|
170
|
+
if (!this.initiated)
|
|
171
|
+
return;
|
|
172
|
+
if (typeof pPacketName === "number") {
|
|
173
|
+
const packetName = this.reversedPacketMap.get(pPacketName);
|
|
174
|
+
if (!packetName) {
|
|
175
|
+
if (pVerbose) {
|
|
176
|
+
console.group(`Kit.${this.name}Plugin.onNetwork`);
|
|
177
|
+
console.warn(`Unknown packet index: ${pPacketName}`);
|
|
178
|
+
console.groupEnd();
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const listener = this.listeners.get(packetName);
|
|
183
|
+
if (pVerbose) {
|
|
184
|
+
console.group(`Kit.${this.name}Plugin.onNetwork`);
|
|
185
|
+
if (!listener) {
|
|
186
|
+
console.warn(`No listener was registered for this packet: ${packetName}`);
|
|
187
|
+
}
|
|
188
|
+
console.log(`Packet name: ${pPacketName}`);
|
|
189
|
+
console.log(`Resolved packet name: ${packetName}`);
|
|
190
|
+
console.log(`Data:`, pData);
|
|
191
|
+
console.groupEnd();
|
|
192
|
+
}
|
|
193
|
+
listener?.(pClient, ...pData);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
registerPackets(pPackets) {
|
|
197
|
+
this.packets.clear();
|
|
198
|
+
this.reversedPacketMap.clear();
|
|
199
|
+
pPackets.forEach((name, index) => {
|
|
200
|
+
this.packets.set(name, index);
|
|
201
|
+
this.reversedPacketMap.set(index, name);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
getPacket(pPacketName) {
|
|
205
|
+
const packet = this.packets.get(pPacketName);
|
|
206
|
+
if (packet === undefined) {
|
|
207
|
+
console.warn(`Packet '${pPacketName}' is not registered.`);
|
|
208
|
+
}
|
|
209
|
+
return packet;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// kit-game-templates/multi/src/map-types.ts
|
|
213
|
+
VYLO.setType("Tile", {
|
|
214
|
+
atlasName: "default-atlas",
|
|
215
|
+
iconName: "cobble"
|
|
216
|
+
});
|
|
217
|
+
VYLO.setType("Mob/Player", {
|
|
218
|
+
atlasName: "default-atlas",
|
|
219
|
+
iconName: "player"
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// kit-game-templates/multi/src/client/packets/s-packets.ts
|
|
223
|
+
var serverPackets = [
|
|
224
|
+
"SERVER_EXAMPLE1_PACKET",
|
|
225
|
+
"SERVER_EXAMPLE2_PACKET",
|
|
226
|
+
"SERVER_EXAMPLE3_PACKET"
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
// kit-game-templates/multi/src/client/c-network.ts
|
|
230
|
+
Kit.registerPlugin(Network);
|
|
231
|
+
var networkPlugin = Kit.getPlugin("Network");
|
|
232
|
+
if (!networkPlugin) {
|
|
233
|
+
throw new Error("Network plugin not found.");
|
|
234
|
+
}
|
|
235
|
+
networkPlugin.registerPackets(serverPackets);
|
|
236
|
+
networkPlugin.on("SERVER_EXAMPLE3_PACKET", (pClient, pData, pData2, pData3) => {
|
|
237
|
+
console.log("data", pData, pData2, pData3);
|
|
238
|
+
});
|
|
239
|
+
VYLO.setType("Client", {
|
|
240
|
+
onPacket(pPacketName, pData) {
|
|
241
|
+
networkPlugin?.onNetwork(this, pPacketName, pData, true);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
// kit-game-templates/multi/resource.json
|
|
245
|
+
var resource_default = {
|
|
246
|
+
interface: [],
|
|
247
|
+
icon: [],
|
|
248
|
+
map: [],
|
|
249
|
+
sound: [],
|
|
250
|
+
macros: []
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// kit-game-templates/multi/src/client/index.ts
|
|
254
|
+
await Kit.setResources(resource_default);
|
|
255
|
+
var networkPlugin2 = Kit.getPlugin("Network");
|
|
256
|
+
VYLO.setType("World", {
|
|
257
|
+
onNew() {
|
|
258
|
+
console.log("World created.");
|
|
259
|
+
},
|
|
260
|
+
onMapLoaded(pName) {
|
|
261
|
+
console.log(`'${pName}' map loaded.`);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
VYLO.setType("Client", {
|
|
265
|
+
mainOutput: "",
|
|
266
|
+
maxFPS: 0,
|
|
267
|
+
hideFPS: false,
|
|
268
|
+
screenView: {
|
|
269
|
+
scaleTo: "normal",
|
|
270
|
+
scaleNearest: true,
|
|
271
|
+
disableImageSmoothing: true
|
|
272
|
+
},
|
|
273
|
+
onConnect() {
|
|
274
|
+
console.log("onConnect");
|
|
275
|
+
this.sendPacket(networkPlugin2?.getPacket("SERVER_EXAMPLE2_PACKET"), [1, 2, 3]);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
VYLO.setType("Mob/Player", {
|
|
279
|
+
onLogin() {
|
|
280
|
+
console.log("onLogin");
|
|
281
|
+
},
|
|
282
|
+
onLogout() {
|
|
283
|
+
console.log("onLogout");
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
await VYLO.load();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-bundler.d.ts","sourceRoot":"","sources":["../../src/cli/app-bundler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-bundler.d.ts","sourceRoot":"","sources":["../../src/cli/app-bundler.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,YAAY,EAAE,mBAAmB,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAYvE;AA+DD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA2OhI"}
|
package/lib/cli/app-bundler.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { promises as fs, existsSync } from 'node:fs';
|
|
2
|
-
import { join, dirname, extname } from 'node:path';
|
|
2
|
+
import { join, dirname, extname, resolve } from 'node:path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import Bun from 'bun';
|
|
5
|
+
import { theme } from './theme';
|
|
5
6
|
/**
|
|
6
7
|
* Detects the project architecture based on existing entrypoints in the source directory.
|
|
7
8
|
* @param pSrcDir - Path to the project's source directory.
|
|
@@ -123,6 +124,7 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
123
124
|
const startStamp = Date.now();
|
|
124
125
|
const clientResult = await Bun.build({
|
|
125
126
|
entrypoints: [join(srcDir, 'index.ts')],
|
|
127
|
+
root: pProjectRoot,
|
|
126
128
|
naming: {
|
|
127
129
|
entry: 'index.[ext]',
|
|
128
130
|
chunk: '[name]-[hash].[ext]',
|
|
@@ -136,7 +138,21 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
136
138
|
identifiers: shouldObfuscate,
|
|
137
139
|
syntax: true,
|
|
138
140
|
whitespace: true
|
|
139
|
-
} : false
|
|
141
|
+
} : false,
|
|
142
|
+
plugins: [
|
|
143
|
+
{
|
|
144
|
+
name: 'kit-project-resolver',
|
|
145
|
+
setup(build) {
|
|
146
|
+
build.onResolve({ filter: /^resource\.json$/ }, () => {
|
|
147
|
+
const resourcePath = resolve(pProjectRoot, 'resource.json');
|
|
148
|
+
if (existsSync(resourcePath)) {
|
|
149
|
+
return { path: resourcePath };
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
]
|
|
140
156
|
});
|
|
141
157
|
if (!clientResult.success) {
|
|
142
158
|
console.error(clientResult.logs);
|
|
@@ -153,7 +169,7 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
153
169
|
}
|
|
154
170
|
const elapsed = Date.now() - startStamp;
|
|
155
171
|
if (isVerbose) {
|
|
156
|
-
console.log(
|
|
172
|
+
console.log(theme.info(`[Kit CLI] Singleplayer Client Build took: ${elapsed}ms`));
|
|
157
173
|
}
|
|
158
174
|
return { architecture: 'single', clientBuildTime: elapsed, success: true };
|
|
159
175
|
}
|
|
@@ -166,6 +182,7 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
166
182
|
const clientStart = Date.now();
|
|
167
183
|
const clientResult = await Bun.build({
|
|
168
184
|
entrypoints: [clientEntry],
|
|
185
|
+
root: pProjectRoot,
|
|
169
186
|
naming: {
|
|
170
187
|
entry: 'index.[ext]',
|
|
171
188
|
chunk: '[name]-[hash].[ext]',
|
|
@@ -179,7 +196,21 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
179
196
|
identifiers: shouldObfuscate,
|
|
180
197
|
syntax: true,
|
|
181
198
|
whitespace: true
|
|
182
|
-
} : false
|
|
199
|
+
} : false,
|
|
200
|
+
plugins: [
|
|
201
|
+
{
|
|
202
|
+
name: 'kit-project-resolver',
|
|
203
|
+
setup(build) {
|
|
204
|
+
build.onResolve({ filter: /^resource\.json$/ }, () => {
|
|
205
|
+
const resourcePath = resolve(pProjectRoot, 'resource.json');
|
|
206
|
+
if (existsSync(resourcePath)) {
|
|
207
|
+
return { path: resourcePath };
|
|
208
|
+
}
|
|
209
|
+
return undefined;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
]
|
|
183
214
|
});
|
|
184
215
|
if (!clientResult.success) {
|
|
185
216
|
console.error(clientResult.logs);
|
|
@@ -197,6 +228,7 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
197
228
|
const serverStart = Date.now();
|
|
198
229
|
const serverResult = await Bun.build({
|
|
199
230
|
entrypoints: [serverEntry],
|
|
231
|
+
root: pProjectRoot,
|
|
200
232
|
naming: {
|
|
201
233
|
entry: 'server.[ext]',
|
|
202
234
|
chunk: '[name]-[hash].[ext]',
|
|
@@ -210,7 +242,21 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
210
242
|
identifiers: shouldObfuscate,
|
|
211
243
|
syntax: true,
|
|
212
244
|
whitespace: true
|
|
213
|
-
} : false
|
|
245
|
+
} : false,
|
|
246
|
+
plugins: [
|
|
247
|
+
{
|
|
248
|
+
name: 'kit-project-resolver',
|
|
249
|
+
setup(build) {
|
|
250
|
+
build.onResolve({ filter: /^resource\.json$/ }, () => {
|
|
251
|
+
const resourcePath = resolve(pProjectRoot, 'resource.json');
|
|
252
|
+
if (existsSync(resourcePath)) {
|
|
253
|
+
return { path: resourcePath };
|
|
254
|
+
}
|
|
255
|
+
return undefined;
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
]
|
|
214
260
|
});
|
|
215
261
|
if (!serverResult.success) {
|
|
216
262
|
console.error(serverResult.logs);
|
|
@@ -228,10 +274,10 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
228
274
|
}
|
|
229
275
|
if (isVerbose) {
|
|
230
276
|
if (clientElapsed) {
|
|
231
|
-
console.log(
|
|
277
|
+
console.log(theme.info(`[Kit CLI] Multiplayer Client Build took: ${clientElapsed}ms`));
|
|
232
278
|
}
|
|
233
279
|
if (serverElapsed) {
|
|
234
|
-
console.log(
|
|
280
|
+
console.log(theme.info(`[Kit CLI] Multiplayer Server Build took: ${serverElapsed}ms`));
|
|
235
281
|
}
|
|
236
282
|
}
|
|
237
283
|
return {
|
|
@@ -244,7 +290,13 @@ export async function bundleApp(pProjectRoot, pOutDir, pOptions = {}) {
|
|
|
244
290
|
return { architecture: 'none', success: true };
|
|
245
291
|
}
|
|
246
292
|
catch (pError) {
|
|
247
|
-
console.error(
|
|
293
|
+
console.error(theme.error(`[Kit CLI Build Error] ${pError}`));
|
|
294
|
+
if (pError?.logs) {
|
|
295
|
+
console.error(pError.logs);
|
|
296
|
+
}
|
|
297
|
+
else if (pError?.errors) {
|
|
298
|
+
console.error(pError.errors);
|
|
299
|
+
}
|
|
248
300
|
return { architecture, success: false };
|
|
249
301
|
}
|
|
250
302
|
}
|
package/lib/cli/create.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/cli/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/cli/create.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAkDD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C1E"}
|
package/lib/cli/create.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import { theme } from './theme';
|
|
4
5
|
/**
|
|
5
6
|
* Formats a given name into a PascalCase class name.
|
|
6
7
|
* @param pName - Raw identifier input.
|
|
@@ -53,12 +54,12 @@ export class ${pClassName} extends KitPlugin {
|
|
|
53
54
|
export async function processCreate(pOptions) {
|
|
54
55
|
const { type, name, verbose } = pOptions;
|
|
55
56
|
if (!type || !name) {
|
|
56
|
-
console.error(
|
|
57
|
+
console.error(theme.error('\nError: Both type and name are required. Usage: kit create <type> <name>'));
|
|
57
58
|
process.exit(1);
|
|
58
59
|
}
|
|
59
60
|
const normalizedType = type.toLowerCase();
|
|
60
61
|
if (normalizedType !== 'plugin') {
|
|
61
|
-
console.error(
|
|
62
|
+
console.error(theme.error(`\nError: Unknown create type '${type}'. Supported types: 'plugin'`));
|
|
62
63
|
process.exit(1);
|
|
63
64
|
}
|
|
64
65
|
const className = toPascalCase(name);
|
|
@@ -70,19 +71,19 @@ export async function processCreate(pOptions) {
|
|
|
70
71
|
await fs.mkdir(pluginsDir, { recursive: true });
|
|
71
72
|
const fileExists = await fs.stat(targetPath).then(() => true).catch(() => false);
|
|
72
73
|
if (fileExists) {
|
|
73
|
-
console.error(
|
|
74
|
+
console.error(theme.error(`\nError: File already exists at ${targetPath}`));
|
|
74
75
|
process.exit(1);
|
|
75
76
|
}
|
|
76
77
|
const sourceCode = generatePluginSource(className, className);
|
|
77
78
|
await fs.writeFile(targetPath, sourceCode, 'utf8');
|
|
78
|
-
console.log(`\n ${
|
|
79
|
+
console.log(`\n ${theme.successIcon('✓')} Created plugin ${theme.brandBold(className)} at ${theme.secondary(targetPath)}\n`);
|
|
79
80
|
if (verbose) {
|
|
80
|
-
console.log(
|
|
81
|
+
console.log(theme.secondary(sourceCode));
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
catch (pError) {
|
|
84
85
|
const message = pError instanceof Error ? pError.message : String(pError);
|
|
85
|
-
console.error(
|
|
86
|
+
console.error(theme.error(`\nError creating plugin: ${message}`));
|
|
86
87
|
process.exit(1);
|
|
87
88
|
}
|
|
88
89
|
}
|
package/lib/cli/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAUD;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,GAAE,aAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0MlF"}
|
package/lib/cli/doctor.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
|
+
import { theme } from './theme';
|
|
5
6
|
/**
|
|
6
7
|
* Runs diagnostics on the local development environment and project health.
|
|
7
8
|
* @param pOptions - Options passed from the CLI.
|
|
@@ -9,24 +10,34 @@ import chalk from 'chalk';
|
|
|
9
10
|
export async function processDoctor(pOptions = {}) {
|
|
10
11
|
const isVerbose = Boolean(pOptions.verbose);
|
|
11
12
|
const results = [];
|
|
12
|
-
console.log(`\n ${
|
|
13
|
+
console.log(`\n ${theme.brandBold('Kit Doctor')} ${chalk.dim('-')} Environment & Project Health Check\n`);
|
|
13
14
|
// 1. Runtime Check: Bun
|
|
14
|
-
|
|
15
|
-
if (!bunCheck.error && bunCheck.status === 0) {
|
|
15
|
+
if (typeof Bun !== 'undefined') {
|
|
16
16
|
results.push({
|
|
17
17
|
category: 'Runtime',
|
|
18
18
|
title: 'Bun Runtime',
|
|
19
19
|
passed: true,
|
|
20
|
-
details: `
|
|
20
|
+
details: `v${Bun.version}`
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
const bunCheck = spawnSync('bun', ['--version'], { encoding: 'utf8', shell: true });
|
|
25
|
+
if (!bunCheck.error && bunCheck.status === 0) {
|
|
26
|
+
results.push({
|
|
27
|
+
category: 'Runtime',
|
|
28
|
+
title: 'Bun Runtime',
|
|
29
|
+
passed: true,
|
|
30
|
+
details: `v${bunCheck.stdout.trim()}`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
results.push({
|
|
35
|
+
category: 'Runtime',
|
|
36
|
+
title: 'Bun Runtime',
|
|
37
|
+
passed: false,
|
|
38
|
+
details: 'Bun is not installed or not in PATH. Download at https://bun.sh/'
|
|
39
|
+
});
|
|
40
|
+
}
|
|
30
41
|
}
|
|
31
42
|
// 2. Version Control Check: Git
|
|
32
43
|
const gitCheck = spawnSync('git', ['--version'], { encoding: 'utf8', shell: true });
|
|
@@ -54,33 +65,48 @@ export async function processDoctor(pOptions = {}) {
|
|
|
54
65
|
try {
|
|
55
66
|
const rawPkg = readFileSync(pkgPath, 'utf8');
|
|
56
67
|
const pkg = JSON.parse(rawPkg);
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
pkg.
|
|
68
|
+
const isKitCoreRepo = pkg.name === '@evitcastudio/kit';
|
|
69
|
+
const kitVersionSpec = pkg.dependencies?.['@evitcastudio/kit'] ||
|
|
70
|
+
pkg.devDependencies?.['@evitcastudio/kit'];
|
|
71
|
+
const hasKitDependency = Boolean(kitVersionSpec || isKitCoreRepo);
|
|
60
72
|
results.push({
|
|
61
73
|
category: 'Project',
|
|
62
74
|
title: 'package.json configuration',
|
|
63
75
|
passed: true,
|
|
64
|
-
details:
|
|
76
|
+
details: `${pkg.name || 'unnamed'}${pkg.version ? ` v${pkg.version}` : ''}`
|
|
65
77
|
});
|
|
78
|
+
let kitDependencyDetails = 'Missing @evitcastudio/kit dependency in package.json';
|
|
79
|
+
if (isKitCoreRepo) {
|
|
80
|
+
kitDependencyDetails = 'Core Framework Repository';
|
|
81
|
+
}
|
|
82
|
+
else if (kitVersionSpec) {
|
|
83
|
+
kitDependencyDetails = `@evitcastudio/kit: ${kitVersionSpec}`;
|
|
84
|
+
}
|
|
66
85
|
results.push({
|
|
67
86
|
category: 'Project',
|
|
68
87
|
title: 'Kit framework dependency',
|
|
69
88
|
passed: hasKitDependency,
|
|
70
|
-
details:
|
|
71
|
-
? 'Found @evitcastudio/kit in project configuration'
|
|
72
|
-
: 'Missing @evitcastudio/kit dependency in package.json'
|
|
89
|
+
details: kitDependencyDetails
|
|
73
90
|
});
|
|
74
91
|
// If running inside a consumer game project, check game asset directory structure
|
|
75
|
-
const isKitCoreRepo = pkg.name === '@evitcastudio/kit';
|
|
76
92
|
if (!isKitCoreRepo) {
|
|
77
93
|
const resourcesDir = join(cwd, 'src', 'resources');
|
|
78
94
|
const hasResources = existsSync(resourcesDir);
|
|
95
|
+
let assetDetails = 'src/resources directory not found';
|
|
96
|
+
if (hasResources) {
|
|
97
|
+
try {
|
|
98
|
+
const items = readdirSync(resourcesDir, { recursive: true });
|
|
99
|
+
assetDetails = `Ready (${items.length} asset${items.length === 1 ? '' : 's'})`;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
assetDetails = 'Asset directory present';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
79
105
|
results.push({
|
|
80
106
|
category: 'Project',
|
|
81
107
|
title: 'Asset Directory (src/resources)',
|
|
82
108
|
passed: hasResources,
|
|
83
|
-
details:
|
|
109
|
+
details: assetDetails
|
|
84
110
|
});
|
|
85
111
|
}
|
|
86
112
|
// Detect project type (multiplayer vs single-player)
|
|
@@ -132,13 +158,13 @@ export async function processDoctor(pOptions = {}) {
|
|
|
132
158
|
const buildPipelinePassed = hasBuildScript || hasKitBuildScript;
|
|
133
159
|
let buildDetails = 'No build pipeline configured';
|
|
134
160
|
if (hasKitBuildScript && hasBuildScript) {
|
|
135
|
-
buildDetails = '
|
|
161
|
+
buildDetails = 'Native CLI build ("kit build") + bun-build.ts';
|
|
136
162
|
}
|
|
137
163
|
else if (hasKitBuildScript) {
|
|
138
|
-
buildDetails = '
|
|
164
|
+
buildDetails = 'Native CLI build ("kit build")';
|
|
139
165
|
}
|
|
140
166
|
else if (hasBuildScript) {
|
|
141
|
-
buildDetails = 'Legacy bun-build.ts
|
|
167
|
+
buildDetails = 'Legacy build script (bun-build.ts)';
|
|
142
168
|
}
|
|
143
169
|
results.push({
|
|
144
170
|
category: 'Project',
|
|
@@ -158,11 +184,12 @@ export async function processDoctor(pOptions = {}) {
|
|
|
158
184
|
// Render results
|
|
159
185
|
let allPassed = true;
|
|
160
186
|
for (const res of results) {
|
|
161
|
-
const icon = res.passed ?
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
187
|
+
const icon = res.passed ? theme.successIcon('✓') : theme.error('✗');
|
|
188
|
+
const categoryBadge = `${theme.bracket('[')}${theme.brandBold(res.category)}${theme.bracket(']')}`;
|
|
189
|
+
const titleText = res.passed ? theme.title(res.title) : theme.error(res.title);
|
|
190
|
+
console.log(` ${icon} ${categoryBadge} ${titleText}`);
|
|
191
|
+
if (res.details) {
|
|
192
|
+
console.log(` ${theme.secondary(res.details)}`);
|
|
166
193
|
}
|
|
167
194
|
if (!res.passed) {
|
|
168
195
|
allPassed = false;
|
|
@@ -170,10 +197,10 @@ export async function processDoctor(pOptions = {}) {
|
|
|
170
197
|
}
|
|
171
198
|
console.log('\n');
|
|
172
199
|
if (allPassed) {
|
|
173
|
-
console.log(` ${
|
|
200
|
+
console.log(` ${theme.successIcon('✔')} ${theme.brandBold('All doctor diagnostics passed!')}\n`);
|
|
174
201
|
}
|
|
175
202
|
else {
|
|
176
|
-
console.log(` ${
|
|
203
|
+
console.log(` ${theme.warning('▲ Some issues were detected. Check the items above.')}\n`);
|
|
177
204
|
}
|
|
178
205
|
return allPassed;
|
|
179
206
|
}
|
package/lib/cli/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/cli/host.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/cli/host.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,MAAM,CAAC,EAAE;QAAE,IAAI,IAAI,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAoBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,QAAQ,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAuHjF"}
|