@life-and-dev/mdsite 0.0.3

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 (133) hide show
  1. package/README.md +228 -0
  2. package/bin/mdsite.js +3 -0
  3. package/dist/commands/commands.test.d.ts +1 -0
  4. package/dist/commands/commands.test.js +302 -0
  5. package/dist/commands/commands.test.js.map +1 -0
  6. package/dist/commands/generate.d.ts +1 -0
  7. package/dist/commands/generate.js +20 -0
  8. package/dist/commands/generate.js.map +1 -0
  9. package/dist/commands/init.d.ts +1 -0
  10. package/dist/commands/init.js +16 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/prepare.d.ts +1 -0
  13. package/dist/commands/prepare.js +111 -0
  14. package/dist/commands/prepare.js.map +1 -0
  15. package/dist/commands/prepare.test.d.ts +1 -0
  16. package/dist/commands/prepare.test.js +131 -0
  17. package/dist/commands/prepare.test.js.map +1 -0
  18. package/dist/commands/preview.d.ts +5 -0
  19. package/dist/commands/preview.js +62 -0
  20. package/dist/commands/preview.js.map +1 -0
  21. package/dist/commands/start.d.ts +5 -0
  22. package/dist/commands/start.js +50 -0
  23. package/dist/commands/start.js.map +1 -0
  24. package/dist/commands/stop.d.ts +1 -0
  25. package/dist/commands/stop.js +26 -0
  26. package/dist/commands/stop.js.map +1 -0
  27. package/dist/commands/workflows.test.d.ts +1 -0
  28. package/dist/commands/workflows.test.js +183 -0
  29. package/dist/commands/workflows.test.js.map +1 -0
  30. package/dist/config/default-mdsite-config.d.ts +2 -0
  31. package/dist/config/default-mdsite-config.js +82 -0
  32. package/dist/config/default-mdsite-config.js.map +1 -0
  33. package/dist/config/default-mdsite-config.test.d.ts +1 -0
  34. package/dist/config/default-mdsite-config.test.js +42 -0
  35. package/dist/config/default-mdsite-config.test.js.map +1 -0
  36. package/dist/config/mdsite-config.d.ts +42 -0
  37. package/dist/config/mdsite-config.js +74 -0
  38. package/dist/config/mdsite-config.js.map +1 -0
  39. package/dist/config/mdsite-config.test.d.ts +1 -0
  40. package/dist/config/mdsite-config.test.js +115 -0
  41. package/dist/config/mdsite-config.test.js.map +1 -0
  42. package/dist/config/menu.d.ts +3 -0
  43. package/dist/config/menu.js +58 -0
  44. package/dist/config/menu.js.map +1 -0
  45. package/dist/config/menu.test.d.ts +1 -0
  46. package/dist/config/menu.test.js +53 -0
  47. package/dist/config/menu.test.js.map +1 -0
  48. package/dist/index.d.ts +2 -0
  49. package/dist/index.js +99 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/index.test.d.ts +1 -0
  52. package/dist/index.test.js +133 -0
  53. package/dist/index.test.js.map +1 -0
  54. package/dist/process/child-process.d.ts +9 -0
  55. package/dist/process/child-process.js +142 -0
  56. package/dist/process/child-process.js.map +1 -0
  57. package/dist/process/child-process.test.d.ts +1 -0
  58. package/dist/process/child-process.test.js +131 -0
  59. package/dist/process/child-process.test.js.map +1 -0
  60. package/dist/process/runtime-state.d.ts +16 -0
  61. package/dist/process/runtime-state.js +42 -0
  62. package/dist/process/runtime-state.js.map +1 -0
  63. package/dist/process/runtime-state.test.d.ts +1 -0
  64. package/dist/process/runtime-state.test.js +57 -0
  65. package/dist/process/runtime-state.test.js.map +1 -0
  66. package/dist/renderer/mdsite-nuxt.d.ts +22 -0
  67. package/dist/renderer/mdsite-nuxt.js +194 -0
  68. package/dist/renderer/mdsite-nuxt.js.map +1 -0
  69. package/dist/renderer/mdsite-nuxt.test.d.ts +1 -0
  70. package/dist/renderer/mdsite-nuxt.test.js +226 -0
  71. package/dist/renderer/mdsite-nuxt.test.js.map +1 -0
  72. package/mdsite-nuxt/app/app.vue +7 -0
  73. package/mdsite-nuxt/app/assets/css/bible-tooltips.css +87 -0
  74. package/mdsite-nuxt/app/assets/css/markdown.css +195 -0
  75. package/mdsite-nuxt/app/assets/css/print.css +133 -0
  76. package/mdsite-nuxt/app/components/AppBar.vue +138 -0
  77. package/mdsite-nuxt/app/components/AppFooter.vue +88 -0
  78. package/mdsite-nuxt/app/components/AppNavigation.vue +162 -0
  79. package/mdsite-nuxt/app/components/AppTableOfContents.vue +149 -0
  80. package/mdsite-nuxt/app/components/BreadcrumbNav.vue +139 -0
  81. package/mdsite-nuxt/app/components/NavigationTree.vue +169 -0
  82. package/mdsite-nuxt/app/components/SearchBox.vue +212 -0
  83. package/mdsite-nuxt/app/components/TocItem.vue +75 -0
  84. package/mdsite-nuxt/app/components/TreeNode.vue +264 -0
  85. package/mdsite-nuxt/app/components/content/MarkdownAlert.vue +42 -0
  86. package/mdsite-nuxt/app/components/content/Mermaid.vue +103 -0
  87. package/mdsite-nuxt/app/components/content/ProseA.vue +57 -0
  88. package/mdsite-nuxt/app/components/content/ProseBlockquote.vue +14 -0
  89. package/mdsite-nuxt/app/components/content/ProsePre.vue +49 -0
  90. package/mdsite-nuxt/app/components/content/ProseTable.vue +143 -0
  91. package/mdsite-nuxt/app/composables/useAppTheme.ts +89 -0
  92. package/mdsite-nuxt/app/composables/useBibleTooltips.ts +21 -0
  93. package/mdsite-nuxt/app/composables/useBreadcrumbs.ts +70 -0
  94. package/mdsite-nuxt/app/composables/useContentPostProcessing.ts +89 -0
  95. package/mdsite-nuxt/app/composables/useNavigationTree.ts +174 -0
  96. package/mdsite-nuxt/app/composables/useSearchIndex.ts +47 -0
  97. package/mdsite-nuxt/app/composables/useSearchRelevance.test.ts +255 -0
  98. package/mdsite-nuxt/app/composables/useSearchRelevance.ts +207 -0
  99. package/mdsite-nuxt/app/composables/useSidebarState.ts +62 -0
  100. package/mdsite-nuxt/app/composables/useSiteConfig.ts +37 -0
  101. package/mdsite-nuxt/app/composables/useSourceEdit.ts +69 -0
  102. package/mdsite-nuxt/app/composables/useTableOfContents.ts +141 -0
  103. package/mdsite-nuxt/app/composables/useTableParser.ts +106 -0
  104. package/mdsite-nuxt/app/composables/useTooltipConfig.ts +20 -0
  105. package/mdsite-nuxt/app/config/themes.ts +17 -0
  106. package/mdsite-nuxt/app/layouts/default.vue +376 -0
  107. package/mdsite-nuxt/app/pages/[...slug].vue +56 -0
  108. package/mdsite-nuxt/app/pages/index.vue +54 -0
  109. package/mdsite-nuxt/app/plugins/bible-tooltips.client.ts +401 -0
  110. package/mdsite-nuxt/app/plugins/bible-tooltips.test.ts +284 -0
  111. package/mdsite-nuxt/app/types/content.d.ts +10 -0
  112. package/mdsite-nuxt/app/types/table.ts +57 -0
  113. package/mdsite-nuxt/app/utils/bible-book-names.ts +37 -0
  114. package/mdsite-nuxt/app/utils/bible-verse-utils.test.ts +148 -0
  115. package/mdsite-nuxt/app/utils/bible-verse-utils.ts +236 -0
  116. package/mdsite-nuxt/content.config.ts +18 -0
  117. package/mdsite-nuxt/example.config.yml +67 -0
  118. package/mdsite-nuxt/nuxt.config.ts +247 -0
  119. package/mdsite-nuxt/package-lock.json +15922 -0
  120. package/mdsite-nuxt/package.json +50 -0
  121. package/mdsite-nuxt/playwright.config.js +47 -0
  122. package/mdsite-nuxt/public/robots.txt +2 -0
  123. package/mdsite-nuxt/scripts/generate-favicons.ts +192 -0
  124. package/mdsite-nuxt/scripts/generate-indices.ts +508 -0
  125. package/mdsite-nuxt/scripts/renderer-hooks.test.ts +277 -0
  126. package/mdsite-nuxt/scripts/renderer-hooks.ts +141 -0
  127. package/mdsite-nuxt/scripts/start.test.ts +164 -0
  128. package/mdsite-nuxt/scripts/start.ts +55 -0
  129. package/mdsite-nuxt/scripts/sync-content.ts +504 -0
  130. package/mdsite-nuxt/tsconfig.json +18 -0
  131. package/mdsite-nuxt/utils/mdsite-config.ts +240 -0
  132. package/mdsite-nuxt/vitest.config.ts +7 -0
  133. package/package.json +36 -0
