github-issue-tower-defence-management 1.104.4 → 1.105.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +8 -7
- package/bin/adapter/entry-points/cli/index.js +21 -13
- package/bin/adapter/entry-points/cli/index.js.map +1 -1
- package/bin/adapter/entry-points/console/{consoleServer.js → webServer.js} +11 -11
- package/bin/adapter/entry-points/console/webServer.js.map +1 -0
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js +41 -2
- package/bin/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.js.map +1 -1
- package/bin/adapter/entry-points/handlers/dashboardRowWriter.js +34 -0
- package/bin/adapter/entry-points/handlers/dashboardRowWriter.js.map +1 -0
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js +60 -0
- package/bin/adapter/entry-points/handlers/machineStatusWriter.js.map +1 -0
- package/bin/adapter/entry-points/handlers/tokenStatusWriter.js +98 -0
- package/bin/adapter/entry-points/handlers/tokenStatusWriter.js.map +1 -0
- package/bin/adapter/proxy/RateLimitCache.js +3 -0
- package/bin/adapter/proxy/RateLimitCache.js.map +1 -1
- package/bin/adapter/repositories/ProcHostMetricsRepository.js +136 -0
- package/bin/adapter/repositories/ProcHostMetricsRepository.js.map +1 -0
- package/bin/adapter/repositories/ProcTakeOwnershipSpawnRepository.js +131 -0
- package/bin/adapter/repositories/ProcTakeOwnershipSpawnRepository.js.map +1 -0
- package/bin/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.js +3 -0
- package/bin/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.js.map +1 -0
- package/bin/domain/usecases/dashboard/GenerateDashboardRowUseCase.js +38 -0
- package/bin/domain/usecases/dashboard/GenerateDashboardRowUseCase.js.map +1 -0
- package/bin/domain/usecases/dashboard/GenerateTokenStatusUseCase.js +115 -0
- package/bin/domain/usecases/dashboard/GenerateTokenStatusUseCase.js.map +1 -0
- package/package.json +1 -1
- package/src/adapter/entry-points/cli/index.test.ts +74 -21
- package/src/adapter/entry-points/cli/index.ts +146 -136
- package/src/adapter/entry-points/console/ui/e2e/consoleTestHarness.ts +2 -2
- package/src/adapter/entry-points/console/{consoleServer.test.ts → webServer.test.ts} +32 -32
- package/src/adapter/entry-points/console/{consoleServer.ts → webServer.ts} +15 -17
- package/src/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.ts +52 -0
- package/src/adapter/entry-points/handlers/dashboardRowWriter.test.ts +111 -0
- package/src/adapter/entry-points/handlers/dashboardRowWriter.ts +51 -0
- package/src/adapter/entry-points/handlers/machineStatusWriter.test.ts +100 -0
- package/src/adapter/entry-points/handlers/machineStatusWriter.ts +79 -0
- package/src/adapter/entry-points/handlers/tokenStatusWriter.test.ts +176 -0
- package/src/adapter/entry-points/handlers/tokenStatusWriter.ts +139 -0
- package/src/adapter/proxy/RateLimitCache.test.ts +32 -0
- package/src/adapter/proxy/RateLimitCache.ts +6 -0
- package/src/adapter/repositories/ProcHostMetricsRepository.test.ts +135 -0
- package/src/adapter/repositories/ProcHostMetricsRepository.ts +136 -0
- package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.test.ts +130 -0
- package/src/adapter/repositories/ProcTakeOwnershipSpawnRepository.ts +118 -0
- package/src/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.ts +8 -0
- package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.test.ts +159 -0
- package/src/domain/usecases/dashboard/GenerateDashboardRowUseCase.ts +72 -0
- package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.test.ts +209 -0
- package/src/domain/usecases/dashboard/GenerateTokenStatusUseCase.ts +195 -0
- package/types/adapter/entry-points/cli/index.d.ts.map +1 -1
- package/types/adapter/entry-points/console/{consoleServer.d.ts → webServer.d.ts} +7 -7
- package/types/adapter/entry-points/console/webServer.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/HandleScheduledEventUseCaseHandler.d.ts.map +1 -1
- package/types/adapter/entry-points/handlers/dashboardRowWriter.d.ts +15 -0
- package/types/adapter/entry-points/handlers/dashboardRowWriter.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts +16 -0
- package/types/adapter/entry-points/handlers/machineStatusWriter.d.ts.map +1 -0
- package/types/adapter/entry-points/handlers/tokenStatusWriter.d.ts +21 -0
- package/types/adapter/entry-points/handlers/tokenStatusWriter.d.ts.map +1 -0
- package/types/adapter/proxy/RateLimitCache.d.ts +2 -0
- package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -1
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts +23 -0
- package/types/adapter/repositories/ProcHostMetricsRepository.d.ts.map +1 -0
- package/types/adapter/repositories/ProcTakeOwnershipSpawnRepository.d.ts +11 -0
- package/types/adapter/repositories/ProcTakeOwnershipSpawnRepository.d.ts.map +1 -0
- package/types/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.d.ts +8 -0
- package/types/domain/usecases/adapter-interfaces/TakeOwnershipSpawnRepository.d.ts.map +1 -0
- package/types/domain/usecases/dashboard/GenerateDashboardRowUseCase.d.ts +19 -0
- package/types/domain/usecases/dashboard/GenerateDashboardRowUseCase.d.ts.map +1 -0
- package/types/domain/usecases/dashboard/GenerateTokenStatusUseCase.d.ts +53 -0
- package/types/domain/usecases/dashboard/GenerateTokenStatusUseCase.d.ts.map +1 -0
- package/bin/adapter/entry-points/console/consoleServer.js.map +0 -1
- package/types/adapter/entry-points/console/consoleServer.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -73,23 +73,22 @@ jest.mock('../handlers/HandleScheduledEventUseCaseHandler', () => ({
|
|
|
73
73
|
handle: jest.fn().mockResolvedValue(null),
|
|
74
74
|
})),
|
|
75
75
|
}));
|
|
76
|
-
import type {
|
|
76
|
+
import type { StartWebServerOptions } from '../console/webServer';
|
|
77
77
|
|
|
78
|
-
const
|
|
79
|
-
.fn<Promise<unknown>, [
|
|
78
|
+
const mockStartWebServer = jest
|
|
79
|
+
.fn<Promise<unknown>, [StartWebServerOptions]>()
|
|
80
80
|
.mockResolvedValue({
|
|
81
81
|
close: jest.fn(),
|
|
82
82
|
address: jest.fn().mockReturnValue({ port: 9981 }),
|
|
83
83
|
});
|
|
84
|
-
jest.mock('../console/
|
|
84
|
+
jest.mock('../console/webServer', () => {
|
|
85
85
|
const actual: Record<string, unknown> = jest.requireActual(
|
|
86
|
-
'../console/
|
|
86
|
+
'../console/webServer',
|
|
87
87
|
);
|
|
88
88
|
return {
|
|
89
89
|
...actual,
|
|
90
|
-
|
|
91
|
-
options
|
|
92
|
-
): Promise<unknown> => mockStartConsoleServer(options),
|
|
90
|
+
startWebServer: (options: StartWebServerOptions): Promise<unknown> =>
|
|
91
|
+
mockStartWebServer(options),
|
|
93
92
|
};
|
|
94
93
|
});
|
|
95
94
|
|
|
@@ -1677,10 +1676,10 @@ mysteryKey: 'value'
|
|
|
1677
1676
|
});
|
|
1678
1677
|
});
|
|
1679
1678
|
|
|
1680
|
-
describe('
|
|
1679
|
+
describe('serveWeb', () => {
|
|
1681
1680
|
it('should appear in the CLI help output', () => {
|
|
1682
1681
|
const helpText = program.helpInformation();
|
|
1683
|
-
expect(helpText).toContain('
|
|
1682
|
+
expect(helpText).toContain('serveWeb');
|
|
1684
1683
|
});
|
|
1685
1684
|
|
|
1686
1685
|
it('should start the server on the default port 9981 when --port is omitted', async () => {
|
|
@@ -1690,13 +1689,13 @@ mysteryKey: 'value'
|
|
|
1690
1689
|
await program.parseAsync([
|
|
1691
1690
|
'node',
|
|
1692
1691
|
'test',
|
|
1693
|
-
'
|
|
1692
|
+
'serveWeb',
|
|
1694
1693
|
'--configFilePath',
|
|
1695
1694
|
configFilePath,
|
|
1696
1695
|
]);
|
|
1697
1696
|
|
|
1698
|
-
expect(
|
|
1699
|
-
const callArg =
|
|
1697
|
+
expect(mockStartWebServer).toHaveBeenCalledTimes(1);
|
|
1698
|
+
const callArg = mockStartWebServer.mock.calls[0][0];
|
|
1700
1699
|
expect(callArg.port).toBe(9981);
|
|
1701
1700
|
expect(callArg.accessToken).toBe('config-token');
|
|
1702
1701
|
expect(callArg.consoleDataOutputDir).toBeNull();
|
|
@@ -1717,7 +1716,7 @@ mysteryKey: 'value'
|
|
|
1717
1716
|
await program.parseAsync([
|
|
1718
1717
|
'node',
|
|
1719
1718
|
'test',
|
|
1720
|
-
'
|
|
1719
|
+
'serveWeb',
|
|
1721
1720
|
'--configFilePath',
|
|
1722
1721
|
configFilePath,
|
|
1723
1722
|
'--port',
|
|
@@ -1726,7 +1725,7 @@ mysteryKey: 'value'
|
|
|
1726
1725
|
'/tmp/console-data',
|
|
1727
1726
|
]);
|
|
1728
1727
|
|
|
1729
|
-
const callArg =
|
|
1728
|
+
const callArg = mockStartWebServer.mock.calls[0][0];
|
|
1730
1729
|
expect(callArg.port).toBe(12345);
|
|
1731
1730
|
expect(callArg.consoleDataOutputDir).toBe('/tmp/console-data');
|
|
1732
1731
|
|
|
@@ -1746,7 +1745,7 @@ mysteryKey: 'value'
|
|
|
1746
1745
|
program.parseAsync([
|
|
1747
1746
|
'node',
|
|
1748
1747
|
'test',
|
|
1749
|
-
'
|
|
1748
|
+
'serveWeb',
|
|
1750
1749
|
'--configFilePath',
|
|
1751
1750
|
configFilePath,
|
|
1752
1751
|
]),
|
|
@@ -1774,7 +1773,7 @@ mysteryKey: 'value'
|
|
|
1774
1773
|
program.parseAsync([
|
|
1775
1774
|
'node',
|
|
1776
1775
|
'test',
|
|
1777
|
-
'
|
|
1776
|
+
'serveWeb',
|
|
1778
1777
|
'--configFilePath',
|
|
1779
1778
|
configFilePath,
|
|
1780
1779
|
'--port',
|
|
@@ -1795,12 +1794,12 @@ mysteryKey: 'value'
|
|
|
1795
1794
|
await program.parseAsync([
|
|
1796
1795
|
'node',
|
|
1797
1796
|
'test',
|
|
1798
|
-
'
|
|
1797
|
+
'serveWeb',
|
|
1799
1798
|
'--configFilePath',
|
|
1800
1799
|
configFilePath,
|
|
1801
1800
|
]);
|
|
1802
1801
|
|
|
1803
|
-
const callArg =
|
|
1802
|
+
const callArg = mockStartWebServer.mock.calls[0][0];
|
|
1804
1803
|
expect(callArg.issueRepository).not.toBeNull();
|
|
1805
1804
|
expect(callArg.issueTitleStateCache).not.toBeNull();
|
|
1806
1805
|
|
|
@@ -1833,7 +1832,7 @@ mysteryKey: 'value'
|
|
|
1833
1832
|
program.parseAsync([
|
|
1834
1833
|
'node',
|
|
1835
1834
|
'test',
|
|
1836
|
-
'
|
|
1835
|
+
'serveWeb',
|
|
1837
1836
|
'--configFilePath',
|
|
1838
1837
|
configFilePath,
|
|
1839
1838
|
]),
|
|
@@ -1865,7 +1864,7 @@ mysteryKey: 'value'
|
|
|
1865
1864
|
program.parseAsync([
|
|
1866
1865
|
'node',
|
|
1867
1866
|
'test',
|
|
1868
|
-
'
|
|
1867
|
+
'serveWeb',
|
|
1869
1868
|
'--configFilePath',
|
|
1870
1869
|
configFilePath,
|
|
1871
1870
|
]),
|
|
@@ -1879,4 +1878,58 @@ mysteryKey: 'value'
|
|
|
1879
1878
|
processExitSpy.mockRestore();
|
|
1880
1879
|
});
|
|
1881
1880
|
});
|
|
1881
|
+
|
|
1882
|
+
describe('serveConsole (deprecated alias)', () => {
|
|
1883
|
+
it('should appear in the CLI help output', () => {
|
|
1884
|
+
const helpText = program.helpInformation();
|
|
1885
|
+
expect(helpText).toContain('serveConsole');
|
|
1886
|
+
});
|
|
1887
|
+
|
|
1888
|
+
it('should route to the same handler as serveWeb on the default port 9981', async () => {
|
|
1889
|
+
writeConfig({ ...defaultConfig, consoleAccessToken: 'config-token' });
|
|
1890
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
1891
|
+
|
|
1892
|
+
await program.parseAsync([
|
|
1893
|
+
'node',
|
|
1894
|
+
'test',
|
|
1895
|
+
'serveConsole',
|
|
1896
|
+
'--configFilePath',
|
|
1897
|
+
configFilePath,
|
|
1898
|
+
]);
|
|
1899
|
+
|
|
1900
|
+
expect(mockStartWebServer).toHaveBeenCalledTimes(1);
|
|
1901
|
+
const callArg = mockStartWebServer.mock.calls[0][0];
|
|
1902
|
+
expect(callArg.port).toBe(9981);
|
|
1903
|
+
expect(callArg.accessToken).toBe('config-token');
|
|
1904
|
+
expect(callArg.consoleDataOutputDir).toBeNull();
|
|
1905
|
+
expect(callArg.uiDistDir).toBe(
|
|
1906
|
+
path.join(__dirname, '..', 'console', 'ui-dist'),
|
|
1907
|
+
);
|
|
1908
|
+
|
|
1909
|
+
logSpy.mockRestore();
|
|
1910
|
+
});
|
|
1911
|
+
|
|
1912
|
+
it('should use the provided --port and --consoleDataOutputDir', async () => {
|
|
1913
|
+
writeConfig({ ...defaultConfig, consoleAccessToken: 'config-token' });
|
|
1914
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
1915
|
+
|
|
1916
|
+
await program.parseAsync([
|
|
1917
|
+
'node',
|
|
1918
|
+
'test',
|
|
1919
|
+
'serveConsole',
|
|
1920
|
+
'--configFilePath',
|
|
1921
|
+
configFilePath,
|
|
1922
|
+
'--port',
|
|
1923
|
+
'12345',
|
|
1924
|
+
'--consoleDataOutputDir',
|
|
1925
|
+
'/tmp/console-data',
|
|
1926
|
+
]);
|
|
1927
|
+
|
|
1928
|
+
const callArg = mockStartWebServer.mock.calls[0][0];
|
|
1929
|
+
expect(callArg.port).toBe(12345);
|
|
1930
|
+
expect(callArg.consoleDataOutputDir).toBe('/tmp/console-data');
|
|
1931
|
+
|
|
1932
|
+
logSpy.mockRestore();
|
|
1933
|
+
});
|
|
1934
|
+
});
|
|
1882
1935
|
});
|
|
@@ -32,10 +32,7 @@ import { GitHubIssueCommentRepository } from '../../repositories/GitHubIssueComm
|
|
|
32
32
|
import { FetchWebhookRepository } from '../../repositories/FetchWebhookRepository';
|
|
33
33
|
import { RevertOrphanedPreparationUseCase } from '../../../domain/usecases/RevertOrphanedPreparationUseCase';
|
|
34
34
|
import * as path from 'path';
|
|
35
|
-
import {
|
|
36
|
-
DEFAULT_CONSOLE_PORT,
|
|
37
|
-
startConsoleServer,
|
|
38
|
-
} from '../console/consoleServer';
|
|
35
|
+
import { DEFAULT_WEB_PORT, startWebServer } from '../console/webServer';
|
|
39
36
|
import { IssueTitleStateCache } from '../console/consoleReadApi';
|
|
40
37
|
import {
|
|
41
38
|
buildPjcodeToProjectUrl,
|
|
@@ -73,7 +70,7 @@ type CheckIssueReviewReadinessOptions = {
|
|
|
73
70
|
configFilePath: string;
|
|
74
71
|
};
|
|
75
72
|
|
|
76
|
-
type
|
|
73
|
+
type ServeWebOptions = {
|
|
77
74
|
configFilePath: string;
|
|
78
75
|
port?: string;
|
|
79
76
|
consoleDataOutputDir?: string;
|
|
@@ -596,146 +593,159 @@ program
|
|
|
596
593
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
597
594
|
});
|
|
598
595
|
|
|
599
|
-
|
|
600
|
-
.
|
|
601
|
-
|
|
602
|
-
.
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
'--dashboardDir <path>',
|
|
620
|
-
`Directory containing the dashboard HTML fragment tdpm.txt served unauthenticated at /tdpm.txt (default: ${DEFAULT_DASHBOARD_DIR})`,
|
|
621
|
-
)
|
|
622
|
-
.action(async (options: ServeConsoleOptions) => {
|
|
623
|
-
const config = loadConfigFile(options.configFilePath);
|
|
624
|
-
|
|
625
|
-
const accessToken = config.consoleAccessToken;
|
|
626
|
-
if (!accessToken) {
|
|
596
|
+
const runServeWeb = async (options: ServeWebOptions): Promise<void> => {
|
|
597
|
+
const config = loadConfigFile(options.configFilePath);
|
|
598
|
+
|
|
599
|
+
const accessToken = config.consoleAccessToken;
|
|
600
|
+
if (!accessToken) {
|
|
601
|
+
console.error(
|
|
602
|
+
'consoleAccessToken is required. Provide it via the config file.',
|
|
603
|
+
);
|
|
604
|
+
process.exit(1);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
let port = DEFAULT_WEB_PORT;
|
|
608
|
+
if (options.port !== undefined) {
|
|
609
|
+
const parsedPort = Number(options.port);
|
|
610
|
+
if (
|
|
611
|
+
!Number.isFinite(parsedPort) ||
|
|
612
|
+
!Number.isInteger(parsedPort) ||
|
|
613
|
+
parsedPort <= 0 ||
|
|
614
|
+
parsedPort > 65535
|
|
615
|
+
) {
|
|
627
616
|
console.error(
|
|
628
|
-
'
|
|
617
|
+
'Invalid value for --port. It must be a positive integer between 1 and 65535.',
|
|
629
618
|
);
|
|
630
619
|
process.exit(1);
|
|
631
620
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
621
|
+
port = parsedPort;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
const token = process.env.GH_TOKEN;
|
|
625
|
+
if (!token) {
|
|
626
|
+
console.error('GH_TOKEN environment variable is required');
|
|
627
|
+
process.exit(1);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
const projectUrl = config.projectUrl;
|
|
631
|
+
if (!projectUrl) {
|
|
632
|
+
console.error(
|
|
633
|
+
'projectUrl is required. Provide it via the config file or project README.',
|
|
634
|
+
);
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const projectName = config.projectName ?? 'default';
|
|
639
|
+
const localStorageRepository = new LocalStorageRepository();
|
|
640
|
+
const cachePath = `./tmp/cache/${projectName}`;
|
|
641
|
+
const localStorageCacheRepository = new LocalStorageCacheRepository(
|
|
642
|
+
localStorageRepository,
|
|
643
|
+
cachePath,
|
|
644
|
+
);
|
|
645
|
+
const githubRepositoryParams = buildGithubRepositoryParams(
|
|
646
|
+
localStorageRepository,
|
|
647
|
+
token,
|
|
648
|
+
);
|
|
649
|
+
const projectRepository = new GraphqlProjectRepository(
|
|
650
|
+
...githubRepositoryParams,
|
|
651
|
+
);
|
|
652
|
+
const apiV3IssueRepository = new ApiV3IssueRepository(
|
|
653
|
+
...githubRepositoryParams,
|
|
654
|
+
);
|
|
655
|
+
const restIssueRepository = new RestIssueRepository(
|
|
656
|
+
...githubRepositoryParams,
|
|
657
|
+
);
|
|
658
|
+
const graphqlProjectItemRepository = new GraphqlProjectItemRepository(
|
|
659
|
+
...githubRepositoryParams,
|
|
660
|
+
);
|
|
661
|
+
const issueRepository = new ApiV3CheerioRestIssueRepository(
|
|
662
|
+
apiV3IssueRepository,
|
|
663
|
+
restIssueRepository,
|
|
664
|
+
graphqlProjectItemRepository,
|
|
665
|
+
localStorageCacheRepository,
|
|
666
|
+
...githubRepositoryParams,
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
const pjcodeToProjectUrl = buildPjcodeToProjectUrl(
|
|
670
|
+
projectName,
|
|
671
|
+
projectUrl,
|
|
672
|
+
config.consoleProjects ?? null,
|
|
673
|
+
);
|
|
674
|
+
const resolveProject = createConsoleProjectResolver(
|
|
675
|
+
pjcodeToProjectUrl,
|
|
676
|
+
async (targetProjectUrl: string) => {
|
|
677
|
+
const targetProjectId =
|
|
678
|
+
await projectRepository.findProjectIdByUrl(targetProjectUrl);
|
|
679
|
+
if (!targetProjectId) {
|
|
680
|
+
console.error(`No project found for projectUrl ${targetProjectUrl}`);
|
|
681
|
+
return null;
|
|
682
|
+
}
|
|
683
|
+
const loadedProject = await projectRepository.getProject(targetProjectId);
|
|
684
|
+
if (!loadedProject) {
|
|
642
685
|
console.error(
|
|
643
|
-
|
|
686
|
+
`Failed to load project for projectUrl ${targetProjectUrl}`,
|
|
644
687
|
);
|
|
645
|
-
|
|
688
|
+
return null;
|
|
646
689
|
}
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
690
|
+
return loadedProject;
|
|
691
|
+
},
|
|
692
|
+
);
|
|
693
|
+
|
|
694
|
+
const uiDistDir = path.join(__dirname, '..', 'console', 'ui-dist');
|
|
695
|
+
const consoleDataOutputDir = options.consoleDataOutputDir ?? null;
|
|
696
|
+
const inTmuxDataDir = options.inTmuxDataDir ?? DEFAULT_IN_TMUX_DATA_DIR;
|
|
697
|
+
const dashboardDir = options.dashboardDir ?? DEFAULT_DASHBOARD_DIR;
|
|
698
|
+
|
|
699
|
+
await startWebServer({
|
|
700
|
+
accessToken,
|
|
701
|
+
uiDistDir,
|
|
702
|
+
consoleDataOutputDir,
|
|
703
|
+
inTmuxDataDir,
|
|
704
|
+
dashboardDir,
|
|
705
|
+
githubToken: token,
|
|
706
|
+
issueRepository,
|
|
707
|
+
resolveProject,
|
|
708
|
+
issueTitleStateCache: new IssueTitleStateCache(),
|
|
709
|
+
port,
|
|
710
|
+
});
|
|
711
|
+
console.log(`TDPM web server listening on port ${port}`);
|
|
712
|
+
};
|
|
663
713
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
)
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
714
|
+
const addServeWebOptions = (command: Command): Command =>
|
|
715
|
+
command
|
|
716
|
+
.requiredOption(
|
|
717
|
+
'--configFilePath <path>',
|
|
718
|
+
'Path to config file for tower defence management',
|
|
719
|
+
)
|
|
720
|
+
.option(
|
|
721
|
+
'--port <number>',
|
|
722
|
+
`Port for the web HTTP server (default: ${DEFAULT_WEB_PORT})`,
|
|
723
|
+
)
|
|
724
|
+
.option(
|
|
725
|
+
'--consoleDataOutputDir <path>',
|
|
726
|
+
'Directory where console data files are written and served from',
|
|
727
|
+
)
|
|
728
|
+
.option(
|
|
729
|
+
'--inTmuxDataDir <path>',
|
|
730
|
+
`Directory containing the flat in-tmux-by-human static JSON files served at /in-tmux-by-human/*.json (default: ${DEFAULT_IN_TMUX_DATA_DIR})`,
|
|
731
|
+
)
|
|
732
|
+
.option(
|
|
733
|
+
'--dashboardDir <path>',
|
|
734
|
+
`Directory containing the dashboard HTML fragment tdpm.txt served unauthenticated at /tdpm.txt (default: ${DEFAULT_DASHBOARD_DIR})`,
|
|
735
|
+
);
|
|
736
|
+
|
|
737
|
+
addServeWebOptions(program.command('serveWeb'))
|
|
738
|
+
.description(
|
|
739
|
+
'Start the local TDPM web server (console tabs, dashboard, and in-tmux session list)',
|
|
740
|
+
)
|
|
741
|
+
.action(async (options: ServeWebOptions) => {
|
|
742
|
+
await runServeWeb(options);
|
|
743
|
+
});
|
|
694
744
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
);
|
|
700
|
-
const resolveProject = createConsoleProjectResolver(
|
|
701
|
-
pjcodeToProjectUrl,
|
|
702
|
-
async (targetProjectUrl: string) => {
|
|
703
|
-
const targetProjectId =
|
|
704
|
-
await projectRepository.findProjectIdByUrl(targetProjectUrl);
|
|
705
|
-
if (!targetProjectId) {
|
|
706
|
-
console.error(`No project found for projectUrl ${targetProjectUrl}`);
|
|
707
|
-
return null;
|
|
708
|
-
}
|
|
709
|
-
const loadedProject =
|
|
710
|
-
await projectRepository.getProject(targetProjectId);
|
|
711
|
-
if (!loadedProject) {
|
|
712
|
-
console.error(
|
|
713
|
-
`Failed to load project for projectUrl ${targetProjectUrl}`,
|
|
714
|
-
);
|
|
715
|
-
return null;
|
|
716
|
-
}
|
|
717
|
-
return loadedProject;
|
|
718
|
-
},
|
|
719
|
-
);
|
|
720
|
-
|
|
721
|
-
const uiDistDir = path.join(__dirname, '..', 'console', 'ui-dist');
|
|
722
|
-
const consoleDataOutputDir = options.consoleDataOutputDir ?? null;
|
|
723
|
-
const inTmuxDataDir = options.inTmuxDataDir ?? DEFAULT_IN_TMUX_DATA_DIR;
|
|
724
|
-
const dashboardDir = options.dashboardDir ?? DEFAULT_DASHBOARD_DIR;
|
|
725
|
-
|
|
726
|
-
await startConsoleServer({
|
|
727
|
-
accessToken,
|
|
728
|
-
uiDistDir,
|
|
729
|
-
consoleDataOutputDir,
|
|
730
|
-
inTmuxDataDir,
|
|
731
|
-
dashboardDir,
|
|
732
|
-
githubToken: token,
|
|
733
|
-
issueRepository,
|
|
734
|
-
resolveProject,
|
|
735
|
-
issueTitleStateCache: new IssueTitleStateCache(),
|
|
736
|
-
port,
|
|
737
|
-
});
|
|
738
|
-
console.log(`TDPM Console server listening on port ${port}`);
|
|
745
|
+
addServeWebOptions(program.command('serveConsole'))
|
|
746
|
+
.description('Deprecated alias for serveWeb. Use serveWeb instead.')
|
|
747
|
+
.action(async (options: ServeWebOptions) => {
|
|
748
|
+
await runServeWeb(options);
|
|
739
749
|
});
|
|
740
750
|
|
|
741
751
|
program
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
} from '../../../../../domain/usecases/adapter-interfaces/IssueRepository';
|
|
14
14
|
import type { ConsoleProjectBinding } from '../../consoleOperationApi';
|
|
15
15
|
import { IssueTitleStateCache } from '../../consoleReadApi';
|
|
16
|
-
import {
|
|
16
|
+
import { startWebServer } from '../../webServer';
|
|
17
17
|
|
|
18
18
|
export const CONSOLE_E2E_PJCODE = 'umino';
|
|
19
19
|
export const CONSOLE_E2E_TOKEN = 'console-e2e-fixture-token-3f9c1a';
|
|
@@ -362,7 +362,7 @@ export const startConsoleE2eHarness = async (): Promise<ConsoleE2eHarness> => {
|
|
|
362
362
|
): Promise<ConsoleProjectBinding | null> =>
|
|
363
363
|
pjcode === CONSOLE_E2E_PJCODE ? { pjcode, project } : null;
|
|
364
364
|
|
|
365
|
-
const server = await
|
|
365
|
+
const server = await startWebServer({
|
|
366
366
|
accessToken: CONSOLE_E2E_TOKEN,
|
|
367
367
|
uiDistDir,
|
|
368
368
|
consoleDataOutputDir,
|