@cdm-lang/cli 0.1.34
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 +101 -0
- package/README.npm.md +97 -0
- package/bin/cdm.js +36 -0
- package/index.js +29 -0
- package/package.json +52 -0
- package/scripts/install.js +159 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# CDM CLI - npm Package
|
|
2
|
+
|
|
3
|
+
This directory contains the npm distribution package for CDM CLI. The npm package automatically downloads and installs the appropriate pre-built binary for the user's platform.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm/
|
|
9
|
+
├── package.json # npm package configuration
|
|
10
|
+
├── index.js # Module entry point for programmatic usage
|
|
11
|
+
├── bin/
|
|
12
|
+
│ └── cdm.js # CLI wrapper script
|
|
13
|
+
├── scripts/
|
|
14
|
+
│ └── install.js # Post-install script to download binary
|
|
15
|
+
├── .npmignore # Files to exclude from npm package
|
|
16
|
+
└── README.npm.md # README shown on npm registry
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
|
|
21
|
+
1. User runs `npm install @cdm-lang/cli`
|
|
22
|
+
2. The `postinstall` script (`scripts/install.js`) runs automatically
|
|
23
|
+
3. It detects the user's platform and architecture
|
|
24
|
+
4. Downloads the appropriate pre-built binary from GitHub releases
|
|
25
|
+
5. Verifies the checksum for security
|
|
26
|
+
6. Makes the binary executable (Unix-like systems)
|
|
27
|
+
7. The `bin/cdm.js` wrapper allows users to run `cdm` commands
|
|
28
|
+
|
|
29
|
+
## Publishing to npm
|
|
30
|
+
|
|
31
|
+
### Prerequisites
|
|
32
|
+
|
|
33
|
+
1. Make sure you're logged into npm:
|
|
34
|
+
```bash
|
|
35
|
+
npm login
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. Ensure the version in `package.json` matches the Cargo version
|
|
39
|
+
|
|
40
|
+
### Publish Steps
|
|
41
|
+
|
|
42
|
+
1. Navigate to the npm directory:
|
|
43
|
+
```bash
|
|
44
|
+
cd npm
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
2. Test the package locally:
|
|
48
|
+
```bash
|
|
49
|
+
npm install
|
|
50
|
+
npm pack
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
3. Publish to npm:
|
|
54
|
+
```bash
|
|
55
|
+
npm publish --access public
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Note: The `--access public` flag is required for scoped packages (@cdm-lang/cli)
|
|
59
|
+
|
|
60
|
+
### Automation
|
|
61
|
+
|
|
62
|
+
You can automate npm publishing in the GitHub release workflow by adding an npm publish step after the CLI binaries are released.
|
|
63
|
+
|
|
64
|
+
## Testing Locally
|
|
65
|
+
|
|
66
|
+
Before publishing, test the package locally:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cd npm
|
|
70
|
+
npm install
|
|
71
|
+
./bin/cdm.js --help
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or test as if installed globally:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
cd npm
|
|
78
|
+
npm pack
|
|
79
|
+
npm install -g cdm-lang-cli-<version>.tgz
|
|
80
|
+
cdm --help
|
|
81
|
+
npm uninstall -g @cdm-lang/cli
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Version Management
|
|
85
|
+
|
|
86
|
+
Keep the version in `npm/package.json` synchronized with `crates/cdm/Cargo.toml`. When cutting a new release:
|
|
87
|
+
|
|
88
|
+
1. Update version in `Cargo.toml`
|
|
89
|
+
2. Update version in `npm/package.json`
|
|
90
|
+
3. Create git tag and push (triggers GitHub release)
|
|
91
|
+
4. After binaries are built, publish to npm
|
|
92
|
+
|
|
93
|
+
## Important Notes on Self-Update
|
|
94
|
+
|
|
95
|
+
The CDM CLI has a built-in `cdm update` command that can update the binary directly. However, when CDM is installed via npm, users should be aware:
|
|
96
|
+
|
|
97
|
+
- `cdm update` will work and update the binary in `node_modules/@cdm-lang/cli/bin/cdm`
|
|
98
|
+
- However, this creates a version mismatch - npm will still think the old version is installed
|
|
99
|
+
- Running `npm install` again will re-download the version specified in `package.json`, overwriting manual updates
|
|
100
|
+
|
|
101
|
+
**Recommendation**: Users should update via npm (`npm update -g @cdm-lang/cli`) rather than using `cdm update` to keep package versions in sync. This is documented in `README.npm.md`.
|
package/README.npm.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# CDM CLI
|
|
2
|
+
|
|
3
|
+
**CDM (Common Data Model)** is a language for defining data models and generating code across multiple platforms.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install via npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @cdm-lang/cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or use it in a project:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install --save-dev @cdm-lang/cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
After installation, the `cdm` command will be available:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cdm --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Command Line
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Run CDM CLI
|
|
31
|
+
cdm <command> [options]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Programmatic Usage
|
|
35
|
+
|
|
36
|
+
You can also use CDM programmatically in Node.js:
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
const cdm = require('@cdm-lang/cli');
|
|
40
|
+
|
|
41
|
+
// Get the path to the binary
|
|
42
|
+
const binaryPath = cdm.getBinaryPath();
|
|
43
|
+
console.log('CDM binary location:', binaryPath);
|
|
44
|
+
|
|
45
|
+
// Run CDM with arguments
|
|
46
|
+
const exitCode = cdm.run(['--help']);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## How It Works
|
|
50
|
+
|
|
51
|
+
This npm package automatically downloads the appropriate pre-built CDM binary for your platform during installation. The binary is built from Rust and distributed via GitHub releases.
|
|
52
|
+
|
|
53
|
+
### Supported Platforms
|
|
54
|
+
|
|
55
|
+
- macOS (Intel x64)
|
|
56
|
+
- macOS (Apple Silicon arm64)
|
|
57
|
+
- Linux (x64)
|
|
58
|
+
- Linux (ARM64)
|
|
59
|
+
- Windows (x64)
|
|
60
|
+
|
|
61
|
+
## Updating
|
|
62
|
+
|
|
63
|
+
To update CDM to a newer version, use npm:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# For global installations
|
|
67
|
+
npm update -g @cdm-lang/cli
|
|
68
|
+
|
|
69
|
+
# For local project installations
|
|
70
|
+
npm update @cdm-lang/cli
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Note**: The CDM CLI has a built-in `cdm update` command, but when installed via npm, you should use `npm update` instead to keep your npm package registry in sync with the actual binary version.
|
|
74
|
+
|
|
75
|
+
## Troubleshooting
|
|
76
|
+
|
|
77
|
+
If you encounter installation issues:
|
|
78
|
+
|
|
79
|
+
1. Make sure you have a stable internet connection
|
|
80
|
+
2. Try clearing npm cache: `npm cache clean --force`
|
|
81
|
+
3. Reinstall: `npm uninstall -g @cdm-lang/cli && npm install -g @cdm-lang/cli`
|
|
82
|
+
|
|
83
|
+
If the binary fails to download, you can manually install CDM from the [GitHub releases page](https://github.com/cdm-lang/cdm/releases).
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MPL-2.0
|
|
88
|
+
|
|
89
|
+
## Links
|
|
90
|
+
|
|
91
|
+
- [GitHub Repository](https://github.com/cdm-lang/cdm)
|
|
92
|
+
- [Issue Tracker](https://github.com/cdm-lang/cdm/issues)
|
|
93
|
+
- [Releases](https://github.com/cdm-lang/cdm/releases)
|
|
94
|
+
|
|
95
|
+
## Contributing
|
|
96
|
+
|
|
97
|
+
Contributions are welcome! Please visit the [GitHub repository](https://github.com/cdm-lang/cdm) for more information.
|
package/bin/cdm.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
const BINARY_NAME = process.platform === 'win32' ? 'cdm.exe' : 'cdm';
|
|
8
|
+
const BINARY_PATH = path.join(__dirname, BINARY_NAME);
|
|
9
|
+
|
|
10
|
+
// Check if binary exists
|
|
11
|
+
if (!fs.existsSync(BINARY_PATH)) {
|
|
12
|
+
console.error('Error: CDM binary not found.');
|
|
13
|
+
console.error('This usually means the installation did not complete successfully.');
|
|
14
|
+
console.error('Try reinstalling the package: npm install @cdm-lang/cdm');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Spawn the binary with all arguments
|
|
19
|
+
const child = spawn(BINARY_PATH, process.argv.slice(2), {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
windowsHide: true,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
child.on('exit', (code, signal) => {
|
|
25
|
+
if (signal) {
|
|
26
|
+
process.kill(process.pid, signal);
|
|
27
|
+
} else {
|
|
28
|
+
process.exit(code);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Handle process termination
|
|
33
|
+
process.on('SIGINT', () => {
|
|
34
|
+
child.kill('SIGINT');
|
|
35
|
+
child.kill('SIGTERM');
|
|
36
|
+
});
|
package/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawnSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
const BINARY_NAME = process.platform === 'win32' ? 'cdm.exe' : 'cdm';
|
|
7
|
+
const BINARY_PATH = path.join(__dirname, 'bin', BINARY_NAME);
|
|
8
|
+
|
|
9
|
+
function getBinaryPath() {
|
|
10
|
+
return BINARY_PATH;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function run(args = []) {
|
|
14
|
+
const result = spawnSync(BINARY_PATH, args, {
|
|
15
|
+
stdio: 'inherit',
|
|
16
|
+
windowsHide: true,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
if (result.error) {
|
|
20
|
+
throw result.error;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return result.status;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
getBinaryPath,
|
|
28
|
+
run,
|
|
29
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cdm-lang/cli",
|
|
3
|
+
"version": "0.1.34",
|
|
4
|
+
"description": "CDM (Common Data Model) - A language for defining data models and generating code",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"cdm": "./bin/cdm.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"postinstall": "node scripts/install.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cdm",
|
|
15
|
+
"data-model",
|
|
16
|
+
"schema",
|
|
17
|
+
"code-generation",
|
|
18
|
+
"cli",
|
|
19
|
+
"rust"
|
|
20
|
+
],
|
|
21
|
+
"author": "CDM Lang",
|
|
22
|
+
"license": "MPL-2.0",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/cdm-lang/cdm.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/cdm-lang/cdm/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/cdm-lang/cdm#readme",
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=14.0.0"
|
|
36
|
+
},
|
|
37
|
+
"os": [
|
|
38
|
+
"darwin",
|
|
39
|
+
"linux",
|
|
40
|
+
"win32"
|
|
41
|
+
],
|
|
42
|
+
"cpu": [
|
|
43
|
+
"x64",
|
|
44
|
+
"arm64"
|
|
45
|
+
],
|
|
46
|
+
"files": [
|
|
47
|
+
"bin/cdm.js",
|
|
48
|
+
"scripts/",
|
|
49
|
+
"index.js",
|
|
50
|
+
"README.npm.md"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const { promisify } = require('util');
|
|
8
|
+
const { pipeline } = require('stream');
|
|
9
|
+
|
|
10
|
+
const streamPipeline = promisify(pipeline);
|
|
11
|
+
|
|
12
|
+
const MANIFEST_URL = 'https://raw.githubusercontent.com/cdm-lang/cdm/main/cli-releases.json';
|
|
13
|
+
const BINARY_DIR = path.join(__dirname, '..', 'bin');
|
|
14
|
+
const BINARY_NAME = process.platform === 'win32' ? 'cdm.exe' : 'cdm';
|
|
15
|
+
const BINARY_PATH = path.join(BINARY_DIR, BINARY_NAME);
|
|
16
|
+
|
|
17
|
+
function getPlatformInfo() {
|
|
18
|
+
const platform = process.platform;
|
|
19
|
+
const arch = process.arch;
|
|
20
|
+
|
|
21
|
+
const platformMap = {
|
|
22
|
+
darwin: {
|
|
23
|
+
x64: 'x86_64-apple-darwin',
|
|
24
|
+
arm64: 'aarch64-apple-darwin',
|
|
25
|
+
},
|
|
26
|
+
linux: {
|
|
27
|
+
x64: 'x86_64-unknown-linux-gnu',
|
|
28
|
+
arm64: 'aarch64-unknown-linux-gnu',
|
|
29
|
+
},
|
|
30
|
+
win32: {
|
|
31
|
+
x64: 'x86_64-pc-windows-msvc.exe',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (!platformMap[platform] || !platformMap[platform][arch]) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Unsupported platform: ${platform}-${arch}. ` +
|
|
38
|
+
`CDM supports: macOS (x64, arm64), Linux (x64, arm64), Windows (x64)`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return platformMap[platform][arch];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function fetchJSON(url) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
https.get(url, (res) => {
|
|
48
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
49
|
+
return fetchJSON(res.headers.location).then(resolve).catch(reject);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (res.statusCode !== 200) {
|
|
53
|
+
return reject(new Error(`Failed to fetch ${url}: ${res.statusCode}`));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let data = '';
|
|
57
|
+
res.on('data', (chunk) => data += chunk);
|
|
58
|
+
res.on('end', () => {
|
|
59
|
+
try {
|
|
60
|
+
resolve(JSON.parse(data));
|
|
61
|
+
} catch (err) {
|
|
62
|
+
reject(err);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}).on('error', reject);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function downloadFile(url, destPath) {
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
https.get(url, (res) => {
|
|
72
|
+
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
73
|
+
return downloadFile(res.headers.location, destPath).then(resolve).catch(reject);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (res.statusCode !== 200) {
|
|
77
|
+
return reject(new Error(`Failed to download ${url}: ${res.statusCode}`));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
81
|
+
streamPipeline(res, fileStream)
|
|
82
|
+
.then(resolve)
|
|
83
|
+
.catch(reject);
|
|
84
|
+
}).on('error', reject);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function verifyChecksum(filePath, expectedChecksum) {
|
|
89
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
90
|
+
const hash = crypto.createHash('sha256');
|
|
91
|
+
hash.update(fileBuffer);
|
|
92
|
+
const actualChecksum = hash.digest('hex');
|
|
93
|
+
|
|
94
|
+
if (actualChecksum !== expectedChecksum) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Checksum verification failed!\n` +
|
|
97
|
+
`Expected: ${expectedChecksum}\n` +
|
|
98
|
+
`Actual: ${actualChecksum}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function install() {
|
|
104
|
+
console.log('Installing CDM CLI...');
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
// Get platform info
|
|
108
|
+
const platformKey = getPlatformInfo();
|
|
109
|
+
console.log(`Platform: ${platformKey}`);
|
|
110
|
+
|
|
111
|
+
// Fetch manifest
|
|
112
|
+
console.log('Fetching release manifest...');
|
|
113
|
+
const manifest = await fetchJSON(MANIFEST_URL);
|
|
114
|
+
|
|
115
|
+
const latestVersion = manifest.latest;
|
|
116
|
+
console.log(`Latest version: ${latestVersion}`);
|
|
117
|
+
|
|
118
|
+
const release = manifest.releases[latestVersion];
|
|
119
|
+
if (!release) {
|
|
120
|
+
throw new Error(`Release ${latestVersion} not found in manifest`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const platformInfo = release.platforms[platformKey];
|
|
124
|
+
if (!platformInfo) {
|
|
125
|
+
throw new Error(`Platform ${platformKey} not found in release ${latestVersion}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const { url, checksum } = platformInfo;
|
|
129
|
+
const expectedChecksum = checksum.replace('sha256:', '');
|
|
130
|
+
|
|
131
|
+
// Create bin directory
|
|
132
|
+
if (!fs.existsSync(BINARY_DIR)) {
|
|
133
|
+
fs.mkdirSync(BINARY_DIR, { recursive: true });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Download binary
|
|
137
|
+
console.log(`Downloading from ${url}...`);
|
|
138
|
+
await downloadFile(url, BINARY_PATH);
|
|
139
|
+
|
|
140
|
+
// Verify checksum
|
|
141
|
+
console.log('Verifying checksum...');
|
|
142
|
+
verifyChecksum(BINARY_PATH, expectedChecksum);
|
|
143
|
+
|
|
144
|
+
// Make executable (Unix only)
|
|
145
|
+
if (process.platform !== 'win32') {
|
|
146
|
+
fs.chmodSync(BINARY_PATH, 0o755);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
console.log('CDM CLI installed successfully!');
|
|
150
|
+
console.log(`Binary location: ${BINARY_PATH}`);
|
|
151
|
+
console.log('\nRun "cdm --help" to get started.');
|
|
152
|
+
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error('Installation failed:', error.message);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
install();
|