gdx 0.1.0
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 +21 -0
- package/README.md +254 -0
- package/dist/index.js +1018 -0
- package/dist/keytar-hqpjzrak.node +0 -0
- package/package.json +65 -0
- package/scripts/launcher.cjs +37 -0
- package/scripts/postinstall.cjs +272 -0
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gdx",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Git, but with better DX. The raw power of Git, aligned with human workflows.",
|
|
5
|
+
"homepage": "https://github.com/Type-Delta/gdx#readme",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/Type-Delta/gdx/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Type-Delta/gdx.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "Type-Delta",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "dist/index.js",
|
|
17
|
+
"bin": {
|
|
18
|
+
"gdx": "scripts/launcher.cjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist/",
|
|
22
|
+
"scripts/postinstall.cjs",
|
|
23
|
+
"scripts/launcher.cjs",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"prepare-dev": "bun i && bun run transpile-esm",
|
|
29
|
+
"start": "bun run src/index.ts",
|
|
30
|
+
"start:profile": "bun --cpu-prof src/index.ts",
|
|
31
|
+
"start:node": "tsx src/index.ts",
|
|
32
|
+
"transpile-esm": "npx tsc -p lib/tsconfig.json && bun run scripts/transform-tools.mjs",
|
|
33
|
+
"lint": "eslint src --ext .ts -c eslint.config.ts --fix",
|
|
34
|
+
"build": "bun run transpile-esm && bun build ./src/index.ts --outfile=./bin/gdx --compile --bytecode --production --keep-names",
|
|
35
|
+
"package:node": "bun run transpile-esm && bun build ./src/index.ts --outdir=./dist --target=node --format=esm --production --keep-names",
|
|
36
|
+
"prepack": "bun run package:node",
|
|
37
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
38
|
+
"prettier": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"./*.md\"",
|
|
39
|
+
"dummy-editor": "bun ./scripts/dummyEditor.mjs"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@babel/cli": "^7.28.0",
|
|
43
|
+
"@babel/core": "^7.28.0",
|
|
44
|
+
"@babel/preset-env": "^7.27.2",
|
|
45
|
+
"@babel/preset-typescript": "^7.27.1",
|
|
46
|
+
"@eslint/js": "^9.22.0",
|
|
47
|
+
"@types/chai": "^5.2.3",
|
|
48
|
+
"@typescript-eslint/eslint-plugin": "^8.13.0",
|
|
49
|
+
"@typescript-eslint/parser": "^8.13.0",
|
|
50
|
+
"bun-types": "latest",
|
|
51
|
+
"chai": "^6.2.1",
|
|
52
|
+
"eslint": "^9.22.0",
|
|
53
|
+
"jiti": "^2.6.1",
|
|
54
|
+
"tsx": "^4.21.0",
|
|
55
|
+
"prettier": "^3.6.2",
|
|
56
|
+
"typescript": "^5.8.3",
|
|
57
|
+
"typescript-eslint": "^8.50.0",
|
|
58
|
+
"cspell-lib": "^9.4.0",
|
|
59
|
+
"dedent": "^1.7.0",
|
|
60
|
+
"execa": "^9.6.1",
|
|
61
|
+
"keytar": "^7.9.0",
|
|
62
|
+
"openai": "^6.14.0",
|
|
63
|
+
"smol-toml": "^1.5.2"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-undef */
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { spawn } = require('child_process');
|
|
8
|
+
|
|
9
|
+
const DIST_DIR = path.join(__dirname, '../dist');
|
|
10
|
+
const NATIVE_DIR = path.join(DIST_DIR, 'native');
|
|
11
|
+
const isWin = process.platform === 'win32';
|
|
12
|
+
const binaryName = isWin ? 'gdx.exe' : 'gdx';
|
|
13
|
+
const binaryPath = path.join(NATIVE_DIR, binaryName);
|
|
14
|
+
|
|
15
|
+
// Check if native binary exists
|
|
16
|
+
if (fs.existsSync(binaryPath)) {
|
|
17
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
18
|
+
stdio: 'inherit'
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
child.on('close', (code) => {
|
|
22
|
+
process.exit(code);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
child.on('error', (err) => {
|
|
26
|
+
console.error('Failed to start native binary:', err);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
// Fallback to Node.js runtime (dist/index.js)
|
|
31
|
+
// Since dist/index.js is ESM, we use dynamic import
|
|
32
|
+
const jsEntry = path.join(DIST_DIR, 'index.js');
|
|
33
|
+
import(require('url').pathToFileURL(jsEntry)).catch(err => {
|
|
34
|
+
console.error('Failed to load JS fallback:', err);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/* eslint-disable no-undef */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawnSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
// Configuration
|
|
8
|
+
const PACKAGE_JSON_PATH = path.join(__dirname, '../package.json');
|
|
9
|
+
const BIN_DIR = path.join(__dirname, '../bin');
|
|
10
|
+
const NATIVE_DIR = path.join(BIN_DIR, 'native');
|
|
11
|
+
const PKG_SRC_PATH = path.join(__dirname, '../dist/index.js');
|
|
12
|
+
const INSTALL_INFO_PATH = path.join(NATIVE_DIR, 'install.json');
|
|
13
|
+
const PREBUILT_BASE_URL = process.env.GDX_PREBUILT_BASE_URL || 'https://github.com/Type-Delta/gdx/releases/download';
|
|
14
|
+
|
|
15
|
+
// Ensure native directory exists
|
|
16
|
+
function ensureBinDir() {
|
|
17
|
+
if (!fs.existsSync(NATIVE_DIR)) {
|
|
18
|
+
fs.mkdirSync(NATIVE_DIR, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getPackageVersion() {
|
|
23
|
+
const pkg = JSON.parse(fs.readFileSync(PACKAGE_JSON_PATH, 'utf8'));
|
|
24
|
+
return pkg.version;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function log(message) {
|
|
28
|
+
console.log(`[gdx-install] ${message}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function error(message) {
|
|
32
|
+
console.error(`[gdx-install] ERROR: ${message}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writeInstallInfo(info) {
|
|
36
|
+
fs.writeFileSync(INSTALL_INFO_PATH, JSON.stringify(info, null, 2));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isTruthy(v) {
|
|
40
|
+
return v === '1' || v === 'true' || v === 'yes';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getPrefixFromEnvOrNpm() {
|
|
44
|
+
if (process.env.npm_config_prefix) {
|
|
45
|
+
return process.env.npm_config_prefix;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Fallback: ask npm (works on modern npm)
|
|
49
|
+
const npmExecPath = process.env.npm_execpath;
|
|
50
|
+
if (!npmExecPath) return null;
|
|
51
|
+
|
|
52
|
+
const prefix = execFileSync(
|
|
53
|
+
process.execPath,
|
|
54
|
+
[npmExecPath, 'config', 'get', 'prefix'],
|
|
55
|
+
{ encoding: 'utf8' }
|
|
56
|
+
).trim();
|
|
57
|
+
|
|
58
|
+
return prefix || null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async function checkUrlExists(url) {
|
|
63
|
+
try {
|
|
64
|
+
const res = await fetch(url, { method: 'HEAD', redirect: 'follow' });
|
|
65
|
+
return res.ok;
|
|
66
|
+
} catch (err) {
|
|
67
|
+
throw new Error(`Network error while checking prebuilt availability: ${err.message} (${url})`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function downloadFile(url, tmpPath, destPath) {
|
|
72
|
+
const res = await fetch(url, { method: 'GET', redirect: 'follow' });
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
throw new Error(`Failed to download: ${res.statusText} (${url})`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
78
|
+
const stream = require('stream');
|
|
79
|
+
const { promisify } = require('util');
|
|
80
|
+
const pipeline = promisify(stream.pipeline);
|
|
81
|
+
|
|
82
|
+
await pipeline(res.body, fileStream);
|
|
83
|
+
fs.renameSync(tmpPath, destPath);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function setExecutable(filePath) {
|
|
87
|
+
if (process.platform !== 'win32') {
|
|
88
|
+
fs.chmodSync(filePath, 0o755);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function writeFileExecutable(filePath, content) {
|
|
93
|
+
fs.writeFileSync(filePath, content, { encoding: 'utf8' });
|
|
94
|
+
setExecutable(filePath);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getNpmGlobalBinDir() {
|
|
98
|
+
if (!isTruthy(process.env.npm_config_global)) return null;
|
|
99
|
+
|
|
100
|
+
const prefix = getPrefixFromEnvOrNpm();
|
|
101
|
+
if (!prefix) return null;
|
|
102
|
+
|
|
103
|
+
if (process.platform === 'win32') {
|
|
104
|
+
// On Windows, shims are in the prefix dir itself
|
|
105
|
+
return prefix;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// On Unix, shims are in <prefix>/bin
|
|
109
|
+
return path.join(prefix, 'bin');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
function overwriteGlobalShim(nativeAbsPath) {
|
|
114
|
+
if (!isTruthy(process.env.npm_config_global))
|
|
115
|
+
return false;
|
|
116
|
+
|
|
117
|
+
if (!(process.env.npm_config_user_agent || '').includes('npm/')) {
|
|
118
|
+
log('Non-npm global install detected; skipping global shim overwrite.');
|
|
119
|
+
log('This may result in overhead introduced by the Node.js launch script.');
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const globalBin = getNpmGlobalBinDir();
|
|
124
|
+
if (!globalBin) return false;
|
|
125
|
+
|
|
126
|
+
if (process.platform === 'win32') {
|
|
127
|
+
const cmdPath = path.join(globalBin, 'gdx.cmd');
|
|
128
|
+
const ps1Path = path.join(globalBin, 'gdx.ps1');
|
|
129
|
+
|
|
130
|
+
const cmd = [
|
|
131
|
+
'@echo off',
|
|
132
|
+
`"${nativeAbsPath}" %*`,
|
|
133
|
+
'exit /b %ERRORLEVEL%',
|
|
134
|
+
''
|
|
135
|
+
].join('\r\n');
|
|
136
|
+
|
|
137
|
+
const ps1 = [
|
|
138
|
+
`& "${nativeAbsPath}" @args`,
|
|
139
|
+
'exit $LASTEXITCODE',
|
|
140
|
+
''
|
|
141
|
+
].join('\r\n');
|
|
142
|
+
|
|
143
|
+
writeFileExecutable(cmdPath, cmd);
|
|
144
|
+
writeFileExecutable(ps1Path, ps1);
|
|
145
|
+
} else {
|
|
146
|
+
const shPath = path.join(globalBin, 'gdx');
|
|
147
|
+
|
|
148
|
+
const sh = [
|
|
149
|
+
'#!/usr/bin/env sh',
|
|
150
|
+
`exec "${nativeAbsPath}" "$@"`,
|
|
151
|
+
''
|
|
152
|
+
].join('\n');
|
|
153
|
+
|
|
154
|
+
writeFileExecutable(shPath, sh);
|
|
155
|
+
}
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function tryDownloadPrebuilt() {
|
|
160
|
+
const version = getPackageVersion();
|
|
161
|
+
const platform = process.platform;
|
|
162
|
+
const arch = process.arch;
|
|
163
|
+
|
|
164
|
+
// Currently only supporting win32-x64
|
|
165
|
+
if (platform !== 'win32' || arch !== 'x64') {
|
|
166
|
+
throw new Error(`gdx: prebuilt binary not available for ${platform}/${arch} yet. Please reinstall without GDX_USE_PREBUILT=1 (unset GDX_USE_PREBUILT or use GDX_BUILD_NATIVE=1).`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const ext = platform === 'win32' ? '.exe' : '';
|
|
170
|
+
const assetName = `gdx-${platform}-${arch}${ext}`;
|
|
171
|
+
const url = `${PREBUILT_BASE_URL}/v${version}/${assetName}`;
|
|
172
|
+
|
|
173
|
+
log(`Checking availability of prebuilt binary: ${url}`);
|
|
174
|
+
const exists = await checkUrlExists(url);
|
|
175
|
+
if (!exists) {
|
|
176
|
+
throw new Error(`gdx: prebuilt binary not available for ${platform}/${arch} yet (404). Please reinstall without GDX_USE_PREBUILT=1 (unset GDX_USE_PREBUILT or use GDX_BUILD_NATIVE=1).`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
log(`Downloading prebuilt binary...`);
|
|
180
|
+
const tmpPath = path.join(NATIVE_DIR, `${assetName}.tmp`);
|
|
181
|
+
const finalPath = path.join(NATIVE_DIR, 'gdx' + ext);
|
|
182
|
+
|
|
183
|
+
ensureBinDir();
|
|
184
|
+
await downloadFile(url, tmpPath, finalPath);
|
|
185
|
+
setExecutable(finalPath);
|
|
186
|
+
|
|
187
|
+
log(`Prebuilt binary installed to ${finalPath}`);
|
|
188
|
+
|
|
189
|
+
writeInstallInfo({
|
|
190
|
+
mode: 'prebuilt',
|
|
191
|
+
platform,
|
|
192
|
+
arch,
|
|
193
|
+
version,
|
|
194
|
+
userAgent: process.env.npm_config_user_agent || null,
|
|
195
|
+
useNativeShim: overwriteGlobalShim(finalPath),
|
|
196
|
+
ts: (new Date).toLocaleString(),
|
|
197
|
+
binaryPath: finalPath
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function tryBuildNative() {
|
|
202
|
+
log('Attempting local native build with Bun...');
|
|
203
|
+
|
|
204
|
+
// Check for bun
|
|
205
|
+
const bunCheck = spawnSync('bun', ['--version'], { encoding: 'utf8', shell: true });
|
|
206
|
+
if (bunCheck.error || bunCheck.status !== 0) {
|
|
207
|
+
throw new Error('Bun is not installed or not found in PATH. Cannot build native binary. Please install Bun or reinstall without GDX_BUILD_NATIVE=1. (unset GDX_BUILD_NATIVE or set GDX_USE_PREBUILT to use prebuilt binary if available)');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const platform = process.platform;
|
|
211
|
+
const arch = process.arch;
|
|
212
|
+
const isWin = platform === 'win32';
|
|
213
|
+
const binaryName = isWin ? 'gdx.exe' : 'gdx';
|
|
214
|
+
const finalPath = path.join(NATIVE_DIR, binaryName);
|
|
215
|
+
|
|
216
|
+
// Build command
|
|
217
|
+
const args = [
|
|
218
|
+
'build',
|
|
219
|
+
PKG_SRC_PATH,
|
|
220
|
+
`--outfile=${finalPath}`,
|
|
221
|
+
'--compile',
|
|
222
|
+
'--bytecode',
|
|
223
|
+
'--production',
|
|
224
|
+
'--keep-names',
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
ensureBinDir();
|
|
228
|
+
log(`Running: bun ${args.join(' ')}`);
|
|
229
|
+
const build = spawnSync('bun', args, { stdio: 'inherit', shell: true });
|
|
230
|
+
|
|
231
|
+
if (build.status !== 0) {
|
|
232
|
+
throw new Error('Native build failed. Please check output above.');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
log(`Native binary built at ${finalPath}`);
|
|
236
|
+
|
|
237
|
+
writeInstallInfo({
|
|
238
|
+
mode: 'built',
|
|
239
|
+
platform,
|
|
240
|
+
arch,
|
|
241
|
+
version: getPackageVersion(),
|
|
242
|
+
userAgent: process.env.npm_config_user_agent || null,
|
|
243
|
+
useNativeShim: overwriteGlobalShim(finalPath),
|
|
244
|
+
ts: (new Date).toLocaleString(),
|
|
245
|
+
binaryPath: finalPath
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async function main() {
|
|
250
|
+
const ignoreScripts = isTruthy(process.env.npm_config_ignore_scripts) ||
|
|
251
|
+
isTruthy(process.env.NPM_CONFIG_IGNORE_SCRIPTS);
|
|
252
|
+
if (ignoreScripts) {
|
|
253
|
+
log('Scripts ignored by configuration. Skipping native setup.');
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
try {
|
|
258
|
+
if (isTruthy(process.env.GDX_USE_PREBUILT)) {
|
|
259
|
+
await tryDownloadPrebuilt();
|
|
260
|
+
} else if (isTruthy(process.env.GDX_BUILD_NATIVE)) {
|
|
261
|
+
tryBuildNative();
|
|
262
|
+
} else {
|
|
263
|
+
log('No native install requested (default). Using Node.js fallback.');
|
|
264
|
+
// Do nothing
|
|
265
|
+
}
|
|
266
|
+
} catch (err) {
|
|
267
|
+
error(err.message);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
main();
|