@rtorr/nah 1.0.7 → 1.0.12
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 +112 -0
- package/{bin → npm-bin}/nah +1 -1
- package/{scripts → npm-scripts}/install.js +22 -6
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# NAH - Native Application Host
|
|
2
|
+
|
|
3
|
+
[](https://github.com/rtorr/nah/actions/workflows/ci.yml)
|
|
4
|
+
[](https://nah.rtorr.com/)
|
|
5
|
+
|
|
6
|
+
NAH is a launch contract system for native applications.
|
|
7
|
+
|
|
8
|
+
When you deploy a native application, someone must figure out how to launch it: which binary, what library paths, which environment variables, what SDK version. This information typically lives in documentation that drifts, install scripts that diverge, or tribal knowledge that doesn't scale.
|
|
9
|
+
|
|
10
|
+
NAH eliminates this by making applications self-describing. Apps declare what they need. SDKs declare what they provide. Hosts declare policy. NAH composes these into a launch contract - the exact parameters needed to run the application.
|
|
11
|
+
|
|
12
|
+
## What NAH Provides
|
|
13
|
+
|
|
14
|
+
**For host operators**: Install an app, query its launch contract. No need to read documentation or reverse-engineer scripts. The contract tells you the binary path, library paths, environment variables, and working directory.
|
|
15
|
+
|
|
16
|
+
**For app developers**: Embed a manifest declaring your SDK requirement and entrypoint. Ship one package that works on any host with a compatible SDK, regardless of where the SDK is installed.
|
|
17
|
+
|
|
18
|
+
**For SDK developers**: Package your libraries once. Multiple versions coexist on the same host. Apps pin to compatible versions at install time. Update the SDK without breaking existing apps.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Install from local files
|
|
24
|
+
nah --root /opt/nah nak install vendor-sdk-2.1.0.nak
|
|
25
|
+
nah --root /opt/nah app install myapp-1.0.0.nap
|
|
26
|
+
|
|
27
|
+
# Or install directly from URLs
|
|
28
|
+
nah --root /opt/nah nak install https://example.com/vendor-sdk-2.1.0.nak
|
|
29
|
+
nah --root /opt/nah app install https://example.com/myapp-1.0.0.nap
|
|
30
|
+
|
|
31
|
+
# Query the launch contract
|
|
32
|
+
nah --root /opt/nah contract show com.example.myapp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
Application: com.example.myapp v1.0.0
|
|
37
|
+
SDK: com.vendor.sdk v2.1.0
|
|
38
|
+
Binary: /opt/nah/apps/com.example.myapp-1.0.0/bin/myapp
|
|
39
|
+
CWD: /opt/nah/apps/com.example.myapp-1.0.0
|
|
40
|
+
Library Paths: /opt/nah/naks/com.vendor.sdk/2.1.0/lib
|
|
41
|
+
Environment:
|
|
42
|
+
NAH_APP_ID=com.example.myapp
|
|
43
|
+
NAH_APP_VERSION=1.0.0
|
|
44
|
+
NAH_NAK_ROOT=/opt/nah/naks/com.vendor.sdk/2.1.0
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The contract is deterministic. Same inputs, same output. Auditable before execution.
|
|
48
|
+
|
|
49
|
+
## Key Properties
|
|
50
|
+
|
|
51
|
+
- **No network at launch time**: Contract composition uses only local state
|
|
52
|
+
- **No dependency solving**: Apps declare requirements, hosts install SDKs, NAH matches them
|
|
53
|
+
- **Version coexistence**: Multiple SDK versions installed side-by-side
|
|
54
|
+
- **Install-time pinning**: SDK version locked when app is installed, not resolved at launch
|
|
55
|
+
- **Host controls layout**: SDKs and apps go where the host decides, not where the app expects
|
|
56
|
+
|
|
57
|
+
## When to Use NAH
|
|
58
|
+
|
|
59
|
+
NAH is designed for environments where:
|
|
60
|
+
|
|
61
|
+
- Apps and SDKs come from different vendors or teams
|
|
62
|
+
- Hosts need to control where software is installed
|
|
63
|
+
- Multiple SDK versions must coexist for different apps
|
|
64
|
+
- Launch configuration must be auditable
|
|
65
|
+
- Apps must remain portable across different host configurations
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# npm (recommended)
|
|
71
|
+
npm install -g @rtorr/nah
|
|
72
|
+
|
|
73
|
+
# Linux (manual)
|
|
74
|
+
curl -L https://github.com/rtorr/nah/releases/latest/download/nah-linux-x64.tar.gz | tar xz
|
|
75
|
+
sudo mv nah /usr/local/bin/
|
|
76
|
+
|
|
77
|
+
# macOS (manual)
|
|
78
|
+
curl -L https://github.com/rtorr/nah/releases/latest/download/nah-macos-arm64.tar.gz | tar xz
|
|
79
|
+
sudo mv nah /usr/local/bin/
|
|
80
|
+
|
|
81
|
+
# From source
|
|
82
|
+
git clone https://github.com/rtorr/nah.git && cd nah
|
|
83
|
+
cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build
|
|
84
|
+
sudo cmake --install build
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Library Integration
|
|
88
|
+
|
|
89
|
+
NAH can be embedded as a C++ library:
|
|
90
|
+
|
|
91
|
+
```cmake
|
|
92
|
+
include(FetchContent)
|
|
93
|
+
FetchContent_Declare(nah GIT_REPOSITORY https://github.com/rtorr/nah.git GIT_TAG v1.0.0)
|
|
94
|
+
FetchContent_MakeAvailable(nah)
|
|
95
|
+
target_link_libraries(your_target PRIVATE nahhost)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
| Document | Description |
|
|
101
|
+
|----------|-------------|
|
|
102
|
+
| [Concepts](docs/concepts.md) | Core terminology: manifests, NAKs, profiles, contracts |
|
|
103
|
+
| [Getting Started: Host](docs/getting-started-host.md) | Set up a host and deploy applications |
|
|
104
|
+
| [Getting Started: SDK](docs/getting-started-nak.md) | Package an SDK for distribution |
|
|
105
|
+
| [Getting Started: App](docs/getting-started-app.md) | Build an application with a manifest |
|
|
106
|
+
| [CLI Reference](docs/cli.md) | Command-line interface documentation |
|
|
107
|
+
| [Specification](SPEC.md) | Normative specification |
|
|
108
|
+
| [Contributing](CONTRIBUTING.md) | Development setup and releasing |
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|
package/{bin → npm-bin}/nah
RENAMED
|
@@ -9,7 +9,7 @@ const binaryPath = path.join(__dirname, binaryName);
|
|
|
9
9
|
|
|
10
10
|
if (!fs.existsSync(binaryPath)) {
|
|
11
11
|
console.error("nah binary not found. Try reinstalling the package:");
|
|
12
|
-
console.error(" npm uninstall -g nah
|
|
12
|
+
console.error(" npm uninstall -g @rtorr/nah && npm install -g @rtorr/nah");
|
|
13
13
|
process.exit(1);
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -41,13 +41,19 @@ function downloadFile(url) {
|
|
|
41
41
|
|
|
42
42
|
https
|
|
43
43
|
.get(url, (response) => {
|
|
44
|
-
if (
|
|
44
|
+
if (
|
|
45
|
+
response.statusCode >= 300 &&
|
|
46
|
+
response.statusCode < 400 &&
|
|
47
|
+
response.headers.location
|
|
48
|
+
) {
|
|
45
49
|
follow(response.headers.location, redirects + 1);
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
if (response.statusCode !== 200) {
|
|
50
|
-
reject(
|
|
54
|
+
reject(
|
|
55
|
+
new Error(`Failed to download: HTTP ${response.statusCode}`),
|
|
56
|
+
);
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -95,8 +101,16 @@ function extractTar(tarData, destDir) {
|
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
// Parse header
|
|
98
|
-
const name = header
|
|
99
|
-
|
|
104
|
+
const name = header
|
|
105
|
+
.slice(0, 100)
|
|
106
|
+
.toString("utf8")
|
|
107
|
+
.replace(/\0/g, "")
|
|
108
|
+
.trim();
|
|
109
|
+
const sizeOctal = header
|
|
110
|
+
.slice(124, 136)
|
|
111
|
+
.toString("utf8")
|
|
112
|
+
.replace(/\0/g, "")
|
|
113
|
+
.trim();
|
|
100
114
|
const size = parseInt(sizeOctal, 8) || 0;
|
|
101
115
|
const typeFlag = header[156];
|
|
102
116
|
|
|
@@ -130,11 +144,13 @@ async function main() {
|
|
|
130
144
|
|
|
131
145
|
if (!supportedPlatform) {
|
|
132
146
|
console.error(`Unsupported platform: ${platformKey}`);
|
|
133
|
-
console.error(
|
|
147
|
+
console.error(
|
|
148
|
+
`Supported platforms: ${Object.keys(PLATFORM_MAP).join(", ")}`,
|
|
149
|
+
);
|
|
134
150
|
process.exit(1);
|
|
135
151
|
}
|
|
136
152
|
|
|
137
|
-
const binDir = path.join(__dirname, "..", "bin");
|
|
153
|
+
const binDir = path.join(__dirname, "..", "npm-bin");
|
|
138
154
|
const binaryPath = path.join(binDir, getBinaryName());
|
|
139
155
|
|
|
140
156
|
// Check if binary already exists
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rtorr/nah",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "Native Application Host - Manage native applications, NAKs, profiles, and launch contracts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"native",
|
|
@@ -22,17 +22,17 @@
|
|
|
22
22
|
},
|
|
23
23
|
"homepage": "https://github.com/rtorr/nah#readme",
|
|
24
24
|
"bin": {
|
|
25
|
-
"nah": "bin/nah"
|
|
25
|
+
"nah": "npm-bin/nah"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
|
-
"postinstall": "node scripts/install.js"
|
|
28
|
+
"postinstall": "node npm-scripts/install.js"
|
|
29
29
|
},
|
|
30
30
|
"engines": {
|
|
31
31
|
"node": ">=14"
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
34
|
-
"bin",
|
|
35
|
-
"scripts"
|
|
34
|
+
"npm-bin",
|
|
35
|
+
"npm-scripts"
|
|
36
36
|
],
|
|
37
37
|
"os": [
|
|
38
38
|
"darwin",
|