package/dist/index.js ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ import { readFile } from 'node:fs/promises';
3
+ import process from 'node:process';
4
+ import { runGenerateCommand } from './commands/generate.js';
5
+ import { runInitCommand } from './commands/init.js';
6
+ import { runPrepareGithubCommand } from './commands/prepare.js';
7
+ import { runPreviewCommand } from './commands/preview.js';
8
+ import { runStartCommand } from './commands/start.js';
9
+ import { runStopCommand } from './commands/stop.js';
10
+ const helpText = `mdsite - local-first CLI for mdsite-nuxt
11
+
12
+ Usage:
13
+ mdsite help [-h|--help]
14
+ mdsite init
15
+ mdsite start [-d|--detached]
16
+ mdsite generate
17
+ mdsite preview [-d|--detached]
18
+ mdsite stop
19
+ mdsite version
20
+ mdsite prepare github
21
+
22
+ Commands:
23
+ init Create mdsite.yml in the current directory
24
+ start Start the checked-in mdsite-nuxt renderer for local content
25
+ generate Build static output through mdsite-nuxt
26
+ preview Preview the generated site through mdsite-nuxt
27
+ stop Stop tracked start and preview processes
28
+ version Print the CLI package version
29
+ prepare Generate the GitHub Pages workflow for this content directory
30
+
31
+ Options:
32
+ -h, --help Show this help output
33
+ -d, --detached Run mdsite start or preview in the background and write runtime state
34
+ `;
35
+ async function readPackageVersion() {
36
+ const packageJsonPath = new URL('../package.json', import.meta.url);
37
+ const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
38
+ if (typeof packageJson.version !== 'string') {
39
+ throw new Error('Unable to read package version from package.json');
40
+ }
41
+ return packageJson.version;
42
+ }
43
+ async function main() {
44
+ const [command, subcommand] = process.argv.slice(2);
45
+ const currentDirectory = process.cwd();
46
+ switch (command) {
47
+ case undefined:
48
+ case 'help':
49
+ case '--help':
50
+ case '-h':
51
+ console.log(helpText);
52
+ return;
53
+ case 'init':
54
+ await runInitCommand(currentDirectory);
55
+ console.log(`Created mdsite.yml in ${currentDirectory}`);
56
+ return;
57
+ case 'start':
58
+ {
59
+ const message = await runStartCommand(currentDirectory, { detached: subcommand === '-d' || subcommand === '--detached' });
60
+ if (message) {
61
+ console.log(message);
62
+ }
63
+ }
64
+ return;
65
+ case 'generate':
66
+ console.log(await runGenerateCommand(currentDirectory));
67
+ return;
68
+ case 'preview':
69
+ {
70
+ const message = await runPreviewCommand(currentDirectory, { detached: subcommand === '-d' || subcommand === '--detached' });
71
+ if (message) {
72
+ console.log(message);
73
+ }
74
+ }
75
+ return;
76
+ case 'stop':
77
+ console.log(await runStopCommand(currentDirectory));
78
+ return;
79
+ case 'version':
80
+ case '--version':
81
+ case '-v':
82
+ console.log(await readPackageVersion());
83
+ return;
84
+ case 'prepare':
85
+ if (subcommand === 'github') {
86
+ console.log(await runPrepareGithubCommand(currentDirectory));
87
+ return;
88
+ }
89
+ throw new Error(`Unsupported command: prepare${subcommand ? ` ${subcommand}` : ''}. Run \`mdsite help\` for supported local commands.`);
90
+ default:
91
+ throw new Error(`Unsupported command: ${command}. Run \`mdsite help\` for supported local commands.`);
92
+ }
93
+ }
94
+ main().catch((error) => {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ console.error(`Error: ${message}`);
97
+ process.exitCode = 1;
98
+ });
99
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,133 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import process from 'node:process';
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
+ vi.mock('./commands/init.js', () => ({ runInitCommand: vi.fn() }));
5
+ vi.mock('./commands/start.js', () => ({ runStartCommand: vi.fn() }));
6
+ vi.mock('./commands/generate.js', () => ({ runGenerateCommand: vi.fn() }));
7
+ vi.mock('./commands/preview.js', () => ({ runPreviewCommand: vi.fn() }));
8
+ vi.mock('./commands/stop.js', () => ({ runStopCommand: vi.fn() }));
9
+ vi.mock('./commands/prepare.js', () => ({ runPrepareGithubCommand: vi.fn() }));
10
+ import { runPrepareGithubCommand } from './commands/prepare.js';
11
+ import { runPreviewCommand } from './commands/preview.js';
12
+ import { runStartCommand } from './commands/start.js';
13
+ const runPrepareGithubCommandMock = vi.mocked(runPrepareGithubCommand);
14
+ const runPreviewCommandMock = vi.mocked(runPreviewCommand);
15
+ const runStartCommandMock = vi.mocked(runStartCommand);
16
+ async function readRootPackageVersion() {
17
+ const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
18
+ if (typeof packageJson.version !== 'string') {
19
+ throw new Error('Unable to read package version from package.json');
20
+ }
21
+ return packageJson.version;
22
+ }
23
+ describe('root CLI entrypoint', () => {
24
+ const originalArgv = process.argv;
25
+ const originalExitCode = process.exitCode;
26
+ let logSpy;
27
+ let errorSpy;
28
+ beforeEach(() => {
29
+ vi.resetModules();
30
+ process.exitCode = undefined;
31
+ logSpy = vi.spyOn(console, 'log').mockImplementation(() => undefined);
32
+ errorSpy = vi.spyOn(console, 'error').mockImplementation(() => undefined);
33
+ });
34
+ afterEach(() => {
35
+ process.argv = originalArgv;
36
+ process.exitCode = originalExitCode;
37
+ vi.restoreAllMocks();
38
+ });
39
+ it('prints local-first help output when no command is provided', async () => {
40
+ process.argv = ['node', 'mdsite'];
41
+ await import('./index.js');
42
+ await new Promise((resolve) => setTimeout(resolve, 0));
43
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('mdsite - local-first CLI for mdsite-nuxt'));
44
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('prepare github'));
45
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('mdsite preview [-d|--detached]'));
46
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('-d, --detached'));
47
+ expect(errorSpy).not.toHaveBeenCalled();
48
+ });
49
+ it('dispatches mdsite start in foreground mode by default', async () => {
50
+ process.argv = ['node', 'mdsite', 'start'];
51
+ runStartCommandMock.mockResolvedValue(undefined);
52
+ await import('./index.js');
53
+ await new Promise((resolve) => setTimeout(resolve, 0));
54
+ expect(runStartCommandMock).toHaveBeenCalledWith(process.cwd(), { detached: false });
55
+ expect(logSpy).not.toHaveBeenCalled();
56
+ expect(errorSpy).not.toHaveBeenCalled();
57
+ });
58
+ it('dispatches mdsite start detached mode for -d', async () => {
59
+ process.argv = ['node', 'mdsite', 'start', '-d'];
60
+ runStartCommandMock.mockResolvedValueOnce('detached');
61
+ await import('./index.js');
62
+ await new Promise((resolve) => setTimeout(resolve, 0));
63
+ expect(runStartCommandMock).toHaveBeenCalledWith(process.cwd(), { detached: true });
64
+ expect(logSpy).toHaveBeenCalledWith('detached');
65
+ expect(errorSpy).not.toHaveBeenCalled();
66
+ });
67
+ it('dispatches mdsite start detached mode for --detached', async () => {
68
+ process.argv = ['node', 'mdsite', 'start', '--detached'];
69
+ runStartCommandMock.mockResolvedValueOnce('detached');
70
+ await import('./index.js');
71
+ await new Promise((resolve) => setTimeout(resolve, 0));
72
+ expect(runStartCommandMock).toHaveBeenCalledWith(process.cwd(), { detached: true });
73
+ expect(logSpy).toHaveBeenCalledWith('detached');
74
+ expect(errorSpy).not.toHaveBeenCalled();
75
+ });
76
+ it('dispatches mdsite preview in foreground mode by default', async () => {
77
+ process.argv = ['node', 'mdsite', 'preview'];
78
+ runPreviewCommandMock.mockResolvedValue(undefined);
79
+ await import('./index.js');
80
+ await new Promise((resolve) => setTimeout(resolve, 0));
81
+ expect(runPreviewCommandMock).toHaveBeenCalledWith(process.cwd(), { detached: false });
82
+ expect(logSpy).not.toHaveBeenCalled();
83
+ expect(errorSpy).not.toHaveBeenCalled();
84
+ });
85
+ it.each(['-d', '--detached'])('dispatches mdsite preview detached mode for %s', async (flag) => {
86
+ process.argv = ['node', 'mdsite', 'preview', flag];
87
+ runPreviewCommandMock.mockResolvedValueOnce('detached preview');
88
+ await import('./index.js');
89
+ await new Promise((resolve) => setTimeout(resolve, 0));
90
+ expect(runPreviewCommandMock).toHaveBeenCalledWith(process.cwd(), { detached: true });
91
+ expect(logSpy).toHaveBeenCalledWith('detached preview');
92
+ expect(errorSpy).not.toHaveBeenCalled();
93
+ });
94
+ it.each(['help', '-h', '--help'])('prints help output when %s is requested', async (helpCommand) => {
95
+ process.argv = ['node', 'mdsite', helpCommand];
96
+ await import('./index.js');
97
+ await new Promise((resolve) => setTimeout(resolve, 0));
98
+ expect(logSpy).toHaveBeenCalledWith(expect.stringContaining('prepare github'));
99
+ expect(errorSpy).not.toHaveBeenCalled();
100
+ expect(process.exitCode).toBeUndefined();
101
+ });
102
+ it('prints the package version when the version command is requested', async () => {
103
+ process.argv = ['node', 'mdsite', 'version'];
104
+ await import('./index.js');
105
+ await new Promise((resolve) => setTimeout(resolve, 0));
106
+ expect(logSpy).toHaveBeenCalledWith(await readRootPackageVersion());
107
+ expect(errorSpy).not.toHaveBeenCalled();
108
+ });
109
+ it('dispatches mdsite prepare github to the GitHub workflow command', async () => {
110
+ process.argv = ['node', 'mdsite', 'prepare', 'github'];
111
+ runPrepareGithubCommandMock.mockResolvedValue('Generated GitHub Pages workflow at /workspace/content/.github/workflows/deploy.yml');
112
+ await import('./index.js');
113
+ await new Promise((resolve) => setTimeout(resolve, 0));
114
+ expect(runPrepareGithubCommandMock).toHaveBeenCalledWith(process.cwd());
115
+ expect(logSpy).toHaveBeenCalledWith('Generated GitHub Pages workflow at /workspace/content/.github/workflows/deploy.yml');
116
+ expect(errorSpy).not.toHaveBeenCalled();
117
+ });
118
+ it('rejects mdsite prepare without github as unsupported', async () => {
119
+ process.argv = ['node', 'mdsite', 'prepare'];
120
+ await import('./index.js');
121
+ await new Promise((resolve) => setTimeout(resolve, 0));
122
+ expect(errorSpy).toHaveBeenCalledWith('Error: Unsupported command: prepare. Run `mdsite help` for supported local commands.');
123
+ expect(process.exitCode).toBe(1);
124
+ });
125
+ it('reports unsupported commands as errors and sets a non-zero exit code', async () => {
126
+ process.argv = ['node', 'mdsite', 'wat'];
127
+ await import('./index.js');
128
+ await new Promise((resolve) => setTimeout(resolve, 0));
129
+ expect(errorSpy).toHaveBeenCalledWith('Error: Unsupported command: wat. Run `mdsite help` for supported local commands.');
130
+ expect(process.exitCode).toBe(1);
131
+ });
132
+ });
133
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare function runForeground(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv): Promise<void>;
2
+ export declare function runBackground(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv, logPath: string): Promise<number>;
3
+ export declare function openUrlInBrowser(url: string): Promise<boolean>;
4
+ export declare function waitForTcpPort(host: string, port: number, options?: {
5
+ retryIntervalMs?: number;
6
+ timeoutMs?: number;
7
+ connectTimeoutMs?: number;
8
+ }): Promise<boolean>;
9
+ export declare function stopProcess(pid: number): Promise<boolean>;
@@ -0,0 +1,142 @@
1
+ import { mkdir, open } from 'node:fs/promises';
2
+ import { spawn } from 'node:child_process';
3
+ import net from 'node:net';
4
+ import path from 'node:path';
5
+ export async function runForeground(command, args, cwd, env) {
6
+ const child = spawn(command, args, {
7
+ cwd,
8
+ env,
9
+ stdio: 'inherit'
10
+ });
11
+ const exitCode = await new Promise((resolve, reject) => {
12
+ child.once('error', reject);
13
+ child.once('close', (code) => resolve(code ?? 0));
14
+ });
15
+ if (exitCode !== 0) {
16
+ throw new Error(`${command} ${args.join(' ')} failed with exit code ${exitCode}.`);
17
+ }
18
+ }
19
+ export async function runBackground(command, args, cwd, env, logPath) {
20
+ await mkdir(path.dirname(logPath), { recursive: true });
21
+ const logFile = await open(logPath, 'a');
22
+ const child = spawn(command, args, {
23
+ cwd,
24
+ env,
25
+ detached: process.platform !== 'win32',
26
+ stdio: ['ignore', logFile.fd, logFile.fd]
27
+ });
28
+ child.once('error', async (error) => {
29
+ await logFile.appendFile(`${error instanceof Error ? error.stack || error.message : String(error)}\n`);
30
+ });
31
+ child.unref();
32
+ await logFile.close();
33
+ if (!child.pid) {
34
+ throw new Error(`Failed to start ${command} ${args.join(' ')}.`);
35
+ }
36
+ return child.pid;
37
+ }
38
+ export async function openUrlInBrowser(url) {
39
+ const openCommand = getBrowserOpenCommand(url);
40
+ if (!openCommand) {
41
+ return false;
42
+ }
43
+ return new Promise((resolve) => {
44
+ try {
45
+ const child = spawn(openCommand.command, openCommand.args, {
46
+ detached: true,
47
+ stdio: 'ignore'
48
+ });
49
+ child.once('error', () => resolve(false));
50
+ child.once('spawn', () => {
51
+ child.unref();
52
+ resolve(true);
53
+ });
54
+ }
55
+ catch {
56
+ resolve(false);
57
+ }
58
+ });
59
+ }
60
+ export async function waitForTcpPort(host, port, options = {}) {
61
+ const retryIntervalMs = options.retryIntervalMs ?? 100;
62
+ const timeoutMs = options.timeoutMs ?? 5_000;
63
+ const connectTimeoutMs = options.connectTimeoutMs ?? retryIntervalMs;
64
+ const deadline = Date.now() + timeoutMs;
65
+ while (Date.now() < deadline) {
66
+ if (await canConnectToTcpPort(host, port, connectTimeoutMs)) {
67
+ return true;
68
+ }
69
+ if (Date.now() >= deadline) {
70
+ break;
71
+ }
72
+ await new Promise((resolve) => setTimeout(resolve, retryIntervalMs));
73
+ }
74
+ return false;
75
+ }
76
+ export async function stopProcess(pid) {
77
+ if (!isRunning(pid)) {
78
+ return false;
79
+ }
80
+ try {
81
+ sendSignal(pid, 'SIGTERM');
82
+ }
83
+ catch {
84
+ return false;
85
+ }
86
+ for (let attempt = 0; attempt < 20; attempt += 1) {
87
+ await new Promise((resolve) => setTimeout(resolve, 150));
88
+ if (!isRunning(pid)) {
89
+ return true;
90
+ }
91
+ }
92
+ try {
93
+ sendSignal(pid, 'SIGKILL');
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ return !isRunning(pid);
99
+ }
100
+ function isRunning(pid) {
101
+ try {
102
+ process.kill(pid, 0);
103
+ return true;
104
+ }
105
+ catch {
106
+ return false;
107
+ }
108
+ }
109
+ async function canConnectToTcpPort(host, port, timeoutMs) {
110
+ return new Promise((resolve) => {
111
+ const socket = net.connect({ host, port });
112
+ const finish = (connected) => {
113
+ socket.removeAllListeners();
114
+ socket.destroy();
115
+ resolve(connected);
116
+ };
117
+ socket.setTimeout(timeoutMs);
118
+ socket.once('connect', () => finish(true));
119
+ socket.once('error', () => finish(false));
120
+ socket.once('timeout', () => finish(false));
121
+ });
122
+ }
123
+ function sendSignal(pid, signal) {
124
+ if (process.platform === 'win32') {
125
+ process.kill(pid, signal);
126
+ return;
127
+ }
128
+ process.kill(-pid, signal);
129
+ }
130
+ function getBrowserOpenCommand(url) {
131
+ switch (process.platform) {
132
+ case 'darwin':
133
+ return { command: 'open', args: [url] };
134
+ case 'win32':
135
+ return { command: 'cmd', args: ['/c', 'start', '', url] };
136
+ case 'linux':
137
+ return { command: 'xdg-open', args: [url] };
138
+ default:
139
+ return null;
140
+ }
141
+ }
142
+ //# sourceMappingURL=child-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process.js","sourceRoot":"","sources":["../../src/process/child-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,131 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ const { mkdirMock, openMock, spawnMock, connectMock } = vi.hoisted(() => ({
3
+ mkdirMock: vi.fn(),
4
+ openMock: vi.fn(),
5
+ spawnMock: vi.fn(),
6
+ connectMock: vi.fn()
7
+ }));
8
+ vi.mock('node:fs/promises', () => ({
9
+ mkdir: mkdirMock,
10
+ open: openMock
11
+ }));
12
+ vi.mock('node:child_process', () => ({
13
+ spawn: spawnMock
14
+ }));
15
+ vi.mock('node:net', () => ({
16
+ default: {
17
+ connect: connectMock
18
+ }
19
+ }));
20
+ import { openUrlInBrowser, runBackground, waitForTcpPort } from './child-process.js';
21
+ describe('child-process helpers', () => {
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ mkdirMock.mockResolvedValue(undefined);
25
+ openMock.mockResolvedValue({
26
+ fd: 17,
27
+ close: vi.fn().mockResolvedValue(undefined),
28
+ appendFile: vi.fn().mockResolvedValue(undefined)
29
+ });
30
+ spawnMock.mockReturnValue({
31
+ pid: 1234,
32
+ once: vi.fn(),
33
+ unref: vi.fn()
34
+ });
35
+ });
36
+ it('creates the parent log directory before opening a background process log file', async () => {
37
+ await expect(runBackground('npm', ['run', 'preview'], '/renderer', { TEST: '1' }, '/content/mdsite.log')).resolves.toBe(1234);
38
+ expect(mkdirMock).toHaveBeenCalledWith('/content', { recursive: true });
39
+ expect(openMock).toHaveBeenCalledWith('/content/mdsite.log', 'a');
40
+ expect(mkdirMock.mock.invocationCallOrder[0]).toBeLessThan(openMock.mock.invocationCallOrder[0] ?? Number.POSITIVE_INFINITY);
41
+ });
42
+ it('uses the same parent-directory log setup for start background processes', async () => {
43
+ await expect(runBackground('npm', ['run', 'dev'], '/renderer', { TEST: '1' }, '/content/.mdsite-runtime/start.log')).resolves.toBe(1234);
44
+ expect(mkdirMock).toHaveBeenCalledWith('/content/.mdsite-runtime', { recursive: true });
45
+ expect(openMock).toHaveBeenCalledWith('/content/.mdsite-runtime/start.log', 'a');
46
+ });
47
+ it('opens preview URLs in the default browser on supported platforms', async () => {
48
+ const onceMock = vi.fn((event, handler) => {
49
+ if (event === 'spawn') {
50
+ handler();
51
+ }
52
+ return browserChild;
53
+ });
54
+ const browserChild = {
55
+ once: onceMock,
56
+ unref: vi.fn()
57
+ };
58
+ spawnMock.mockReturnValueOnce(browserChild);
59
+ await expect(openUrlInBrowser('http://localhost:3000')).resolves.toBe(true);
60
+ expect(spawnMock).toHaveBeenCalledWith('xdg-open', ['http://localhost:3000'], {
61
+ detached: true,
62
+ stdio: 'ignore'
63
+ });
64
+ expect(browserChild.unref).toHaveBeenCalled();
65
+ });
66
+ it('returns false when browser opening is unsupported or unavailable', async () => {
67
+ const onceMock = vi.fn((event, handler) => {
68
+ if (event === 'error') {
69
+ handler();
70
+ }
71
+ return browserChild;
72
+ });
73
+ const browserChild = {
74
+ once: onceMock,
75
+ unref: vi.fn()
76
+ };
77
+ spawnMock.mockReturnValueOnce(browserChild);
78
+ await expect(openUrlInBrowser('http://localhost:3000')).resolves.toBe(false);
79
+ });
80
+ it('waitForTcpPort retries until the port accepts connections', async () => {
81
+ vi.useFakeTimers();
82
+ let attempts = 0;
83
+ connectMock.mockImplementation(() => {
84
+ const handlers = new Map();
85
+ const socket = {
86
+ once: vi.fn((event, handler) => {
87
+ handlers.set(event, handler);
88
+ return socket;
89
+ }),
90
+ setTimeout: vi.fn(),
91
+ removeAllListeners: vi.fn(),
92
+ destroy: vi.fn()
93
+ };
94
+ queueMicrotask(() => {
95
+ attempts += 1;
96
+ const event = attempts < 3 ? 'error' : 'connect';
97
+ handlers.get(event)?.();
98
+ });
99
+ return socket;
100
+ });
101
+ const waitPromise = waitForTcpPort('localhost', 3000, { retryIntervalMs: 25, timeoutMs: 100 });
102
+ await vi.advanceTimersByTimeAsync(50);
103
+ await expect(waitPromise).resolves.toBe(true);
104
+ expect(connectMock).toHaveBeenCalledTimes(3);
105
+ expect(connectMock).toHaveBeenNthCalledWith(1, { host: 'localhost', port: 3000 });
106
+ });
107
+ it('waitForTcpPort returns false after the bounded timeout', async () => {
108
+ vi.useFakeTimers();
109
+ connectMock.mockImplementation(() => {
110
+ const handlers = new Map();
111
+ const socket = {
112
+ once: vi.fn((event, handler) => {
113
+ handlers.set(event, handler);
114
+ return socket;
115
+ }),
116
+ setTimeout: vi.fn(),
117
+ removeAllListeners: vi.fn(),
118
+ destroy: vi.fn()
119
+ };
120
+ queueMicrotask(() => {
121
+ handlers.get('timeout')?.();
122
+ });
123
+ return socket;
124
+ });
125
+ const waitPromise = waitForTcpPort('127.0.0.1', 4173, { retryIntervalMs: 25, timeoutMs: 70, connectTimeoutMs: 10 });
126
+ await vi.advanceTimersByTimeAsync(100);
127
+ await expect(waitPromise).resolves.toBe(false);
128
+ expect(connectMock).toHaveBeenCalledTimes(3);
129
+ });
130
+ });
131
+ //# sourceMappingURL=child-process.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"child-process.test.js","sourceRoot":"","sources":["../../src/process/child-process.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7D,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACxE,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;IAClB,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;IACjB,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE;IAClB,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;CACrB,CAAC,CAAC,CAAA;AAEH,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,QAAQ;CACf,CAAC,CAAC,CAAA;AAEH,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,KAAK,EAAE,SAAS;CACjB,CAAC,CAAC,CAAA;AAEH,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IACzB,OAAO,EAAE;QACP,OAAO,EAAE,WAAW;KACrB;CACF,CAAC,CAAC,CAAA;AAEH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEpF,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,SAAS,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAA;QACtC,QAAQ,CAAC,iBAAiB,CAAC;YACzB,EAAE,EAAE,EAAE;YACN,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;YAC3C,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;SACjD,CAAC,CAAA;QACF,SAAS,CAAC,eAAe,CAAC;YACxB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE;YACb,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;SACf,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAE7H,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvE,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAA;QACjE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAA;IAC9H,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,oCAAoC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAExI,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,0BAA0B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACvF,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAA;IAClF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,KAAa,EAAE,OAAmB,EAAE,EAAE;YAC5D,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAA;YACX,CAAC;YACD,OAAO,YAAY,CAAA;QACrB,CAAC,CAAC,CAAA;QACF,MAAM,YAAY,GAAG;YACnB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;SACf,CAAA;QACD,SAAS,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAA;QAE3C,MAAM,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3E,MAAM,CAAC,SAAS,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,CAAC,uBAAuB,CAAC,EAAE;YAC5E,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAA;QACF,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,gBAAgB,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,KAAa,EAAE,OAAmB,EAAE,EAAE;YAC5D,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAA;YACX,CAAC;YACD,OAAO,YAAY,CAAA;QACrB,CAAC,CAAC,CAAA;QACF,MAAM,YAAY,GAAG;YACnB,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;SACf,CAAA;QACD,SAAS,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAA;QAE3C,MAAM,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC9E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,WAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAA;YAC9C,MAAM,MAAM,GAAG;gBACb,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAa,EAAE,OAAmB,EAAE,EAAE;oBACjD,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;oBAC5B,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC;gBACF,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;gBACnB,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;gBAC3B,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;aACjB,CAAA;YAED,cAAc,CAAC,GAAG,EAAE;gBAClB,QAAQ,IAAI,CAAC,CAAA;gBACb,MAAM,KAAK,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;gBAChD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,CAAA;YACzB,CAAC,CAAC,CAAA;YAEF,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAA;QAC9F,MAAM,EAAE,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAA;QAErC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;QAC5C,MAAM,CAAC,WAAW,CAAC,CAAC,uBAAuB,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACnF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,EAAE,CAAC,aAAa,EAAE,CAAA;QAClB,WAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAA;YAC9C,MAAM,MAAM,GAAG;gBACb,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAa,EAAE,OAAmB,EAAE,EAAE;oBACjD,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;oBAC5B,OAAO,MAAM,CAAA;gBACf,CAAC,CAAC;gBACF,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;gBACnB,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;gBAC3B,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;aACjB,CAAA;YAED,cAAc,CAAC,GAAG,EAAE;gBAClB,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,EAAE,CAAA;YAC7B,CAAC,CAAC,CAAA;YAEF,OAAO,MAAM,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC,CAAA;QACnH,MAAM,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAA;QAEtC,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9C,MAAM,CAAC,WAAW,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,16 @@
1
+ export type RuntimeProcessKind = 'start' | 'preview';
2
+ export interface RuntimeProcessState {
3
+ kind: RuntimeProcessKind;
4
+ pid: number;
5
+ logPath: string;
6
+ rendererDir: string;
7
+ contentDir: string;
8
+ command: string[];
9
+ startedAt: string;
10
+ }
11
+ export declare function getRuntimeDir(contentDir: string): string;
12
+ export declare function getRuntimeLogPath(contentDir: string, kind: RuntimeProcessKind): string;
13
+ export declare function readRuntimeState(contentDir: string, kind: RuntimeProcessKind): Promise<RuntimeProcessState | null>;
14
+ export declare function writeRuntimeState(contentDir: string, state: RuntimeProcessState): Promise<void>;
15
+ export declare function clearRuntimeState(contentDir: string, kind: RuntimeProcessKind): Promise<void>;
16
+ export declare function isProcessRunning(pid: number): boolean;
@@ -0,0 +1,42 @@
1
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const runtimeDirectoryName = '.mdsite-runtime';
4
+ export function getRuntimeDir(contentDir) {
5
+ return path.join(contentDir, runtimeDirectoryName);
6
+ }
7
+ export function getRuntimeLogPath(contentDir, kind) {
8
+ if (kind === 'preview') {
9
+ return path.join(contentDir, 'mdsite.log');
10
+ }
11
+ return path.join(getRuntimeDir(contentDir), `${kind}.log`);
12
+ }
13
+ export async function readRuntimeState(contentDir, kind) {
14
+ const statePath = getStatePath(contentDir, kind);
15
+ try {
16
+ const content = await readFile(statePath, 'utf8');
17
+ return JSON.parse(content);
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ export async function writeRuntimeState(contentDir, state) {
24
+ await mkdir(getRuntimeDir(contentDir), { recursive: true });
25
+ await writeFile(getStatePath(contentDir, state.kind), `${JSON.stringify(state, null, 2)}\n`, 'utf8');
26
+ }
27
+ export async function clearRuntimeState(contentDir, kind) {
28
+ await rm(getStatePath(contentDir, kind), { force: true });
29
+ }
30
+ export function isProcessRunning(pid) {
31
+ try {
32
+ process.kill(pid, 0);
33
+ return true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ function getStatePath(contentDir, kind) {
40
+ return path.join(getRuntimeDir(contentDir), `${kind}.json`);
41
+ }
42
+ //# sourceMappingURL=runtime-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-state.js","sourceRoot":"","sources":["../../src/process/runtime-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjE,OAAO,IAAI,MAAM,WAAW,CAAA;AAc5B,MAAM,oBAAoB,GAAG,iBAAiB,CAAA;AAE9C,MAAM,UAAU,aAAa,CAAC,UAAkB;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAA;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,IAAwB;IAC5E,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IAC5C,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,MAAM,CAAC,CAAA;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,UAAkB,EAAE,IAAwB;IACjF,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAEhD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAwB,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB,EAAE,KAA0B;IACpF,MAAM,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3D,MAAM,SAAS,CAAC,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AACtG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB,EAAE,IAAwB;IAClF,MAAM,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC3D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,UAAkB,EAAE,IAAwB;IAChE,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAA;AAC7D,CAAC"}
@@ -0,0 +1 @@
1
+ export {};