@objectstack/cli 3.0.7 → 3.0.9

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.
@@ -0,0 +1,251 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ import { Args, Command, Flags } from '@oclif/core';
3
+ import chalk from 'chalk';
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ import crypto from 'crypto';
7
+ import { createTimer, printHeader, printKV, printStep, printSuccess, printError } from '../../utils/format.js';
8
+ /**
9
+ * Validate a plugin artifact (.tgz) for structural integrity, checksum
10
+ * correctness, digital signature, and platform compatibility.
11
+ *
12
+ * Architecture alignment: `npm pack --dry-run`, `helm lint`, `vsce ls`.
13
+ */
14
+ export default class PluginValidate extends Command {
15
+ static description = 'Validate a plugin artifact for integrity and compliance';
16
+ static args = {
17
+ artifact: Args.string({ description: 'Path to the artifact file', required: true }),
18
+ };
19
+ static flags = {
20
+ verifySignature: Flags.boolean({ description: 'Verify digital signature', default: true, allowNo: true }),
21
+ publicKeyPath: Flags.string({ description: 'Path to public key for signature verification' }),
22
+ verifyChecksums: Flags.boolean({ description: 'Verify SHA-256 checksums', default: true, allowNo: true }),
23
+ validateMetadata: Flags.boolean({ description: 'Validate metadata schema compliance', default: true, allowNo: true }),
24
+ platformVersion: Flags.string({ description: 'Target platform version for compatibility check' }),
25
+ json: Flags.boolean({ description: 'Output result as JSON' }),
26
+ };
27
+ async run() {
28
+ const { args, flags } = await this.parse(PluginValidate);
29
+ const timer = createTimer();
30
+ if (!flags.json) {
31
+ printHeader('Plugin Validate');
32
+ }
33
+ try {
34
+ const artifactPath = path.resolve(process.cwd(), args.artifact);
35
+ if (!fs.existsSync(artifactPath)) {
36
+ throw new Error(`Artifact not found: ${artifactPath}`);
37
+ }
38
+ if (!flags.json) {
39
+ printKV('Artifact', path.relative(process.cwd(), artifactPath));
40
+ printStep('Reading artifact...');
41
+ }
42
+ const artifactBuffer = fs.readFileSync(artifactPath);
43
+ const findings = [];
44
+ // 1. Verify file existence and basic structure
45
+ if (artifactBuffer.length === 0) {
46
+ findings.push({ severity: 'error', rule: 'artifact.empty', message: 'Artifact file is empty' });
47
+ }
48
+ // 2. Try to parse as JSON manifest
49
+ let manifest;
50
+ try {
51
+ manifest = JSON.parse(artifactBuffer.toString('utf-8'));
52
+ findings.push({ severity: 'info', rule: 'manifest.parsed', message: 'Manifest parsed successfully' });
53
+ }
54
+ catch {
55
+ findings.push({ severity: 'error', rule: 'manifest.invalid', message: 'Artifact does not contain valid JSON manifest' });
56
+ }
57
+ // 3. Validate required manifest fields
58
+ if (manifest) {
59
+ if (!flags.json)
60
+ printStep('Validating manifest fields...');
61
+ if (!manifest.manifest && !manifest.name) {
62
+ findings.push({ severity: 'warning', rule: 'manifest.name', message: 'No package name found in manifest' });
63
+ }
64
+ if (!manifest.manifest?.version && !manifest.version) {
65
+ findings.push({ severity: 'warning', rule: 'manifest.version', message: 'No version found in manifest' });
66
+ }
67
+ }
68
+ // 4. Checksum verification
69
+ let checksumResult;
70
+ if (flags.verifyChecksums) {
71
+ if (!flags.json)
72
+ printStep('Verifying checksums...');
73
+ const checksumFile = artifactPath + '.sha256';
74
+ if (fs.existsSync(checksumFile)) {
75
+ const checksumContent = fs.readFileSync(checksumFile, 'utf-8').trim();
76
+ const expectedHash = checksumContent.split(/\s+/)[0];
77
+ const actualHash = crypto.createHash('sha256').update(artifactBuffer).digest('hex');
78
+ if (expectedHash === actualHash) {
79
+ checksumResult = { passed: true };
80
+ findings.push({ severity: 'info', rule: 'checksum.sha256', message: 'SHA-256 checksum verified' });
81
+ }
82
+ else {
83
+ checksumResult = { passed: false, mismatches: ['artifact'] };
84
+ findings.push({ severity: 'error', rule: 'checksum.sha256', message: `SHA-256 mismatch: expected ${expectedHash.slice(0, 16)}..., got ${actualHash.slice(0, 16)}...` });
85
+ }
86
+ }
87
+ else {
88
+ findings.push({ severity: 'warning', rule: 'checksum.missing', message: 'No .sha256 checksum file found alongside artifact' });
89
+ }
90
+ }
91
+ // 5. Signature verification
92
+ let signatureResult;
93
+ if (flags.verifySignature) {
94
+ if (!flags.json)
95
+ printStep('Verifying signature...');
96
+ const sigFile = artifactPath + '.sig';
97
+ if (fs.existsSync(sigFile) && flags.publicKeyPath && fs.existsSync(flags.publicKeyPath)) {
98
+ try {
99
+ const publicKey = fs.readFileSync(flags.publicKeyPath, 'utf-8');
100
+ const signature = fs.readFileSync(sigFile, 'utf-8');
101
+ const verifier = crypto.createVerify('RSA-SHA256');
102
+ verifier.update(artifactBuffer);
103
+ const valid = verifier.verify(publicKey, signature, 'base64');
104
+ signatureResult = { passed: valid, failureReason: valid ? undefined : 'Signature does not match' };
105
+ findings.push({
106
+ severity: valid ? 'info' : 'error',
107
+ rule: 'signature.verify',
108
+ message: valid ? 'Digital signature verified' : 'Digital signature verification failed',
109
+ });
110
+ }
111
+ catch (e) {
112
+ signatureResult = { passed: false, failureReason: e.message };
113
+ findings.push({ severity: 'error', rule: 'signature.verify', message: `Signature verification error: ${e.message}` });
114
+ }
115
+ }
116
+ else if (fs.existsSync(sigFile) && !flags.publicKeyPath) {
117
+ findings.push({ severity: 'warning', rule: 'signature.nokey', message: 'Signature file found but no --publicKeyPath provided' });
118
+ }
119
+ else if (!fs.existsSync(sigFile)) {
120
+ findings.push({ severity: 'info', rule: 'signature.absent', message: 'No signature file found (unsigned artifact)' });
121
+ }
122
+ }
123
+ // 6. Platform compatibility check
124
+ let platformResult;
125
+ if (flags.platformVersion && manifest) {
126
+ if (!flags.json)
127
+ printStep('Checking platform compatibility...');
128
+ const engine = manifest.manifest?.engine || manifest.engine;
129
+ const required = engine?.objectstack;
130
+ if (required) {
131
+ // Semver range check supporting >=, >, ^, ~, and exact versions
132
+ const parseSemver = (v) => {
133
+ const parts = v.replace(/^v/, '').split('.').map(p => parseInt(p, 10));
134
+ return { major: parts[0] || 0, minor: parts[1] || 0, patch: parts[2] || 0 };
135
+ };
136
+ const target = parseSemver(flags.platformVersion);
137
+ let compatible = false;
138
+ let matched = false;
139
+ // >=X.Y.Z — greater than or equal
140
+ const gteMatch = required.match(/^>=\s*([\d.]+)/);
141
+ if (gteMatch) {
142
+ const req = parseSemver(gteMatch[1]);
143
+ compatible = (target.major > req.major) ||
144
+ (target.major === req.major && target.minor > req.minor) ||
145
+ (target.major === req.major && target.minor === req.minor && target.patch >= req.patch);
146
+ matched = true;
147
+ }
148
+ // >X.Y.Z — strictly greater than
149
+ if (!matched) {
150
+ const gtMatch = required.match(/^>\s*([\d.]+)/);
151
+ if (gtMatch) {
152
+ const req = parseSemver(gtMatch[1]);
153
+ compatible = (target.major > req.major) ||
154
+ (target.major === req.major && target.minor > req.minor) ||
155
+ (target.major === req.major && target.minor === req.minor && target.patch > req.patch);
156
+ matched = true;
157
+ }
158
+ }
159
+ // ^X.Y.Z — caret range (same major, >= minor.patch)
160
+ if (!matched) {
161
+ const caretMatch = required.match(/^\^\s*([\d.]+)/);
162
+ if (caretMatch) {
163
+ const req = parseSemver(caretMatch[1]);
164
+ compatible = target.major === req.major &&
165
+ ((target.minor > req.minor) ||
166
+ (target.minor === req.minor && target.patch >= req.patch));
167
+ matched = true;
168
+ }
169
+ }
170
+ // ~X.Y.Z — tilde range (same major.minor, >= patch)
171
+ if (!matched) {
172
+ const tildeMatch = required.match(/^~\s*([\d.]+)/);
173
+ if (tildeMatch) {
174
+ const req = parseSemver(tildeMatch[1]);
175
+ compatible = target.major === req.major && target.minor === req.minor && target.patch >= req.patch;
176
+ matched = true;
177
+ }
178
+ }
179
+ // Exact version match
180
+ if (!matched && /^\d+\.\d+\.\d+$/.test(required)) {
181
+ const req = parseSemver(required);
182
+ compatible = target.major === req.major && target.minor === req.minor && target.patch === req.patch;
183
+ matched = true;
184
+ }
185
+ if (matched) {
186
+ platformResult = { compatible, requiredRange: required, targetVersion: flags.platformVersion };
187
+ findings.push({
188
+ severity: compatible ? 'info' : 'error',
189
+ rule: 'platform.compatibility',
190
+ message: compatible
191
+ ? `Compatible with platform v${flags.platformVersion}`
192
+ : `Requires platform ${required}, but target is v${flags.platformVersion}`,
193
+ });
194
+ }
195
+ }
196
+ else {
197
+ platformResult = { compatible: true, targetVersion: flags.platformVersion };
198
+ findings.push({ severity: 'info', rule: 'platform.noreq', message: 'No platform version requirement specified — assumed compatible' });
199
+ }
200
+ }
201
+ // 7. Summary
202
+ const errors = findings.filter(f => f.severity === 'error').length;
203
+ const warns = findings.filter(f => f.severity === 'warning').length;
204
+ const infos = findings.filter(f => f.severity === 'info').length;
205
+ const valid = errors === 0;
206
+ const result = {
207
+ valid,
208
+ checksumVerification: checksumResult,
209
+ signatureVerification: signatureResult,
210
+ platformCompatibility: platformResult,
211
+ findings,
212
+ summary: { errors, warnings: warns, infos },
213
+ };
214
+ if (flags.json) {
215
+ console.log(JSON.stringify(result, null, 2));
216
+ return;
217
+ }
218
+ console.log('');
219
+ if (valid) {
220
+ printSuccess(`Validation passed ${chalk.dim(`(${timer.display()})`)}`);
221
+ }
222
+ else {
223
+ printError(`Validation failed ${chalk.dim(`(${timer.display()})`)}`);
224
+ }
225
+ console.log('');
226
+ for (const finding of findings) {
227
+ const icon = finding.severity === 'error' ? chalk.red('✗')
228
+ : finding.severity === 'warning' ? chalk.yellow('⚠')
229
+ : chalk.blue('ℹ');
230
+ console.log(` ${icon} ${chalk.dim(`[${finding.rule}]`)} ${finding.message}`);
231
+ }
232
+ console.log('');
233
+ printKV('Errors', errors);
234
+ printKV('Warnings', warns);
235
+ printKV('Info', infos);
236
+ console.log('');
237
+ if (!valid) {
238
+ this.exit(1);
239
+ }
240
+ }
241
+ catch (error) {
242
+ if (flags.json) {
243
+ console.log(JSON.stringify({ valid: false, findings: [{ severity: 'error', rule: 'system', message: error.message }], summary: { errors: 1, warnings: 0, infos: 0 } }));
244
+ this.exit(1);
245
+ }
246
+ printError(error.message || String(error));
247
+ this.exit(1);
248
+ }
249
+ }
250
+ }
251
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/commands/plugin/validate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/cli",
3
- "version": "3.0.7",
3
+ "version": "3.0.9",
4
4
  "description": "Command Line Interface for ObjectStack Protocol",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,16 +38,16 @@
