@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.
- package/README.md +60 -0
- package/dist/src/asset-pack/eslint.config.js +43 -0
- package/dist/src/asset-pack/scripts/postinstall.js +64 -0
- package/dist/src/asset-pack/src/index.js +1 -0
- package/dist/src/core/cli.js +306 -0
- package/dist/src/core/common.js +324 -0
- package/dist/src/core/index.js +6 -0
- package/dist/src/core/tools/build-project.js +450 -0
- package/dist/src/core/tools/index.js +2 -0
- package/dist/src/core/tools/new-asset-pack.js +150 -0
- package/dist/src/core/tools/new-project.js +292 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/dependencies.js +82 -0
- package/dist/src/electron/IpcSerializableError.js +38 -0
- package/dist/src/electron/api.js +7 -0
- package/dist/src/electron/backend/actions.js +56 -0
- package/dist/src/electron/backend/handler.js +441 -0
- package/dist/src/electron/backend/logging.js +41 -0
- package/dist/src/electron/backend/main.js +315 -0
- package/dist/src/electron/backend/menu.js +208 -0
- package/dist/src/electron/backend/state.js +201 -0
- package/dist/src/electron/backend/tools/const.js +9 -0
- package/dist/src/electron/backend/tools/file-server.js +383 -0
- package/dist/src/electron/backend/tools/open-project.js +261 -0
- package/dist/src/electron/backend/window.js +161 -0
- package/dist/src/templates/eslint.config.js +43 -0
- package/dist/src/templates/scripts/genesys/build-project.js +42 -0
- package/dist/src/templates/scripts/genesys/calc-bounding-box.js +205 -0
- package/dist/src/templates/scripts/genesys/common.js +36 -0
- package/dist/src/templates/scripts/genesys/const.js +9 -0
- package/dist/src/templates/scripts/genesys/dev/dump-default-scene.js +8 -0
- package/dist/src/templates/scripts/genesys/dev/generate-manifest.js +116 -0
- package/dist/src/templates/scripts/genesys/dev/launcher.js +39 -0
- package/dist/src/templates/scripts/genesys/dev/storage-provider.js +188 -0
- package/dist/src/templates/scripts/genesys/dev/update-template-scenes.js +67 -0
- package/dist/src/templates/scripts/genesys/doc-server.js +12 -0
- package/dist/src/templates/scripts/genesys/genesys-mcp.js +413 -0
- package/dist/src/templates/scripts/genesys/mcp/doc-tools.js +70 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-functions.js +123 -0
- package/dist/src/templates/scripts/genesys/mcp/editor-tools.js +51 -0
- package/dist/src/templates/scripts/genesys/mcp/get-scene-state.js +26 -0
- package/dist/src/templates/scripts/genesys/mcp/run-subprocess.js +23 -0
- package/dist/src/templates/scripts/genesys/mcp/search-actors.js +703 -0
- package/dist/src/templates/scripts/genesys/mcp/search-assets.js +296 -0
- package/dist/src/templates/scripts/genesys/mcp/utils.js +234 -0
- package/dist/src/templates/scripts/genesys/misc.js +32 -0
- package/dist/src/templates/scripts/genesys/mock.js +5 -0
- package/dist/src/templates/scripts/genesys/place-actors.js +112 -0
- package/dist/src/templates/scripts/genesys/post-install.js +25 -0
- package/dist/src/templates/scripts/genesys/remove-engine-comments.js +113 -0
- package/dist/src/templates/scripts/genesys/storageProvider.js +146 -0
- package/dist/src/templates/scripts/genesys/validate-prefabs.js +115 -0
- package/dist/src/templates/src/index.js +20 -0
- package/dist/src/templates/src/templates/firstPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/firstPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/firstPerson/src/player.js +60 -0
- package/dist/src/templates/src/templates/fps/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/fps/src/game.js +30 -0
- package/dist/src/templates/src/templates/fps/src/player.js +64 -0
- package/dist/src/templates/src/templates/fps/src/weapon.js +62 -0
- package/dist/src/templates/src/templates/freeCamera/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/freeCamera/src/game.js +30 -0
- package/dist/src/templates/src/templates/freeCamera/src/player.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/sideScroller/src/const.js +43 -0
- package/dist/src/templates/src/templates/sideScroller/src/game.js +103 -0
- package/dist/src/templates/src/templates/sideScroller/src/level-generator.js +249 -0
- package/dist/src/templates/src/templates/sideScroller/src/player.js +105 -0
- package/dist/src/templates/src/templates/thirdPerson/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/thirdPerson/src/game.js +30 -0
- package/dist/src/templates/src/templates/thirdPerson/src/player.js +63 -0
- package/dist/src/templates/src/templates/vehicle/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vehicle/src/base-vehicle.js +122 -0
- package/dist/src/templates/src/templates/vehicle/src/game.js +33 -0
- package/dist/src/templates/src/templates/vehicle/src/mesh-vehicle.js +189 -0
- package/dist/src/templates/src/templates/vehicle/src/player.js +102 -0
- package/dist/src/templates/src/templates/vehicle/src/primitive-vehicle.js +259 -0
- package/dist/src/templates/src/templates/vehicle/src/ui-hints.js +100 -0
- package/dist/src/templates/src/templates/vr-game/src/auto-imports.js +1 -0
- package/dist/src/templates/src/templates/vr-game/src/game.js +55 -0
- package/dist/src/templates/src/templates/vr-game/src/sample-vr-actor.js +29 -0
- package/dist/src/templates/vite.config.js +46 -0
- package/package.json +176 -0
- package/scripts/post-install.ts +143 -0
- package/src/asset-pack/.gitattributes +89 -0
- package/src/asset-pack/eslint.config.js +45 -0
- package/src/asset-pack/gitignore +11 -0
- package/src/asset-pack/scripts/postinstall.ts +81 -0
- package/src/asset-pack/src/index.ts +0 -0
- package/src/asset-pack/tsconfig.json +34 -0
- package/src/templates/.cursor/mcp.json +20 -0
- package/src/templates/.cursorignore +2 -0
- package/src/templates/.gitattributes +89 -0
- package/src/templates/.vscode/settings.json +6 -0
- package/src/templates/AGENTS.md +86 -0
- package/src/templates/CLAUDE.md +1 -0
- package/src/templates/README.md +24 -0
- package/src/templates/eslint.config.js +45 -0
- package/src/templates/gitignore +11 -0
- package/src/templates/index.html +34 -0
- package/src/templates/pnpm-lock.yaml +3676 -0
- package/src/templates/scripts/genesys/build-project.ts +51 -0
- package/src/templates/scripts/genesys/calc-bounding-box.ts +272 -0
- package/src/templates/scripts/genesys/common.ts +46 -0
- package/src/templates/scripts/genesys/const.ts +9 -0
- package/src/templates/scripts/genesys/dev/dump-default-scene.ts +11 -0
- package/src/templates/scripts/genesys/dev/generate-manifest.ts +146 -0
- package/src/templates/scripts/genesys/dev/launcher.ts +46 -0
- package/src/templates/scripts/genesys/dev/storage-provider.ts +229 -0
- package/src/templates/scripts/genesys/dev/update-template-scenes.ts +84 -0
- package/src/templates/scripts/genesys/doc-server.ts +16 -0
- package/src/templates/scripts/genesys/genesys-mcp.ts +526 -0
- package/src/templates/scripts/genesys/mcp/doc-tools.ts +86 -0
- package/src/templates/scripts/genesys/mcp/editor-functions.ts +151 -0
- package/src/templates/scripts/genesys/mcp/editor-tools.ts +73 -0
- package/src/templates/scripts/genesys/mcp/get-scene-state.ts +35 -0
- package/src/templates/scripts/genesys/mcp/run-subprocess.ts +30 -0
- package/src/templates/scripts/genesys/mcp/search-actors.ts +858 -0
- package/src/templates/scripts/genesys/mcp/search-assets.ts +380 -0
- package/src/templates/scripts/genesys/mcp/utils.ts +281 -0
- package/src/templates/scripts/genesys/misc.ts +42 -0
- package/src/templates/scripts/genesys/mock.ts +6 -0
- package/src/templates/scripts/genesys/place-actors.ts +179 -0
- package/src/templates/scripts/genesys/post-install.ts +30 -0
- package/src/templates/scripts/genesys/prefab.schema.json +85 -0
- package/src/templates/scripts/genesys/remove-engine-comments.ts +135 -0
- package/src/templates/scripts/genesys/run-mcp-inspector.bat +5 -0
- package/src/templates/scripts/genesys/storageProvider.ts +182 -0
- package/src/templates/scripts/genesys/validate-prefabs.ts +138 -0
- package/src/templates/src/index.ts +22 -0
- package/src/templates/src/templates/firstPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/firstPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/firstPerson/src/game.ts +39 -0
- package/src/templates/src/templates/firstPerson/src/player.ts +63 -0
- package/src/templates/src/templates/fps/assets/default.genesys-scene +9460 -0
- package/src/templates/src/templates/fps/assets/models/SM_Beam_400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_ChamferCube.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thick_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Floor_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Ramp_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Rifle.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x200_Orange.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400.glb +0 -0
- package/src/templates/src/templates/fps/assets/models/SM_Wall_Thin_400x400_Orange.glb +0 -0
- package/src/templates/src/templates/fps/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/fps/src/game.ts +39 -0
- package/src/templates/src/templates/fps/src/player.ts +69 -0
- package/src/templates/src/templates/fps/src/weapon.ts +54 -0
- package/src/templates/src/templates/freeCamera/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/freeCamera/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/freeCamera/src/game.ts +39 -0
- package/src/templates/src/templates/freeCamera/src/player.ts +45 -0
- package/src/templates/src/templates/sideScroller/assets/default.genesys-scene +122 -0
- package/src/templates/src/templates/sideScroller/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/sideScroller/src/const.ts +46 -0
- package/src/templates/src/templates/sideScroller/src/game.ts +122 -0
- package/src/templates/src/templates/sideScroller/src/level-generator.ts +361 -0
- package/src/templates/src/templates/sideScroller/src/player.ts +125 -0
- package/src/templates/src/templates/thirdPerson/assets/default.genesys-scene +166 -0
- package/src/templates/src/templates/thirdPerson/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/thirdPerson/src/game.ts +39 -0
- package/src/templates/src/templates/thirdPerson/src/player.ts +61 -0
- package/src/templates/src/templates/vehicle/assets/default.genesys-scene +226 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/chassis.glb +0 -0
- package/src/templates/src/templates/vehicle/assets/models/cyberTruck/wheel.glb +0 -0
- package/src/templates/src/templates/vehicle/src/auto-imports.ts +0 -0
- package/src/templates/src/templates/vehicle/src/base-vehicle.ts +145 -0
- package/src/templates/src/templates/vehicle/src/game.ts +43 -0
- package/src/templates/src/templates/vehicle/src/mesh-vehicle.ts +191 -0
- package/src/templates/src/templates/vehicle/src/player.ts +109 -0
- package/src/templates/src/templates/vehicle/src/primitive-vehicle.ts +266 -0
- package/src/templates/src/templates/vehicle/src/ui-hints.ts +101 -0
- package/src/templates/src/templates/vr-game/assets/default.genesys-scene +247 -0
- package/src/templates/src/templates/vr-game/src/auto-imports.ts +1 -0
- package/src/templates/src/templates/vr-game/src/game.ts +66 -0
- package/src/templates/src/templates/vr-game/src/sample-vr-actor.ts +26 -0
- package/src/templates/tsconfig.json +35 -0
- package/src/templates/vite.config.ts +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[](https://github.com/directivegames/genesys.sdk/actions/workflows/ci.yml)
|
|
2
|
+
[](https://github.com/directivegames/genesys.sdk/actions/workflows/publish.yml)
|
|
3
|
+
|
|
4
|
+

|
|
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();
|