jamdesk 1.1.100 → 1.1.102

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=banner-art-sync.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner-art-sync.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/banner-art-sync.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Drift guard for the 3-place ASCII "Jamdesk" banner art.
3
+ *
4
+ * The same figlet art is emitted from three representations that cannot
5
+ * share a module — a raw text asset read by the npm postinstall, a bash
6
+ * here-string in the curl|bash bootstrap installer, and a PowerShell
7
+ * Write-Host block in the iwr|iex bootstrap installer:
8
+ *
9
+ * - builder/cli/scripts/banner.txt (npm postinstall asset)
10
+ * - builder/cli/scripts/install.sh print_banner (bash, backslash/backtick-escaped)
11
+ * - builder/cli/scripts/install.ps1 Write-Banner (PowerShell, backtick-escaped)
12
+ *
13
+ * Same rationale as the documented OpenAPI-patch trio (see
14
+ * openapi-schema-patch-sync.test.ts and builder/CLAUDE.md): comments alone
15
+ * don't stop drift, a test does. Edit the art in one place and forget the
16
+ * others and a user gets a different banner from `npm i -g` vs the curl
17
+ * installer.
18
+ *
19
+ * The snippets below are deliberately escaping-invariant: each contains no
20
+ * backslash, backtick, or quote, so it appears byte-identical in the raw
21
+ * asset, the bash-escaped string, and the PowerShell-escaped string. They
22
+ * are also interior substrings (not line-anchored), so per-line trailing
23
+ * whitespace and the `echo "`/`Write-Host "` prefixes don't matter — what
24
+ * is pinned is the art's shape, one fragment per line.
25
+ */
26
+ import { describe, it, expect } from 'vitest';
27
+ import fs from 'fs-extra';
28
+ import path from 'path';
29
+ import { fileURLToPath } from 'url';
30
+ const here = path.dirname(fileURLToPath(import.meta.url));
31
+ const scripts = path.join(here, '../../../scripts');
32
+ const SITES = {
33
+ 'npm asset (banner.txt)': path.join(scripts, 'banner.txt'),
34
+ 'bash installer (install.sh)': path.join(scripts, 'install.sh'),
35
+ 'powershell installer (install.ps1)': path.join(scripts, 'install.ps1'),
36
+ };
37
+ // One fragment per art line. No \ ` " ' so escaping in any representation
38
+ // can't change them; internal whitespace IS the art and is preserved.
39
+ const ART_LINES = [
40
+ '_ _ _',
41
+ '| | __ _ _ __ ___ __| | ___ ___| | __',
42
+ '__| |/ /',
43
+ '(_| | | | | | | (_| | __',
44
+ '___||___',
45
+ ];
46
+ describe('Jamdesk banner art sync (3-place drift guard)', () => {
47
+ for (const [name, file] of Object.entries(SITES)) {
48
+ it(`${name} carries the full art`, async () => {
49
+ const src = await fs.readFile(file, 'utf-8');
50
+ for (const line of ART_LINES) {
51
+ expect(src, `${name} art drifted — missing line: ${line}`).toContain(line);
52
+ }
53
+ });
54
+ }
55
+ });
56
+ //# sourceMappingURL=banner-art-sync.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner-art-sync.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/banner-art-sync.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;AAEpD,MAAM,KAAK,GAAG;IACZ,wBAAwB,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;IAC1D,6BAA6B,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/D,oCAAoC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC;CACxE,CAAC;AAEF,0EAA0E;AAC1E,sEAAsE;AACtE,MAAM,SAAS,GAAG;IAChB,qCAAqC;IACrC,0CAA0C;IAC1C,UAAU;IACV,2BAA2B;IAC3B,UAAU;CACX,CAAC;AAEF,QAAQ,CAAC,+CAA+C,EAAE,GAAG,EAAE;IAC7D,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,EAAE,CAAC,GAAG,IAAI,uBAAuB,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC7C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,gCAAgC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=first-run-banner.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-run-banner.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/first-run-banner.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * First-run banner contract (src/lib/first-run-banner.ts).
3
+ *
4
+ * The npm postinstall banner is undeliverable for `npm i -g` (npm swallows
5
+ * global postinstall stdout — see install-banner-gating.test.ts). This
6
+ * first-run banner is the replacement; these tests pin its gating so it
7
+ * shows exactly once, on the first real command, in a real terminal only.
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
+ import fs from 'fs';
11
+ import os from 'os';
12
+ import path from 'path';
13
+ import { maybeShowFirstRunBanner } from '../../lib/first-run-banner.js';
14
+ let tmp;
15
+ let writeSpy;
16
+ const savedTTY = Object.getOwnPropertyDescriptor(process.stdout, 'isTTY');
17
+ const savedEnv = { CI: process.env.CI, JAMDESK_INSTALLER: process.env.JAMDESK_INSTALLER };
18
+ function out() {
19
+ return writeSpy.mock.calls.map((c) => String(c[0])).join('');
20
+ }
21
+ beforeEach(() => {
22
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'jd-firstrun-'));
23
+ writeSpy = vi.spyOn(process.stdout, 'write').mockReturnValue(true);
24
+ // A real interactive terminal is a TTY; vitest's stdout is not.
25
+ Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true });
26
+ delete process.env.CI;
27
+ delete process.env.JAMDESK_INSTALLER;
28
+ });
29
+ afterEach(() => {
30
+ writeSpy.mockRestore();
31
+ if (savedTTY)
32
+ Object.defineProperty(process.stdout, 'isTTY', savedTTY);
33
+ for (const [k, v] of Object.entries(savedEnv)) {
34
+ if (v === undefined)
35
+ delete process.env[k];
36
+ else
37
+ process.env[k] = v;
38
+ }
39
+ fs.rmSync(tmp, { recursive: true, force: true });
40
+ });
41
+ describe('maybeShowFirstRunBanner', () => {
42
+ it('shows the art once on the first real command, then writes the sentinel', async () => {
43
+ await maybeShowFirstRunBanner({ argv: ['dev'], jamdeskDir: tmp });
44
+ const text = out();
45
+ expect(text).toContain('| | __ _ _ __ ___ __| | ___ ___| | __'); // art line
46
+ expect(text).toContain('Get started:');
47
+ expect(text).toContain('jamdesk init');
48
+ expect(fs.existsSync(path.join(tmp, '.welcomed'))).toBe(true);
49
+ });
50
+ it('stays silent once the sentinel exists (shows exactly once)', async () => {
51
+ fs.writeFileSync(path.join(tmp, '.welcomed'), 'x\n');
52
+ await maybeShowFirstRunBanner({ argv: ['dev'], jamdeskDir: tmp });
53
+ expect(out()).toBe('');
54
+ });
55
+ it('does not show OR consume first-run for --version', async () => {
56
+ await maybeShowFirstRunBanner({ argv: ['--version'], jamdeskDir: tmp });
57
+ expect(out()).toBe('');
58
+ expect(fs.existsSync(path.join(tmp, '.welcomed'))).toBe(false);
59
+ });
60
+ it('does not show for bare `jamdesk` (help) or --json', async () => {
61
+ await maybeShowFirstRunBanner({ argv: [], jamdeskDir: tmp });
62
+ await maybeShowFirstRunBanner({ argv: ['doctor', '--json'], jamdeskDir: tmp });
63
+ expect(out()).toBe('');
64
+ expect(fs.existsSync(path.join(tmp, '.welcomed'))).toBe(false);
65
+ });
66
+ it('stays silent in CI', async () => {
67
+ process.env.CI = 'true';
68
+ await maybeShowFirstRunBanner({ argv: ['dev'], jamdeskDir: tmp });
69
+ expect(out()).toBe('');
70
+ });
71
+ it('stays silent when stdout is not a TTY (piped / scripted)', async () => {
72
+ Object.defineProperty(process.stdout, 'isTTY', { value: false, configurable: true });
73
+ await maybeShowFirstRunBanner({ argv: ['dev'], jamdeskDir: tmp });
74
+ expect(out()).toBe('');
75
+ });
76
+ it('still prints (and never throws) if the sentinel write fails', async () => {
77
+ // jamdeskDir points at a file → mkdir/write fail, banner must still show.
78
+ const asFile = path.join(tmp, 'not-a-dir');
79
+ fs.writeFileSync(asFile, 'x');
80
+ await expect(maybeShowFirstRunBanner({ argv: ['dev'], jamdeskDir: asFile })).resolves.toBeUndefined();
81
+ expect(out()).toContain('Get started:');
82
+ });
83
+ });
84
+ //# sourceMappingURL=first-run-banner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-run-banner.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/first-run-banner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=install-banner-gating.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-banner-gating.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/install-banner-gating.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Gating contract for the npm postinstall banner (scripts/install-banner.js).
3
+ *
4
+ * Regression guard for the 1.1.101 ship bug: the script gated on
5
+ * `process.stdout.isTTY`, but npm >=7 runs `postinstall` with stdout PIPED
6
+ * (never a TTY) unless the user passes `--foreground-scripts`. That gate
7
+ * therefore suppressed the banner on every normal `npm i -g jamdesk` — the
8
+ * feature was dead on arrival and no test caught it.
9
+ *
10
+ * These tests run the REAL shipped script as a child process with stdout
11
+ * piped — i.e. exactly npm's postinstall condition (child.stdout.isTTY is
12
+ * undefined). A correctly-gated banner MUST still print here. The script is
13
+ * un-exported and side-effecting by design (zero-dep, must never fail an
14
+ * install), so we assert through its observable output, not internals.
15
+ */
16
+ import { describe, it, expect } from 'vitest';
17
+ import { spawnSync } from 'node:child_process';
18
+ import path from 'node:path';
19
+ import { fileURLToPath } from 'node:url';
20
+ const here = path.dirname(fileURLToPath(import.meta.url));
21
+ const script = path.join(here, '../../../scripts/install-banner.js');
22
+ // A clean global-install env: only what node needs + npm's global marker.
23
+ // Built from scratch (not spreading process.env) so the host's CI=… or a
24
+ // stray npm_config_* can't leak in and flip the gate under test.
25
+ function run(env) {
26
+ return spawnSync(process.execPath, [script], {
27
+ env: { PATH: process.env.PATH ?? '', NO_COLOR: '1', ...env },
28
+ encoding: 'utf8',
29
+ });
30
+ }
31
+ const GLOBAL_INSTALL = { npm_config_global: 'true' };
32
+ describe('install-banner postinstall gating', () => {
33
+ it('prints the banner on a normal global install with PIPED stdout (npm postinstall reality)', () => {
34
+ const { stdout, status } = run(GLOBAL_INSTALL);
35
+ // The exact regression: child stdout is a pipe here, never a TTY.
36
+ expect(stdout).toContain('Jamdesk CLI installed:');
37
+ expect(stdout).toContain('jamdesk init');
38
+ // Cosmetic — must never fail the install.
39
+ expect(status).toBe(0);
40
+ });
41
+ it('stays silent for a non-global install (npm i / npm ci of deps)', () => {
42
+ expect(run({}).stdout).toBe('');
43
+ });
44
+ it('stays silent in CI', () => {
45
+ expect(run({ ...GLOBAL_INSTALL, CI: 'true' }).stdout).toBe('');
46
+ });
47
+ it('stays silent when the bootstrap installer already showed a banner', () => {
48
+ expect(run({ ...GLOBAL_INSTALL, JAMDESK_INSTALLER: '1' }).stdout).toBe('');
49
+ });
50
+ it('stays silent at a quiet loglevel (npm i -g --silent / Docker)', () => {
51
+ expect(run({ ...GLOBAL_INSTALL, npm_config_loglevel: 'silent' }).stdout).toBe('');
52
+ });
53
+ });
54
+ //# sourceMappingURL=install-banner-gating.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-banner-gating.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/install-banner-gating.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oCAAoC,CAAC,CAAC;AAErE,0EAA0E;AAC1E,yEAAyE;AACzE,iEAAiE;AACjE,SAAS,GAAG,CAAC,GAA2B;IACtC,OAAO,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE;QAC3C,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE;QAC5D,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,cAAc,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AAErD,QAAQ,CAAC,mCAAmC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,0FAA0F,EAAE,GAAG,EAAE;QAClG,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;QAC/C,kEAAkE;QAClE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACzC,0CAA0C;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,cAAc,EAAE,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,cAAc,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ import { loadConfig } from './lib/config.js';
11
11
  import { createRequire } from 'module';
