@polyhedral/cli 0.1.0-beta.1
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 +51 -0
- package/dist/commands/dev.d.ts +2 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +85 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +41 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +32 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +38 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/pull.d.ts +2 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +34 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +2 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +36 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +33 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +30 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +55 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/config.d.ts +5 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +31 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/format.d.ts +3 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +8 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/manifest.d.ts +6 -0
- package/dist/lib/manifest.d.ts.map +1 -0
- package/dist/lib/manifest.js +29 -0
- package/dist/lib/manifest.js.map +1 -0
- package/dist/lib/template-data.d.ts +11 -0
- package/dist/lib/template-data.d.ts.map +1 -0
- package/dist/lib/template-data.js +11 -0
- package/dist/lib/template-data.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +38 -0
- package/templates/sheet.jsx +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# @polyhedral/cli
|
|
2
|
+
|
|
3
|
+
CLI for building custom character sheet templates on [Polyhedral](https://polyhedral.co). Edit locally in your own editor, push to the server, and preview changes live.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @polyhedral/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js 20+. Or use `npx @polyhedral/cli` without installing.
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Log in with your API key (get one from Connected Apps in your account settings)
|
|
17
|
+
polyhedral login
|
|
18
|
+
|
|
19
|
+
# Scaffold a new template project
|
|
20
|
+
polyhedral init my-sheet
|
|
21
|
+
cd my-sheet
|
|
22
|
+
|
|
23
|
+
# Start the live preview loop — edit, save, see it update
|
|
24
|
+
polyhedral dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
| Command | Description |
|
|
30
|
+
| -------------------- | --------------------------------------------------- |
|
|
31
|
+
| `polyhedral login` | Authenticate with your API key |
|
|
32
|
+
| `polyhedral init` | Scaffold a new template project |
|
|
33
|
+
| `polyhedral dev` | Watch file, auto-push on save, open live preview |
|
|
34
|
+
| `polyhedral push` | Validate and upload the local template |
|
|
35
|
+
| `polyhedral pull` | Download a template to a local file |
|
|
36
|
+
| `polyhedral list` | List all your custom sheet templates |
|
|
37
|
+
| `polyhedral validate`| Check a template file for syntax errors |
|
|
38
|
+
|
|
39
|
+
## How It Works
|
|
40
|
+
|
|
41
|
+
Templates are JSX files using the Polyhedral SDK component library. The CLI wraps the [REST API](https://polyhedral.co/developers/api) to manage templates from the terminal.
|
|
42
|
+
|
|
43
|
+
The `dev` command is the main workflow: it pushes your template, opens the preview page, and watches for file changes. When you save, it validates and pushes automatically. The preview page uses realtime subscriptions, so it updates without a manual refresh.
|
|
44
|
+
|
|
45
|
+
## Docs
|
|
46
|
+
|
|
47
|
+
Full documentation at [polyhedral.co/developers/cli](https://polyhedral.co/developers/cli).
|
|
48
|
+
|
|
49
|
+
## License
|
|
50
|
+
|
|
51
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAUA,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA2ChD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { watch } from 'chokidar';
|
|
4
|
+
import { requireConfig } from '../lib/config.js';
|
|
5
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
6
|
+
import { loadManifest, saveManifest } from '../lib/manifest.js';
|
|
7
|
+
import { formatValidationError } from '../lib/format.js';
|
|
8
|
+
import { buildTemplatePayload } from '../lib/template-data.js';
|
|
9
|
+
export async function devCommand() {
|
|
10
|
+
const config = await requireConfig();
|
|
11
|
+
const client = new ApiClient(config);
|
|
12
|
+
const manifest = await loadManifest();
|
|
13
|
+
const filePath = join(process.cwd(), manifest.file);
|
|
14
|
+
console.log('Pushing current version...');
|
|
15
|
+
const previewUrl = await initialPush(config, client, manifest, filePath);
|
|
16
|
+
if (!previewUrl) {
|
|
17
|
+
console.error('Initial push failed. Fix the errors above and try again.');
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
console.log(`\nOpening preview: ${previewUrl}`);
|
|
21
|
+
const open = (await import('open')).default;
|
|
22
|
+
await open(previewUrl);
|
|
23
|
+
console.log(`\nWatching ${manifest.file} for changes... (Ctrl+C to stop)\n`);
|
|
24
|
+
let debounceTimer = null;
|
|
25
|
+
const watcher = watch(filePath, {
|
|
26
|
+
ignoreInitial: true,
|
|
27
|
+
awaitWriteFinish: {
|
|
28
|
+
stabilityThreshold: 300,
|
|
29
|
+
pollInterval: 100,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
watcher.on('change', () => {
|
|
33
|
+
if (debounceTimer)
|
|
34
|
+
clearTimeout(debounceTimer);
|
|
35
|
+
debounceTimer = setTimeout(async () => {
|
|
36
|
+
await pushOnChange(client, manifest, filePath);
|
|
37
|
+
}, 500);
|
|
38
|
+
});
|
|
39
|
+
process.on('SIGINT', () => {
|
|
40
|
+
console.log('\nStopping dev mode.');
|
|
41
|
+
watcher.close();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function initialPush(config, client, manifest, filePath) {
|
|
46
|
+
const code = await readFile(filePath, 'utf-8');
|
|
47
|
+
const validation = await client.validate(code);
|
|
48
|
+
if (!validation.valid) {
|
|
49
|
+
console.error(`Validation failed: ${formatValidationError(validation)}`);
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
const data = buildTemplatePayload(manifest, code);
|
|
53
|
+
let templateId = manifest.templateId;
|
|
54
|
+
if (templateId) {
|
|
55
|
+
await client.updateTemplate(templateId, data);
|
|
56
|
+
console.log('Template updated.');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const created = await client.createTemplate(data);
|
|
60
|
+
templateId = created.id;
|
|
61
|
+
manifest.templateId = templateId;
|
|
62
|
+
await saveManifest(manifest);
|
|
63
|
+
console.log(`Template created with ID: ${templateId}`);
|
|
64
|
+
}
|
|
65
|
+
return `${config.apiUrl}/home/sheets/preview/${templateId}`;
|
|
66
|
+
}
|
|
67
|
+
async function pushOnChange(client, manifest, filePath) {
|
|
68
|
+
const timestamp = new Date().toLocaleTimeString();
|
|
69
|
+
try {
|
|
70
|
+
const code = await readFile(filePath, 'utf-8');
|
|
71
|
+
const validation = await client.validate(code);
|
|
72
|
+
if (!validation.valid) {
|
|
73
|
+
console.error(`[${timestamp}] Invalid: ${formatValidationError(validation)}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const data = buildTemplatePayload(manifest, code);
|
|
77
|
+
await client.updateTemplate(manifest.templateId, data);
|
|
78
|
+
console.log(`[${timestamp}] Pushed.`);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
82
|
+
console.error(`[${timestamp}] Push failed: ${message}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAQA,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC7D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { mkdir, copyFile, access } from 'node:fs/promises';
|
|
2
|
+
import { join, dirname, resolve, basename } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { saveManifest } from '../lib/manifest.js';
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
export async function initCommand(dir) {
|
|
7
|
+
const targetDir = dir ? resolve(dir) : process.cwd();
|
|
8
|
+
try {
|
|
9
|
+
await access(join(targetDir, 'polyhedral.json'));
|
|
10
|
+
console.error('polyhedral.json already exists in this directory.');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// Expected — file doesn't exist yet
|
|
15
|
+
}
|
|
16
|
+
await mkdir(targetDir, { recursive: true });
|
|
17
|
+
const name = dir ? basename(resolve(dir)) : 'my-sheet';
|
|
18
|
+
const manifest = {
|
|
19
|
+
name,
|
|
20
|
+
file: './sheet.jsx',
|
|
21
|
+
buildType: 'in-app',
|
|
22
|
+
description: '',
|
|
23
|
+
fieldSchema: [],
|
|
24
|
+
nameField: 'name',
|
|
25
|
+
};
|
|
26
|
+
await saveManifest(manifest, targetDir);
|
|
27
|
+
const templateSrc = join(__dirname, '..', '..', 'templates', 'sheet.jsx');
|
|
28
|
+
const templateDest = join(targetDir, 'sheet.jsx');
|
|
29
|
+
await copyFile(templateSrc, templateDest);
|
|
30
|
+
console.log(`Initialized polyhedral project in ${targetDir}`);
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log('Files created:');
|
|
33
|
+
console.log(' polyhedral.json — project manifest');
|
|
34
|
+
console.log(' sheet.jsx — starter template');
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log('Next steps:');
|
|
37
|
+
console.log(' 1. Edit sheet.jsx in your editor');
|
|
38
|
+
console.log(' 2. Run `polyhedral push` to upload');
|
|
39
|
+
console.log(' 3. Run `polyhedral dev` for live preview');
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAY;IAC5C,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;IAEpD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAA;QAChD,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAA;QAClE,OAAM;IACR,CAAC;IAAC,MAAM,CAAC;QACP,oCAAoC;IACtC,CAAC;IAED,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3C,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAA;IAEtD,MAAM,QAAQ,GAAa;QACzB,IAAI;QACJ,IAAI,EAAE,aAAa;QACnB,SAAS,EAAE,QAAQ;QACnB,WAAW,EAAE,EAAE;QACf,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,MAAM;KAClB,CAAA;IAED,MAAM,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IAEvC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAA;IACzE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACjD,MAAM,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;IAEzC,OAAO,CAAC,GAAG,CAAC,qCAAqC,SAAS,EAAE,CAAC,CAAA;IAC7D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAC7B,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;IACpD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;IACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACf,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAC1B,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;IACjD,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAA;IACnD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAA;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAGA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAkCjD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { requireConfig } from '../lib/config.js';
|
|
2
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
3
|
+
export async function listCommand() {
|
|
4
|
+
const config = await requireConfig();
|
|
5
|
+
const client = new ApiClient(config);
|
|
6
|
+
const templates = await client.listTemplates();
|
|
7
|
+
if (templates.length === 0) {
|
|
8
|
+
console.log('No templates found. Run `polyhedral init` to create one.');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const nameWidth = Math.max(20, ...templates.map((t) => t.name.length)) + 2;
|
|
12
|
+
const idWidth = 38;
|
|
13
|
+
const typeWidth = 12;
|
|
14
|
+
const header = [
|
|
15
|
+
'Name'.padEnd(nameWidth),
|
|
16
|
+
'ID'.padEnd(idWidth),
|
|
17
|
+
'Build Type'.padEnd(typeWidth),
|
|
18
|
+
'Updated',
|
|
19
|
+
].join('');
|
|
20
|
+
console.log(header);
|
|
21
|
+
console.log('-'.repeat(header.length));
|
|
22
|
+
for (const t of templates) {
|
|
23
|
+
const updated = new Date(t.updated_at).toLocaleDateString();
|
|
24
|
+
console.log([
|
|
25
|
+
t.name.padEnd(nameWidth),
|
|
26
|
+
t.id.padEnd(idWidth),
|
|
27
|
+
t.build_type.padEnd(typeWidth),
|
|
28
|
+
updated,
|
|
29
|
+
].join(''));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;IAEpC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAA;IAE9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAA;QACvE,OAAM;IACR,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,EAAE,CAAA;IAClB,MAAM,SAAS,GAAG,EAAE,CAAA;IACpB,MAAM,MAAM,GAAG;QACb,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QACpB,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC;QAC9B,SAAS;KACV,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACV,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACnB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;IAEtC,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,kBAAkB,EAAE,CAAA;QAC3D,OAAO,CAAC,GAAG,CACT;YACE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACxB,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;YACpB,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC;YAC9B,OAAO;SACR,CAAC,IAAI,CAAC,EAAE,CAAC,CACX,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAqClD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline/promises';
|
|
2
|
+
import { stdin, stdout } from 'node:process';
|
|
3
|
+
import { loadConfig, saveConfig } from '../lib/config.js';
|
|
4
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
5
|
+
export async function loginCommand() {
|
|
6
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
7
|
+
try {
|
|
8
|
+
const existing = await loadConfig();
|
|
9
|
+
console.log('Log in to Polyhedral with your API key.');
|
|
10
|
+
console.log('Generate one at https://polyhedral.co/home/connected-apps\n');
|
|
11
|
+
const apiKey = await rl.question('API key: ');
|
|
12
|
+
if (!apiKey.trim()) {
|
|
13
|
+
console.error('No API key provided.');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const apiUrl = await rl.question(`API URL (${existing.apiUrl}): `);
|
|
17
|
+
const config = {
|
|
18
|
+
apiKey: apiKey.trim(),
|
|
19
|
+
apiUrl: apiUrl.trim() || existing.apiUrl,
|
|
20
|
+
};
|
|
21
|
+
console.log('\nValidating API key...');
|
|
22
|
+
const client = new ApiClient(config);
|
|
23
|
+
try {
|
|
24
|
+
await client.listTemplates();
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const message = err instanceof Error ? err.message : 'Unknown error';
|
|
28
|
+
console.error(`Authentication failed: ${message}`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
await saveConfig(config);
|
|
32
|
+
console.log('Logged in successfully. Config saved to ~/.polyhedral/config.json');
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
rl.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAE5D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,UAAU,EAAE,CAAA;QAEnC,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAA;QACtD,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;QAE1E,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;QAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAA;YACrC,OAAM;QACR,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAA;QAElE,MAAM,MAAM,GAAG;YACb,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACrB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC,MAAM;SACzC,CAAA;QAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;QACtC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,aAAa,EAAE,CAAA;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAA;YACpE,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAA;YAClD,OAAM;QACR,CAAC;QAED,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;QACxB,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAA;IAClF,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAA;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAOA,wBAAsB,WAAW,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkC5D"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { requireConfig } from '../lib/config.js';
|
|
4
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
5
|
+
import { tryLoadManifest, saveManifest } from '../lib/manifest.js';
|
|
6
|
+
export async function pullCommand(id) {
|
|
7
|
+
const config = await requireConfig();
|
|
8
|
+
const client = new ApiClient(config);
|
|
9
|
+
const manifest = await tryLoadManifest();
|
|
10
|
+
const templateId = id ?? manifest?.templateId;
|
|
11
|
+
if (!templateId) {
|
|
12
|
+
console.error('No template ID provided. Pass an ID or run from a project directory.');
|
|
13
|
+
console.error('Usage: polyhedral pull [id]');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
console.log(`Pulling template ${templateId}...`);
|
|
17
|
+
const template = await client.getTemplate(templateId);
|
|
18
|
+
const filePath = manifest?.file ?? './sheet.jsx';
|
|
19
|
+
const fullPath = join(process.cwd(), filePath);
|
|
20
|
+
await writeFile(fullPath, template.code, 'utf-8');
|
|
21
|
+
const updatedManifest = {
|
|
22
|
+
name: template.name,
|
|
23
|
+
templateId: template.id,
|
|
24
|
+
file: filePath,
|
|
25
|
+
buildType: template.build_type,
|
|
26
|
+
description: template.description ?? undefined,
|
|
27
|
+
fieldSchema: template.field_schema ?? undefined,
|
|
28
|
+
nameField: template.name_field,
|
|
29
|
+
};
|
|
30
|
+
await saveManifest(updatedManifest);
|
|
31
|
+
console.log(`Wrote ${filePath}`);
|
|
32
|
+
console.log(`Updated polyhedral.json`);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=pull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGlE,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAW;IAC3C,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;IAEpC,MAAM,QAAQ,GAAG,MAAM,eAAe,EAAE,CAAA;IAExC,MAAM,UAAU,GAAG,EAAE,IAAI,QAAQ,EAAE,UAAU,CAAA;IAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,sEAAsE,CAAC,CAAA;QACrF,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,UAAU,KAAK,CAAC,CAAA;IAChD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IAErD,MAAM,QAAQ,GAAG,QAAQ,EAAE,IAAI,IAAI,aAAa,CAAA;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC9C,MAAM,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAEjD,MAAM,eAAe,GAAa;QAChC,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,QAAQ,CAAC,UAAmC;QACvD,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,SAAS;QAC9C,WAAW,EAAE,QAAQ,CAAC,YAAY,IAAI,SAAS;QAC/C,SAAS,EAAE,QAAQ,CAAC,UAAU;KAC/B,CAAA;IAED,MAAM,YAAY,CAAC,eAAe,CAAC,CAAA;IAEnC,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAA;IAChC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAQA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA+BjD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { requireConfig } from '../lib/config.js';
|
|
4
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
5
|
+
import { loadManifest, saveManifest } from '../lib/manifest.js';
|
|
6
|
+
import { formatValidationError } from '../lib/format.js';
|
|
7
|
+
import { buildTemplatePayload } from '../lib/template-data.js';
|
|
8
|
+
export async function pushCommand() {
|
|
9
|
+
const config = await requireConfig();
|
|
10
|
+
const client = new ApiClient(config);
|
|
11
|
+
const manifest = await loadManifest();
|
|
12
|
+
const filePath = join(process.cwd(), manifest.file);
|
|
13
|
+
const code = await readFile(filePath, 'utf-8');
|
|
14
|
+
const validation = await client.validate(code);
|
|
15
|
+
if (!validation.valid) {
|
|
16
|
+
console.error(`Validation failed: ${formatValidationError(validation)}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const data = buildTemplatePayload(manifest, code);
|
|
20
|
+
let templateId = manifest.templateId;
|
|
21
|
+
if (templateId) {
|
|
22
|
+
console.log(`Updating template ${templateId}...`);
|
|
23
|
+
await client.updateTemplate(templateId, data);
|
|
24
|
+
console.log('Template updated.');
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
console.log('Creating new template...');
|
|
28
|
+
const created = await client.createTemplate(data);
|
|
29
|
+
templateId = created.id;
|
|
30
|
+
manifest.templateId = templateId;
|
|
31
|
+
await saveManifest(manifest);
|
|
32
|
+
console.log(`Template created with ID: ${templateId}`);
|
|
33
|
+
}
|
|
34
|
+
console.log(`Preview: ${config.apiUrl}/home/sheets/preview/${templateId}`);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAE9D,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;IACpC,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAA;IAErC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAA;IACnD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAE9C,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,sBAAsB,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;QACxE,OAAM;IACR,CAAC;IAED,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACjD,IAAI,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAA;IAEpC,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,qBAAqB,UAAU,KAAK,CAAC,CAAA;QACjD,MAAM,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QAC7C,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;IAClC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;QACvC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;QACjD,UAAU,GAAG,OAAO,CAAC,EAAE,CAAA;QACvB,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAA;QAChC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAA;IACxD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,wBAAwB,UAAU,EAAE,CAAC,CAAA;AAC5E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAOA,wBAAsB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBlE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { requireConfig } from '../lib/config.js';
|
|
4
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
5
|
+
import { loadManifest } from '../lib/manifest.js';
|
|
6
|
+
import { formatValidationError } from '../lib/format.js';
|
|
7
|
+
export async function validateCommand(file) {
|
|
8
|
+
const config = await requireConfig();
|
|
9
|
+
const client = new ApiClient(config);
|
|
10
|
+
const filePath = file ?? await getFileFromManifest();
|
|
11
|
+
const fullPath = join(process.cwd(), filePath);
|
|
12
|
+
const code = await readFile(fullPath, 'utf-8');
|
|
13
|
+
console.log(`Validating ${filePath}...`);
|
|
14
|
+
const result = await client.validate(code);
|
|
15
|
+
if (result.valid) {
|
|
16
|
+
console.log('Valid.');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.error(`Invalid: ${formatValidationError(result)}`);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
async function getFileFromManifest() {
|
|
23
|
+
try {
|
|
24
|
+
const manifest = await loadManifest();
|
|
25
|
+
return manifest.file;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
console.error('No file specified and no polyhedral.json found.');
|
|
29
|
+
console.error('Usage: polyhedral validate [file]');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAa;IACjD,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAA;IAEpC,MAAM,QAAQ,GAAG,IAAI,IAAI,MAAM,mBAAmB,EAAE,CAAA;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;IAC9C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAE9C,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,KAAK,CAAC,CAAA;IACxC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAE1C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACrB,OAAM;IACR,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,YAAY,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAA;QACrC,OAAO,QAAQ,CAAC,IAAI,CAAA;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;QAChE,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
8
|
+
import { loginCommand } from './commands/login.js';
|
|
9
|
+
import { initCommand } from './commands/init.js';
|
|
10
|
+
import { listCommand } from './commands/list.js';
|
|
11
|
+
import { pullCommand } from './commands/pull.js';
|
|
12
|
+
import { pushCommand } from './commands/push.js';
|
|
13
|
+
import { validateCommand } from './commands/validate.js';
|
|
14
|
+
import { devCommand } from './commands/dev.js';
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name('polyhedral')
|
|
18
|
+
.description('CLI for local Polyhedral custom sheet template development')
|
|
19
|
+
.version(pkg.version);
|
|
20
|
+
program
|
|
21
|
+
.command('login')
|
|
22
|
+
.description('Authenticate with your Polyhedral API key')
|
|
23
|
+
.action(loginCommand);
|
|
24
|
+
program
|
|
25
|
+
.command('init [dir]')
|
|
26
|
+
.description('Scaffold a new template project')
|
|
27
|
+
.action(initCommand);
|
|
28
|
+
program
|
|
29
|
+
.command('list')
|
|
30
|
+
.description('List all your custom sheet templates')
|
|
31
|
+
.action(listCommand);
|
|
32
|
+
program
|
|
33
|
+
.command('pull [id]')
|
|
34
|
+
.description('Download a template to a local file')
|
|
35
|
+
.action(pullCommand);
|
|
36
|
+
program
|
|
37
|
+
.command('push')
|
|
38
|
+
.description('Validate and upload the local template')
|
|
39
|
+
.action(pushCommand);
|
|
40
|
+
program
|
|
41
|
+
.command('validate [file]')
|
|
42
|
+
.description('Validate a template file without pushing')
|
|
43
|
+
.action(validateCommand);
|
|
44
|
+
program
|
|
45
|
+
.command('dev')
|
|
46
|
+
.description('Watch file, auto-push on save, and open live preview')
|
|
47
|
+
.action(devCommand);
|
|
48
|
+
program.parse();
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;AAEvB,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,2CAA2C,CAAC;KACxD,MAAM,CAAC,YAAY,CAAC,CAAA;AAEvB,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,WAAW,CAAC;KACpB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,WAAW,CAAC,CAAA;AAEtB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,eAAe,CAAC,CAAA;AAE1B,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,UAAU,CAAC,CAAA;AAErB,OAAO,CAAC,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { CliConfig, Template, ValidationResult } from '../types.js';
|
|
2
|
+
export declare class ApiClient {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private apiKey;
|
|
5
|
+
constructor(config: CliConfig);
|
|
6
|
+
private request;
|
|
7
|
+
listTemplates(): Promise<Template[]>;
|
|
8
|
+
getTemplate(id: string): Promise<Template>;
|
|
9
|
+
createTemplate(data: {
|
|
10
|
+
name: string;
|
|
11
|
+
code: string;
|
|
12
|
+
buildType: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
fieldSchema?: unknown[];
|
|
15
|
+
nameField?: string | null;
|
|
16
|
+
}): Promise<Template>;
|
|
17
|
+
updateTemplate(id: string, data: {
|
|
18
|
+
name?: string;
|
|
19
|
+
code?: string;
|
|
20
|
+
buildType?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
fieldSchema?: unknown[];
|
|
23
|
+
nameField?: string | null;
|
|
24
|
+
}): Promise<Template>;
|
|
25
|
+
deleteTemplate(id: string): Promise<{
|
|
26
|
+
success: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
validate(code: string): Promise<ValidationResult>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAY,MAAM,aAAa,CAAA;AAElF,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAQ;gBAEV,MAAM,EAAE,SAAS;YAKf,OAAO;IAqBf,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIpC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAI1C,cAAc,CAAC,IAAI,EAAE;QACzB,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAA;QACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOf,cAAc,CAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE;QACJ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAA;QACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAC1B,GACA,OAAO,CAAC,QAAQ,CAAC;IAOd,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAMzD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAMxD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export class ApiClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
apiKey;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.baseUrl = config.apiUrl.replace(/\/$/, '');
|
|
6
|
+
this.apiKey = config.apiKey;
|
|
7
|
+
}
|
|
8
|
+
async request(path, options = {}) {
|
|
9
|
+
const url = `${this.baseUrl}${path}`;
|
|
10
|
+
const res = await fetch(url, {
|
|
11
|
+
...options,
|
|
12
|
+
headers: {
|
|
13
|
+
'Content-Type': 'application/json',
|
|
14
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
15
|
+
...options.headers,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const body = await res.json();
|
|
19
|
+
if (!res.ok) {
|
|
20
|
+
const err = body;
|
|
21
|
+
throw new Error(err.error ?? `Request failed with status ${res.status}`);
|
|
22
|
+
}
|
|
23
|
+
return body;
|
|
24
|
+
}
|
|
25
|
+
async listTemplates() {
|
|
26
|
+
return this.request('/api/custom-sheet-templates');
|
|
27
|
+
}
|
|
28
|
+
async getTemplate(id) {
|
|
29
|
+
return this.request(`/api/custom-sheet-templates/${id}`);
|
|
30
|
+
}
|
|
31
|
+
async createTemplate(data) {
|
|
32
|
+
return this.request('/api/custom-sheet-templates', {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
body: JSON.stringify(data),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async updateTemplate(id, data) {
|
|
38
|
+
return this.request(`/api/custom-sheet-templates/${id}`, {
|
|
39
|
+
method: 'PATCH',
|
|
40
|
+
body: JSON.stringify(data),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async deleteTemplate(id) {
|
|
44
|
+
return this.request(`/api/custom-sheet-templates/${id}`, {
|
|
45
|
+
method: 'DELETE',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async validate(code) {
|
|
49
|
+
return this.request('/api/custom-sheet-templates/validate', {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
body: JSON.stringify({ code }),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,SAAS;IACZ,OAAO,CAAQ;IACf,MAAM,CAAQ;IAEtB,YAAY,MAAiB;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAC/C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC7B,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,UAAuB,EAAE;QAC9D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAA;QACpC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,GAAG,OAAO,CAAC,OAAO;aACnB;SACF,CAAC,CAAA;QAEF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAE7B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,IAAgB,CAAA;YAC5B,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;QAC1E,CAAC;QAED,OAAO,IAAS,CAAA;IAClB,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,IAAI,CAAC,OAAO,CAAa,6BAA6B,CAAC,CAAA;IAChE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,EAAU;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAW,+BAA+B,EAAE,EAAE,CAAC,CAAA;IACpE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAOpB;QACC,OAAO,IAAI,CAAC,OAAO,CAAW,6BAA6B,EAAE;YAC3D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,EAAU,EACV,IAOC;QAED,OAAO,IAAI,CAAC,OAAO,CAAW,+BAA+B,EAAE,EAAE,EAAE;YACjE,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,EAAU;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAuB,+BAA+B,EAAE,EAAE,EAAE;YAC7E,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,OAAO,IAAI,CAAC,OAAO,CAAmB,sCAAsC,EAAE;YAC5E,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;SAC/B,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CliConfig } from '../types.js';
|
|
2
|
+
export declare function loadConfig(): Promise<CliConfig>;
|
|
3
|
+
export declare function saveConfig(config: CliConfig): Promise<void>;
|
|
4
|
+
export declare function requireConfig(): Promise<CliConfig>;
|
|
5
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAU5C,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAOrD;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjE;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC,CAOxD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.polyhedral');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
apiKey: '',
|
|
8
|
+
apiUrl: 'https://polyhedral.co',
|
|
9
|
+
};
|
|
10
|
+
export async function loadConfig() {
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(CONFIG_FILE, 'utf-8');
|
|
13
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { ...DEFAULT_CONFIG };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function saveConfig(config) {
|
|
20
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
21
|
+
await writeFile(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n', 'utf-8');
|
|
22
|
+
}
|
|
23
|
+
export async function requireConfig() {
|
|
24
|
+
const config = await loadConfig();
|
|
25
|
+
if (!config.apiKey) {
|
|
26
|
+
console.error('Not logged in. Run `polyhedral login` first.');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
return config;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGhC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AACjD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;AAEnD,MAAM,cAAc,GAAc;IAChC,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,uBAAuB;CAChC,CAAA;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAChD,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,cAAc,EAAE,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC5C,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAA;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAEnD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAMtE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function formatValidationError(result) {
|
|
2
|
+
if (result.line) {
|
|
3
|
+
const column = result.column ? `, column ${result.column}` : '';
|
|
4
|
+
return `Line ${result.line}${column}: ${result.error}`;
|
|
5
|
+
}
|
|
6
|
+
return result.error ?? 'Unknown validation error';
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,qBAAqB,CAAC,MAAwB;IAC5D,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC/D,OAAO,QAAQ,MAAM,CAAC,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,KAAK,EAAE,CAAA;IACxD,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,IAAI,0BAA0B,CAAA;AACnD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Manifest } from '../types.js';
|
|
2
|
+
export declare function manifestPath(dir?: string): string;
|
|
3
|
+
export declare function loadManifest(dir?: string): Promise<Manifest>;
|
|
4
|
+
export declare function tryLoadManifest(dir?: string): Promise<Manifest | undefined>;
|
|
5
|
+
export declare function saveManifest(manifest: Manifest, dir?: string): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAI3C,wBAAgB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAsB,YAAY,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOlE;AAED,wBAAsB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAQjF;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const MANIFEST_NAME = 'polyhedral.json';
|
|
4
|
+
export function manifestPath(dir) {
|
|
5
|
+
return join(dir ?? process.cwd(), MANIFEST_NAME);
|
|
6
|
+
}
|
|
7
|
+
export async function loadManifest(dir) {
|
|
8
|
+
const result = await tryLoadManifest(dir);
|
|
9
|
+
if (!result) {
|
|
10
|
+
console.error(`Could not read ${MANIFEST_NAME}. Are you in a polyhedral project directory?`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
export async function tryLoadManifest(dir) {
|
|
16
|
+
const path = manifestPath(dir);
|
|
17
|
+
try {
|
|
18
|
+
const raw = await readFile(path, 'utf-8');
|
|
19
|
+
return JSON.parse(raw);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function saveManifest(manifest, dir) {
|
|
26
|
+
const path = manifestPath(dir);
|
|
27
|
+
await writeFile(path, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/lib/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGhC,MAAM,aAAa,GAAG,iBAAiB,CAAA;AAEvC,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAY;IAC7C,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,kBAAkB,aAAa,8CAA8C,CAAC,CAAA;QAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAY;IAChD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAa,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAkB,EAAE,GAAY;IACjE,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAA;AAC1E,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Manifest } from '../types.js';
|
|
2
|
+
export interface TemplatePayload {
|
|
3
|
+
name: string;
|
|
4
|
+
code: string;
|
|
5
|
+
buildType: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
fieldSchema?: unknown[];
|
|
8
|
+
nameField?: string | null;
|
|
9
|
+
}
|
|
10
|
+
export declare function buildTemplatePayload(manifest: Manifest, code: string): TemplatePayload;
|
|
11
|
+
//# sourceMappingURL=template-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-data.d.ts","sourceRoot":"","sources":["../../src/lib/template-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,CAStF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function buildTemplatePayload(manifest, code) {
|
|
2
|
+
return {
|
|
3
|
+
name: manifest.name,
|
|
4
|
+
code,
|
|
5
|
+
buildType: manifest.buildType,
|
|
6
|
+
description: manifest.description,
|
|
7
|
+
fieldSchema: manifest.fieldSchema,
|
|
8
|
+
nameField: manifest.nameField,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=template-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-data.js","sourceRoot":"","sources":["../../src/lib/template-data.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,oBAAoB,CAAC,QAAkB,EAAE,IAAY;IACnE,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,IAAI;QACJ,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,SAAS,EAAE,QAAQ,CAAC,SAAS;KAC9B,CAAA;AACH,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface CliConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Manifest {
|
|
6
|
+
name: string;
|
|
7
|
+
templateId?: string;
|
|
8
|
+
file: string;
|
|
9
|
+
buildType: 'in-app' | 'external';
|
|
10
|
+
description?: string;
|
|
11
|
+
fieldSchema?: FieldSchemaEntry[];
|
|
12
|
+
nameField?: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface FieldSchemaEntry {
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
default?: unknown;
|
|
19
|
+
}
|
|
20
|
+
export interface Template {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
code: string;
|
|
24
|
+
build_type: string;
|
|
25
|
+
description: string | null;
|
|
26
|
+
source: string | null;
|
|
27
|
+
field_schema: FieldSchemaEntry[] | null;
|
|
28
|
+
name_field: string | null;
|
|
29
|
+
thumbnail_url: string | null;
|
|
30
|
+
user_id: string;
|
|
31
|
+
created_at: string;
|
|
32
|
+
updated_at: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ValidationResult {
|
|
35
|
+
valid: boolean;
|
|
36
|
+
error?: string;
|
|
37
|
+
line?: number;
|
|
38
|
+
column?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface ApiError {
|
|
41
|
+
error: string;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,GAAG,UAAU,CAAA;IAChC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAA;IACvC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAA;CACd"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polyhedral/cli",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "CLI tool for local Polyhedral custom sheet template development",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"polyhedral": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && chmod +x dist/index.js",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"prepare": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"templates"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"polyhedral",
|
|
21
|
+
"ttrpg",
|
|
22
|
+
"character-sheet",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"chokidar": "^4.0.3",
|
|
31
|
+
"commander": "^13.1.0",
|
|
32
|
+
"open": "^10.1.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.17.47",
|
|
36
|
+
"typescript": "5.9.3"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const { Sheet, Section, Row, EditableText, Portrait, NumberInput } =
|
|
2
|
+
Polyhedral.components;
|
|
3
|
+
|
|
4
|
+
function CharacterSheet() {
|
|
5
|
+
return (
|
|
6
|
+
<Sheet>
|
|
7
|
+
<Section>
|
|
8
|
+
<Row gap={16}>
|
|
9
|
+
<Portrait field="portrait" size="lg" />
|
|
10
|
+
<div style={{ flex: 1 }}>
|
|
11
|
+
<EditableText
|
|
12
|
+
field="name"
|
|
13
|
+
label="Character Name"
|
|
14
|
+
placeholder="Enter name..."
|
|
15
|
+
/>
|
|
16
|
+
<EditableText field="race" label="Race" />
|
|
17
|
+
<EditableText field="class" label="Class" />
|
|
18
|
+
</div>
|
|
19
|
+
</Row>
|
|
20
|
+
</Section>
|
|
21
|
+
|
|
22
|
+
<Section title="Ability Scores">
|
|
23
|
+
<Row>
|
|
24
|
+
<NumberInput field="strength" label="STR" />
|
|
25
|
+
<NumberInput field="dexterity" label="DEX" />
|
|
26
|
+
<NumberInput field="constitution" label="CON" />
|
|
27
|
+
<NumberInput field="intelligence" label="INT" />
|
|
28
|
+
<NumberInput field="wisdom" label="WIS" />
|
|
29
|
+
<NumberInput field="charisma" label="CHA" />
|
|
30
|
+
</Row>
|
|
31
|
+
</Section>
|
|
32
|
+
|
|
33
|
+
<Section title="Notes">
|
|
34
|
+
<EditableText field="notes" label="Notes" multiline />
|
|
35
|
+
</Section>
|
|
36
|
+
</Sheet>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ReactDOM.render(<CharacterSheet />, document.getElementById("root"));
|