@devkitvault/recall 1.0.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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -0
  3. package/bin/recall.js +169 -0
  4. package/package.json +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) devkitvault
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,52 @@
1
+ # @devkitvault/recall
2
+
3
+ **Install the recall CLI from npm** — on first run, this package downloads the official native binary for your OS from [GitHub Releases](https://github.com/devkitvault/recall/releases) into `~/.local/bin`, then runs it. Later runs reuse the same binary.
4
+
5
+ recall is a **cloud-synced command vault**: save shell commands, templates, snippets, env sets, and aliases — same account as [recall.devkitvault.com](https://recall.devkitvault.com) and the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=devkitvault.recall-cmd).
6
+
7
+ ## Requirements
8
+
9
+ - **Node.js 18+** (only for this installer wrapper)
10
+ - **Supported platforms** (prebuilt binaries): macOS (Apple Silicon + Intel), Linux x64, Windows x64
11
+
12
+ Other architectures: use the [curl / PowerShell installers](https://devkitvault.com) or build from source in `packages/cli`.
13
+
14
+ ## Install
15
+
16
+ ```sh
17
+ npm install -g @devkitvault/recall
18
+ ```
19
+
20
+ Ensure `~/.local/bin` is on your `PATH` (the installer places `recall` there). On Windows, that path is `%USERPROFILE%\.local\bin`.
21
+
22
+ ## Use
23
+
24
+ ```sh
25
+ recall --help
26
+ recall auth login
27
+ recall save "docker compose up -d" -n "start stack"
28
+ recall search docker
29
+ ```
30
+
31
+ ## Re-download the binary
32
+
33
+ If a release was updated or your download was corrupted:
34
+
35
+ ```sh
36
+ RECALL_REINSTALL=1 recall --version
37
+ ```
38
+
39
+ ## Release tag vs npm version
40
+
41
+ Downloads use a Git **tag** on `devkitvault/recall` (default: `v` + `version` from this package’s `package.json`). If you ship an npm **patch** without a matching GitHub tag, set either:
42
+
43
+ - `recall.releaseTag` in `package.json`, or
44
+ - environment variable `RECALL_RELEASE_TAG` (e.g. `v1.0.0`)
45
+
46
+ before running `recall`, so the wrapper points at an existing release.
47
+
48
+ Maintainers: after [Release CLI](https://github.com/devkitvault/recall/blob/master/.github/workflows/release.yml) publishes assets for `vX.Y.Z`, publish this npm package with the same `version` **or** set `recall.releaseTag` accordingly.
49
+
50
+ ## License
51
+
52
+ MIT © [devkitvault](https://devkitvault.com)
package/bin/recall.js ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @devkitvault/recall — thin installer for the native recall CLI.
4
+ * First run downloads the matching GitHub release binary into ~/.local/bin, then execs it.
5
+ * @see https://github.com/devkitvault/recall/releases
6
+ */
7
+ 'use strict'
8
+
9
+ const fs = require('fs')
10
+ const path = require('path')
11
+ const os = require('os')
12
+ const https = require('https')
13
+ const http = require('http')
14
+ const { spawnSync } = require('child_process')
15
+
16
+ const BINARY_MAP = {
17
+ 'darwin-arm64': 'recall-macos-arm64',
18
+ 'darwin-x64': 'recall-macos-x64',
19
+ 'linux-x64': 'recall-linux-x64',
20
+ 'win32-x64': 'recall-windows-x64.exe',
21
+ }
22
+
23
+ const USER_AGENT = 'devkitvault-recall-npm/1.0 (+https://www.npmjs.com/package/@devkitvault/recall)'
24
+
25
+ function platformKey() {
26
+ return `${process.platform}-${process.arch}`
27
+ }
28
+
29
+ function binaryAssetName() {
30
+ const key = platformKey()
31
+ const name = BINARY_MAP[key]
32
+ if (!name) {
33
+ console.error(
34
+ `recall: no prebuilt binary for "${key}".\n` +
35
+ `Supported: ${Object.keys(BINARY_MAP).join(', ')}\n` +
36
+ 'Install from https://devkitvault.com or build from source (packages/cli).',
37
+ )
38
+ process.exit(1)
39
+ }
40
+ return name
41
+ }
42
+
43
+ function readPkg() {
44
+ return require(path.join(__dirname, '..', 'package.json'))
45
+ }
46
+
47
+ function releaseTag(pkg) {
48
+ if (process.env.RECALL_RELEASE_TAG) {
49
+ const t = process.env.RECALL_RELEASE_TAG.trim()
50
+ return t.startsWith('v') ? t : `v${t}`
51
+ }
52
+ const t = pkg.recall && pkg.recall.releaseTag
53
+ if (typeof t === 'string' && t.length) return t.startsWith('v') ? t : `v${t}`
54
+ return `v${pkg.version}`
55
+ }
56
+
57
+ function binPaths() {
58
+ const binDir = path.join(os.homedir(), '.local', 'bin')
59
+ const binName = process.platform === 'win32' ? 'recall.exe' : 'recall'
60
+ return { binDir, binPath: path.join(binDir, binName) }
61
+ }
62
+
63
+ function httpGet(url, redirectsLeft) {
64
+ return new Promise((resolve, reject) => {
65
+ if (redirectsLeft <= 0) return reject(new Error('Too many redirects'))
66
+ const lib = url.startsWith('https:') ? https : http
67
+ const req = lib.get(
68
+ url,
69
+ {
70
+ headers: { 'User-Agent': USER_AGENT },
71
+ },
72
+ (res) => {
73
+ const loc = res.headers.location
74
+ if (loc && res.statusCode >= 300 && res.statusCode < 400) {
75
+ res.resume()
76
+ const next = new URL(loc, url).href
77
+ return httpGet(next, redirectsLeft - 1).then(resolve).catch(reject)
78
+ }
79
+ if (res.statusCode !== 200) {
80
+ res.resume()
81
+ return reject(new Error(`HTTP ${res.statusCode} GET ${url}`))
82
+ }
83
+ resolve(res)
84
+ },
85
+ )
86
+ req.on('error', reject)
87
+ })
88
+ }
89
+
90
+ function streamToFile(readable, destPath) {
91
+ return fs.promises.mkdir(path.dirname(destPath), { recursive: true }).then(() => {
92
+ const tmp = `${destPath}.${process.pid}.${Date.now()}.part`
93
+ return new Promise((resolve, reject) => {
94
+ const w = fs.createWriteStream(tmp, { mode: 0o644 })
95
+ readable.pipe(w)
96
+ w.on('finish', () => w.close((err) => (err ? reject(err) : resolve(tmp))))
97
+ w.on('error', reject)
98
+ readable.on('error', reject)
99
+ }).then(async (tmpPath) => {
100
+ try {
101
+ await fs.promises.rename(tmpPath, destPath)
102
+ } catch (e) {
103
+ try {
104
+ await fs.promises.unlink(tmpPath)
105
+ } catch { /* ignore */ }
106
+ throw e
107
+ }
108
+ })
109
+ })
110
+ }
111
+
112
+ async function ensureBinary(binPath, tag, assetName) {
113
+ const url = `https://github.com/devkitvault/recall/releases/download/${tag}/${assetName}`
114
+ process.stderr.write(`recall: downloading ${assetName} (${tag}) …\n`)
115
+ const res = await httpGet(url, 16)
116
+ await streamToFile(res, binPath)
117
+ if (process.platform !== 'win32') {
118
+ await fs.promises.chmod(binPath, 0o755)
119
+ }
120
+ }
121
+
122
+ async function main() {
123
+ const pkg = readPkg()
124
+ const tag = releaseTag(pkg)
125
+ const assetName = binaryAssetName()
126
+ const { binPath } = binPaths()
127
+
128
+ const reinstall =
129
+ process.env.RECALL_REINSTALL === '1' ||
130
+ process.env.FORCE_RECALL_REINSTALL === '1'
131
+
132
+ if (reinstall) {
133
+ try {
134
+ await fs.promises.unlink(binPath)
135
+ } catch { /* missing is fine */ }
136
+ }
137
+
138
+ let exists = false
139
+ try {
140
+ const st = await fs.promises.stat(binPath)
141
+ exists = st.isFile() && st.size > 0
142
+ } catch {
143
+ exists = false
144
+ }
145
+
146
+ if (!exists) {
147
+ try {
148
+ await ensureBinary(binPath, tag, assetName)
149
+ } catch (err) {
150
+ const msg = err instanceof Error ? err.message : String(err)
151
+ console.error(`recall: install failed: ${msg}`)
152
+ console.error(`Expected release assets at: https://github.com/devkitvault/recall/releases/tag/${tag}`)
153
+ console.error('Tip: set RECALL_RELEASE_TAG=vX.Y.Z if your npm version differs from the CLI release tag.')
154
+ process.exit(1)
155
+ }
156
+ }
157
+
158
+ const result = spawnSync(binPath, process.argv.slice(2), { stdio: 'inherit' })
159
+ if (result.error) {
160
+ console.error(result.error.message || result.error)
161
+ process.exit(1)
162
+ }
163
+ process.exit(result.status === null ? 1 : result.status)
164
+ }
165
+
166
+ main().catch((e) => {
167
+ console.error(e instanceof Error ? e.message : e)
168
+ process.exit(1)
169
+ })
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@devkitvault/recall",
3
+ "version": "1.0.0",
4
+ "description": "recall CLI installer — cloud-synced shell command vault (downloads native binary from GitHub releases)",
5
+ "keywords": [
6
+ "cli",
7
+ "shell",
8
+ "commands",
9
+ "devtools",
10
+ "recall",
11
+ "vault",
12
+ "sync",
13
+ "kubernetes",
14
+ "docker",
15
+ "terminal",
16
+ "devkitvault"
17
+ ],
18
+ "author": "devkitvault",
19
+ "license": "MIT",
20
+ "homepage": "https://recall.devkitvault.com",
21
+ "bugs": {
22
+ "url": "https://github.com/devkitvault/recall/issues"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/devkitvault/recall.git",
27
+ "directory": "packages/npm-cli"
28
+ },
29
+ "bin": {
30
+ "recall": "bin/recall.js"
31
+ },
32
+ "files": [
33
+ "bin",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "prepublishOnly": "node --check bin/recall.js"
45
+ },
46
+ "recall": {
47
+ "releaseTag": "v1.0.0"
48
+ }
49
+ }