12
12
  import { isUserError } from './lib/errors.js';
13
13
  import { output } from './lib/output.js';
14
+ import { maybeShowFirstRunBanner } from './lib/first-run-banner.js';
14
15
  const require = createRequire(import.meta.url);
15
16
  const pkg = require('../package.json');
16
17
  // Detect local dev: published package doesn't include src/
@@ -399,6 +400,10 @@ Supported targets:
399
400
  process.exit(1);
400
401
  }
401
402
  });
403
+ // One-time welcome banner before command dispatch. Self-gating, never
404
+ // throws — npm can't deliver an install-time banner for `npm i -g`
405
+ // (install-banner-gating.test.ts), so first run is where users see it.
406
+ await maybeShowFirstRunBanner();
402
407
  try {
403
408
  await program.parseAsync();
404
409
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface FirstRunBannerOptions {
2
+ argv?: string[];
3
+ /** ~/.jamdesk by default; injectable for tests (mirrors clean.ts ctx). */
4
+ jamdeskDir?: string;
5
+ }
6
+ export declare function maybeShowFirstRunBanner({ argv, jamdeskDir, }?: FirstRunBannerOptions): Promise<void>;
7
+ //# sourceMappingURL=first-run-banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-run-banner.d.ts","sourceRoot":"","sources":["../../src/lib/first-run-banner.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,uBAAuB,CAAC,EAC5C,IAA4B,EAC5B,UAA6C,GAC9C,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC5C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * First-run welcome banner.
3
+ *
4
+ * Shows the ASCII "Jamdesk" art once — the first time the user runs a real
5
+ * command after install. npm swallows successful global `postinstall` stdout
6
+ * for `npm i -g` (verified on npm 11; see install-banner-gating.test.ts), so
7
+ * an install-time banner can never reach those users. A first-run banner is
8
+ * the reliable delivery path and behaves the same across npm/pnpm/yarn/bun.
9
+ *
10
+ * Cosmetic and defensive: it never throws and never blocks the CLI. Worst
11
+ * case it shows twice (the sentinel write failed) — harmless.
12
+ */
13
+ import fs from 'fs';
14
+ import path from 'path';
15
+ import { homedir } from 'os';
16
+ import { fileURLToPath } from 'url';
17
+ import chalk from 'chalk';
18
+ // Args that aren't a real command invocation. We skip the banner AND leave
19
+ // first-run unconsumed, so the user still gets it on their first real
20
+ // command. `--json` is excluded too — banner text would corrupt machine
21
+ // output (e.g. `jamdesk doctor --json`).
22
+ const SKIP_ARGS = new Set(['-v', '-V', '--version', '-h', '--help', '--json']);
23
+ function shouldSkip(argv) {
24
+ if (process.env.CI)
25
+ return true;
26
+ if (process.env.JAMDESK_INSTALLER)
27
+ return true;
28
+ // A real interactive terminal IS a TTY here — unlike an npm postinstall,
29
+ // which npm always pipes. This is the correct place for an isTTY gate.
30
+ if (!process.stdout.isTTY)
31
+ return true;
32
+ if (argv.length === 0)
33
+ return true; // bare `jamdesk` just prints help
34
+ return argv.some((a) => SKIP_ARGS.has(a));
35
+ }
36
+ export async function maybeShowFirstRunBanner({ argv = process.argv.slice(2), jamdeskDir = path.join(homedir(), '.jamdesk'), } = {}) {
37
+ try {
38
+ if (shouldSkip(argv))
39
+ return;
40
+ const sentinel = path.join(jamdeskDir, '.welcomed');
41
+ if (fs.existsSync(sentinel))
42
+ return;
43
+ // banner.txt is shipped (package.json "files") and is the single
44
+ // drift-guarded source of the art (banner-art-sync.test.ts). From
45
+ // dist/lib/first-run-banner.js the package root is ../../.
46
+ const here = path.dirname(fileURLToPath(import.meta.url));
47
+ const art = fs
48
+ .readFileSync(path.join(here, '..', '..', 'scripts', 'banner.txt'), 'utf8')
49
+ .replace(/\n$/, '');
50
+ // chalk respects NO_COLOR / non-TTY itself, so no manual color gate.
51
+ process.stdout.write(`\n${chalk.blue(art)}\n\n` +
52
+ 'Welcome to Jamdesk — build docs sites from MDX.\n\n' +
53
+ 'Get started:\n' +
54
+ ' jamdesk init # Create a new docs project\n' +
55
+ ' jamdesk dev # Start the dev server\n' +
56
+ ' jamdesk --help # See all commands\n\n');
57
+ // Best-effort: mark welcomed so it shows exactly once. If this fails the
58
+ // banner just shows again next run — never worth failing a command over.
59
+ try {
60
+ fs.mkdirSync(jamdeskDir, { recursive: true });
61
+ fs.writeFileSync(sentinel, `${new Date().toISOString()}\n`);
62
+ }
63
+ catch {
64
+ /* non-fatal */
65
+ }
66
+ }
67
+ catch {
68
+ // Cosmetic only — a missing/garbled banner must never break the CLI.
69
+ }
70
+ }
71
+ //# sourceMappingURL=first-run-banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-run-banner.js","sourceRoot":"","sources":["../../src/lib/first-run-banner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,yCAAyC;AACzC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE/E,SAAS,UAAU,CAAC,IAAc;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAC/C,yEAAyE;IACzE,uEAAuE;IACvE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,kCAAkC;IACtE,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAC5C,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAC5B,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,MACpB,EAAE;IAC3B,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO;QAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO;QAEpC,iEAAiE;QACjE,kEAAkE;QAClE,2DAA2D;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,EAAE;aACX,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC;aAC1E,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAEtB,qEAAqE;QACrE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,KAAK,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM;YACxB,qDAAqD;YACrD,gBAAgB;YAChB,mDAAmD;YACnD,8CAA8C;YAC9C,4CAA4C,CAC/C,CAAC;QAEF,yEAAyE;QACzE,yEAAyE;QACzE,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.100",
3
+ "version": "1.1.102",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
@@ -60,6 +60,8 @@
60
60
  "bin/",
61
61
  "dist/",
62
62
  "scripts/patch-openapi-schemas.js",
63
+ "scripts/install-banner.js",
64
+ "scripts/banner.txt",
63
65
  "templates/",
64
66
  "vendored/components/",
65
67
  "vendored/contexts/",
@@ -96,7 +98,7 @@
96
98
  "test:local": "node scripts/test-local.js",
97
99
  "lint": "eslint src/",
98
100
  "dev": "tsc --watch",
99
- "postinstall": "node scripts/patch-openapi-schemas.js"
101
+ "postinstall": "node scripts/patch-openapi-schemas.js && node scripts/install-banner.js"
100
102
  },
