@directivegames/genesys.sdk 3.2.2

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 (181) hide show
  1. package/README.md +60 -0
  2. package/dist/src/asset-pack/eslint.config.js +43 -0
  3. package/dist/src/asset-pack/scripts/postinstall.js +64 -0
  4. package/dist/src/asset-pack/src/index.js +1 -0
  5. package/dist/src/core/cli.js +306 -0
  6. package/dist/src/core/common.js +324 -0
  7. package/dist/src/core/index.js +6 -0
  8. package/dist/src/core/tools/build-project.js +450 -0
  9. package/dist/src/core/tools/index.js +2 -0
  10. package/dist/src/core/tools/new-asset-pack.js +150 -0
  11. package/dist/src/core/tools/new-project.js +292 -0
  12. package/dist/src/core/types.js +1 -0
  13. package/dist/src/dependencies.js +82 -0
  14. package/dist/src/electron/IpcSerializableError.js +38 -0
  15. package/dist/src/electron/api.js +7 -0
  16. package/dist/src/electron/backend/actions.js +56 -0
  17. package/dist/src/electron/backend/handler.js +441 -0
  18. package/dist/src/electron/backend/logging.js +41 -0
  19. package/dist/src/electron/backend/main.js +315 -0
  20. package/dist/src/electron/backend/menu.js +208 -0
  21. package/dist/src/electron/backend/state.js +201 -0
  22. package/dist/src/electron/backend/tools/const.js +9 -0
  23. package/dist/src/electron/backend/tools/file-server.js +383 -0
  24. package/dist/src/electron/backend/tools/open-project.js +261 -0
  25. package/dist/src/electron/backend/window.js +161 -0
  26. package/dist/src/templates/eslint.config.js +43 -0
  27. package/dist/src/templates/scripts/genesys/build-project.js +42 -0
  28. package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
  29. package/dist/src/templates/scripts/genesys/common.js +36 -0
  30. package/dist/src/templates/scripts/genesys/const.js +9 -0
  31. package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
  32. package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
  33. package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
  34. package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
  35. package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
  36. package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
  37. package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
  38. package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
  39. package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
  40. package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
  41. package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
  42. package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
  43. package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
  44. package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
  45. package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
  46. package/dist/src/templates/scripts/genesys/misc.js +32 -0
  47. package/dist/src/templates/scripts/genesys/mock.js +5 -0
  48. package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
  49. package/dist/src/templates/scripts/genesys/post-install.js +25 -0
  50. package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
  51. package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
  52. package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
  53. package/dist/src/templates/src/index.js +20 -0
  54. package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
  55. package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
  56. package/dist/src/templates/src/templates/firstPerson/src/player.js +60 -0
  57. package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
  58. package/dist/src/templates/src/templates/fps/src/game.js +30 -0
  59. package/dist/src/templates/src/templates/fps/src/player.js +64 -0
  60. package/dist/src/templates/src/templates/fps/src/weapon.js +62 -0
  61. package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
  62. package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
  63. package/dist/src/templates/src/templates/freeCamera/src/player.js +43 -0
  64. package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
  65. package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
  66. package/dist/src/templates/src/templates/sideScroller/src/game.js +103 -0
  67. package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
  68. package/dist/src/templates/src/templates/sideScroller/src/player.js +105 -0
  69. package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
  70. package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
  71. package/dist/src/templates/src/templates/thirdPerson/src/player.js +63 -0
  72. package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
  73. package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
  74. package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
  75. package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +189 -0
  76. package/dist/src/templates/src/templates/vehicle/src/player.js +102 -0
  77. package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +259 -0
  78. package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
  79. package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
  80. package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
  81. package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
  82. package/dist/src/templates/vite.config.js +46 -0
  83. package/package.json +176 -0
  84. package/scripts/post-install.ts +143 -0
  85. package/src/asset-pack/.gitattributes +89 -0
  86. package/src/asset-pack/eslint.config.js +45 -0
  87. package/src/asset-pack/gitignore +11 -0
  88. package/src/asset-pack/scripts/postinstall.ts +81 -0
  89. package/src/asset-pack/src/index.ts +0 -0
  90. package/src/asset-pack/tsconfig.json +34 -0
  91. package/src/templates/.cursor/mcp.json +20 -0
  92. package/src/templates/.cursorignore +2 -0
  93. package/src/templates/.gitattributes +89 -0
  94. package/src/templates/.vscode/settings.json +6 -0
  95. package/src/templates/AGENTS.md +86 -0
  96. package/src/templates/CLAUDE.md +1 -0
  97. package/src/templates/README.md +24 -0
  98. package/src/templates/eslint.config.js +45 -0
  99. package/src/templates/gitignore +11 -0
  100. package/src/templates/index.html +34 -0
  101. package/src/templates/pnpm-lock.yaml +3676 -0
  102. package/src/templates/scripts/genesys/build-project.ts +51 -0
  103. package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
  104. package/src/templates/scripts/genesys/common.ts +46 -0
  105. package/src/templates/scripts/genesys/const.ts +9 -0
  106. package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
  107. package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
  108. package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
  109. package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
  110. package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
  111. package/src/templates/scripts/genesys/doc-server.ts +16 -0
  112. package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
  113. package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
  114. package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
  115. package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
  116. package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
  117. package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
  118. package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
  119. package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
  120. package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
  121. package/src/templates/scripts/genesys/misc.ts +42 -0
  122. package/src/templates/scripts/genesys/mock.ts +6 -0
  123. package/src/templates/scripts/genesys/place-actors.ts +179 -0
  124. package/src/templates/scripts/genesys/post-install.ts +30 -0
  125. package/src/templates/scripts/genesys/prefab.schema.json +85 -0
  126. package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
  127. package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
  128. package/src/templates/scripts/genesys/storageProvider.ts +182 -0
  129. package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
  130. package/src/templates/src/index.ts +22 -0
  131. package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
  132. package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
  133. package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
  134. package/src/templates/src/templates/firstPerson/src/player.ts +63 -0
  135. package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
  136. package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
  137. package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
  138. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
  139. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
  140. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
  141. package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
  142. package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
  143. package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
  144. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
  145. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
  146. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
  147. package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
  148. package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
  149. package/src/templates/src/templates/fps/src/game.ts +39 -0
  150. package/src/templates/src/templates/fps/src/player.ts +69 -0
  151. package/src/templates/src/templates/fps/src/weapon.ts +54 -0
  152. package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
  153. package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
  154. package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
  155. package/src/templates/src/templates/freeCamera/src/player.ts +45 -0
  156. package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
  157. package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
  158. package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
  159. package/src/templates/src/templates/sideScroller/src/game.ts +122 -0
  160. package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
  161. package/src/templates/src/templates/sideScroller/src/player.ts +125 -0
  162. package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
  163. package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
  164. package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
  165. package/src/templates/src/templates/thirdPerson/src/player.ts +61 -0
  166. package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
  167. package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
  168. package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
  169. package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
  170. package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
  171. package/src/templates/src/templates/vehicle/src/game.ts +43 -0
  172. package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -0
  173. package/src/templates/src/templates/vehicle/src/player.ts +109 -0
  174. package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -0
  175. package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
  176. package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
  177. package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
  178. package/src/templates/src/templates/vr-game/src/game.ts +66 -0
  179. package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
  180. package/src/templates/tsconfig.json +35 -0
  181. package/src/templates/vite.config.ts +52 -0
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ [![CI](https://github.com/directivegames/genesys.sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/directivegames/genesys.sdk/actions/workflows/ci.yml)
2
+ [![Publish](https://github.com/directivegames/genesys.sdk/actions/workflows/publish.yml/badge.svg)](https://github.com/directivegames/genesys.sdk/actions/workflows/publish.yml)
3
+
4
+ ![Version](https://gist.githubusercontent.com/haowang1013/d024d16ac57a7bfd7038ae32bf239d07/raw/genesys.sdk.svg)
5
+
6
+ # User Workflow
7
+ - Download and install the latest version from the [Release](https://github.com/directivegames/genesys.sdk/releases) page.
8
+ - Create an empty folder on your disk to store the project.
9
+ - Open the empty folder created earlier in this app, select a template and create a project, then start the file server.
10
+ - Launch the web editor and cursor to develop.
11
+
12
+ # Developer
13
+
14
+ ## Run Locally
15
+ - `pnpm install`
16
+ - `pnpm dev`: to run the dev version, connects to localhost:3000 if available
17
+ - run `pnpm dev` on [genesys.ai](https://github.com/directivegames/genesys.ai) to start localhost:3000
18
+ - if localhost:3000 is started after the sdk, refresh the sdk with Ctrl+R/Ctrl+Shift+R
19
+ - `pnpm dev:watch`: same as `pnpm dev` but with auto-restart on file changes using nodemon
20
+ - `pnpm dev:hosted`: connects to the hosted genesys.ai site.
21
+ - `pnpm dist`: to build the app locally. Installer will be generated in the `dist` folder that you can use to install the app directly on your machine.
22
+
23
+ ## CLI Tools
24
+ The SDK includes command-line tools for creating and building projects without launching the GUI.
25
+
26
+ ### Available Commands
27
+ ```bash
28
+ # Show help and available commands
29
+ genesys-sdk --help
30
+
31
+ # Show version
32
+ genesys-sdk --version
33
+
34
+ # Create a new project
35
+ genesys-sdk new -n <project-name> -t <template-id> [-p <parent-path>]
36
+
37
+ # Build an existing project (with TypeScript type checking)
38
+ genesys-sdk build [-p <project-path>]
39
+
40
+ # Build without type checking (faster)
41
+ genesys-sdk build [-p <project-path>] --no-tsc
42
+
43
+ # List available project templates
44
+ genesys-sdk list-templates
45
+ ```
46
+
47
+ ## New Project Template
48
+ - The logic to setup a new project is in [new-project.ts](src/backend/tools//new-project.ts), it contains a few steps:
49
+ - Generate `game.ts` and `default.genesys-scene` based on the selected template.
50
+ - Generate `package.json` and `{project}.code-workspace` from code.
51
+ - Copy the files from `assets/new-project` to the project folder.
52
+ - Run `pnpm install` and `pnpm build` in the project folder.
53
+
54
+ ## Add Electron API
55
+ Electron API is for exposing code that relies on the nodejs environment to the frontend environment.
56
+
57
+ To add a new one, following this:
58
+ - Define the API in [api.ts](src/api.ts)
59
+ - Add the API wrapper in [preload.ts](src/preload.ts)
60
+ - Implement the API in [handler.ts](src/backend/handler.ts)
@@ -0,0 +1,43 @@
1
+ import tsParser from '@typescript-eslint/parser';
2
+ import noDefaultClassFields from './node_modules/genesys.js/eslint-rules/no-default-class-fields.js';
3
+ import defaultGetterReturnType from './node_modules/genesys.js/eslint-rules/default-getter-return-type.js';
4
+ import constructorTypeConsistency from './node_modules/genesys.js/eslint-rules/constructor-type-consistency.js';
5
+ import noOverrideMethods from './node_modules/genesys.js/eslint-rules/no-override-methods.js';
6
+ export default [
7
+ {
8
+ ignores: ['dist/**', '.engine/**', 'node_modules/**']
9
+ },
10
+ {
11
+ files: ['**/*.ts', '**/*.tsx'],
12
+ languageOptions: {
13
+ parser: tsParser,
14
+ parserOptions: {
15
+ project: ['./tsconfig.json']
16
+ }
17
+ },
18
+ plugins: {
19
+ 'custom': {
20
+ rules: {
21
+ 'no-override-methods': noOverrideMethods,
22
+ 'no-default-class-fields': noDefaultClassFields,
23
+ 'default-getter-return-type': defaultGetterReturnType,
24
+ 'constructor-type-consistency': constructorTypeConsistency,
25
+ }
26
+ }
27
+ },
28
+ rules: {
29
+ 'custom/no-override-methods': 'error',
30
+ 'custom/no-default-class-fields': 'error',
31
+ 'custom/default-getter-return-type': 'error',
32
+ 'custom/constructor-type-consistency': 'error',
33
+ }
34
+ },
35
+ {
36
+ files: ['games/**/*.ts', 'games/**/*.tsx'],
37
+ rules: {
38
+ 'no-restricted-imports': ['error', {
39
+ patterns: ['../src/**', '!../src/index.js']
40
+ }]
41
+ }
42
+ }
43
+ ];
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ // Get the directory of this script
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ /**
9
+ * Find the parent project root by traversing up from node_modules
10
+ * For pnpm structure like: /project/node_modules/.pnpm/package@version/node_modules/package
11
+ * We want to find: /project
12
+ */
13
+ function findProjectRoot() {
14
+ // Split the current directory path into parts
15
+ const parts = __dirname.split(path.sep);
16
+ // Find the first occurrence of 'node_modules' in the path
17
+ const nodeModulesIndex = parts.indexOf('node_modules');
18
+ if (nodeModulesIndex > 0) {
19
+ // Take everything before 'node_modules' and join it back
20
+ return parts.slice(0, nodeModulesIndex).join(path.sep);
21
+ }
22
+ return null;
23
+ }
24
+ // Only run when installed as a dependency in another project
25
+ // Skip if running in the package's own directory during development
26
+ const isInstalledAsDependency = __dirname.includes('node_modules');
27
+ if (isInstalledAsDependency) {
28
+ try {
29
+ // Read package.json to get the package name
30
+ const packageJsonPath = path.resolve(__dirname, '../../package.json');
31
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
32
+ const packageName = packageJson.name;
33
+ // Source: assets folder in this package
34
+ const sourceAssetsDir = path.resolve(__dirname, '../../assets');
35
+ // Find the parent project root
36
+ const parentProjectRoot = findProjectRoot();
37
+ if (!parentProjectRoot) {
38
+ console.error('Error: Could not find parent project root');
39
+ process.exit(1);
40
+ }
41
+ // Destination: <parent-project>/packs/<package-name>/assets
42
+ const targetPackDir = path.join(parentProjectRoot, 'packs', packageName);
43
+ const targetAssetsDir = path.join(targetPackDir, 'assets');
44
+ // Check if source assets directory exists
45
+ if (fs.existsSync(sourceAssetsDir)) {
46
+ // Delete target directory if it already exists
47
+ if (fs.existsSync(targetPackDir)) {
48
+ fs.rmSync(targetPackDir, { recursive: true, force: true });
49
+ }
50
+ // Create target directory
51
+ fs.mkdirSync(targetPackDir, { recursive: true });
52
+ // Copy entire assets folder
53
+ fs.cpSync(sourceAssetsDir, targetAssetsDir, { recursive: true });
54
+ console.log(`✓ Assets from "${packageName}" copied to: ${path.relative(parentProjectRoot, targetPackDir)}`);
55
+ }
56
+ else {
57
+ console.log(`⚠ No assets folder found in "${packageName}"`);
58
+ }
59
+ }
60
+ catch (error) {
61
+ console.error('Error during postinstall:', error);
62
+ process.exit(1);
63
+ }
64
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from 'fs';
3
+ import path from 'path';
4
+ import { createInterface } from 'readline';
5
+ import { fileURLToPath } from 'url';
6
+ import { Command } from 'commander';
7
+ import { getProjectRoot } from './common.js';
8
+ import { buildProject } from './tools/build-project.js';
9
+ import { newAssetPack } from './tools/new-asset-pack.js';
10
+ import { newProject, TEMPLATES } from './tools/new-project.js';
11
+ // CLI Logger implementation
12
+ class ConsoleLogger {
13
+ getTimestamp() {
14
+ return new Date().toLocaleTimeString('en-US', { hour12: false });
15
+ }
16
+ log(...params) {
17
+ console.log(`[${this.getTimestamp()}] [INFO]`, ...params);
18
+ }
19
+ warn(...params) {
20
+ console.warn(`[${this.getTimestamp()}] [WARN]`, ...params);
21
+ }
22
+ error(...params) {
23
+ console.error(`[${this.getTimestamp()}] [ERROR]`, ...params);
24
+ }
25
+ verbose(...params) {
26
+ if (process.env.VERBOSE) {
27
+ console.log(`[${this.getTimestamp()}] [VERBOSE]`, ...params);
28
+ }
29
+ }
30
+ }
31
+ // Module-level logger instance
32
+ const logger = new ConsoleLogger();
33
+ // CLI Handler implementation (stub for UI/OS interactions)
34
+ class ConsoleHandler {
35
+ ui = {
36
+ async showLoadingOverlay(message) {
37
+ if (message) {
38
+ logger.log(message);
39
+ }
40
+ },
41
+ async showErrorDialog(title, message) {
42
+ logger.error(`${title}: ${message}`);
43
+ }
44
+ };
45
+ os = {
46
+ async openPath(path) {
47
+ logger.log(`Project created at: ${path}`);
48
+ }
49
+ };
50
+ app = {
51
+ isPackaged: false,
52
+ resourcesPath: getProjectRoot()
53
+ };
54
+ }
55
+ function printTemplates() {
56
+ logger.log('\nAvailable Project Templates:\n');
57
+ for (const template of TEMPLATES) {
58
+ logger.log(` ${template.id.padEnd(15)} - ${template.name}`);
59
+ logger.log('');
60
+ }
61
+ }
62
+ // Check if running from an installed package (not local development)
63
+ function isInstalledPackage() {
64
+ try {
65
+ const currentFile = fileURLToPath(import.meta.url);
66
+ return currentFile.includes('node_modules');
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ // Get current package version
73
+ function getCurrentVersion() {
74
+ try {
75
+ const packageJsonPath = path.join(getProjectRoot(), 'package.json');
76
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
77
+ return packageJson.version;
78
+ }
79
+ catch {
80
+ return 'unknown';
81
+ }
82
+ }
83
+ // Check for updates and prompt user
84
+ async function checkForUpdates() {
85
+ try {
86
+ // Only check for updates if running from an installed package
87
+ if (!isInstalledPackage())
88
+ return;
89
+ logger.log('Checking for updates...');
90
+ const currentVersion = getCurrentVersion();
91
+ if (currentVersion === 'unknown')
92
+ return;
93
+ // Fetch latest version from npm registry
94
+ const response = await fetch('https://registry.npmjs.org/genesys.sdk/latest');
95
+ if (!response.ok)
96
+ return;
97
+ const data = await response.json();
98
+ const latestVersion = data.version;
99
+ if (!latestVersion || latestVersion === currentVersion)
100
+ return;
101
+ // Compare versions (simple comparison - assumes semantic versioning)
102
+ if (isNewerVersion(latestVersion, currentVersion)) {
103
+ logger.log('\n' + '='.repeat(60));
104
+ logger.log(`🔔 Update Available: ${currentVersion} -> ${latestVersion}`);
105
+ logger.log('='.repeat(60));
106
+ // Prompt user if they want to upgrade now
107
+ const answer = await promptUser('Would you like to upgrade now? (Y/n): ');
108
+ if (answer === '' || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
109
+ logger.log('\nUpgrading genesys.sdk...\n');
110
+ const { execSync } = await import('child_process');
111
+ const packageName = '@directivegames/genesys.sdk';
112
+ try {
113
+ execSync(`pnpm remove -g ${packageName} && pnpm add -g ${packageName}`, {
114
+ stdio: 'inherit'
115
+ });
116
+ logger.log('\n✅ Upgrade complete! Please run your command again.');
117
+ process.exit(0);
118
+ }
119
+ catch (error) {
120
+ logger.error('\n❌ Upgrade failed. Please run the commands manually.');
121
+ logger.log(` pnpm remove -g ${packageName}`);
122
+ logger.log(` pnpm add -g ${packageName}\n`);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ catch {
128
+ // Silently fail - don't interrupt user workflow with version check errors
129
+ }
130
+ }
131
+ // Compare semantic versions
132
+ function isNewerVersion(latest, current) {
133
+ const latestParts = latest.split('.').map(Number);
134
+ const currentParts = current.split('.').map(Number);
135
+ for (let i = 0; i < 3; i++) {
136
+ const latestPart = latestParts[i] || 0;
137
+ const currentPart = currentParts[i] || 0;
138
+ if (latestPart > currentPart)
139
+ return true;
140
+ if (latestPart < currentPart)
141
+ return false;
142
+ }
143
+ return false;
144
+ }
145
+ // Prompt user for input
146
+ function promptUser(question) {
147
+ const rl = createInterface({
148
+ input: process.stdin,
149
+ output: process.stdout
150
+ });
151
+ return new Promise((resolve) => {
152
+ rl.question(question, (answer) => {
153
+ rl.close();
154
+ resolve(answer.trim());
155
+ });
156
+ });
157
+ }
158
+ async function main() {
159
+ // Check for updates at startup
160
+ await checkForUpdates();
161
+ const program = new Command();
162
+ const handler = new ConsoleHandler();
163
+ const currentVersion = getCurrentVersion();
164
+ program
165
+ .name('genesys-sdk')
166
+ .description('Genesys SDK CLI - Game Project Management Tool')
167
+ .version(currentVersion)
168
+ .option('--verbose', 'Enable verbose logging');
169
+ // New project command
170
+ program
171
+ .command('new')
172
+ .description('Create a new game project')
173
+ .option('-p, --parent-path <path>', 'Parent directory where the project will be created (defaults to current directory)')
174
+ .requiredOption('-n, --name <name>', 'Name of the new project')
175
+ .requiredOption('-t, --template <id>', 'Template ID (use list-templates to see available templates)')
176
+ .action(async (options) => {
177
+ try {
178
+ // Validate template ID
179
+ const template = TEMPLATES.find(t => t.id === options.template);
180
+ if (!template) {
181
+ logger.error(`Error: Invalid template ID "${options.template}"\n`);
182
+ printTemplates();
183
+ process.exit(1);
184
+ }
185
+ const absoluteParentPath = path.resolve(options.parentPath ?? process.cwd());
186
+ logger.log(`Creating new project "${options.name}" with template "${options.template}"...`);
187
+ logger.log(`Parent directory: ${absoluteParentPath}\n`);
188
+ const result = await newProject(absoluteParentPath, options.name, options.template, logger, handler);
189
+ if (result.success) {
190
+ logger.log(`\n✅ ${result.message}`);
191
+ process.exit(0);
192
+ }
193
+ else {
194
+ logger.error(`\n❌ ${result.message}`);
195
+ if (result.error) {
196
+ logger.error(result.error);
197
+ }
198
+ process.exit(1);
199
+ }
200
+ }
201
+ catch (error) {
202
+ logger.error('\n❌ An unexpected error occurred:');
203
+ logger.error(error);
204
+ process.exit(1);
205
+ }
206
+ });
207
+ // Build project command
208
+ program
209
+ .command('build')
210
+ .description('Build an existing game project')
211
+ .option('-p, --path <path>', 'Path to the project to build (defaults to current directory)')
212
+ .option('--no-tsc', 'Skip TypeScript type checking (faster builds)')
213
+ .action(async (options) => {
214
+ try {
215
+ const absoluteProjectPath = path.resolve(options.path ?? process.cwd());
216
+ const runTsc = options.tsc;
217
+ logger.log(`Building project at: ${absoluteProjectPath}`);
218
+ if (!runTsc) {
219
+ logger.log('(Skipping TypeScript type checking)');
220
+ }
221
+ logger.log('');
222
+ const result = await buildProject(absoluteProjectPath, runTsc, logger, handler);
223
+ if (result.success) {
224
+ logger.log(`\n✅ ${result.message}`);
225
+ process.exit(0);
226
+ }
227
+ else {
228
+ logger.error(`\n❌ ${result.message}`);
229
+ if (result.error) {
230
+ logger.error(result.error);
231
+ }
232
+ process.exit(1);
233
+ }
234
+ }
235
+ catch (error) {
236
+ logger.error('\n❌ An unexpected error occurred:');
237
+ logger.error(error);
238
+ process.exit(1);
239
+ }
240
+ });
241
+ // New asset pack command
242
+ program
243
+ .command('new-asset-pack')
244
+ .description('Create a new asset pack')
245
+ .option('-p, --parent-path <path>', 'Parent directory where the asset pack will be created (defaults to current directory)')
246
+ .requiredOption('-n, --name <name>', 'Name of the new asset pack')
247
+ .action(async (options) => {
248
+ try {
249
+ const absoluteParentPath = path.resolve(options.parentPath ?? process.cwd());
250
+ logger.log(`Creating new asset pack "${options.name}"...`);
251
+ logger.log(`Parent directory: ${absoluteParentPath}\n`);
252
+ const result = await newAssetPack(absoluteParentPath, options.name, logger, handler);
253
+ if (result.success) {
254
+ logger.log(`\n✅ ${result.message}`);
255
+ process.exit(0);
256
+ }
257
+ else {
258
+ logger.error(`\n❌ ${result.message}`);
259
+ if (result.error) {
260
+ logger.error(result.error);
261
+ }
262
+ process.exit(1);
263
+ }
264
+ }
265
+ catch (error) {
266
+ logger.error('\n❌ An unexpected error occurred:');
267
+ logger.error(error);
268
+ process.exit(1);
269
+ }
270
+ });
271
+ // List templates command
272
+ program
273
+ .command('list-templates')
274
+ .description('List available project templates')
275
+ .action(() => {
276
+ printTemplates();
277
+ });
278
+ // Add examples to help
279
+ program.addHelpText('after', `
280
+ Examples:
281
+ # Create a new FPS game project in current directory
282
+ $ genesys-sdk new -n my-fps-game -t fps
283
+
284
+ # Create a new FPS game project in a specific directory
285
+ $ genesys-sdk new -p ./projects -n my-fps-game -t fps
286
+
287
+ # Build current directory project with type checking
288
+ $ genesys-sdk build
289
+
290
+ # Build a specific project with type checking
291
+ $ genesys-sdk build -p ./projects/my-game
292
+
293
+ # Create a new asset pack in current directory
294
+ $ genesys-sdk new-asset-pack -n my-asset-pack
295
+
296
+ # Create a new asset pack in a specific directory
297
+ $ genesys-sdk new-asset-pack -p ./packs -n my-asset-pack
298
+
299
+ # List all available templates
300
+ $ genesys-sdk list-templates
301
+ `);
302
+ // Parse arguments
303
+ await program.parseAsync(process.argv);
304
+ }
305
+ // Run the CLI
306
+ main();