@kumos/tree-sitter-parsers 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ivan Porto Carrero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # Breeze Tree-sitter Parsers
2
+
3
+ Pre-compiled Tree-sitter parsers for 163 programming languages, distributed as native binaries via npm.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @kumos/tree-sitter-parsers
9
+ ```
10
+
11
+ The appropriate binary for your platform will be automatically downloaded during installation.
12
+
13
+ ## Usage
14
+
15
+ ### Get the binary path
16
+
17
+ ```js
18
+ const { binaryPath, metadataPath } = require('@kumos/tree-sitter-parsers');
19
+
20
+ console.log(binaryPath); // Path to the static library
21
+ console.log(metadataPath); // Path to the grammars metadata JSON
22
+ ```
23
+
24
+ ### Command-line usage
25
+
26
+ ```bash
27
+ # Get the path to the binary
28
+ npx tree-sitter-parsers-path
29
+ ```
30
+
31
+ ### Build tools integration
32
+
33
+ The binary path can be used in build scripts:
34
+
35
+ ```bash
36
+ # In a build script
37
+ PARSER_LIB=$(npx tree-sitter-parsers-path)
38
+ gcc myapp.c $PARSER_LIB -o myapp
39
+ ```
40
+
41
+ ## Supported Platforms
42
+
43
+ - Linux x64 (glibc and musl)
44
+ - Linux ARM64 (glibc and musl)
45
+ - macOS x64
46
+ - macOS ARM64
47
+ - Windows x64
48
+ - Windows ARM64
49
+
50
+ ## Building from Source
51
+
52
+ ### Prerequisites
53
+
54
+ - Node.js 20+
55
+ - Git
56
+ - Zig (for cross-compilation)
57
+ - C/C++ compiler (for native builds)
58
+
59
+ ### Build Commands
60
+
61
+ ```bash
62
+ # Clone the repository
63
+ git clone https://github.com/casualjim/breeze-tree-sitter-parsers.git
64
+ cd breeze-tree-sitter-parsers
65
+
66
+ # Fetch all grammar repositories
67
+ npm run fetch
68
+
69
+ # Build for current platform
70
+ npm run build
71
+
72
+ # Build for all platforms (requires Zig)
73
+ npm run build:all
74
+
75
+ # Create npm packages for distribution
76
+ npm run create-packages
77
+ ```
78
+
79
+ ## Architecture
80
+
81
+ This project consists of:
82
+
83
+ 1. **Main package** (`@kumos/tree-sitter-parsers`) - Platform detection and binary resolution
84
+ 2. **Platform packages** - Platform-specific binaries (e.g., `@kumos/tree-sitter-parsers-darwin-arm64`)
85
+
86
+ The main package uses npm's `optionalDependencies` to install only the relevant platform binary. If the platform package isn't available, it falls back to downloading the binary from GitHub releases.
87
+
88
+ ## License
89
+
90
+ MIT
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ try {
4
+ const { binaryPath } = require('../index.js');
5
+ console.log(binaryPath);
6
+ process.exit(0);
7
+ } catch (error) {
8
+ console.error(error.message);
9
+ process.exit(1);
10
+ }
package/index.js ADDED
@@ -0,0 +1,128 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+
5
+ function getPlatformPackage() {
6
+ const platform = os.platform();
7
+ const arch = os.arch();
8
+
9
+ let platformPackage;
10
+
11
+ switch (platform) {
12
+ case 'darwin':
13
+ platformPackage = `@kumos/tree-sitter-parsers-darwin-${arch === 'arm64' ? 'arm64' : 'x64'}`;
14
+ break;
15
+ case 'linux':
16
+ // Check if using musl libc (Alpine Linux, etc.)
17
+ const isMusl = (() => {
18
+ try {
19
+ // First try ldd
20
+ const lddOutput = require('child_process').execSync('ldd --version 2>&1', { encoding: 'utf8' });
21
+ if (lddOutput.includes('musl')) return true;
22
+ } catch {
23
+ // ldd might not exist or fail
24
+ }
25
+
26
+ // Check if /lib/ld-musl* exists (Alpine/musl systems)
27
+ try {
28
+ const files = fs.readdirSync('/lib');
29
+ return files.some(f => f.startsWith('ld-musl'));
30
+ } catch {
31
+ return false;
32
+ }
33
+ })();
34
+
35
+ const archSuffix = arch === 'arm64' ? 'arm64' : 'x64';
36
+ platformPackage = `@kumos/tree-sitter-parsers-linux-${archSuffix}${isMusl ? '-musl' : ''}`;
37
+ break;
38
+ case 'win32':
39
+ platformPackage = `@kumos/tree-sitter-parsers-win32-${arch === 'arm64' ? 'arm64' : 'x64'}`;
40
+ break;
41
+ default:
42
+ throw new Error(`Unsupported platform: ${platform} ${arch}`);
43
+ }
44
+
45
+ return platformPackage;
46
+ }
47
+
48
+ function getBinaryPath() {
49
+ const platformPackage = getPlatformPackage();
50
+
51
+ try {
52
+ // Try to resolve the platform-specific package
53
+ const packagePath = require.resolve(platformPackage);
54
+ const packageDir = path.dirname(packagePath);
55
+
56
+ // Map platform to expected binary filename
57
+ const platform = os.platform();
58
+ const arch = os.arch();
59
+ let binaryName;
60
+
61
+ switch (platform) {
62
+ case 'darwin':
63
+ binaryName = `libtree-sitter-parsers-all-macos-${arch === 'arm64' ? 'aarch64' : 'x86_64'}.a`;
64
+ break;
65
+ case 'linux':
66
+ const isMusl = platformPackage.includes('musl');
67
+ const archName = arch === 'arm64' ? 'aarch64' : 'x86_64';
68
+ binaryName = `libtree-sitter-parsers-all-linux-${archName}-${isMusl ? 'musl' : 'glibc'}.a`;
69
+ break;
70
+ case 'win32':
71
+ binaryName = `libtree-sitter-parsers-all-windows-${arch === 'arm64' ? 'aarch64' : 'x86_64'}.a`;
72
+ break;
73
+ }
74
+
75
+ const binaryPath = path.join(packageDir, binaryName);
76
+
77
+ if (fs.existsSync(binaryPath)) {
78
+ return binaryPath;
79
+ }
80
+
81
+ // Fallback to downloaded binary location
82
+ const fallbackPath = path.join(__dirname, 'binaries', binaryName);
83
+ if (fs.existsSync(fallbackPath)) {
84
+ return fallbackPath;
85
+ }
86
+
87
+ throw new Error(`Binary not found at ${binaryPath} or ${fallbackPath}`);
88
+ } catch (error) {
89
+ // Platform package not installed, check fallback location
90
+ const fallbackDir = path.join(__dirname, 'binaries');
91
+ if (fs.existsSync(fallbackDir)) {
92
+ const files = fs.readdirSync(fallbackDir);
93
+ const binary = files.find(f => f.endsWith('.a'));
94
+ if (binary) {
95
+ return path.join(fallbackDir, binary);
96
+ }
97
+ }
98
+
99
+ throw new Error(`Could not find tree-sitter parsers binary. Platform package ${platformPackage} not installed and no fallback binary found.`);
100
+ }
101
+ }
102
+
103
+ function getMetadataPath() {
104
+ const binaryPath = getBinaryPath();
105
+ const dir = path.dirname(binaryPath);
106
+ const binaryName = path.basename(binaryPath, '.a');
107
+ const metadataName = binaryName.replace('libtree-sitter-parsers-all-', 'grammars-') + '.json';
108
+ return path.join(dir, metadataName);
109
+ }
110
+
111
+ const binaryPath = getBinaryPath();
112
+ const metadataPath = getMetadataPath();
113
+
114
+ module.exports = {
115
+ binaryPath,
116
+ metadataPath,
117
+ platformPackage: getPlatformPackage(),
118
+
119
+ // Utility function to get all available grammars
120
+ getGrammars() {
121
+ try {
122
+ return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
123
+ } catch (error) {
124
+ console.error('Failed to load grammars metadata:', error);
125
+ return [];
126
+ }
127
+ }
128
+ };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "author": "",
3
+ "bin": {
4
+ "tree-sitter-parsers-path": "./bin/tree-sitter-parsers-path.js"
5
+ },
6
+ "description": "Pre-compiled Tree-sitter parsers for 163 programming languages",
7
+ "devDependencies": {
8
+ "tree-sitter-cli": "^0.25.6"
9
+ },
10
+ "engines": {
11
+ "node": ">=20.0.0"
12
+ },
13
+ "files": [
14
+ "index.js",
15
+ "postinstall.js",
16
+ "bin/"
17
+ ],
18
+ "keywords": [
19
+ "tree-sitter",
20
+ "parser",
21
+ "syntax",
22
+ "ast"
23
+ ],
24
+ "license": "MIT",
25
+ "main": "index.js",
26
+ "name": "@kumos/tree-sitter-parsers",
27
+ "optionalDependencies": {
28
+ "@kumos/tree-sitter-parsers-darwin-arm64": "0.1.1",
29
+ "@kumos/tree-sitter-parsers-darwin-x64": "0.1.1",
30
+ "@kumos/tree-sitter-parsers-linux-arm64": "0.1.1",
31
+ "@kumos/tree-sitter-parsers-linux-arm64-musl": "0.1.1",
32
+ "@kumos/tree-sitter-parsers-linux-x64": "0.1.1",
33
+ "@kumos/tree-sitter-parsers-linux-x64-musl": "0.1.1",
34
+ "@kumos/tree-sitter-parsers-win32-arm64": "0.1.1",
35
+ "@kumos/tree-sitter-parsers-win32-x64": "0.1.1"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/casualjim/breeze-tree-sitter-parsers.git"
40
+ },
41
+ "scripts": {
42
+ "build": "node build-grammars.js",
43
+ "build:all": "node build-grammars.js --all-platforms",
44
+ "compile": "node build-grammars.js --compile-only",
45
+ "create-packages": "node create-platform-packages.js",
46
+ "fetch": "node build-grammars.js --fetch-only",
47
+ "postinstall": "node postinstall.js",
48
+ "publish-all": "bash publish-packages.sh",
49
+ "test-distribution": "node test-distribution.js",
50
+ "test-distribution:arm64": "node test-distribution.js --arch arm64",
51
+ "test-distribution:x64": "node test-distribution.js --arch x64"
52
+ },
53
+ "version": "0.1.1"
54
+ }
package/postinstall.js ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+
3
+ const os = require('os');
4
+ const path = require('path');
5
+ const fs = require('fs');
6
+ const https = require('https');
7
+ const { promisify } = require('util');
8
+ const pipeline = promisify(require('stream').pipeline);
9
+
10
+ // Configuration
11
+ const REPO_OWNER = 'casualjim';
12
+ const REPO_NAME = 'breeze-tree-sitter-parsers';
13
+ const VERSION = require('./package.json').version;
14
+
15
+ async function downloadFile(url, destination) {
16
+ const dir = path.dirname(destination);
17
+ if (!fs.existsSync(dir)) {
18
+ fs.mkdirSync(dir, { recursive: true });
19
+ }
20
+
21
+ return new Promise((resolve, reject) => {
22
+ https.get(url, { headers: { 'User-Agent': 'breeze-tree-sitter-parsers' } }, (response) => {
23
+ if (response.statusCode === 302 || response.statusCode === 301) {
24
+ // Follow redirect
25
+ downloadFile(response.headers.location, destination).then(resolve).catch(reject);
26
+ return;
27
+ }
28
+
29
+ if (response.statusCode !== 200) {
30
+ reject(new Error(`Failed to download: ${response.statusCode}`));
31
+ return;
32
+ }
33
+
34
+ const file = fs.createWriteStream(destination);
35
+ pipeline(response, file)
36
+ .then(() => resolve())
37
+ .catch(reject);
38
+ }).on('error', reject);
39
+ });
40
+ }
41
+
42
+ function getPlatformBinaryName() {
43
+ const platform = os.platform();
44
+ const arch = os.arch();
45
+
46
+ switch (platform) {
47
+ case 'darwin':
48
+ return `libtree-sitter-parsers-all-macos-${arch === 'arm64' ? 'aarch64' : 'x86_64'}.a`;
49
+ case 'linux':
50
+ // Try to detect musl
51
+ const isMusl = (() => {
52
+ try {
53
+ // First try ldd
54
+ const lddOutput = require('child_process').execSync('ldd --version 2>&1', { encoding: 'utf8' });
55
+ if (lddOutput.includes('musl')) return true;
56
+ } catch {
57
+ // ldd might not exist or fail
58
+ }
59
+
60
+ // Check if /lib/ld-musl* exists (Alpine/musl systems)
61
+ try {
62
+ const fs = require('fs');
63
+ const files = fs.readdirSync('/lib');
64
+ return files.some(f => f.startsWith('ld-musl'));
65
+ } catch {
66
+ return false;
67
+ }
68
+ })();
69
+
70
+ const archName = arch === 'arm64' ? 'aarch64' : 'x86_64';
71
+ return `libtree-sitter-parsers-all-linux-${archName}-${isMusl ? 'musl' : 'glibc'}.a`;
72
+ case 'win32':
73
+ return `libtree-sitter-parsers-all-windows-${arch === 'arm64' ? 'aarch64' : 'x86_64'}.a`;
74
+ default:
75
+ throw new Error(`Unsupported platform: ${platform} ${arch}`);
76
+ }
77
+ }
78
+
79
+ function getMetadataFileName() {
80
+ const binaryName = getPlatformBinaryName();
81
+ return binaryName.replace('libtree-sitter-parsers-all-', 'grammars-').replace('.a', '.json');
82
+ }
83
+
84
+ async function checkOptionalDependency() {
85
+ try {
86
+ // Simply try to load the main module - if it works, we have what we need
87
+ const { binaryPath, metadataPath } = require('./index.js');
88
+
89
+ // Verify the files actually exist
90
+ if (fs.existsSync(binaryPath) && fs.existsSync(metadataPath)) {
91
+ console.log('Tree-sitter parsers binary found.');
92
+ return true;
93
+ }
94
+ console.log(`Binary not found at: ${binaryPath}`);
95
+ console.log(`Metadata not found at: ${metadataPath}`);
96
+ } catch (error) {
97
+ // Binary not found via normal package installation
98
+ console.log('Error loading index.js:', error.message);
99
+ }
100
+
101
+ console.log('Binary not found in platform package, will use fallback download.');
102
+ return false;
103
+ }
104
+
105
+ async function downloadBinaries() {
106
+ const binaryName = getPlatformBinaryName();
107
+ const metadataName = getMetadataFileName();
108
+ const binariesDir = path.join(__dirname, 'binaries');
109
+
110
+ const binaryPath = path.join(binariesDir, binaryName);
111
+ const metadataPath = path.join(binariesDir, metadataName);
112
+
113
+ // Check if already downloaded
114
+ if (fs.existsSync(binaryPath) && fs.existsSync(metadataPath)) {
115
+ console.log('Binaries already downloaded.');
116
+ return;
117
+ }
118
+
119
+ console.log(`Downloading tree-sitter parsers for your platform...`);
120
+
121
+ // Construct download URLs
122
+ const releaseUrl = `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/v${VERSION}`;
123
+ const binaryUrl = `${releaseUrl}/${binaryName}`;
124
+ const metadataUrl = `${releaseUrl}/${metadataName}`;
125
+
126
+ try {
127
+ // Download both files
128
+ console.log(`Downloading ${binaryName}...`);
129
+ await downloadFile(binaryUrl, binaryPath);
130
+
131
+ console.log(`Downloading ${metadataName}...`);
132
+ await downloadFile(metadataUrl, metadataPath);
133
+
134
+ console.log('Download complete!');
135
+ } catch (error) {
136
+ console.error('Failed to download binaries:', error.message);
137
+ console.error('You may need to manually download the binaries from:');
138
+ console.error(` ${binaryUrl}`);
139
+ console.error(` ${metadataUrl}`);
140
+ process.exit(1);
141
+ }
142
+ }
143
+
144
+ async function main() {
145
+ // Skip in CI environments or when explicitly disabled
146
+ if (process.env.CI || process.env.BREEZE_SKIP_DOWNLOAD) {
147
+ console.log('Skipping postinstall download.');
148
+ return;
149
+ }
150
+
151
+ // Check if optional dependency was installed
152
+ const hasOptionalDep = await checkOptionalDependency();
153
+
154
+ if (!hasOptionalDep) {
155
+ console.log('Downloading tree-sitter parsers for your platform...');
156
+ await downloadBinaries();
157
+ }
158
+ }
159
+
160
+ // Only run if called directly
161
+ if (require.main === module) {
162
+ main().catch(error => {
163
+ console.error('Postinstall failed:', error);
164
+ process.exit(1);
165
+ });
166
+ }