101
103
  "dependencies": {
102
104
  "@apidevtools/swagger-parser": "^12.1.0",
@@ -0,0 +1,5 @@
1
+ _ _ _
2
+ | | __ _ _ __ ___ __| | ___ ___| | __
3
+ _ | |/ _` | '_ ` _ \ / _` |/ _ \/ __| |/ /
4
+ | |_| | (_| | | | | | | (_| | __/\__ \ <
5
+ \___/ \__,_|_| |_| |_|\__,_|\___||___/_|\_\
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Postinstall banner for `npm install -g jamdesk`.
4
+ *
5
+ * Shows the same ASCII "Jamdesk" art the curl/iwr bootstrap installer prints,
6
+ * so a plain `npm i -g jamdesk` gets the same first-run experience.
7
+ *
8
+ * This is cosmetic and must NEVER fail an install: every branch is guarded
9
+ * and the process always exits 0, even on a read error.
10
+ *
11
+ * Zero-dependency by design: a postinstall runs before the package's own
12
+ * node_modules is guaranteed resolvable, so this inlines ANSI/TTY/version
13
+ * logic instead of importing from src/ (chalk/ora). Same constraint and
14
+ * precedent as the sibling scripts/patch-openapi-schemas.js — do not "DRY"
15
+ * this against src/lib/output.ts; it would break `npm install`.
16
+ *
17
+ * It deliberately stays quiet unless this is a user-initiated global install:
18
+ * - JAMDESK_INSTALLER set → the bootstrap installer already showed a banner
19
+ * - not a global install → don't spam dependency installs / `npm ci`
20
+ * - CI / quiet loglevel → no banner in pipelines, Docker layers, logs
21
+ *
22
+ * Deliberately NOT gated on `process.stdout.isTTY`: npm >=7 runs postinstall
23
+ * with stdout PIPED, never a TTY, unless the user passes --foreground-scripts.
24
+ * A TTY gate here suppressed the banner on every real `npm i -g` (shipped
25
+ * dead in 1.1.101). The CI / loglevel / global gates already keep it out of
26
+ * pipelines and Docker. Do not re-add an isTTY check — see
27
+ * install-banner-gating.test.ts.
28
+ */
29
+ import { readFileSync } from 'node:fs';
30
+ import { fileURLToPath } from 'node:url';
31
+ import { dirname, join } from 'node:path';
32
+
33
+ // npm's default loglevel is `notice`; these are the only levels quieter than
34
+ // it (silent < error < warn < notice). A user on default still sees the
35
+ // banner; `npm i -g --quiet` (→ warn) or `--silent` suppresses it.
36
+ const QUIET_LOGLEVELS = ['silent', 'error', 'warn'];
37
+
38
+ function shouldShow() {
39
+ if (process.env.JAMDESK_INSTALLER) return false;
40
+ // npm sets npm_config_global=true for `npm install -g`.
41
+ if (process.env.npm_config_global !== 'true') return false;
42
+ if (process.env.CI) return false;
43
+ if (QUIET_LOGLEVELS.includes(process.env.npm_config_loglevel)) return false;
44
+ return true;
45
+ }
46
+
47
+ try {
48
+ if (shouldShow()) {
49
+ const here = dirname(fileURLToPath(import.meta.url));
50
+ const art = readFileSync(join(here, 'banner.txt'), 'utf8').replace(/\n$/, '');
51
+ const { version } = JSON.parse(
52
+ readFileSync(join(here, '..', 'package.json'), 'utf8'),
53
+ );
54
+
55
+ const color = !process.env.NO_COLOR;
56
+ const blue = color ? '\x1b[34m' : '';
57
+ const green = color ? '\x1b[32m' : '';
58
+ const reset = color ? '\x1b[0m' : '';
59
+
60
+ process.stdout.write(
61
+ `\n${blue}${art}${reset}\n\n` +
62
+ `${green}[OK]${reset} Jamdesk CLI installed: ${version}\n\n` +
63
+ 'Get started:\n' +
64
+ ' jamdesk init # Create new docs project\n' +
65
+ ' jamdesk dev # Start dev server\n' +
66
+ ' jamdesk --help # See all commands\n\n',
67
+ );
68
+ }
69
+ } catch {
70
+ // Intentionally fully silent — unlike the sibling patch-openapi-schemas.js,
71
+ // which console.warn's on failure because a failed schema patch has
72
+ // functional consequences the user must know about. A missing decorative
73
+ // banner has none, so a `[jamdesk] …` warning here would be pure noise
74
+ // during install. Never worth failing (or even cluttering) `npm install`.
75
+ }