@fias/plugin-dev-harness 1.1.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.
Files changed (125) hide show
  1. package/dist/bridge/live-handler.d.ts +27 -0
  2. package/dist/bridge/live-handler.d.ts.map +1 -0
  3. package/dist/bridge/live-handler.js +47 -0
  4. package/dist/bridge/live-handler.js.map +1 -0
  5. package/dist/bridge/live-handler.test.d.ts +2 -0
  6. package/dist/bridge/live-handler.test.d.ts.map +1 -0
  7. package/dist/bridge/live-handler.test.js +182 -0
  8. package/dist/bridge/live-handler.test.js.map +1 -0
  9. package/dist/bridge/mock-handler.d.ts +25 -0
  10. package/dist/bridge/mock-handler.d.ts.map +1 -0
  11. package/dist/bridge/mock-handler.js +81 -0
  12. package/dist/bridge/mock-handler.js.map +1 -0
  13. package/dist/bridge/mock-handler.test.d.ts +2 -0
  14. package/dist/bridge/mock-handler.test.d.ts.map +1 -0
  15. package/dist/bridge/mock-handler.test.js +322 -0
  16. package/dist/bridge/mock-handler.test.js.map +1 -0
  17. package/dist/bridge/types.d.ts +18 -0
  18. package/dist/bridge/types.d.ts.map +1 -0
  19. package/dist/bridge/types.js +8 -0
  20. package/dist/bridge/types.js.map +1 -0
  21. package/dist/cli/dev.d.ts +15 -0
  22. package/dist/cli/dev.d.ts.map +1 -0
  23. package/dist/cli/dev.js +64 -0
  24. package/dist/cli/dev.js.map +1 -0
  25. package/dist/cli/dev.test.d.ts +2 -0
  26. package/dist/cli/dev.test.d.ts.map +1 -0
  27. package/dist/cli/dev.test.js +114 -0
  28. package/dist/cli/dev.test.js.map +1 -0
  29. package/dist/cli/entities.d.ts +9 -0
  30. package/dist/cli/entities.d.ts.map +1 -0
  31. package/dist/cli/entities.js +71 -0
  32. package/dist/cli/entities.js.map +1 -0
  33. package/dist/cli/entities.test.d.ts +2 -0
  34. package/dist/cli/entities.test.d.ts.map +1 -0
  35. package/dist/cli/entities.test.js +179 -0
  36. package/dist/cli/entities.test.js.map +1 -0
  37. package/dist/cli/index.d.ts +9 -0
  38. package/dist/cli/index.d.ts.map +1 -0
  39. package/dist/cli/index.js +29 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cli/index.test.d.ts +2 -0
  42. package/dist/cli/index.test.d.ts.map +1 -0
  43. package/dist/cli/index.test.js +55 -0
  44. package/dist/cli/index.test.js.map +1 -0
  45. package/dist/cli/login.d.ts +9 -0
  46. package/dist/cli/login.d.ts.map +1 -0
  47. package/dist/cli/login.js +80 -0
  48. package/dist/cli/login.js.map +1 -0
  49. package/dist/cli/login.test.d.ts +2 -0
  50. package/dist/cli/login.test.d.ts.map +1 -0
  51. package/dist/cli/login.test.js +53 -0
  52. package/dist/cli/login.test.js.map +1 -0
  53. package/dist/cli/submit.d.ts +9 -0
  54. package/dist/cli/submit.d.ts.map +1 -0
  55. package/dist/cli/submit.js +250 -0
  56. package/dist/cli/submit.js.map +1 -0
  57. package/dist/cli/submit.test.d.ts +2 -0
  58. package/dist/cli/submit.test.d.ts.map +1 -0
  59. package/dist/cli/submit.test.js +381 -0
  60. package/dist/cli/submit.test.js.map +1 -0
  61. package/dist/cli/validate.d.ts +9 -0
  62. package/dist/cli/validate.d.ts.map +1 -0
  63. package/dist/cli/validate.js +154 -0
  64. package/dist/cli/validate.js.map +1 -0
  65. package/dist/cli/validate.test.d.ts +2 -0
  66. package/dist/cli/validate.test.d.ts.map +1 -0
  67. package/dist/cli/validate.test.js +275 -0
  68. package/dist/cli/validate.test.js.map +1 -0
  69. package/dist/config/config-loader.d.ts +25 -0
  70. package/dist/config/config-loader.d.ts.map +1 -0
  71. package/dist/config/config-loader.js +78 -0
  72. package/dist/config/config-loader.js.map +1 -0
  73. package/dist/config/config-loader.test.d.ts +2 -0
  74. package/dist/config/config-loader.test.d.ts.map +1 -0
  75. package/dist/config/config-loader.test.js +163 -0
  76. package/dist/config/config-loader.test.js.map +1 -0
  77. package/dist/config/credentials.d.ts +11 -0
  78. package/dist/config/credentials.d.ts.map +1 -0
  79. package/dist/config/credentials.js +71 -0
  80. package/dist/config/credentials.js.map +1 -0
  81. package/dist/config/credentials.test.d.ts +2 -0
  82. package/dist/config/credentials.test.d.ts.map +1 -0
  83. package/dist/config/credentials.test.js +115 -0
  84. package/dist/config/credentials.test.js.map +1 -0
  85. package/dist/index.d.ts +9 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +12 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/mocks/entity-responses.d.ts +15 -0
  90. package/dist/mocks/entity-responses.d.ts.map +1 -0
  91. package/dist/mocks/entity-responses.js +21 -0
  92. package/dist/mocks/entity-responses.js.map +1 -0
  93. package/dist/mocks/entity-responses.test.d.ts +2 -0
  94. package/dist/mocks/entity-responses.test.d.ts.map +1 -0
  95. package/dist/mocks/entity-responses.test.js +53 -0
  96. package/dist/mocks/entity-responses.test.js.map +1 -0
  97. package/dist/mocks/theme.d.ts +22 -0
  98. package/dist/mocks/theme.d.ts.map +1 -0
  99. package/dist/mocks/theme.js +37 -0
  100. package/dist/mocks/theme.js.map +1 -0
  101. package/dist/mocks/theme.test.d.ts +2 -0
  102. package/dist/mocks/theme.test.d.ts.map +1 -0
  103. package/dist/mocks/theme.test.js +66 -0
  104. package/dist/mocks/theme.test.js.map +1 -0
  105. package/dist/mocks/user.d.ts +12 -0
  106. package/dist/mocks/user.d.ts.map +1 -0
  107. package/dist/mocks/user.js +14 -0
  108. package/dist/mocks/user.js.map +1 -0
  109. package/dist/mocks/user.test.d.ts +2 -0
  110. package/dist/mocks/user.test.d.ts.map +1 -0
  111. package/dist/mocks/user.test.js +23 -0
  112. package/dist/mocks/user.test.js.map +1 -0
  113. package/dist/server/harness-server.d.ts +24 -0
  114. package/dist/server/harness-server.d.ts.map +1 -0
  115. package/dist/server/harness-server.js +433 -0
  116. package/dist/server/harness-server.js.map +1 -0
  117. package/dist/server/harness-server.test.d.ts +2 -0
  118. package/dist/server/harness-server.test.d.ts.map +1 -0
  119. package/dist/server/harness-server.test.js +178 -0
  120. package/dist/server/harness-server.test.js.map +1 -0
  121. package/dist/server/static/harness.css +160 -0
  122. package/dist/server/static/harness.html +35 -0
  123. package/dist/server/static/harness.js +345 -0
  124. package/package.json +43 -0
  125. package/templates/fias-dev.config.json +12 -0
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * `fias-dev entities` Command — Browse available entities
4
+ *
5
+ * Lists entities available for invocation from plugins,
6
+ * fetched from the FIAS production API.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.registerEntitiesCommand = registerEntitiesCommand;
13
+ const chalk_1 = __importDefault(require("chalk"));
14
+ const credentials_1 = require("../config/credentials");
15
+ const config_loader_1 = require("../config/config-loader");
16
+ function registerEntitiesCommand(program) {
17
+ program
18
+ .command('entities')
19
+ .description('List available entities for plugin invocation')
20
+ .option('--search <query>', 'Search entities by name/description')
21
+ .option('--type <type>', 'Filter by entity type (prompt, specialized-model, etc.)')
22
+ .option('--limit <n>', 'Number of results', '20')
23
+ .action(async (options) => {
24
+ const credentials = (0, credentials_1.loadCredentials)();
25
+ if (!credentials.apiKey) {
26
+ console.error(chalk_1.default.red('No API key found. Run `fias-dev login` first.'));
27
+ process.exit(1);
28
+ }
29
+ const config = (0, config_loader_1.loadConfig)();
30
+ const params = new URLSearchParams();
31
+ if (options.search)
32
+ params.set('search', options.search);
33
+ if (options.type)
34
+ params.set('type', options.type);
35
+ params.set('limit', options.limit);
36
+ const url = `${config.apiUrl}/developer/entities?${params.toString()}`;
37
+ try {
38
+ const response = await fetch(url, {
39
+ headers: { Authorization: `Bearer ${credentials.apiKey}` },
40
+ });
41
+ if (!response.ok) {
42
+ const err = await response.json().catch(() => ({}));
43
+ console.error(chalk_1.default.red(`API error: ${err.error?.message || response.statusText}`));
44
+ process.exit(1);
45
+ }
46
+ const data = (await response.json());
47
+ if (data.entities.length === 0) {
48
+ console.log(chalk_1.default.dim('\nNo entities found.\n'));
49
+ return;
50
+ }
51
+ console.log(chalk_1.default.bold(`\n Entities (${data.total} total)\n`));
52
+ for (const entity of data.entities) {
53
+ console.log(` ${chalk_1.default.cyan(entity.entityId)} ${chalk_1.default.bold(entity.name)} ${chalk_1.default.dim(`[${entity.type}]`)}`);
54
+ if (entity.description) {
55
+ console.log(` ${chalk_1.default.dim(entity.description.substring(0, 80))}`);
56
+ }
57
+ }
58
+ if (data.total > data.entities.length) {
59
+ console.log(chalk_1.default.dim(`\n Showing ${data.entities.length} of ${data.total}. Use --limit to see more.\n`));
60
+ }
61
+ else {
62
+ console.log('');
63
+ }
64
+ }
65
+ catch (err) {
66
+ console.error(chalk_1.default.red(`Failed to fetch entities: ${err instanceof Error ? err.message : String(err)}`));
67
+ process.exit(1);
68
+ }
69
+ });
70
+ }
71
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/cli/entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=entities.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.test.d.ts","sourceRoot":"","sources":["../../src/cli/entities.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ jest.mock('../config/credentials', () => ({
4
+ loadCredentials: jest.fn(),
5
+ }));
6
+ jest.mock('../config/config-loader', () => ({
7
+ loadConfig: jest.fn(),
8
+ }));
9
+ const commander_1 = require("commander");
10
+ const entities_1 = require("./entities");
11
+ const credentials_1 = require("../config/credentials");
12
+ const config_loader_1 = require("../config/config-loader");
13
+ const mockedLoadCredentials = jest.mocked(credentials_1.loadCredentials);
14
+ const mockedLoadConfig = jest.mocked(config_loader_1.loadConfig);
15
+ describe('cli/entities', () => {
16
+ let program;
17
+ let mockExit;
18
+ let consoleSpy;
19
+ let consoleErrorSpy;
20
+ let originalFetch;
21
+ const defaultConfigValue = {
22
+ pluginUrl: 'http://localhost:3100',
23
+ port: 3200,
24
+ permissions: [],
25
+ mockUser: { userId: 'dev_user_001', displayName: 'Dev User', avatar: null },
26
+ mockTheme: 'light',
27
+ apiUrl: 'https://api.fias.app/v1',
28
+ };
29
+ beforeEach(() => {
30
+ jest.clearAllMocks();
31
+ originalFetch = global.fetch;
32
+ program = new commander_1.Command();
33
+ program.exitOverride();
34
+ (0, entities_1.registerEntitiesCommand)(program);
35
+ mockExit = jest.spyOn(process, 'exit').mockImplementation(((code) => {
36
+ throw new Error(`process.exit(${code})`);
37
+ }));
38
+ consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
39
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
40
+ mockedLoadConfig.mockReturnValue({ ...defaultConfigValue });
41
+ });
42
+ afterEach(() => {
43
+ mockExit.mockRestore();
44
+ consoleSpy.mockRestore();
45
+ consoleErrorSpy.mockRestore();
46
+ global.fetch = originalFetch;
47
+ });
48
+ it('exits with error when no API key is configured', async () => {
49
+ mockedLoadCredentials.mockReturnValue({ apiKey: '' });
50
+ await expect(program.parseAsync(['entities'], { from: 'user' })).rejects.toThrow('process.exit(1)');
51
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('No API key found'));
52
+ });
53
+ it('displays entities when API returns results', async () => {
54
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
55
+ global.fetch = jest.fn().mockResolvedValue({
56
+ ok: true,
57
+ json: () => Promise.resolve({
58
+ entities: [
59
+ {
60
+ entityId: 'entity_sum',
61
+ name: 'Summarizer',
62
+ type: 'prompt',
63
+ description: 'Summarizes text',
64
+ fitnessScore: 0.95,
65
+ },
66
+ ],
67
+ total: 1,
68
+ limit: 20,
69
+ offset: 0,
70
+ }),
71
+ });
72
+ await program.parseAsync(['entities'], { from: 'user' });
73
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Entities'));
74
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('entity_sum'));
75
+ });
76
+ it('shows "no entities found" when API returns empty list', async () => {
77
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
78
+ global.fetch = jest.fn().mockResolvedValue({
79
+ ok: true,
80
+ json: () => Promise.resolve({
81
+ entities: [],
82
+ total: 0,
83
+ limit: 20,
84
+ offset: 0,
85
+ }),
86
+ });
87
+ await program.parseAsync(['entities'], { from: 'user' });
88
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('No entities found'));
89
+ });
90
+ it('displays "showing X of Y" message when there are more results', async () => {
91
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
92
+ global.fetch = jest.fn().mockResolvedValue({
93
+ ok: true,
94
+ json: () => Promise.resolve({
95
+ entities: [
96
+ {
97
+ entityId: 'entity_1',
98
+ name: 'Entity 1',
99
+ type: 'prompt',
100
+ description: '',
101
+ fitnessScore: 0.9,
102
+ },
103
+ ],
104
+ total: 50,
105
+ limit: 20,
106
+ offset: 0,
107
+ }),
108
+ });
109
+ await program.parseAsync(['entities'], { from: 'user' });
110
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('Showing 1 of 50'));
111
+ });
112
+ it('passes search, type, and limit query params', async () => {
113
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
114
+ global.fetch = jest.fn().mockResolvedValue({
115
+ ok: true,
116
+ json: () => Promise.resolve({
117
+ entities: [],
118
+ total: 0,
119
+ limit: 5,
120
+ offset: 0,
121
+ }),
122
+ });
123
+ await program.parseAsync(['entities', '--search', 'summarize', '--type', 'prompt', '--limit', '5'], { from: 'user' });
124
+ const fetchCall = global.fetch.mock.calls[0];
125
+ const url = fetchCall[0];
126
+ expect(url).toContain('search=summarize');
127
+ expect(url).toContain('type=prompt');
128
+ expect(url).toContain('limit=5');
129
+ });
130
+ it('exits with error when API returns non-ok response', async () => {
131
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
132
+ global.fetch = jest.fn().mockResolvedValue({
133
+ ok: false,
134
+ statusText: 'Unauthorized',
135
+ json: () => Promise.resolve({ error: { message: 'Invalid API key' } }),
136
+ });
137
+ await expect(program.parseAsync(['entities'], { from: 'user' })).rejects.toThrow('process.exit(1)');
138
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid API key'));
139
+ });
140
+ it('exits with error when API response JSON parsing fails', async () => {
141
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
142
+ global.fetch = jest.fn().mockResolvedValue({
143
+ ok: false,
144
+ statusText: 'Server Error',
145
+ json: () => Promise.reject(new Error('Bad JSON')),
146
+ });
147
+ await expect(program.parseAsync(['entities'], { from: 'user' })).rejects.toThrow('process.exit(1)');
148
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Server Error'));
149
+ });
150
+ it('exits with error when fetch throws (network error)', async () => {
151
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
152
+ global.fetch = jest.fn().mockRejectedValue(new Error('Connection refused'));
153
+ await expect(program.parseAsync(['entities'], { from: 'user' })).rejects.toThrow('process.exit(1)');
154
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Connection refused'));
155
+ });
156
+ it('handles entity without description', async () => {
157
+ mockedLoadCredentials.mockReturnValue({ apiKey: 'fias_sk_test' });
158
+ global.fetch = jest.fn().mockResolvedValue({
159
+ ok: true,
160
+ json: () => Promise.resolve({
161
+ entities: [
162
+ {
163
+ entityId: 'entity_no_desc',
164
+ name: 'No Description',
165
+ type: 'model',
166
+ description: '',
167
+ fitnessScore: 0.5,
168
+ },
169
+ ],
170
+ total: 1,
171
+ limit: 20,
172
+ offset: 0,
173
+ }),
174
+ });
175
+ await program.parseAsync(['entities'], { from: 'user' });
176
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('entity_no_desc'));
177
+ });
178
+ });
179
+ //# sourceMappingURL=entities.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.test.js","sourceRoot":"","sources":["../../src/cli/entities.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * CLI Command Router
3
+ *
4
+ * Configures and exports the commander CLI program with all
5
+ * available fias-dev commands.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function createCli(): Command;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,SAAS,IAAI,OAAO,CAenC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Command Router
4
+ *
5
+ * Configures and exports the commander CLI program with all
6
+ * available fias-dev commands.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createCli = createCli;
10
+ const commander_1 = require("commander");
11
+ const dev_1 = require("./dev");
12
+ const login_1 = require("./login");
13
+ const entities_1 = require("./entities");
14
+ const validate_1 = require("./validate");
15
+ const submit_1 = require("./submit");
16
+ function createCli() {
17
+ const program = new commander_1.Command();
18
+ program
19
+ .name('fias-dev')
20
+ .description('FIAS Plugin Development Harness — build and test plugins locally')
21
+ .version('1.0.0');
22
+ (0, dev_1.registerDevCommand)(program);
23
+ (0, login_1.registerLoginCommand)(program);
24
+ (0, entities_1.registerEntitiesCommand)(program);
25
+ (0, validate_1.registerValidateCommand)(program);
26
+ (0, submit_1.registerSubmitCommand)(program);
27
+ return program;
28
+ }
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AASH,8BAeC;AAtBD,yCAAoC;AACpC,+BAA2C;AAC3C,mCAA+C;AAC/C,yCAAqD;AACrD,yCAAqD;AACrD,qCAAiD;AAEjD,SAAgB,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CAAC,kEAAkE,CAAC;SAC/E,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,IAAA,wBAAkB,EAAC,OAAO,CAAC,CAAC;IAC5B,IAAA,4BAAoB,EAAC,OAAO,CAAC,CAAC;IAC9B,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,kCAAuB,EAAC,OAAO,CAAC,CAAC;IACjC,IAAA,8BAAqB,EAAC,OAAO,CAAC,CAAC;IAE/B,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/cli/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const index_1 = require("./index");
4
+ const commander_1 = require("commander");
5
+ describe('cli/index', () => {
6
+ describe('createCli()', () => {
7
+ it('returns a Commander program instance', () => {
8
+ const program = (0, index_1.createCli)();
9
+ expect(program).toBeInstanceOf(commander_1.Command);
10
+ });
11
+ it('has the program name set to fias-dev', () => {
12
+ const program = (0, index_1.createCli)();
13
+ expect(program.name()).toBe('fias-dev');
14
+ });
15
+ it('has a description set', () => {
16
+ const program = (0, index_1.createCli)();
17
+ expect(program.description()).toBeTruthy();
18
+ expect(program.description()).toContain('FIAS');
19
+ });
20
+ it('has a version set', () => {
21
+ const program = (0, index_1.createCli)();
22
+ expect(program.version()).toBe('1.0.0');
23
+ });
24
+ it('has the dev command registered', () => {
25
+ const program = (0, index_1.createCli)();
26
+ const commands = program.commands.map((cmd) => cmd.name());
27
+ expect(commands).toContain('dev');
28
+ });
29
+ it('has the login command registered', () => {
30
+ const program = (0, index_1.createCli)();
31
+ const commands = program.commands.map((cmd) => cmd.name());
32
+ expect(commands).toContain('login');
33
+ });
34
+ it('has the entities command registered', () => {
35
+ const program = (0, index_1.createCli)();
36
+ const commands = program.commands.map((cmd) => cmd.name());
37
+ expect(commands).toContain('entities');
38
+ });
39
+ it('has the validate command registered', () => {
40
+ const program = (0, index_1.createCli)();
41
+ const commands = program.commands.map((cmd) => cmd.name());
42
+ expect(commands).toContain('validate');
43
+ });
44
+ it('has the submit command registered', () => {
45
+ const program = (0, index_1.createCli)();
46
+ const commands = program.commands.map((cmd) => cmd.name());
47
+ expect(commands).toContain('submit');
48
+ });
49
+ it('has exactly 5 commands registered', () => {
50
+ const program = (0, index_1.createCli)();
51
+ expect(program.commands).toHaveLength(5);
52
+ });
53
+ });
54
+ });
55
+ //# sourceMappingURL=index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/cli/index.test.ts"],"names":[],"mappings":";;AAAA,mCAAoC;AACpC,yCAAoC;AAEpC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,mBAAO,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,OAAO,GAAG,IAAA,iBAAS,GAAE,CAAC;YAC5B,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `fias-dev login` Command — Store API key
3
+ *
4
+ * Saves the developer's API key to ~/.fias/credentials
5
+ * for use with live mode and other authenticated commands.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function registerLoginCommand(program: Command): void;
9
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqB3D"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * `fias-dev login` Command — Store API key
4
+ *
5
+ * Saves the developer's API key to ~/.fias/credentials
6
+ * for use with live mode and other authenticated commands.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.registerLoginCommand = registerLoginCommand;
46
+ const readline = __importStar(require("readline"));
47
+ const chalk_1 = __importDefault(require("chalk"));
48
+ const credentials_1 = require("../config/credentials");
49
+ function registerLoginCommand(program) {
50
+ program
51
+ .command('login')
52
+ .description('Save your FIAS API key for live mode')
53
+ .option('--key <apiKey>', 'API key (fias_sk_...)')
54
+ .action(async (options) => {
55
+ let apiKey = options.key;
56
+ if (!apiKey) {
57
+ apiKey = await promptForApiKey();
58
+ }
59
+ if (!apiKey || !apiKey.startsWith('fias_sk_')) {
60
+ console.error(chalk_1.default.red('Invalid API key format. Keys should start with fias_sk_'));
61
+ process.exit(1);
62
+ }
63
+ (0, credentials_1.saveCredentials)({ apiKey });
64
+ console.log(chalk_1.default.green('\nAPI key saved to ~/.fias/credentials'));
65
+ console.log(chalk_1.default.dim('You can now use `fias-dev --live` for real AI testing.\n'));
66
+ });
67
+ }
68
+ function promptForApiKey() {
69
+ return new Promise((resolve) => {
70
+ const rl = readline.createInterface({
71
+ input: process.stdin,
72
+ output: process.stdout,
73
+ });
74
+ rl.question(chalk_1.default.bold('Enter your FIAS API key (fias_sk_...): '), (answer) => {
75
+ rl.close();
76
+ resolve(answer.trim());
77
+ });
78
+ });
79
+ }
80
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOH,oDAqBC;AAzBD,mDAAqC;AACrC,kDAA0B;AAC1B,uDAAwD;AAExD,SAAgB,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,gBAAgB,EAAE,uBAAuB,CAAC;SACjD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;QAEzB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,MAAM,eAAe,EAAE,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9C,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC,CAAC;YACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAA,6BAAe,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,EAAE,CAAC,QAAQ,CAAC,eAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE;YAC5E,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=login.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.d.ts","sourceRoot":"","sources":["../../src/cli/login.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ jest.mock('../config/credentials', () => ({
4
+ saveCredentials: jest.fn(),
5
+ }));
6
+ const commander_1 = require("commander");
7
+ const login_1 = require("./login");
8
+ const credentials_1 = require("../config/credentials");
9
+ const mockedSaveCredentials = jest.mocked(credentials_1.saveCredentials);
10
+ describe('cli/login', () => {
11
+ let program;
12
+ let mockExit;
13
+ let consoleSpy;
14
+ let consoleErrorSpy;
15
+ beforeEach(() => {
16
+ jest.clearAllMocks();
17
+ program = new commander_1.Command();
18
+ program.exitOverride();
19
+ (0, login_1.registerLoginCommand)(program);
20
+ mockExit = jest.spyOn(process, 'exit').mockImplementation(((code) => {
21
+ throw new Error(`process.exit(${code})`);
22
+ }));
23
+ consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
24
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
25
+ });
26
+ afterEach(() => {
27
+ mockExit.mockRestore();
28
+ consoleSpy.mockRestore();
29
+ consoleErrorSpy.mockRestore();
30
+ });
31
+ it('saves credentials when valid API key is provided via --key', async () => {
32
+ await program.parseAsync(['login', '--key', 'fias_sk_abc123'], {
33
+ from: 'user',
34
+ });
35
+ expect(mockedSaveCredentials).toHaveBeenCalledWith({ apiKey: 'fias_sk_abc123' });
36
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('API key saved'));
37
+ });
38
+ it('exits with error when API key does not start with fias_sk_', async () => {
39
+ await expect(program.parseAsync(['login', '--key', 'invalid_key'], {
40
+ from: 'user',
41
+ })).rejects.toThrow('process.exit(1)');
42
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid API key format'));
43
+ expect(mockedSaveCredentials).not.toHaveBeenCalled();
44
+ });
45
+ it('exits with error when API key has wrong prefix', async () => {
46
+ await expect(program.parseAsync(['login', '--key', 'sk_wrong_prefix_abc'], {
47
+ from: 'user',
48
+ })).rejects.toThrow('process.exit(1)');
49
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid API key format'));
50
+ expect(mockedSaveCredentials).not.toHaveBeenCalled();
51
+ });
52
+ });
53
+ //# sourceMappingURL=login.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.test.js","sourceRoot":"","sources":["../../src/cli/login.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `fias-dev submit` Command — Package and submit plugin
3
+ *
4
+ * Builds the plugin, validates the manifest, creates a tarball,
5
+ * uploads to S3, and submits for review.
6
+ */
7
+ import { Command } from 'commander';
8
+ export declare function registerSubmitCommand(program: Command): void;
9
+ //# sourceMappingURL=submit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../src/cli/submit.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmM5D"}