@blueprintit/shop-os-install 0.5.4 → 0.5.6
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/bin/shop-os-install.js +10 -7
- package/bin/shop-os-update.js +179 -0
- package/package.json +3 -2
package/bin/shop-os-install.js
CHANGED
|
@@ -734,13 +734,16 @@ async function main() {
|
|
|
734
734
|
rl.close();
|
|
735
735
|
fail(`No folder found at: ${vaultPath}\nMake sure the path is correct and the folder exists.`);
|
|
736
736
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
if (!
|
|
742
|
-
rl
|
|
743
|
-
|
|
737
|
+
// Vault folder doesn't exist yet — that's expected for a new install.
|
|
738
|
+
// In --yes mode (setup scripts), proceed silently; the "[3/N] Creating
|
|
739
|
+
// vault at ..." step below prints its own status. In interactive mode,
|
|
740
|
+
// confirm with the user before creating.
|
|
741
|
+
if (!args.yes) {
|
|
742
|
+
const createIt = await confirm(rl, `Create new vault at ${cyan(vaultPath)}?`, { default: true });
|
|
743
|
+
if (!createIt) {
|
|
744
|
+
rl.close();
|
|
745
|
+
fail("Create the folder in Finder / File Explorer first, then re-run this installer.");
|
|
746
|
+
}
|
|
744
747
|
}
|
|
745
748
|
}
|
|
746
749
|
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Shop OS skills updater.
|
|
4
|
+
*
|
|
5
|
+
* Pulls the latest skills from GitHub without re-running the full installer.
|
|
6
|
+
* Safe to run at any time — does not touch your vault or license.
|
|
7
|
+
*
|
|
8
|
+
* Mac / Linux:
|
|
9
|
+
* npx -y --package=@blueprintit/shop-os-install shop-os-update
|
|
10
|
+
*
|
|
11
|
+
* Windows (PowerShell):
|
|
12
|
+
* npx -y --package=@blueprintit/shop-os-install shop-os-update
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { homedir } from "node:os";
|
|
16
|
+
import { join, dirname } from "node:path";
|
|
17
|
+
import { spawnSync } from "node:child_process";
|
|
18
|
+
import {
|
|
19
|
+
existsSync,
|
|
20
|
+
mkdirSync,
|
|
21
|
+
readFileSync,
|
|
22
|
+
rmSync,
|
|
23
|
+
writeFileSync,
|
|
24
|
+
} from "node:fs";
|
|
25
|
+
import { stdout, stderr, exit } from "node:process";
|
|
26
|
+
|
|
27
|
+
// ---------- output helpers ----------
|
|
28
|
+
|
|
29
|
+
const SUPPORTS_COLOR = stdout.isTTY && !process.env.NO_COLOR;
|
|
30
|
+
const c = (code, s) => (SUPPORTS_COLOR ? `\x1b[${code}m${s}\x1b[0m` : s);
|
|
31
|
+
const dim = (s) => c("2", s);
|
|
32
|
+
const bold = (s) => c("1", s);
|
|
33
|
+
const green = (s) => c("32", s);
|
|
34
|
+
const yellow = (s) => c("33", s);
|
|
35
|
+
const red = (s) => c("31", s);
|
|
36
|
+
const cyan = (s) => c("36", s);
|
|
37
|
+
|
|
38
|
+
const print = (msg = "") => stdout.write(msg + "\n");
|
|
39
|
+
const warn = (msg) => stderr.write(yellow("! ") + msg + "\n");
|
|
40
|
+
const fail = (msg) => { stderr.write(red("✗ ") + msg + "\n"); exit(1); };
|
|
41
|
+
const ok = (msg) => print(" " + green("✓") + " " + msg);
|
|
42
|
+
const info = (msg) => print(" " + dim("·") + " " + msg);
|
|
43
|
+
|
|
44
|
+
// ---------- helpers ----------
|
|
45
|
+
|
|
46
|
+
function readJSON(path, fallback) {
|
|
47
|
+
if (!existsSync(path)) return fallback;
|
|
48
|
+
try { return JSON.parse(readFileSync(path, "utf8")); }
|
|
49
|
+
catch { return fallback; }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function writeJSON(path, obj) {
|
|
53
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
54
|
+
writeFileSync(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------- main ----------
|
|
58
|
+
|
|
59
|
+
function banner() {
|
|
60
|
+
[
|
|
61
|
+
"",
|
|
62
|
+
bold(" ╔════════════════════════════════════════════════════════════╗"),
|
|
63
|
+
bold(" ║ ║"),
|
|
64
|
+
bold(" ║ ") + cyan("Shop OS Skills Updater") + bold(" ║"),
|
|
65
|
+
bold(" ║ ") + dim("Pull the latest skills from Blueprint IT") + bold(" ║"),
|
|
66
|
+
bold(" ║ ║"),
|
|
67
|
+
bold(" ╚════════════════════════════════════════════════════════════╝"),
|
|
68
|
+
"",
|
|
69
|
+
].forEach((l) => print(l));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function preflight() {
|
|
73
|
+
const major = Number(process.versions.node.split(".")[0]);
|
|
74
|
+
if (major < 18) fail(`Node.js 18+ required. You have ${process.version}.`);
|
|
75
|
+
|
|
76
|
+
const probe = spawnSync(
|
|
77
|
+
process.platform === "win32" ? "where" : "which",
|
|
78
|
+
["claude"],
|
|
79
|
+
{ stdio: "ignore", shell: false },
|
|
80
|
+
);
|
|
81
|
+
if (probe.status !== 0) {
|
|
82
|
+
fail("Claude Code not found. Make sure it is installed and on your PATH.");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return join(homedir(), ".claude");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function refreshMarketplace(claudeRoot) {
|
|
89
|
+
const installLocation = join(claudeRoot, "plugins", "marketplaces", "blueprint-skills");
|
|
90
|
+
const repoUrl = "https://github.com/blueprintit-ai/blueprint-skills.git";
|
|
91
|
+
|
|
92
|
+
if (existsSync(join(installLocation, ".git"))) {
|
|
93
|
+
const fetch = spawnSync("git", ["fetch", "origin", "main", "--depth=1"], {
|
|
94
|
+
cwd: installLocation,
|
|
95
|
+
stdio: "ignore",
|
|
96
|
+
});
|
|
97
|
+
if (fetch.status === 0) {
|
|
98
|
+
const reset = spawnSync("git", ["reset", "--hard", "FETCH_HEAD"], {
|
|
99
|
+
cwd: installLocation,
|
|
100
|
+
stdio: "ignore",
|
|
101
|
+
});
|
|
102
|
+
if (reset.status === 0) {
|
|
103
|
+
ok("Skills pulled from GitHub");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// fetch/reset failed — wipe and re-clone
|
|
108
|
+
warn("git pull failed, re-cloning marketplace...");
|
|
109
|
+
try { rmSync(installLocation, { recursive: true, force: true }); } catch { /* best-effort */ }
|
|
110
|
+
} else {
|
|
111
|
+
info("Marketplace not found locally — cloning fresh...");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
mkdirSync(dirname(installLocation), { recursive: true });
|
|
115
|
+
const clone = spawnSync("git", ["clone", "--depth=1", repoUrl, installLocation], {
|
|
116
|
+
stdio: "ignore",
|
|
117
|
+
});
|
|
118
|
+
if (clone.status !== 0) fail("Could not reach GitHub. Check your internet connection and try again.");
|
|
119
|
+
ok("Skills cloned from GitHub");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function wipePluginCache(claudeRoot) {
|
|
123
|
+
const cacheDir = join(claudeRoot, "plugins", "cache", "blueprint-skills", "obsidian");
|
|
124
|
+
if (existsSync(cacheDir)) {
|
|
125
|
+
try {
|
|
126
|
+
rmSync(cacheDir, { recursive: true, force: true });
|
|
127
|
+
ok("Plugin cache cleared");
|
|
128
|
+
} catch {
|
|
129
|
+
warn("Could not clear plugin cache — Claude Code may load a stale version. Try restarting Claude Code twice.");
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
ok("Plugin cache already clean");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function resetPluginEntry(claudeRoot) {
|
|
137
|
+
const pluginsPath = join(claudeRoot, "plugins", "installed_plugins.json");
|
|
138
|
+
const data = readJSON(pluginsPath, { version: 2, plugins: {} });
|
|
139
|
+
if (!data.plugins) data.plugins = {};
|
|
140
|
+
|
|
141
|
+
const id = "obsidian@blueprint-skills";
|
|
142
|
+
const now = new Date().toISOString();
|
|
143
|
+
|
|
144
|
+
data.plugins[id] = [
|
|
145
|
+
{
|
|
146
|
+
scope: "user",
|
|
147
|
+
installPath: null,
|
|
148
|
+
version: "pending",
|
|
149
|
+
installedAt: data.plugins[id]?.[0]?.installedAt ?? now,
|
|
150
|
+
lastUpdated: now,
|
|
151
|
+
gitCommitSha: "pending-sync",
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
writeJSON(pluginsPath, data);
|
|
156
|
+
ok("Plugin marked for re-install on next Claude Code launch");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
banner();
|
|
160
|
+
print(dim(" Updating Shop OS skills. Your vault and license are not affected.\n"));
|
|
161
|
+
|
|
162
|
+
print(dim(" [1/3] Refreshing skill files from GitHub"));
|
|
163
|
+
const claudeRoot = preflight();
|
|
164
|
+
refreshMarketplace(claudeRoot);
|
|
165
|
+
|
|
166
|
+
print("");
|
|
167
|
+
print(dim(" [2/3] Clearing plugin cache"));
|
|
168
|
+
wipePluginCache(claudeRoot);
|
|
169
|
+
|
|
170
|
+
print("");
|
|
171
|
+
print(dim(" [3/3] Resetting plugin entry"));
|
|
172
|
+
resetPluginEntry(claudeRoot);
|
|
173
|
+
|
|
174
|
+
print("");
|
|
175
|
+
print(green(" ✓ Update complete."));
|
|
176
|
+
print("");
|
|
177
|
+
print(" " + bold("Restart Claude Code") + " to load the updated skills.");
|
|
178
|
+
print(" Your vault files, license key, and settings are unchanged.");
|
|
179
|
+
print("");
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueprintit/shop-os-install",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "One-command installer for Shop OS — Blueprint IT's AI Operating System for small businesses.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"shop-os-install": "./bin/shop-os-install.js"
|
|
7
|
+
"shop-os-install": "./bin/shop-os-install.js",
|
|
8
|
+
"shop-os-update": "./bin/shop-os-update.js"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"bin",
|