@noormdev/cli 1.0.0-alpha.2 → 1.0.0-alpha.20

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/noorm.js ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Thin shim that execs the platform-specific noorm binary.
5
+ *
6
+ * npm points `bin.noorm` here. On postinstall, the real binary is
7
+ * downloaded to the same directory. This shim finds and execs it,
8
+ * passing through all arguments and signals.
9
+ */
10
+
11
+ import { execFileSync } from 'child_process';
12
+ import { existsSync } from 'fs';
13
+ import { resolve, dirname } from 'path';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ const __dirname = dirname(fileURLToPath(import.meta.url));
17
+ const binaryName = process.platform === 'win32' ? 'noorm.exe' : 'noorm';
18
+ const binaryPath = resolve(__dirname, 'bin', binaryName);
19
+
20
+ if (!existsSync(binaryPath)) {
21
+
22
+ console.error('noorm binary not found. Try reinstalling:');
23
+ console.error(' npm install -g @noormdev/cli');
24
+ process.exit(1);
25
+
26
+ }
27
+
28
+ try {
29
+
30
+ execFileSync(binaryPath, process.argv.slice(2), {
31
+ stdio: 'inherit',
32
+ env: process.env,
33
+ });
34
+
35
+ }
36
+ catch (err) {
37
+
38
+ // execFileSync throws on non-zero exit — forward the exit code
39
+ process.exit(err.status ?? 1);
40
+
41
+ }
package/package.json CHANGED
@@ -1,18 +1,17 @@
1
1
  {
2
2
  "name": "@noormdev/cli",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.20",
4
4
  "description": "Database schema & changeset manager CLI",
5
5
  "type": "module",
6
6
  "bin": {
7
- "noorm": "./dist/index.js"
7
+ "noorm": "./noorm.js"
8
8
  },
9
- "main": "./dist/index.js",
10
9
  "files": [
11
- "dist",
10
+ "noorm.js",
12
11
  "scripts"
13
12
  ],
14
- "dependencies": {
15
- "better-sqlite3": "^12.5.0"
13
+ "scripts": {
14
+ "postinstall": "node scripts/postinstall.js"
16
15
  },
17
16
  "engines": {
18
17
  "node": ">=18"
@@ -25,7 +24,8 @@
25
24
  "noorm"
26
25
  ],
27
26
  "license": "ISC",
28
- "scripts": {
29
- "postinstall": "node scripts/postinstall.js"
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/noormdev/noorm"
30
30
  }
31
- }
31
+ }
@@ -1,80 +1,155 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * Creates a stable symlink in /usr/local/bin for Node version independence.
4
+ * Downloads the platform-specific noorm binary on npm install.
5
5
  *
6
- * When using nvm/fnm, npm bin directories are version-specific. This script
7
- * creates a symlink in /usr/local/bin so `noorm` works across version switches.
6
+ * The @noormdev/cli npm package is a thin wrapper. The actual CLI is a
7
+ * bun-compiled binary hosted on GitHub Releases. This script runs on
8
+ * postinstall to fetch the correct binary for the user's OS and architecture.
8
9
  */
9
10
 
10
- import { symlink, unlink, readlink } from 'fs/promises';
11
- import { existsSync } from 'fs';
11
+ import { createWriteStream, existsSync, chmodSync, mkdirSync } from 'fs';
12
+ import { get as httpsGet } from 'https';
12
13
  import { dirname, resolve } from 'path';
13
14
  import { fileURLToPath } from 'url';
14
15
 
15
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
16
- const BIN_PATH = '/usr/local/bin/noorm';
17
- const SOURCE = resolve(__dirname, '../dist/index.js');
17
+ const PACKAGE_ROOT = resolve(__dirname, '..');
18
+ const BIN_DIR = resolve(PACKAGE_ROOT, 'bin');
19
+ const REPO = 'noormdev/noorm';
18
20
 