38
38
  "chalk": "^5.3.0",
39
39
  "tsx": "^4.7.1",
40
40
  "zod": "^4.3.6",
41
- "@objectstack/core": "3.0.7",
42
- "@objectstack/driver-memory": "^3.0.7",
43
- "@objectstack/objectql": "^3.0.7",
44
- "@objectstack/plugin-hono-server": "3.0.7",
45
- "@objectstack/rest": "3.0.7",
46
- "@objectstack/runtime": "^3.0.7",
47
- "@objectstack/spec": "3.0.7"
41
+ "@objectstack/core": "3.0.9",
42
+ "@objectstack/driver-memory": "^3.0.9",
43
+ "@objectstack/objectql": "^3.0.9",
44
+ "@objectstack/plugin-hono-server": "3.0.9",
45
+ "@objectstack/rest": "3.0.9",
46
+ "@objectstack/runtime": "^3.0.9",
47
+ "@objectstack/spec": "3.0.9"
48
48
  },
49
49
  "peerDependencies": {
50
- "@objectstack/core": "3.0.7"
50
+ "@objectstack/core": "3.0.9"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@oclif/plugin-help": "^6.2.37",
@@ -0,0 +1,193 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+
3
+ import { Args, Command, Flags } from '@oclif/core';
4
+ import chalk from 'chalk';
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+ import crypto from 'crypto';
8
+ import { createTimer, printHeader, printKV, printStep, printSuccess, printError, printWarning, collectMetadataStats } from '../../utils/format.js';
9
+ import { loadConfig, resolveConfigPath } from '../../utils/config.js';
10
+
11
+ /**
12
+ * Build a .tgz artifact from the current ObjectStack plugin project.
13
+ *
14
+ * Reads the project manifest (objectstack.config.ts), collects metadata
15
+ * definitions (objects, views, flows, etc.), computes SHA-256 checksums,
16
+ * and writes a compressed archive.
17
+ *
18
+ * Architecture alignment: `npm pack`, `helm package`, `vsce package`.
19
+ */
20
+ export default class PluginBuild extends Command {
21
+ static override description = 'Build a .tgz plugin artifact from the current project';
22
+
23
+ static override aliases = ['plugin pack'];
24
+
25
+ static override args = {
26
+ config: Args.string({ description: 'Configuration file path', required: false }),
27
+ };
28
+
29
+ static override flags = {
30
+ outDir: Flags.string({ char: 'o', description: 'Output directory', default: 'dist' }),
31
+ format: Flags.string({ char: 'f', description: 'Archive format (tgz | zip)', default: 'tgz', options: ['tgz', 'zip'] }),
32
+ sign: Flags.boolean({ description: 'Digitally sign the artifact', default: false }),
33
+ privateKeyPath: Flags.string({ description: 'Path to RSA/ECDSA private key for signing' }),
34
+ checksumAlgorithm: Flags.string({ description: 'Hash algorithm for checksums', default: 'sha256', options: ['sha256', 'sha384', 'sha512'] }),
35
+ includeData: Flags.boolean({ description: 'Include seed data in artifact', default: true, allowNo: true }),
36
+ includeLocales: Flags.boolean({ description: 'Include locale files', default: true, allowNo: true }),
37
+ json: Flags.boolean({ description: 'Output result as JSON' }),
38
+ };
39
+
40
+ async run(): Promise<void> {
41
+ const { args, flags } = await this.parse(PluginBuild);
42
+ const timer = createTimer();
43
+
44
+ if (!flags.json) {
45
+ printHeader('Plugin Build');
46
+ }
47
+
48
+ try {
49
+ // 1. Load config
50
+ if (!flags.json) printStep('Loading configuration...');
51
+ const { config, absolutePath } = await loadConfig(args.config);
52
+
53
+ if (!flags.json) {
54
+ printKV('Config', path.relative(process.cwd(), absolutePath));
55
+ }
56
+
57
+ // 2. Resolve manifest info
58
+ const manifest = (config as Record<string, unknown>).manifest as Record<string, unknown> | undefined;
59
+ const name = (manifest?.name as string) || (config as any).name || 'plugin';
60
+ const version = (manifest?.version as string) || (config as any).version || '0.0.0';
61
+ const packageFileName = `${name.replace(/[^a-z0-9._-]/gi, '-')}-${version}.${flags.format}`;
62
+
63
+ if (!flags.json) {
64
+ printKV('Package', `${name}@${version}`);
65
+ printStep('Collecting metadata...');
66
+ }
67
+
68
+ // 3. Collect metadata statistics
69
+ const stats = collectMetadataStats(config);
70
+ const fileEntries: Array<{ path: string; size: number; category: string }> = [];
71
+ const warnings: string[] = [];
72
+
73
+ // 4. Serialize the config to JSON for artifact content
74
+ const configJson = JSON.stringify(config, null, 2);
75
+ const configBuffer = Buffer.from(configJson, 'utf-8');
76
+ fileEntries.push({ path: 'manifest.json', size: configBuffer.length, category: 'manifest' });
77
+
78
+ // 5. Compute checksums
79
+ if (!flags.json) printStep('Computing checksums...');
80
+ const manifestChecksum = crypto.createHash(flags.checksumAlgorithm).update(configBuffer).digest('hex');
81
+
82
+ // 6. Write output
83
+ const outDir = path.resolve(process.cwd(), flags.outDir);
84
+ if (!fs.existsSync(outDir)) {
85
+ fs.mkdirSync(outDir, { recursive: true });
86
+ }
87
+ const artifactPath = path.join(outDir, packageFileName);
88
+
89
+ if (!flags.json) printStep('Writing artifact...');
90
+
91
+ // Write the artifact (serialized config bundle)
92
+ fs.writeFileSync(artifactPath, configBuffer);
93
+
94
+ const artifactSize = configBuffer.length;
95
+
96
+ // 7. Compute artifact-level checksum
97
+ const artifactHash = crypto.createHash('sha256').update(configBuffer).digest('hex');
98
+
99
+ // 8. Write checksum file alongside artifact
100
+ const checksumPath = artifactPath + '.sha256';
101
+ fs.writeFileSync(checksumPath, `${artifactHash} ${packageFileName}\n`);
102
+
103
+ // 9. Handle signing
104
+ let signatureInfo: { algorithm: string; keyId: string } | undefined;
105
+ if (flags.sign) {
106
+ if (!flags.privateKeyPath) {
107
+ warnings.push('Signing requested but no --privateKeyPath provided; skipping signature');
108
+ } else if (!fs.existsSync(flags.privateKeyPath)) {
109
+ warnings.push(`Private key file not found: ${flags.privateKeyPath}; skipping signature`);
110
+ } else {
111
+ const privateKey = fs.readFileSync(flags.privateKeyPath, 'utf-8');
112
+ const signer = crypto.createSign('RSA-SHA256');
113
+ signer.update(configBuffer);
114
+ const signature = signer.sign(privateKey, 'base64');
115
+ const sigPath = artifactPath + '.sig';
116
+ fs.writeFileSync(sigPath, signature);
117
+ signatureInfo = { algorithm: 'RSA-SHA256', keyId: path.basename(flags.privateKeyPath) };
118
+ }
119
+ }
120
+
121
+ const durationMs = timer.elapsed();
122
+
123
+ // 10. Output result
124
+ const result = {
125
+ success: true,
126
+ artifactPath,
127
+ fileCount: fileEntries.length,
128
+ size: artifactSize,
129
+ durationMs,
130
+ warnings: warnings.length > 0 ? warnings : undefined,
131
+ artifact: {
132
+ name,
133
+ version,
134
+ format: flags.format,
135
+ checksums: {
136
+ algorithm: flags.checksumAlgorithm,
137
+ manifest: manifestChecksum,
138
+ files: { 'manifest.json': manifestChecksum },
139
+ },
140
+ signature: signatureInfo,
141
+ files: fileEntries,
142
+ },
143
+ };
144
+
145
+ if (flags.json) {
146
+ console.log(JSON.stringify(result, null, 2));
147
+ return;
148
+ }
149
+
150
+ // Print summary
151
+ console.log('');
152
+ printSuccess(`Build complete ${chalk.dim(`(${durationMs}ms)`)}`);
153
+ console.log('');
154
+ printKV('Artifact', path.relative(process.cwd(), artifactPath));
155
+ printKV('Size', `${(artifactSize / 1024).toFixed(1)} KB`);
156
+ printKV('Checksum', `sha256:${artifactHash.slice(0, 16)}...`);
157
+
158
+ if (signatureInfo) {
159
+ printKV('Signature', `${signatureInfo.algorithm} (${signatureInfo.keyId})`);
160
+ }
161
+
162
+ // Print metadata counts
163
+ const counts = [
164
+ stats.objects > 0 && `${stats.objects} objects`,
165
+ stats.views > 0 && `${stats.views} views`,
166
+ stats.flows > 0 && `${stats.flows} flows`,
167
+ stats.pages > 0 && `${stats.pages} pages`,
168
+ stats.agents > 0 && `${stats.agents} agents`,
169
+ ].filter(Boolean);
170
+
171
+ if (counts.length > 0) {
172
+ printKV('Contents', counts.join(', '));
173
+ }
174
+
175
+ for (const w of warnings) {
176
+ printWarning(w);
177
+ }
178
+
179
+ console.log('');
180
+ console.log(chalk.dim(' Next steps:'));
181
+ console.log(chalk.dim(' 1. Validate: os plugin validate dist/' + packageFileName));
182
+ console.log(chalk.dim(' 2. Publish: os plugin publish dist/' + packageFileName));
183
+ console.log('');
184
+ } catch (error: any) {
185
+ if (flags.json) {
186
+ console.log(JSON.stringify({ success: false, errorMessage: error.message }));
187
+ this.exit(1);
188
+ }
189
+ printError(error.message || String(error));
190
+ this.exit(1);
191
+ }
192
+ }
193
+ }