@vimoxshah/tokenflow 1.1.1 → 1.1.2
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/CHANGELOG.md +48 -0
- package/package.json +1 -1
- package/scripts/build-dmg.sh +11 -2
- package/scripts/build-menubar-app.sh +55 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,54 @@
|
|
|
3
3
|
All notable changes to TokenFlow are recorded here. Versions follow
|
|
4
4
|
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
5
|
|
|
6
|
+
## 1.1.2 — 2026-09-03
|
|
7
|
+
|
|
8
|
+
Makes the downloadable app usable on a machine that is not the one that built
|
|
9
|
+
it. 1.1.1 was correct as source and as an npm package; its DMG was not.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **The released app pointed at the machine that built it.** Every build
|
|
14
|
+
embedded the absolute path of its own node binary and CLI, which is right for
|
|
15
|
+
a developer driving their checkout and wrong for a release: the 1.1.1 DMG
|
|
16
|
+
shipped `TokenFlowCLIPath = /Users/runner/work/tokenflow/...`, a path that
|
|
17
|
+
exists on no user's machine. Only path-discovery fallbacks kept the app
|
|
18
|
+
working at all. A distributable build now embeds no path
|
|
19
|
+
(`TOKENFLOW_PORTABLE=1`), the DMG script refuses to package one that does,
|
|
20
|
+
and the release workflow re-checks it after mounting the finished image.
|
|
21
|
+
- **A cask-only install had nothing to run.** The cask installs the app; the
|
|
22
|
+
CLI came from npm. Anyone who only ran `brew install --cask tokenflow` got a
|
|
23
|
+
menu bar that could read an existing status file and do nothing else — no
|
|
24
|
+
refresh, no watcher, no dashboard. The app now carries its own CLI (see
|
|
25
|
+
below).
|
|
26
|
+
- **Node discovery named one specific version.** The first candidate was
|
|
27
|
+
`~/.nvm/versions/node/v24.13.1/bin/node` — whichever version the developer
|
|
28
|
+
happened to have. One `nvm install` away from being wrong for everybody.
|
|
29
|
+
nvm installs are now discovered and the highest one at or above the engine
|
|
30
|
+
floor wins.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **The app bundles its own CLI**, at
|
|
35
|
+
`Contents/Resources/cli/package/bin/tokenflow.js`. It is packed with
|
|
36
|
+
`npm pack` and then pruned to the files the CLI actually executes, so the
|
|
37
|
+
bundle is always a subset of the published package and never carries a file
|
|
38
|
+
npm does not ship. The bundled copy takes priority over any CLI found on the
|
|
39
|
+
system, because the app and the CLI share a contract — the status file's
|
|
40
|
+
shape, the watcher lock format, `/api/ping` — and the copy shipped beside the
|
|
41
|
+
binary is the only one guaranteed to match it. A local build still embeds the
|
|
42
|
+
developer's clone, which wins, so an installed app keeps driving the checkout
|
|
43
|
+
being edited.
|
|
44
|
+
- **A missing dependency now says so.** With no CLI or no Node the menu bar
|
|
45
|
+
reported nothing and every button failed silently. It names the problem and
|
|
46
|
+
the command that fixes it, at launch rather than on the first click.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- The cask states the Node requirement in `caveats` instead of declaring
|
|
51
|
+
`depends_on formula: "node"`, which would install a second Node beside an
|
|
52
|
+
nvm- or asdf-managed one and fight the version manager.
|
|
53
|
+
|
|
6
54
|
## 1.1.1 — 2026-09-03
|
|
7
55
|
|
|
8
56
|
A reliability release. Five defects had combined to leave the app paused, the
|
package/package.json
CHANGED
package/scripts/build-dmg.sh
CHANGED
|
@@ -15,8 +15,17 @@ DIST="$REPO/dist"
|
|
|
15
15
|
APP="$DIST/TokenFlow.app"
|
|
16
16
|
DMG="$DIST/TokenFlow-$VERSION.dmg"
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
# A DMG is for other people's machines, so it must carry no path from this one.
|
|
19
|
+
TOKENFLOW_PORTABLE=1 "$REPO/scripts/build-menubar-app.sh" "$DIST" "$VERSION" >/dev/null
|
|
20
|
+
echo "built TokenFlow.app (portable)"
|
|
21
|
+
|
|
22
|
+
# Fail here rather than shipping an app that points at the build host.
|
|
23
|
+
for KEY in TokenFlowCLIPath TokenFlowNodePath; do
|
|
24
|
+
if /usr/libexec/PlistBuddy -c "Print :$KEY" "$APP/Contents/Info.plist" >/dev/null 2>&1; then
|
|
25
|
+
echo "error: $KEY is embedded in a distributable build" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
20
29
|
|
|
21
30
|
STAGING="$(mktemp -d)"
|
|
22
31
|
trap 'rm -rf "$STAGING"' EXIT
|
|
@@ -4,8 +4,24 @@
|
|
|
4
4
|
# scripts/build-menubar-app.sh [output-dir]
|
|
5
5
|
#
|
|
6
6
|
# Compiles menubar/TokenFlow/main.swift with swiftc (Xcode Command Line Tools)
|
|
7
|
-
# into a minimal .app bundle
|
|
8
|
-
#
|
|
7
|
+
# into a minimal .app bundle.
|
|
8
|
+
#
|
|
9
|
+
# The CLI is ALWAYS bundled into Contents/Resources/cli, packed with `npm pack`
|
|
10
|
+
# so the copy inside the app is byte-for-byte the published package rather than
|
|
11
|
+
# a hand-picked subset of the working tree. The app drives that copy, which is
|
|
12
|
+
# the only one guaranteed to match the binary it ships beside: the app and the
|
|
13
|
+
# CLI share a contract (the status file, the watcher lock format, /api/ping),
|
|
14
|
+
# and an unrelated CLI version next door is a mismatch nobody can reason about.
|
|
15
|
+
#
|
|
16
|
+
# Two build flavours:
|
|
17
|
+
#
|
|
18
|
+
# local (default) also embeds this clone's absolute node + CLI paths, so
|
|
19
|
+
# a developer's installed app drives the checkout they
|
|
20
|
+
# are editing.
|
|
21
|
+
# TOKENFLOW_PORTABLE=1 embeds NO absolute paths. Anything built for
|
|
22
|
+
# distribution must use this: a release built on CI
|
|
23
|
+
# otherwise ships /Users/runner/... in its Info.plist,
|
|
24
|
+
# which exists on no user's machine.
|
|
9
25
|
set -euo pipefail
|
|
10
26
|
|
|
11
27
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
@@ -25,14 +41,40 @@ command -v swiftc >/dev/null 2>&1 || {
|
|
|
25
41
|
NODE_BIN="$(command -v node)"
|
|
26
42
|
CLI_JS="$REPO/bin/tokenflow.js"
|
|
27
43
|
[ -f "$CLI_JS" ] || { echo "error: $CLI_JS missing" >&2; exit 1; }
|
|
44
|
+
PORTABLE="${TOKENFLOW_PORTABLE:-0}"
|
|
28
45
|
|
|
29
46
|
TMP="$(mktemp -d)"
|
|
30
47
|
trap 'rm -rf "$TMP"' EXIT
|
|
31
48
|
|
|
49
|
+
rm -rf "$APP"
|
|
32
50
|
mkdir -p "$APP/Contents/MacOS"
|
|
33
51
|
mkdir -p "$APP/Contents/Resources"
|
|
34
52
|
cp "$REPO/menubar/TokenFlow/AppIcon.icns" "$APP/Contents/Resources/AppIcon.icns"
|
|
35
53
|
|
|
54
|
+
# ---- bundle the CLI ---------------------------------------------------------
|
|
55
|
+
# `npm pack` rather than copying bin/ and src/: the tarball is what npm
|
|
56
|
+
# publishes, filtered by package.json "files", so the app can never ship a file
|
|
57
|
+
# the package does not.
|
|
58
|
+
echo "packing the CLI into the bundle"
|
|
59
|
+
( cd "$REPO" && npm pack --silent --pack-destination "$TMP" >/dev/null )
|
|
60
|
+
TGZ="$(ls "$TMP"/*.tgz | head -1)"
|
|
61
|
+
[ -f "$TGZ" ] || { echo "error: npm pack produced no tarball" >&2; exit 1; }
|
|
62
|
+
mkdir -p "$APP/Contents/Resources/cli"
|
|
63
|
+
tar -xzf "$TGZ" -C "$APP/Contents/Resources/cli"
|
|
64
|
+
BUNDLED_CLI="$APP/Contents/Resources/cli/package/bin/tokenflow.js"
|
|
65
|
+
[ -f "$BUNDLED_CLI" ] || { echo "error: bundled CLI missing at $BUNDLED_CLI" >&2; exit 1; }
|
|
66
|
+
|
|
67
|
+
# Keep only what the CLI actually executes. docs/, skills/, examples/ and
|
|
68
|
+
# scripts/ are never read at runtime — they appear in printed hints and nothing
|
|
69
|
+
# opens them — and they are four fifths of the tarball. Whatever remains still
|
|
70
|
+
# came from `npm pack`, so the bundle is a subset of the published package and
|
|
71
|
+
# never a file npm does not ship.
|
|
72
|
+
( cd "$APP/Contents/Resources/cli/package" \
|
|
73
|
+
&& rm -rf docs skills examples scripts \
|
|
74
|
+
README.md CONTRIBUTING.md SECURITY.md CHANGELOG.md "Refresh & Open Dashboard.command" )
|
|
75
|
+
[ -f "$BUNDLED_CLI" ] || { echo "error: pruning removed the CLI" >&2; exit 1; }
|
|
76
|
+
[ -d "$APP/Contents/Resources/cli/package/src" ] || { echo "error: pruning removed src/" >&2; exit 1; }
|
|
77
|
+
|
|
36
78
|
cat > "$APP/Contents/Info.plist" <<PLIST
|
|
37
79
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
38
80
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -50,12 +92,19 @@ cat > "$APP/Contents/Info.plist" <<PLIST
|
|
|
50
92
|
<key>LSUIElement</key> <true/>
|
|
51
93
|
<key>NSHighResolutionCapable</key> <true/>
|
|
52
94
|
<key>NSHumanReadableCopyright</key> <string>MIT — local-first, nothing leaves your machine.</string>
|
|
53
|
-
<key>TokenFlowNodePath</key> <string>$NODE_BIN</string>
|
|
54
|
-
<key>TokenFlowCLIPath</key> <string>$CLI_JS</string>
|
|
55
95
|
</dict>
|
|
56
96
|
</plist>
|
|
57
97
|
PLIST
|
|
58
98
|
|
|
99
|
+
# A distributable build embeds no machine-specific path. A local one does, so
|
|
100
|
+
# the developer's installed app drives the clone they are working in.
|
|
101
|
+
if [ "$PORTABLE" != "1" ]; then
|
|
102
|
+
/usr/libexec/PlistBuddy \
|
|
103
|
+
-c "Add :TokenFlowNodePath string $NODE_BIN" \
|
|
104
|
+
-c "Add :TokenFlowCLIPath string $CLI_JS" \
|
|
105
|
+
"$APP/Contents/Info.plist" >/dev/null
|
|
106
|
+
fi
|
|
107
|
+
|
|
59
108
|
echo "compiling with $(swiftc --version | head -1)"
|
|
60
109
|
swiftc -O -swift-version 5 \
|
|
61
110
|
-o "$APP/Contents/MacOS/TokenFlow" \
|
|
@@ -63,5 +112,5 @@ swiftc -O -swift-version 5 \
|
|
|
63
112
|
|
|
64
113
|
codesign --force --sign - "$APP" >/dev/null 2>&1 || true
|
|
65
114
|
|
|
66
|
-
SIZE=$(du -
|
|
67
|
-
echo "built: $APP ($SIZE)"
|
|
115
|
+
SIZE=$(du -sh "$APP" | cut -f1 | tr -d ' ')
|
|
116
|
+
echo "built: $APP ($SIZE)$([ "$PORTABLE" = "1" ] && echo ' · portable, no embedded paths')"
|