19
- async function main() {
21
+ /**
22
+ * Resolves the platform suffix used in binary asset names.
23
+ *
24
+ * Maps Node's process.platform and process.arch to the naming convention
25
+ * used by the build-binary script: noorm-{os}-{arch}
26
+ */
27
+ function getPlatformSuffix() {
20
28
 
21
- // Skip on Windows
22
- if (process.platform === 'win32') {
29
+ const platform = process.platform;
30
+ const arch = process.arch;
23
31
 
24
- return;
32
+ const osMap = { darwin: 'darwin', linux: 'linux', win32: 'windows' };
33
+ const archMap = { arm64: 'arm64', x64: 'x64' };
25
34
 
26
- }
35
+ const os = osMap[platform];
36
+ const cpu = archMap[arch];
27
37
 
28
- // Skip if not a global install (local node_modules)
29
- if (__dirname.includes('node_modules') && !__dirname.includes('/lib/node_modules/')) {
38
+ if (!os || !cpu) {
39
+ console.error(`Unsupported platform: ${platform}-${arch}`);
40
+ process.exit(0); // Don't fail install
41
+ }
30
42
 
31
- return;
43
+ const suffix = `${os}-${cpu}`;
32
44
 
45
+ if (platform === 'win32') {
46
+ return `${suffix}.exe`;
33
47
  }
34
48
 
35
- // Check if symlink already exists and points to correct location
36
- if (existsSync(BIN_PATH)) {
49
+ return suffix;
50
+
51
+ }
52
+
53
+ /**
54
+ * Reads the package version to determine which release to download from.
55
+ */
56
+ async function getVersion() {
57
+
58
+ const { readFile } = await import('fs/promises');
59
+ const pkg = JSON.parse(await readFile(resolve(PACKAGE_ROOT, 'package.json'), 'utf8'));
60
+
61
+ return pkg.version;
62
+
63
+ }
64
+
65
+ /**
66
+ * Follow redirects and download a URL to a file path.
67
+ *
68
+ * GitHub Releases URLs redirect to S3. This follows up to 5 redirects.
69
+ */
70
+ function download(url, dest, redirects = 0) {
37
71
 
38
- try {
72
+ if (redirects > 5) {
73
+ return Promise.reject(new Error('Too many redirects'));
74
+ }
39
75
 
40
- const existing = await readlink(BIN_PATH);
76
+ return new Promise((resolve, reject) => {
41
77
 
42
- if (existing === SOURCE) {
78
+ httpsGet(url, { headers: { 'User-Agent': 'noorm-installer' } }, (res) => {
43
79
 
44
- return; // Already correct
80
+ // Follow redirects
81
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
82
+ resolve(download(res.headers.location, dest, redirects + 1));
83
+ return;
84
+ }
45
85
 
86
+ if (res.statusCode !== 200) {
87
+ reject(new Error(`Download failed: HTTP ${res.statusCode}`));
88
+ return;
46
89
  }
47
90
 
48
- await unlink(BIN_PATH);
91
+ const file = createWriteStream(dest);
92
+ res.pipe(file);
49
93
 
50
- }
51
- catch {
94
+ file.on('finish', () => {
95
+ file.close();
96
+ resolve();
97
+ });
52
98
 
53
- // Not a symlink or can't read - try to proceed anyway
99
+ file.on('error', (err) => {
100
+ file.close();
101
+ reject(err);
102
+ });
54
103
 
55
- }
104
+ }).on('error', reject);
56
105
 
57
- }
106
+ });
107
+
108
+ }
109
+
110
+ /**
111
+ * Main postinstall routine.
112
+ *
113
+ * Downloads the correct binary, saves it to bin/, and makes it executable.
114
+ * Exits cleanly on failure so npm install doesn't break.
115
+ */
116
+ async function main() {
58
117
 
59
- try {
118
+ const suffix = getPlatformSuffix();
119
+ const version = await getVersion();
120
+ const assetName = `noorm-${suffix}`;
121
+ const tag = `@noormdev/cli@${version}`;
122
+ const url = `https://github.com/${REPO}/releases/download/${tag}/${assetName}`;
60
123
 
61
- await symlink(SOURCE, BIN_PATH);
62
- console.log(`✓ Symlinked noorm to ${BIN_PATH}`);
124
+ const binaryName = process.platform === 'win32' ? 'noorm.exe' : 'noorm';
125
+ const dest = resolve(BIN_DIR, binaryName);
63
126
 
127
+ // Skip if binary already exists (e.g. reinstall)
128
+ if (existsSync(dest)) {
129
+ console.log(`noorm binary already exists at ${dest}`);
130
+ return;
64
131
  }
65
- catch (err) {
66
132
 
67
- if (err.code === 'EACCES') {
133
+ mkdirSync(BIN_DIR, { recursive: true });
68
134
 
69
- console.log(`\nTo enable noorm globally (survives Node version switches):\n`);
70
- console.log(` sudo ln -sf "${SOURCE}" ${BIN_PATH}\n`);
135
+ console.log(`Downloading noorm ${version} for ${suffix}...`);
71
136
 
72
- }
73
-
74
- // Don't fail install on symlink errors
137
+ await download(url, dest);
75
138
 
139
+ if (process.platform !== 'win32') {
140
+ chmodSync(dest, 0o755);
76
141
  }
77
142
 
143
+ console.log(`✓ noorm ${version} installed`);
144
+
78
145
  }
79
146
 
80
- main();
147
+ main().catch((err) => {
148
+
149
+ console.error(`Warning: Could not download noorm binary: ${err.message}`);
150
+ console.error('You can download it manually from:');
151
+ console.error(` https://github.com/${REPO}/releases`);
152
+ // Don't fail the install
153
+ process.exit(0);
154
+
155
+ });