Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/gentool-schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: GenTool JSON schema validation

permissions:
contents: read

on:
pull_request:
branches:
- main
workflow_dispatch:

jobs:
validate_gentool_schema:
runs-on: ubuntu-latest
defaults:
run:
working-directory: sdk/gentool

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'

- name: Install dependencies
run: npm ci

- name: Validate GenTool enum/interface JSON against schema
run: npm run validate:schemas

11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,14 @@
"**/sdk/platform/Web/src/**/*.hpp": "cpp",
"**/sdk/platform/Web/src/**/*.c": "c",
"**/sdk/platform/Web/src/**/*.cpp": "cpp"
}
},
"json.schemas": [
{
"fileMatch": [
"**/enum/*.json",
"**/interface/*.json"
],
"url": "./sdk/gentool/gentool.schema.json"
}
]
}
35 changes: 35 additions & 0 deletions sdk/gentool/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,40 @@
# GenTool

GenTool generates C, C++, Objective-C, Swift, and JavaScript bindings from `enum/*.json` and `interface/*.json` definitions.

## Quick reference

### Scripts

| Command | Description |
|---------|-------------|
| `npm run generate` | Generate code from enum/interface JSON and update `gentool.schema.generated.json` |
| `npm run validate:schemas` | Validate all enum/interface JSON files against the schema |

### Workflow: adding a new interface or enum

1. Create `interface/MyClass.json` or `enum/MyEnum.json`
2. Run `npm run generate`
3. Commit the generated code and `gentool.schema.generated.json`

### Schema & IDE support

- **`gentool.schema.json`** — JSON Schema for enum/interface definitions. Editors (e.g. VS Code) use it for validation and autocomplete.
- **`gentool.schema.generated.json`** — Generated list of valid parameterized types (`CLASS_MIX:Vector3`, `ENUM:SolvePnPMethod`, etc.). Regenerated by `npm run generate`.
- **Validation** — CI runs `validate:schemas` on PRs. Run it locally before committing.

### Common property patterns

| Pattern | Example |
|---------|---------|
| Simple property | `{ "name": "X", "type": "float" }` |
| Read-only computed | `{ "name": "Length", "type": "float", "getterCustom": true, "hasSetter": false, "hasMemberVar": false }` |
| Class reference | `{ "name": "Position", "type": "CLASS_MIX:Vector3" }` |
| Enum | `{ "name": "Format", "type": "ENUM:ArucoMarkerFormat" }` |
| Array | `{ "name": "Points", "type": "ARRAY_REF:Vector2" }` |

---

## JSON documentation

### Root JSON options
Expand Down
102 changes: 102 additions & 0 deletions sdk/gentool/generate-schema-fragment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Generates gentool.schema.generated.json with enum values for parameterized types
* (CLASS_MIX:Vector3, ENUM:SolvePnPMethod, etc.) so editors can autocomplete them.
*
* Run as part of `npm run generate`.
*/
const fs = require('fs');
const path = require('path');
const shared = require('./shared');

const PRIMITIVES = [
'int8', 'int16', 'int32', 'int64',
'uint8', 'uint16', 'uint32', 'uint64',
'float', 'double', 'boolean', 'string'
];

const CLASS_PREFIXES = ['CLASS', 'CLASS_REF', 'CLASS_MIX', 'CLASS_PTR', 'CLASS_PTR_REF', 'CLASS_PTR_MIX'];
const ARRAY_PREFIXES = ['ARRAY', 'ARRAY_REF', 'ARRAY_MIX', 'ARRAY_PTR', 'ARRAY_PTR_REF', 'ARRAY_PTR_MIX'];

const PARAM_CLASS_PREFIXES = ['CLASS', 'CLASS_REF', 'CLASS_PTR', 'CLASS_PTR_REF'];
const PARAM_ARRAY_PREFIXES = ['ARRAY', 'ARRAY_REF', 'ARRAY_PTR', 'ARRAY_PTR_REF'];

function collectNames(dir, subdir = '') {
const dirPath = path.resolve(__dirname, '..', dir, subdir);
if (!fs.existsSync(dirPath)) return [];
return fs.readdirSync(dirPath, 'utf8')
.filter((f) => f.toLowerCase().endsWith('.json'))
.map((f) => path.basename(f, '.json'));
}

function main() {
const enumNames = collectNames('enum');
if (!shared.ignoreCompileTests && fs.existsSync(path.resolve(__dirname, '..', 'enum', 'CompileTests'))) {
enumNames.push(...collectNames('enum', 'CompileTests'));
}

const interfaceNames = collectNames('interface');
if (!shared.ignoreCompileTests && fs.existsSync(path.resolve(__dirname, '..', 'interface', 'CompileTests'))) {
interfaceNames.push(...collectNames('interface', 'CompileTests'));
}

const allTypeNames = [...new Set([...interfaceNames, ...enumNames])];

const typeKeyEnum = [];
for (const prefix of CLASS_PREFIXES) {
for (const name of interfaceNames) {
typeKeyEnum.push(`${prefix}:${name}`);
}
}
for (const name of enumNames) {
typeKeyEnum.push(`ENUM:${name}`);
}
for (const prefix of ARRAY_PREFIXES) {
for (const p of PRIMITIVES) {
typeKeyEnum.push(`${prefix}:${p}`);
}
for (const name of allTypeNames) {
typeKeyEnum.push(`${prefix}:${name}`);
}
}

const paramTypeKeyEnum = [];
for (const prefix of PARAM_CLASS_PREFIXES) {
for (const name of interfaceNames) {
paramTypeKeyEnum.push(`${prefix}:${name}`);
}
}
for (const name of enumNames) {
paramTypeKeyEnum.push(`ENUM:${name}`);
}
for (const prefix of PARAM_ARRAY_PREFIXES) {
for (const p of PRIMITIVES) {
paramTypeKeyEnum.push(`${prefix}:${p}`);
}
for (const name of allTypeNames) {
paramTypeKeyEnum.push(`${prefix}:${name}`);
}
}

const generated = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
'$id': 'https://posemesh.auki.dev/schemas/gentool.schema.generated.json',
'title': 'Generated type enums for GenTool schema',
'$defs': {
'ParameterizedTypeKey': {
'type': 'string',
'enum': typeKeyEnum.sort()
},
'ParameterizedParamTypeKey': {
'type': 'string',
'enum': paramTypeKeyEnum.sort()
}
}
};

const outPath = path.resolve(__dirname, 'gentool.schema.generated.json');
const content = JSON.stringify(generated, null, 2) + '\n';
fs.writeFileSync(outPath, content, 'utf8');
console.log('Generated gentool.schema.generated.json');
}

main();
Loading