hacklab 0.7.2 → 0.7.4
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/dist/card.d.ts +66 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +151 -0
- package/dist/card.js.map +1 -0
- package/dist/commands/brag.d.ts.map +1 -1
- package/dist/commands/brag.js +5 -0
- package/dist/commands/brag.js.map +1 -1
- package/dist/commands/chat.d.ts +21 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +109 -14
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/drop.d.ts.map +1 -1
- package/dist/commands/drop.js +5 -0
- package/dist/commands/drop.js.map +1 -1
- package/dist/commands/essay.d.ts.map +1 -1
- package/dist/commands/essay.js +13 -0
- package/dist/commands/essay.js.map +1 -1
- package/dist/commands/hacker.d.ts +2 -0
- package/dist/commands/hacker.d.ts.map +1 -0
- package/dist/commands/hacker.js +119 -0
- package/dist/commands/hacker.js.map +1 -0
- package/dist/commands/join.d.ts.map +1 -1
- package/dist/commands/join.js +22 -0
- package/dist/commands/join.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +13 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +2 -0
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +14 -0
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +92 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/posthog.d.ts +9 -0
- package/dist/posthog.d.ts.map +1 -0
- package/dist/posthog.js +20 -0
- package/dist/posthog.js.map +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +13 -0
- package/dist/registry.js.map +1 -1
- package/dist/ui.d.ts +12 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +56 -0
- package/dist/ui.js.map +1 -1
- package/dist/utils/npmGlobal.d.ts +30 -0
- package/dist/utils/npmGlobal.d.ts.map +1 -0
- package/dist/utils/npmGlobal.js +69 -0
- package/dist/utils/npmGlobal.js.map +1 -0
- package/dist/utils/updateCheck.d.ts +6 -0
- package/dist/utils/updateCheck.d.ts.map +1 -1
- package/dist/utils/updateCheck.js +7 -2
- package/dist/utils/updateCheck.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { captureEvent } from '../posthog.js';
|
|
4
|
+
import { loadSession } from '../session.js';
|
|
5
|
+
import { dim, error, info, success } from '../ui.js';
|
|
6
|
+
import { isWritable, npmGlobalRoot, runNpm, userNpmPrefix, } from '../utils/npmGlobal.js';
|
|
7
|
+
import { fetchLatest, isNewerVersion } from '../utils/updateCheck.js';
|
|
8
|
+
// The version we're running now — read from package.json (two levels up from
|
|
9
|
+
// this module, in both `dist/` and `src/`) the same way index.ts does, so it
|
|
10
|
+
// can't drift from a hardcoded string.
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const { version: CURRENT } = require('../../package.json');
|
|
13
|
+
// `hacklab update` — a permission-safe wrapper around `npm i -g hacklab@latest`.
|
|
14
|
+
// A plain `npm i -g` is enough on most machines, but on systems where npm's
|
|
15
|
+
// global folder is root-owned (a stock /usr/local) it dies with EACCES. Rather
|
|
16
|
+
// than surface that stack trace or reach for sudo, we probe writability first
|
|
17
|
+
// and, if needed, reconfigure npm to a user-owned prefix (option H1) before
|
|
18
|
+
// installing. Works on Linux, macOS, and Windows; the prefix reconfigure is a
|
|
19
|
+
// POSIX concern only (Windows installs globals into a user-writable %APPDATA%).
|
|
20
|
+
export async function update() {
|
|
21
|
+
// For analytics only — never block the update on a session read.
|
|
22
|
+
const session = await loadSession().catch(() => null);
|
|
23
|
+
// Short-circuit when there's nothing to do: if the registry says we're already
|
|
24
|
+
// on the latest, skip the install entirely. Crucially this runs BEFORE any
|
|
25
|
+
// writability probe / prefix reconfigure — we never want to touch ~/.npmrc when
|
|
26
|
+
// there's nothing to install. A failed/timed-out lookup returns undefined and
|
|
27
|
+
// falls through to the install (the safe default: attempt it rather than
|
|
28
|
+
// wrongly claim we're current).
|
|
29
|
+
const latest = await fetchLatest();
|
|
30
|
+
if (latest && !isNewerVersion(latest, CURRENT)) {
|
|
31
|
+
success(`already on the latest hacklab (${CURRENT}).`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const reconfiguredPrefix = ensureWritableGlobalPrefix();
|
|
35
|
+
info('updating hacklab (npm i -g hacklab@latest)…');
|
|
36
|
+
const res = runNpm(['install', '-g', 'hacklab@latest']);
|
|
37
|
+
if (res.status !== 0) {
|
|
38
|
+
error('update failed.');
|
|
39
|
+
if (res.error?.message.includes('ENOENT')) {
|
|
40
|
+
info('npm not found — it ships with Node. Install Node 20+ and retry.');
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
info('Try again, or install manually: npm install -g hacklab@latest');
|
|
44
|
+
}
|
|
45
|
+
await captureEvent(session?.handle, 'cli_update_failed');
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
success('hacklab is up to date.');
|
|
49
|
+
if (reconfiguredPrefix) {
|
|
50
|
+
const binDir = join(reconfiguredPrefix, 'bin');
|
|
51
|
+
info(`npm now installs global packages under ${reconfiguredPrefix}.`);
|
|
52
|
+
info('Add its bin dir to your PATH — put this in your shell profile:');
|
|
53
|
+
console.log(dim(` export PATH="${binDir}:$PATH"`));
|
|
54
|
+
info(dim('Prefer the system location? Undo with `npm config delete prefix`, then reinstall with sudo.'));
|
|
55
|
+
}
|
|
56
|
+
await captureEvent(session?.handle, 'cli_update', {
|
|
57
|
+
from: CURRENT,
|
|
58
|
+
to: latest ?? null,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* If npm's global folder isn't writable by this user, reconfigure npm to a
|
|
63
|
+
* user-owned prefix and return that prefix; otherwise return null (nothing to
|
|
64
|
+
* do). The reconfigure is skipped on Windows, where global installs already land
|
|
65
|
+
* in a user-writable location. Exits the process with a clear, actionable
|
|
66
|
+
* message if the reconfigure itself fails.
|
|
67
|
+
*/
|
|
68
|
+
function ensureWritableGlobalPrefix() {
|
|
69
|
+
if (process.platform === 'win32')
|
|
70
|
+
return null;
|
|
71
|
+
const root = npmGlobalRoot();
|
|
72
|
+
if (!root || isWritable(root))
|
|
73
|
+
return null;
|
|
74
|
+
const prefix = userNpmPrefix();
|
|
75
|
+
info(`npm's global folder isn't writable (${root}).`);
|
|
76
|
+
info(`Reconfiguring npm to install under ${prefix} — no sudo needed…`);
|
|
77
|
+
const cfg = runNpm(['config', 'set', 'prefix', prefix], { capture: true });
|
|
78
|
+
if (cfg.status !== 0) {
|
|
79
|
+
error("couldn't reconfigure npm automatically.");
|
|
80
|
+
info('Install into the system location with sudo instead:');
|
|
81
|
+
console.log(dim(' sudo npm install -g hacklab@latest'));
|
|
82
|
+
info('or set a user prefix yourself:');
|
|
83
|
+
console.log(dim(` npm config set prefix "${prefix}" && npm install -g hacklab@latest`));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
// Make the new bin dir usable by anything this process spawns for the rest of
|
|
87
|
+
// the run. The persistent profile edit (printed after install) is only needed
|
|
88
|
+
// for future shells.
|
|
89
|
+
process.env.PATH = `${join(prefix, 'bin')}:${process.env.PATH ?? ''}`;
|
|
90
|
+
return prefix;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { clearSyncPaused, readSyncPaused } from './daily-sync.js';
|
|
4
|
+
import { posthog } from './posthog.js';
|
|
4
5
|
import { COMMANDS, findCommand } from './registry.js';
|
|
5
6
|
import { resolveCommand } from './resolve-command.js';
|
|
6
|
-
import { HACKLAB_ENVIRONMENTS, resolveHacklabEnv } from './session.js';
|
|
7
|
+
import { HACKLAB_ENVIRONMENTS, loadSession, resolveHacklabEnv, } from './session.js';
|
|
7
8
|
import { banner, bold, dim } from './ui.js';
|
|
8
9
|
import { notifyIfOutdated } from './utils/updateCheck.js';
|
|
9
10
|
// Single source of the published version: read it from package.json (one level
|
|
@@ -138,8 +139,11 @@ async function main() {
|
|
|
138
139
|
}
|
|
139
140
|
await command.run(args);
|
|
140
141
|
}
|
|
141
|
-
main().catch((err) => {
|
|
142
|
+
main().catch(async (err) => {
|
|
142
143
|
console.error(err instanceof Error ? err.message : String(err));
|
|
144
|
+
const session = await loadSession().catch(() => null);
|
|
145
|
+
posthog.captureException(err, session?.handle);
|
|
146
|
+
await posthog.flush();
|
|
143
147
|
process.exit(1);
|
|
144
148
|
});
|
|
145
149
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PostHog } from 'posthog-node';
|
|
2
|
+
export declare const posthog: PostHog;
|
|
3
|
+
/**
|
|
4
|
+
* Capture an event and immediately flush it to PostHog. Since the CLI is a
|
|
5
|
+
* short-lived process, flushing after every capture ensures the event is sent
|
|
6
|
+
* before the process exits. No-ops silently if distinctId is absent.
|
|
7
|
+
*/
|
|
8
|
+
export declare function captureEvent(distinctId: string | undefined, event: string, properties?: Record<string, unknown>): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=posthog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posthog.d.ts","sourceRoot":"","sources":["../src/posthog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,eAAO,MAAM,OAAO,SASnB,CAAA;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAIf"}
|
package/dist/posthog.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PostHog } from 'posthog-node';
|
|
2
|
+
export const posthog = new PostHog(process.env.POSTHOG_API_KEY ??
|
|
3
|
+
'phc_CT4u3J62yYaAHUcnYKjmnpAGXTrWqv7ZbmvYQcUTEACK', {
|
|
4
|
+
host: process.env.POSTHOG_HOST ?? 'https://eu.i.posthog.com',
|
|
5
|
+
flushAt: 1,
|
|
6
|
+
flushInterval: 0,
|
|
7
|
+
enableExceptionAutocapture: true,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Capture an event and immediately flush it to PostHog. Since the CLI is a
|
|
11
|
+
* short-lived process, flushing after every capture ensures the event is sent
|
|
12
|
+
* before the process exits. No-ops silently if distinctId is absent.
|
|
13
|
+
*/
|
|
14
|
+
export async function captureEvent(distinctId, event, properties) {
|
|
15
|
+
if (!distinctId)
|
|
16
|
+
return;
|
|
17
|
+
posthog.capture({ distinctId, event, properties });
|
|
18
|
+
await posthog.flush();
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=posthog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posthog.js","sourceRoot":"","sources":["../src/posthog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,CAChC,OAAO,CAAC,GAAG,CAAC,eAAe;IACzB,kDAAkD,EACpD;IACE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,0BAA0B;IAC5D,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,0BAA0B,EAAE,IAAI;CACjC,CACF,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAA8B,EAC9B,KAAa,EACb,UAAoC;IAEpC,IAAI,CAAC,UAAU;QAAE,OAAM;IACvB,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAA;IAClD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;AACvB,CAAC"}
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAkBA,MAAM,MAAM,WAAW,GAAG;IACxB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAA;IACf,0FAA0F;IAC1F,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC9C,CAAA;AAED,eAAO,MAAM,QAAQ,EAAE,WAAW,EAgFjC,CAAA;AAED,kFAAkF;AAClF,eAAO,MAAM,aAAa,UAA8B,CAAA;AAExD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEjE"}
|
package/dist/registry.js
CHANGED
|
@@ -3,11 +3,13 @@ import { chat } from './commands/chat.js';
|
|
|
3
3
|
import { configCommand } from './commands/config.js';
|
|
4
4
|
import { drop, parseDropArgs } from './commands/drop.js';
|
|
5
5
|
import { essay } from './commands/essay.js';
|
|
6
|
+
import { hacker } from './commands/hacker.js';
|
|
6
7
|
import { join } from './commands/join.js';
|
|
7
8
|
import { login } from './commands/login.js';
|
|
8
9
|
import { logout } from './commands/logout.js';
|
|
9
10
|
import { org } from './commands/org.js';
|
|
10
11
|
import { sync } from './commands/sync.js';
|
|
12
|
+
import { update } from './commands/update.js';
|
|
11
13
|
import { whoami } from './commands/whoami.js';
|
|
12
14
|
export const COMMANDS = [
|
|
13
15
|
{
|
|
@@ -77,6 +79,17 @@ export const COMMANDS = [
|
|
|
77
79
|
summary: 'post and manage essays (post/list/view/update/delete)',
|
|
78
80
|
run: (args) => essay(args),
|
|
79
81
|
},
|
|
82
|
+
{
|
|
83
|
+
name: 'hacker',
|
|
84
|
+
args: 'view <handle>',
|
|
85
|
+
summary: 'view a hacker profile (--json for agents)',
|
|
86
|
+
run: (args) => hacker(args),
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'update',
|
|
90
|
+
summary: 'update the hacklab CLI to the latest version',
|
|
91
|
+
run: () => update(),
|
|
92
|
+
},
|
|
80
93
|
];
|
|
81
94
|
/** Every command name, in registry order — the source of truth for resolution. */
|
|
82
95
|
export const COMMAND_NAMES = COMMANDS.map((c) => c.name);
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/ui.d.ts
CHANGED
|
@@ -5,11 +5,23 @@ export declare const red: import("chalk").ChalkInstance;
|
|
|
5
5
|
export declare const yellow: import("chalk").ChalkInstance;
|
|
6
6
|
export declare const white: import("chalk").ChalkInstance;
|
|
7
7
|
export declare const linkBlue: import("chalk").ChalkInstance;
|
|
8
|
+
export declare const mint: import("chalk").ChalkInstance;
|
|
8
9
|
/**
|
|
9
10
|
* Colour a string in the terminal colour for the rank at `level`. A null/unknown
|
|
10
11
|
* level (e.g. older messages without a sender level) falls back to plain bold.
|
|
11
12
|
*/
|
|
12
13
|
export declare function rankColor(level: number | null | undefined, text: string): string;
|
|
14
|
+
/** Display columns a plain string occupies (ANSI stripped, CJK/emoji aware). */
|
|
15
|
+
export declare function displayWidth(s: string): number;
|
|
16
|
+
/**
|
|
17
|
+
* Truncate a PLAIN string to at most `max` display columns, cutting on grapheme
|
|
18
|
+
* boundaries (never mid-emoji / mid-surrogate) and adding a 1-column ellipsis
|
|
19
|
+
* when anything was dropped. Must run before colorizing.
|
|
20
|
+
*/
|
|
21
|
+
export declare function truncateToWidth(s: string, max: number): string;
|
|
22
|
+
/** Right-pad a PLAIN string with spaces to exactly `width` display columns. */
|
|
23
|
+
export declare function padEndTo(s: string, width: number): string;
|
|
24
|
+
export declare function stripControl(s: string): string;
|
|
13
25
|
export declare function banner(): void;
|
|
14
26
|
export declare function success(msg: string): void;
|
|
15
27
|
export declare function error(msg: string): void;
|
package/dist/ui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,GAAG,+BAAY,CAAA;AAC5B,eAAO,MAAM,IAAI,+BAAa,CAAA;AAC9B,eAAO,MAAM,KAAK,+BAAc,CAAA;AAChC,eAAO,MAAM,GAAG,+BAAY,CAAA;AAC5B,eAAO,MAAM,MAAM,+BAAe,CAAA;AAClC,eAAO,MAAM,KAAK,+BAAoB,CAAA;AAGtC,eAAO,MAAM,QAAQ,+BAAuB,CAAA;AAI5C,eAAO,MAAM,IAAI,+BAAuB,CAAA;AAwBxC;;;GAGG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,GACX,MAAM,CAMR;AAcD,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAa9D;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAOD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,wBAAgB,MAAM,SAIrB;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,QAElC;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,QAEhC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,QAE/B"}
|
package/dist/ui.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
+
import stringWidth from 'string-width';
|
|
2
3
|
import { getBeltColor } from './belt.js';
|
|
3
4
|
export const dim = chalk.dim;
|
|
4
5
|
export const bold = chalk.bold;
|
|
@@ -9,6 +10,10 @@ export const white = chalk.whiteBright;
|
|
|
9
10
|
// GitHub's link blue. chalk degrades the hex to the nearest ANSI colour on
|
|
10
11
|
// terminals without truecolor support.
|
|
11
12
|
export const linkBlue = chalk.hex('#79b8ff');
|
|
13
|
+
// Phosphor Mint (DESIGN.md --primary #82F5C6): the "active and alive" signal —
|
|
14
|
+
// the open-to-work status dot and lit activity cells. chalk degrades the hex on
|
|
15
|
+
// terminals without truecolor.
|
|
16
|
+
export const mint = chalk.hex('#82F5C6');
|
|
12
17
|
// Map a belt colour to the nearest standard ANSI terminal colour name. We use
|
|
13
18
|
// chalk's *named* colours (not the hex values from share-card-colors) on
|
|
14
19
|
// purpose: named colours resolve to each viewer's own terminal theme, so the
|
|
@@ -42,6 +47,57 @@ export function rankColor(level, text) {
|
|
|
42
47
|
return bold(text);
|
|
43
48
|
return BELT_ANSI[getBeltColor(level)].bold(text);
|
|
44
49
|
}
|
|
50
|
+
// --- Display-width primitives ----------------------------------------------
|
|
51
|
+
// The hacker card has a fixed column budget, and its content is user-supplied
|
|
52
|
+
// (handles, bios) that can contain CJK, emoji, and ANSI. `.length` is wrong for
|
|
53
|
+
// all three. Render order everywhere is: strip → truncate → measure → colorize
|
|
54
|
+
// LAST — colorizing before truncation would slice an ANSI escape mid-byte, and
|
|
55
|
+
// stringWidth counts ANSI as zero so a coloured string would measure short and
|
|
56
|
+
// truncate into corruption. These helpers therefore operate on PLAIN text.
|
|
57
|
+
// Ambiguous-width characters (⬤, box-drawing) count as 1 column — pinned per
|
|
58
|
+
// DESIGN.md so the card's rules and content agree with a standard terminal.
|
|
59
|
+
const WIDTH_OPTS = { ambiguousIsNarrow: true };
|
|
60
|
+
/** Display columns a plain string occupies (ANSI stripped, CJK/emoji aware). */
|
|
61
|
+
export function displayWidth(s) {
|
|
62
|
+
return stringWidth(s, WIDTH_OPTS);
|
|
63
|
+
}
|
|
64
|
+
const graphemeSegmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
|
|
65
|
+
/**
|
|
66
|
+
* Truncate a PLAIN string to at most `max` display columns, cutting on grapheme
|
|
67
|
+
* boundaries (never mid-emoji / mid-surrogate) and adding a 1-column ellipsis
|
|
68
|
+
* when anything was dropped. Must run before colorizing.
|
|
69
|
+
*/
|
|
70
|
+
export function truncateToWidth(s, max) {
|
|
71
|
+
if (max <= 0)
|
|
72
|
+
return '';
|
|
73
|
+
if (displayWidth(s) <= max)
|
|
74
|
+
return s;
|
|
75
|
+
const budget = max - 1; // reserve one column for the … ellipsis
|
|
76
|
+
let out = '';
|
|
77
|
+
let width = 0;
|
|
78
|
+
for (const { segment } of graphemeSegmenter.segment(s)) {
|
|
79
|
+
const w = displayWidth(segment);
|
|
80
|
+
if (width + w > budget)
|
|
81
|
+
break;
|
|
82
|
+
out += segment;
|
|
83
|
+
width += w;
|
|
84
|
+
}
|
|
85
|
+
return `${out}…`;
|
|
86
|
+
}
|
|
87
|
+
/** Right-pad a PLAIN string with spaces to exactly `width` display columns. */
|
|
88
|
+
export function padEndTo(s, width) {
|
|
89
|
+
const gap = width - displayWidth(s);
|
|
90
|
+
return gap > 0 ? s + ' '.repeat(gap) : s;
|
|
91
|
+
}
|
|
92
|
+
// Strip C0 control characters + DEL from untrusted text before printing it to
|
|
93
|
+
// the terminal. Without this, a hacker could embed ANSI escape sequences in a
|
|
94
|
+
// handle, bio, message, or any user-supplied field to clear/garble or hijack
|
|
95
|
+
// any viewer's terminal. Lives here (not in a command module) so every renderer
|
|
96
|
+
// — chat, the hacker card — can reach it without a circular import.
|
|
97
|
+
export function stripControl(s) {
|
|
98
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: intentionally matching control chars to remove them
|
|
99
|
+
return s.replace(/[\x00-\x1f\x7f]/g, '');
|
|
100
|
+
}
|
|
45
101
|
export function banner() {
|
|
46
102
|
console.log('');
|
|
47
103
|
console.log(bold(' ☠︎ hacklab'));
|
package/dist/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAkB,YAAY,EAAE,MAAM,WAAW,CAAA;AAExD,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;AAC5B,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;AAC9B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;AAChC,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAA;AAC5B,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;AAClC,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAA;AACtC,2EAA2E;AAC3E,uCAAuC;AACvC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type SpawnSyncReturns } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* npm's executable name. On Windows npm is a `.cmd` shim, and recent Node
|
|
4
|
+
* refuses to spawn `.cmd`/`.bat` without a shell, so callers pass `shell: true`
|
|
5
|
+
* on win32 (see {@link runNpm}).
|
|
6
|
+
*/
|
|
7
|
+
export declare const NPM_BIN: string;
|
|
8
|
+
/**
|
|
9
|
+
* Run npm with fixed (never user-supplied) args. `capture` pipes stdout/stderr
|
|
10
|
+
* back as strings; otherwise the child inherits the terminal so npm's own
|
|
11
|
+
* progress shows through. `shell: true` on Windows is required to launch the
|
|
12
|
+
* `.cmd` shim; the args here are all literals, so there's nothing to escape.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runNpm(args: string[], opts?: {
|
|
15
|
+
capture?: boolean;
|
|
16
|
+
}): SpawnSyncReturns<string>;
|
|
17
|
+
/** The directory npm would drop a global package into (`npm root -g`), or ''. */
|
|
18
|
+
export declare function npmGlobalRoot(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Walk up from `p` to the nearest ancestor that exists on disk. We can't test
|
|
21
|
+
* writability of a directory npm hasn't created yet (`…/lib/node_modules`
|
|
22
|
+
* frequently doesn't exist), so we check the closest thing that does — mkdir
|
|
23
|
+
* succeeds iff that ancestor is writable.
|
|
24
|
+
*/
|
|
25
|
+
export declare function firstExistingAncestor(p: string): string;
|
|
26
|
+
/** Can the current user create/write inside `dir` (probing its nearest existing ancestor)? */
|
|
27
|
+
export declare function isWritable(dir: string): boolean;
|
|
28
|
+
/** The user-owned prefix we reconfigure npm to when the system one is read-only. */
|
|
29
|
+
export declare function userNpmPrefix(): string;
|
|
30
|
+
//# sourceMappingURL=npmGlobal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npmGlobal.d.ts","sourceRoot":"","sources":["../../src/utils/npmGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAa,MAAM,oBAAoB,CAAA;AAarE;;;;GAIG;AACH,eAAO,MAAM,OAAO,QAAmD,CAAA;AAEvE;;;;;GAKG;AACH,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,gBAAgB,CAAC,MAAM,CAAC,CAM1B;AAED,iFAAiF;AACjF,wBAAgB,aAAa,IAAI,MAAM,CAGtC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQvD;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAS/C;AAED,oFAAoF;AACpF,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { accessSync, constants, existsSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
// Shared plumbing for the two places that shell out to `npm i -g hacklab`: the
|
|
6
|
+
// `hacklab update` command and (conceptually) the curl|sh installer. The point
|
|
7
|
+
// of the H1 approach is to never let npm's raw EACCES stack trace reach the
|
|
8
|
+
// user: probe whether npm's global folder is writable up front, and if it isn't,
|
|
9
|
+
// reconfigure npm to a user-owned prefix (npm's own documented remedy) instead
|
|
10
|
+
// of escalating to sudo. That fix is persistent, so every future `npm i -g`
|
|
11
|
+
// works too — which is the whole reason the update nag can safely point here.
|
|
12
|
+
/**
|
|
13
|
+
* npm's executable name. On Windows npm is a `.cmd` shim, and recent Node
|
|
14
|
+
* refuses to spawn `.cmd`/`.bat` without a shell, so callers pass `shell: true`
|
|
15
|
+
* on win32 (see {@link runNpm}).
|
|
16
|
+
*/
|
|
17
|
+
export const NPM_BIN = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
18
|
+
/**
|
|
19
|
+
* Run npm with fixed (never user-supplied) args. `capture` pipes stdout/stderr
|
|
20
|
+
* back as strings; otherwise the child inherits the terminal so npm's own
|
|
21
|
+
* progress shows through. `shell: true` on Windows is required to launch the
|
|
22
|
+
* `.cmd` shim; the args here are all literals, so there's nothing to escape.
|
|
23
|
+
*/
|
|
24
|
+
export function runNpm(args, opts = {}) {
|
|
25
|
+
return spawnSync(NPM_BIN, args, {
|
|
26
|
+
stdio: opts.capture ? ['ignore', 'pipe', 'pipe'] : 'inherit',
|
|
27
|
+
encoding: 'utf8',
|
|
28
|
+
shell: process.platform === 'win32',
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** The directory npm would drop a global package into (`npm root -g`), or ''. */
|
|
32
|
+
export function npmGlobalRoot() {
|
|
33
|
+
const res = runNpm(['root', '-g'], { capture: true });
|
|
34
|
+
return res.status === 0 && res.stdout ? res.stdout.trim() : '';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Walk up from `p` to the nearest ancestor that exists on disk. We can't test
|
|
38
|
+
* writability of a directory npm hasn't created yet (`…/lib/node_modules`
|
|
39
|
+
* frequently doesn't exist), so we check the closest thing that does — mkdir
|
|
40
|
+
* succeeds iff that ancestor is writable.
|
|
41
|
+
*/
|
|
42
|
+
export function firstExistingAncestor(p) {
|
|
43
|
+
let d = p;
|
|
44
|
+
while (d && !existsSync(d)) {
|
|
45
|
+
const parent = dirname(d);
|
|
46
|
+
if (parent === d)
|
|
47
|
+
break; // hit the filesystem root
|
|
48
|
+
d = parent;
|
|
49
|
+
}
|
|
50
|
+
return d;
|
|
51
|
+
}
|
|
52
|
+
/** Can the current user create/write inside `dir` (probing its nearest existing ancestor)? */
|
|
53
|
+
export function isWritable(dir) {
|
|
54
|
+
const target = firstExistingAncestor(dir);
|
|
55
|
+
if (!target)
|
|
56
|
+
return false;
|
|
57
|
+
try {
|
|
58
|
+
accessSync(target, constants.W_OK);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** The user-owned prefix we reconfigure npm to when the system one is read-only. */
|
|
66
|
+
export function userNpmPrefix() {
|
|
67
|
+
return join(homedir(), '.npm-global');
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=npmGlobal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npmGlobal.js","sourceRoot":"","sources":["../../src/utils/npmGlobal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,iFAAiF;AACjF,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;AAEvE;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CACpB,IAAc,EACd,OAA8B,EAAE;IAEhC,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QAC9B,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC5D,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAA;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,CAAS;IAC7C,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;QACzB,IAAI,MAAM,KAAK,CAAC;YAAE,MAAK,CAAC,0BAA0B;QAClD,CAAC,GAAG,MAAM,CAAA;IACZ,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACzB,IAAI,CAAC;QACH,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAA;AACvC,CAAC"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** Numeric-dotted compare: is published version `a` newer than running `b`? */
|
|
2
2
|
export declare function isNewerVersion(a: string, b: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Ask the npm registry for hacklab's latest published version. Timeout-guarded
|
|
5
|
+
* and never throws — a failed/slow lookup resolves to undefined so callers (the
|
|
6
|
+
* daily nag, `hacklab update`) can degrade gracefully rather than block.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetchLatest(): Promise<string | undefined>;
|
|
3
9
|
/**
|
|
4
10
|
* Print a one-line "newer version available" nudge to stderr. No-ops (instantly,
|
|
5
11
|
* no network) when stdout isn't a TTY (piped / CI / `--json` consumers) or when
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateCheck.d.ts","sourceRoot":"","sources":["../../src/utils/updateCheck.ts"],"names":[],"mappings":"AAsBA,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAc5D;
|
|
1
|
+
{"version":3,"file":"updateCheck.d.ts","sourceRoot":"","sources":["../../src/utils/updateCheck.ts"],"names":[],"mappings":"AAsBA,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAc5D;AAoBD;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAa/D;AAcD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBrE"}
|
|
@@ -49,7 +49,12 @@ async function readCache() {
|
|
|
49
49
|
}
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Ask the npm registry for hacklab's latest published version. Timeout-guarded
|
|
54
|
+
* and never throws — a failed/slow lookup resolves to undefined so callers (the
|
|
55
|
+
* daily nag, `hacklab update`) can degrade gracefully rather than block.
|
|
56
|
+
*/
|
|
57
|
+
export async function fetchLatest() {
|
|
53
58
|
try {
|
|
54
59
|
const res = await fetch(`https://registry.npmjs.org/${PACKAGE}/latest`, {
|
|
55
60
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),
|
|
@@ -96,7 +101,7 @@ export async function notifyIfOutdated(current) {
|
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
103
|
if (latest && isNewerVersion(latest, current)) {
|
|
99
|
-
console.error(dim(`↑ hacklab ${latest} is available (you have ${current}) · update:
|
|
104
|
+
console.error(dim(`↑ hacklab ${latest} is available (you have ${current}) · update: hacklab update`));
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updateCheck.js","sourceRoot":"","sources":["../../src/utils/updateCheck.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAE9B,iFAAiF;AACjF,iFAAiF;AACjF,iFAAiF;AACjF,qEAAqE;AAErE,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AACxC,iFAAiF;AACjF,6EAA6E;AAC7E,iEAAiE;AACjE,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAC5B,MAAM,OAAO,GAAG,SAAS,CAAA;AAEzB,qFAAqF;AACrF,SAAS,SAAS;IAChB,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAA;AAC7D,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,cAAc,CAAC,CAAS,EAAE,CAAS;IACjD,+EAA+E;IAC/E,8CAA8C;IAC9C,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7C,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAA;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACpB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACpB,gFAAgF;QAChF,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAA;QACpD,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAG5D,CAAA;QACD,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACxE,OAAO;gBACL,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,SAAS,GAAG,YAAY;aACjD,CAAA;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,KAAK,UAAU,WAAW;
|
|
1
|
+
{"version":3,"file":"updateCheck.js","sourceRoot":"","sources":["../../src/utils/updateCheck.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hacklab",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
"@resvg/resvg-js": "^2.6.2",
|
|
31
31
|
"@vercel/og": "^0.11.1",
|
|
32
32
|
"chalk": "^5.6.2",
|
|
33
|
+
"posthog-node": "^5.45.2",
|
|
33
34
|
"satori": "^0.26.0",
|
|
35
|
+
"string-width": "^7.2.0",
|
|
34
36
|
"yaml": "^2.8.3",
|
|
35
37
|
"zod": "^4.3.6"
|
|
36
38
|
},
|