@l4yercak3/cli 1.3.1 → 2.0.0-alpha.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 (357) hide show
  1. package/README.md +10 -220
  2. package/dist/api/client.d.ts +12 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +37 -0
  5. package/dist/api/client.js.map +1 -0
  6. package/dist/api/platform.d.ts +161 -0
  7. package/dist/api/platform.d.ts.map +1 -0
  8. package/dist/api/platform.js +70 -0
  9. package/dist/api/platform.js.map +1 -0
  10. package/dist/bin/sevenlayers.d.ts +3 -0
  11. package/dist/bin/sevenlayers.d.ts.map +1 -0
  12. package/dist/bin/sevenlayers.js +198 -0
  13. package/dist/bin/sevenlayers.js.map +1 -0
  14. package/dist/commands/agent/catalog.d.ts +5 -0
  15. package/dist/commands/agent/catalog.d.ts.map +1 -0
  16. package/dist/commands/agent/catalog.js +142 -0
  17. package/dist/commands/agent/catalog.js.map +1 -0
  18. package/dist/commands/agent/drift.d.ts +5 -0
  19. package/dist/commands/agent/drift.d.ts.map +1 -0
  20. package/dist/commands/agent/drift.js +113 -0
  21. package/dist/commands/agent/drift.js.map +1 -0
  22. package/dist/commands/agent/init.d.ts +5 -0
  23. package/dist/commands/agent/init.d.ts.map +1 -0
  24. package/dist/commands/agent/init.js +75 -0
  25. package/dist/commands/agent/init.js.map +1 -0
  26. package/dist/commands/agent/permissions.d.ts +5 -0
  27. package/dist/commands/agent/permissions.d.ts.map +1 -0
  28. package/dist/commands/agent/permissions.js +88 -0
  29. package/dist/commands/agent/permissions.js.map +1 -0
  30. package/dist/commands/agent/runner.d.ts +14 -0
  31. package/dist/commands/agent/runner.d.ts.map +1 -0
  32. package/dist/commands/agent/runner.js +59 -0
  33. package/dist/commands/agent/runner.js.map +1 -0
  34. package/dist/commands/agent/shared.d.ts +13 -0
  35. package/dist/commands/agent/shared.d.ts.map +1 -0
  36. package/dist/commands/agent/shared.js +31 -0
  37. package/dist/commands/agent/shared.js.map +1 -0
  38. package/dist/commands/agent/template.d.ts +5 -0
  39. package/dist/commands/agent/template.d.ts.map +1 -0
  40. package/dist/commands/agent/template.js +104 -0
  41. package/dist/commands/agent/template.js.map +1 -0
  42. package/dist/commands/app/connect.d.ts +7 -0
  43. package/dist/commands/app/connect.d.ts.map +1 -0
  44. package/dist/commands/app/connect.js +12 -0
  45. package/dist/commands/app/connect.js.map +1 -0
  46. package/dist/commands/app/init.d.ts +7 -0
  47. package/dist/commands/app/init.d.ts.map +1 -0
  48. package/dist/commands/app/init.js +12 -0
  49. package/dist/commands/app/init.js.map +1 -0
  50. package/dist/commands/app/link.d.ts +3 -0
  51. package/dist/commands/app/link.d.ts.map +1 -0
  52. package/dist/commands/app/link.js +92 -0
  53. package/dist/commands/app/link.js.map +1 -0
  54. package/dist/commands/app/pages.d.ts +15 -0
  55. package/dist/commands/app/pages.d.ts.map +1 -0
  56. package/dist/commands/app/pages.js +180 -0
  57. package/dist/commands/app/pages.js.map +1 -0
  58. package/dist/commands/app/register.d.ts +3 -0
  59. package/dist/commands/app/register.d.ts.map +1 -0
  60. package/dist/commands/app/register.js +120 -0
  61. package/dist/commands/app/register.js.map +1 -0
  62. package/dist/commands/app/remote.d.ts +14 -0
  63. package/dist/commands/app/remote.d.ts.map +1 -0
  64. package/dist/commands/app/remote.js +44 -0
  65. package/dist/commands/app/remote.js.map +1 -0
  66. package/dist/commands/app/setup.d.ts +3 -0
  67. package/dist/commands/app/setup.d.ts.map +1 -0
  68. package/dist/commands/app/setup.js +299 -0
  69. package/dist/commands/app/setup.js.map +1 -0
  70. package/dist/commands/app/shared.d.ts +9 -0
  71. package/dist/commands/app/shared.d.ts.map +1 -0
  72. package/dist/commands/app/shared.js +122 -0
  73. package/dist/commands/app/shared.js.map +1 -0
  74. package/dist/commands/app/sync.d.ts +7 -0
  75. package/dist/commands/app/sync.d.ts.map +1 -0
  76. package/dist/commands/app/sync.js +107 -0
  77. package/dist/commands/app/sync.js.map +1 -0
  78. package/dist/commands/booking/check.d.ts +3 -0
  79. package/dist/commands/booking/check.d.ts.map +1 -0
  80. package/dist/commands/booking/check.js +68 -0
  81. package/dist/commands/booking/check.js.map +1 -0
  82. package/dist/commands/booking/setup.d.ts +3 -0
  83. package/dist/commands/booking/setup.d.ts.map +1 -0
  84. package/dist/commands/booking/setup.js +95 -0
  85. package/dist/commands/booking/setup.js.map +1 -0
  86. package/dist/commands/booking/shared.d.ts +31 -0
  87. package/dist/commands/booking/shared.d.ts.map +1 -0
  88. package/dist/commands/booking/shared.js +112 -0
  89. package/dist/commands/booking/shared.js.map +1 -0
  90. package/dist/commands/booking/smoke.d.ts +3 -0
  91. package/dist/commands/booking/smoke.d.ts.map +1 -0
  92. package/dist/commands/booking/smoke.js +101 -0
  93. package/dist/commands/booking/smoke.js.map +1 -0
  94. package/dist/commands/cms/bind.d.ts +3 -0
  95. package/dist/commands/cms/bind.d.ts.map +1 -0
  96. package/dist/commands/cms/bind.js +212 -0
  97. package/dist/commands/cms/bind.js.map +1 -0
  98. package/dist/commands/cms/content.d.ts +40 -0
  99. package/dist/commands/cms/content.d.ts.map +1 -0
  100. package/dist/commands/cms/content.js +169 -0
  101. package/dist/commands/cms/content.js.map +1 -0
  102. package/dist/commands/cms/doctor.d.ts +3 -0
  103. package/dist/commands/cms/doctor.d.ts.map +1 -0
  104. package/dist/commands/cms/doctor.js +69 -0
  105. package/dist/commands/cms/doctor.js.map +1 -0
  106. package/dist/commands/cms/migrate.d.ts +3 -0
  107. package/dist/commands/cms/migrate.d.ts.map +1 -0
  108. package/dist/commands/cms/migrate.js +78 -0
  109. package/dist/commands/cms/migrate.js.map +1 -0
  110. package/dist/commands/cms/registry.d.ts +3 -0
  111. package/dist/commands/cms/registry.d.ts.map +1 -0
  112. package/dist/commands/cms/registry.js +161 -0
  113. package/dist/commands/cms/registry.js.map +1 -0
  114. package/dist/commands/cms/seed.d.ts +3 -0
  115. package/dist/commands/cms/seed.d.ts.map +1 -0
  116. package/dist/commands/cms/seed.js +102 -0
  117. package/dist/commands/cms/seed.js.map +1 -0
  118. package/dist/commands/cms/shared.d.ts +22 -0
  119. package/dist/commands/cms/shared.d.ts.map +1 -0
  120. package/dist/commands/cms/shared.js +82 -0
  121. package/dist/commands/cms/shared.js.map +1 -0
  122. package/dist/commands/doctor/target.d.ts +3 -0
  123. package/dist/commands/doctor/target.d.ts.map +1 -0
  124. package/dist/commands/doctor/target.js +46 -0
  125. package/dist/commands/doctor/target.js.map +1 -0
  126. package/dist/commands/env/list.d.ts +3 -0
  127. package/dist/commands/env/list.d.ts.map +1 -0
  128. package/dist/commands/env/list.js +28 -0
  129. package/dist/commands/env/list.js.map +1 -0
  130. package/dist/commands/env/set.d.ts +3 -0
  131. package/dist/commands/env/set.d.ts.map +1 -0
  132. package/dist/commands/env/set.js +36 -0
  133. package/dist/commands/env/set.js.map +1 -0
  134. package/dist/commands/env/use.d.ts +3 -0
  135. package/dist/commands/env/use.d.ts.map +1 -0
  136. package/dist/commands/env/use.js +15 -0
  137. package/dist/commands/env/use.js.map +1 -0
  138. package/dist/commands/legacy/connect.d.ts +3 -0
  139. package/dist/commands/legacy/connect.d.ts.map +1 -0
  140. package/dist/commands/legacy/connect.js +8 -0
  141. package/dist/commands/legacy/connect.js.map +1 -0
  142. package/dist/commands/legacy/pages.d.ts +3 -0
  143. package/dist/commands/legacy/pages.d.ts.map +1 -0
  144. package/dist/commands/legacy/pages.js +16 -0
  145. package/dist/commands/legacy/pages.js.map +1 -0
  146. package/dist/commands/legacy/spread.d.ts +3 -0
  147. package/dist/commands/legacy/spread.d.ts.map +1 -0
  148. package/dist/commands/legacy/spread.js +8 -0
  149. package/dist/commands/legacy/spread.js.map +1 -0
  150. package/dist/commands/legacy/sync.d.ts +3 -0
  151. package/dist/commands/legacy/sync.d.ts.map +1 -0
  152. package/dist/commands/legacy/sync.js +8 -0
  153. package/dist/commands/legacy/sync.js.map +1 -0
  154. package/dist/config/env-diff.d.ts +10 -0
  155. package/dist/config/env-diff.d.ts.map +1 -0
  156. package/dist/config/env-diff.js +24 -0
  157. package/dist/config/env-diff.js.map +1 -0
  158. package/dist/config/env-parser.d.ts +20 -0
  159. package/dist/config/env-parser.d.ts.map +1 -0
  160. package/dist/config/env-parser.js +70 -0
  161. package/dist/config/env-parser.js.map +1 -0
  162. package/dist/config/env-writer.d.ts +22 -0
  163. package/dist/config/env-writer.d.ts.map +1 -0
  164. package/dist/config/env-writer.js +172 -0
  165. package/dist/config/env-writer.js.map +1 -0
  166. package/dist/config/profile-store.d.ts +29 -0
  167. package/dist/config/profile-store.d.ts.map +1 -0
  168. package/dist/config/profile-store.js +257 -0
  169. package/dist/config/profile-store.js.map +1 -0
  170. package/dist/core/args.d.ts +11 -0
  171. package/dist/core/args.d.ts.map +1 -0
  172. package/dist/core/args.js +106 -0
  173. package/dist/core/args.js.map +1 -0
  174. package/dist/core/colors.d.ts +6 -0
  175. package/dist/core/colors.d.ts.map +1 -0
  176. package/dist/core/colors.js +29 -0
  177. package/dist/core/colors.js.map +1 -0
  178. package/dist/safety/target-guard.d.ts +16 -0
  179. package/dist/safety/target-guard.d.ts.map +1 -0
  180. package/dist/safety/target-guard.js +55 -0
  181. package/dist/safety/target-guard.js.map +1 -0
  182. package/dist/testing/booking-smoke.d.ts +17 -0
  183. package/dist/testing/booking-smoke.d.ts.map +1 -0
  184. package/dist/testing/booking-smoke.js +43 -0
  185. package/dist/testing/booking-smoke.js.map +1 -0
  186. package/dist/tests/agent-commands.test.d.ts +2 -0
  187. package/dist/tests/agent-commands.test.d.ts.map +1 -0
  188. package/dist/tests/agent-commands.test.js +180 -0
  189. package/dist/tests/agent-commands.test.js.map +1 -0
  190. package/dist/tests/agent-governance.test.d.ts +2 -0
  191. package/dist/tests/agent-governance.test.d.ts.map +1 -0
  192. package/dist/tests/agent-governance.test.js +233 -0
  193. package/dist/tests/agent-governance.test.js.map +1 -0
  194. package/dist/tests/app-commands.test.d.ts +2 -0
  195. package/dist/tests/app-commands.test.d.ts.map +1 -0
  196. package/dist/tests/app-commands.test.js +462 -0
  197. package/dist/tests/app-commands.test.js.map +1 -0
  198. package/dist/tests/booking-commands.test.d.ts +2 -0
  199. package/dist/tests/booking-commands.test.d.ts.map +1 -0
  200. package/dist/tests/booking-commands.test.js +204 -0
  201. package/dist/tests/booking-commands.test.js.map +1 -0
  202. package/dist/tests/booking-smoke.test.d.ts +2 -0
  203. package/dist/tests/booking-smoke.test.d.ts.map +1 -0
  204. package/dist/tests/booking-smoke.test.js +183 -0
  205. package/dist/tests/booking-smoke.test.js.map +1 -0
  206. package/dist/tests/cms-commands.test.d.ts +2 -0
  207. package/dist/tests/cms-commands.test.d.ts.map +1 -0
  208. package/dist/tests/cms-commands.test.js +254 -0
  209. package/dist/tests/cms-commands.test.js.map +1 -0
  210. package/dist/tests/cms-ops.test.d.ts +2 -0
  211. package/dist/tests/cms-ops.test.d.ts.map +1 -0
  212. package/dist/tests/cms-ops.test.js +125 -0
  213. package/dist/tests/cms-ops.test.js.map +1 -0
  214. package/dist/tests/env-writer.test.d.ts +2 -0
  215. package/dist/tests/env-writer.test.d.ts.map +1 -0
  216. package/dist/tests/env-writer.test.js +90 -0
  217. package/dist/tests/env-writer.test.js.map +1 -0
  218. package/dist/tests/profile-store.test.d.ts +2 -0
  219. package/dist/tests/profile-store.test.d.ts.map +1 -0
  220. package/dist/tests/profile-store.test.js +88 -0
  221. package/dist/tests/profile-store.test.js.map +1 -0
  222. package/dist/tests/target-guard.test.d.ts +2 -0
  223. package/dist/tests/target-guard.test.d.ts.map +1 -0
  224. package/dist/tests/target-guard.test.js +132 -0
  225. package/dist/tests/target-guard.test.js.map +1 -0
  226. package/dist/ui/logo.d.ts +2 -0
  227. package/dist/ui/logo.d.ts.map +1 -0
  228. package/dist/ui/logo.js +22 -0
  229. package/dist/ui/logo.js.map +1 -0
  230. package/package.json +17 -53
  231. package/.claude/settings.local.json +0 -36
  232. package/.cursor/rules.md +0 -203
  233. package/.eslintrc.js +0 -31
  234. package/CLAUDE.md +0 -100
  235. package/bin/cli.js +0 -116
  236. package/docs/ADDING_FRAMEWORK_DETECTORS.md +0 -391
  237. package/docs/ADDING_NEW_PROJECT_TYPE.md +0 -156
  238. package/docs/ARCHITECTURE_RELATIONSHIPS.md +0 -411
  239. package/docs/CLI_AUTHENTICATION.md +0 -214
  240. package/docs/CLI_PAGE_DETECTION_REQUIREMENTS.md +0 -519
  241. package/docs/CRM-PIPELINES-SEQUENCES-SPEC.md +0 -429
  242. package/docs/DETECTOR_ARCHITECTURE.md +0 -326
  243. package/docs/DEVELOPMENT.md +0 -194
  244. package/docs/IMPLEMENTATION_PHASES.md +0 -468
  245. package/docs/INTEGRATION_PATHS_ARCHITECTURE.md +0 -1543
  246. package/docs/OAUTH_CLARIFICATION.md +0 -258
  247. package/docs/OAUTH_SETUP_GUIDE_TEMPLATE.md +0 -211
  248. package/docs/PHASE_0_PROGRESS.md +0 -120
  249. package/docs/PHASE_1_COMPLETE.md +0 -366
  250. package/docs/PHASE_SUMMARY.md +0 -149
  251. package/docs/PLAN.md +0 -511
  252. package/docs/README.md +0 -56
  253. package/docs/STRIPE_INTEGRATION.md +0 -447
  254. package/docs/SUMMARY.md +0 -230
  255. package/docs/UPDATED_PLAN.md +0 -447
  256. package/docs/mcp_server/MCP_EXTENSION_GUIDE.md +0 -1313
  257. package/docs/mcp_server/MCP_SERVER_ARCHITECTURE.md +0 -1481
  258. package/docs/mcp_server/applicationOntology.ts +0 -817
  259. package/docs/mcp_server/cliApplications.ts +0 -639
  260. package/docs/mcp_server/crmOntology.ts +0 -1063
  261. package/docs/mcp_server/eventOntology.ts +0 -1183
  262. package/docs/mcp_server/formsOntology.ts +0 -1401
  263. package/docs/mcp_server/ontologySchemas.ts +0 -185
  264. package/docs/mcp_server/schema.ts +0 -250
  265. package/docs/microsass_production_machine/CLI_API_REFERENCE.md +0 -1197
  266. package/docs/microsass_production_machine/CLI_PRODUCT_VISION.md +0 -676
  267. package/docs/microsass_production_machine/CLI_REQUIREMENTS.md +0 -606
  268. package/docs/microsass_production_machine/CONNECTED_APPLICATIONS_SPEC.md +0 -390
  269. package/docs/microsass_production_machine/IMPLEMENTATION_ROADMAP.md +0 -725
  270. package/docs/microsass_production_machine/OBJECT_MAPPINGS.md +0 -808
  271. package/docs/microsass_production_machine/REFERENCE_IMPLEMENTATION.md +0 -532
  272. package/src/api/backend-client.js +0 -449
  273. package/src/commands/api-keys.js +0 -119
  274. package/src/commands/connect.js +0 -243
  275. package/src/commands/login.js +0 -332
  276. package/src/commands/logout.js +0 -30
  277. package/src/commands/mcp-server.js +0 -85
  278. package/src/commands/mcp-setup.js +0 -686
  279. package/src/commands/pages.js +0 -317
  280. package/src/commands/scaffold.js +0 -409
  281. package/src/commands/spread.js +0 -861
  282. package/src/commands/status.js +0 -62
  283. package/src/commands/sync.js +0 -169
  284. package/src/commands/upgrade.js +0 -48
  285. package/src/config/config-manager.js +0 -206
  286. package/src/detectors/api-client-detector.js +0 -85
  287. package/src/detectors/base-detector.js +0 -77
  288. package/src/detectors/database-detector.js +0 -245
  289. package/src/detectors/expo-detector.js +0 -166
  290. package/src/detectors/github-detector.js +0 -74
  291. package/src/detectors/index.js +0 -106
  292. package/src/detectors/mapping-suggestor.js +0 -119
  293. package/src/detectors/model-detector.js +0 -318
  294. package/src/detectors/nextjs-detector.js +0 -139
  295. package/src/detectors/oauth-detector.js +0 -122
  296. package/src/detectors/page-detector.js +0 -480
  297. package/src/detectors/registry.js +0 -121
  298. package/src/generators/api-client-generator.js +0 -223
  299. package/src/generators/api-only/client.js +0 -683
  300. package/src/generators/api-only/index.js +0 -96
  301. package/src/generators/api-only/types.js +0 -618
  302. package/src/generators/api-only/webhooks.js +0 -377
  303. package/src/generators/env-generator.js +0 -191
  304. package/src/generators/expo-auth-generator.js +0 -1009
  305. package/src/generators/gitignore-generator.js +0 -92
  306. package/src/generators/index.js +0 -166
  307. package/src/generators/manifest-generator.js +0 -154
  308. package/src/generators/mcp-guide-generator.js +0 -256
  309. package/src/generators/nextauth-generator.js +0 -247
  310. package/src/generators/oauth-guide-generator.js +0 -277
  311. package/src/generators/quickstart/components/index.js +0 -1699
  312. package/src/generators/quickstart/components-mobile/index.js +0 -1440
  313. package/src/generators/quickstart/database/convex.js +0 -1257
  314. package/src/generators/quickstart/database/index.js +0 -34
  315. package/src/generators/quickstart/database/supabase.js +0 -1132
  316. package/src/generators/quickstart/hooks/index.js +0 -1065
  317. package/src/generators/quickstart/index.js +0 -191
  318. package/src/generators/quickstart/pages/index.js +0 -1466
  319. package/src/generators/quickstart/screens/index.js +0 -1498
  320. package/src/logo.js +0 -116
  321. package/src/mcp/auth.js +0 -127
  322. package/src/mcp/registry/domains/applications.js +0 -516
  323. package/src/mcp/registry/domains/benefits.js +0 -798
  324. package/src/mcp/registry/domains/codegen.js +0 -894
  325. package/src/mcp/registry/domains/core.js +0 -324
  326. package/src/mcp/registry/domains/crm.js +0 -591
  327. package/src/mcp/registry/domains/events.js +0 -649
  328. package/src/mcp/registry/domains/forms.js +0 -696
  329. package/src/mcp/registry/index.js +0 -164
  330. package/src/mcp/server.js +0 -116
  331. package/src/utils/file-utils.js +0 -117
  332. package/src/utils/init-helpers.js +0 -243
  333. package/src/utils/prompt-utils.js +0 -195
  334. package/templates/CLAUDE.md +0 -86
  335. package/tests/api-client-detector.test.js +0 -214
  336. package/tests/api-client-generator.test.js +0 -176
  337. package/tests/backend-client.test.js +0 -640
  338. package/tests/base-detector.test.js +0 -101
  339. package/tests/commands/login.test.js +0 -143
  340. package/tests/commands/logout.test.js +0 -84
  341. package/tests/commands/status.test.js +0 -167
  342. package/tests/config-manager.test.js +0 -321
  343. package/tests/database-detector.test.js +0 -221
  344. package/tests/detector-index.test.js +0 -209
  345. package/tests/detector-registry.test.js +0 -93
  346. package/tests/env-generator.test.js +0 -278
  347. package/tests/expo-detector.test.js +0 -263
  348. package/tests/file-utils.test.js +0 -194
  349. package/tests/generators-index.test.js +0 -454
  350. package/tests/github-detector.test.js +0 -145
  351. package/tests/gitignore-generator.test.js +0 -109
  352. package/tests/logo.test.js +0 -96
  353. package/tests/nextauth-generator.test.js +0 -255
  354. package/tests/nextjs-detector.test.js +0 -235
  355. package/tests/oauth-detector.test.js +0 -264
  356. package/tests/oauth-guide-generator.test.js +0 -273
  357. package/tests/page-detector.test.js +0 -371
@@ -1,640 +0,0 @@
1
- /**
2
- * Tests for Backend Client
3
- */
4
-
5
- jest.mock('node-fetch');
6
- jest.mock('../src/config/config-manager');
7
-
8
- const fetch = require('node-fetch');
9
- const configManager = require('../src/config/config-manager');
10
-
11
- // Set up mock before requiring BackendClient
12
- configManager.getBackendUrl.mockReturnValue('https://backend.test.com');
13
-
14
- // Need to require after mocking
15
- const BackendClient = require('../src/api/backend-client');
16
-
17
- // API Base URL for all CLI endpoints (Convex HTTP)
18
- const API_BASE_URL = 'https://agreeable-lion-828.convex.site';
19
- // App URL only for browser login
20
- const APP_URL = 'https://app.l4yercak3.com';
21
-
22
- describe('BackendClient', () => {
23
- beforeEach(() => {
24
- jest.clearAllMocks();
25
- configManager.getBackendUrl.mockReturnValue(API_BASE_URL);
26
- configManager.getSession.mockReturnValue(null);
27
- // Reset URLs since the module was already instantiated
28
- BackendClient.baseUrl = API_BASE_URL;
29
- BackendClient.appUrl = APP_URL;
30
- });
31
-
32
- describe('getHeaders', () => {
33
- it('returns Content-Type header when no session', () => {
34
- configManager.getSession.mockReturnValue(null);
35
-
36
- const headers = BackendClient.getHeaders();
37
-
38
- expect(headers['Content-Type']).toBe('application/json');
39
- expect(headers['Authorization']).toBeUndefined();
40
- });
41
-
42
- it('includes Authorization header when session exists', () => {
43
- configManager.getSession.mockReturnValue({ token: 'test-token-123' });
44
-
45
- const headers = BackendClient.getHeaders();
46
-
47
- expect(headers['Authorization']).toBe('Bearer test-token-123');
48
- });
49
-
50
- it('does not include Authorization when session has no token', () => {
51
- configManager.getSession.mockReturnValue({ expiresAt: Date.now() });
52
-
53
- const headers = BackendClient.getHeaders();
54
-
55
- expect(headers['Authorization']).toBeUndefined();
56
- });
57
- });
58
-
59
- describe('request', () => {
60
- it('makes GET request without body', async () => {
61
- const mockResponse = {
62
- ok: true,
63
- json: jest.fn().mockResolvedValue({ data: 'test' }),
64
- };
65
- fetch.mockResolvedValue(mockResponse);
66
-
67
- const result = await BackendClient.request('GET', '/api/test');
68
-
69
- expect(fetch).toHaveBeenCalledWith(
70
- `${API_BASE_URL}/api/test`,
71
- expect.objectContaining({
72
- method: 'GET',
73
- })
74
- );
75
- expect(result).toEqual({ data: 'test' });
76
- });
77
-
78
- it('makes POST request with body', async () => {
79
- const mockResponse = {
80
- ok: true,
81
- json: jest.fn().mockResolvedValue({ success: true }),
82
- };
83
- fetch.mockResolvedValue(mockResponse);
84
-
85
- await BackendClient.request('POST', '/api/test', { name: 'test' });
86
-
87
- expect(fetch).toHaveBeenCalledWith(
88
- `${API_BASE_URL}/api/test`,
89
- expect.objectContaining({
90
- method: 'POST',
91
- body: JSON.stringify({ name: 'test' }),
92
- })
93
- );
94
- });
95
-
96
- it('makes PUT request with body', async () => {
97
- const mockResponse = {
98
- ok: true,
99
- json: jest.fn().mockResolvedValue({ success: true }),
100
- };
101
- fetch.mockResolvedValue(mockResponse);
102
-
103
- await BackendClient.request('PUT', '/api/test', { name: 'updated' });
104
-
105
- expect(fetch).toHaveBeenCalledWith(
106
- expect.any(String),
107
- expect.objectContaining({
108
- method: 'PUT',
109
- body: JSON.stringify({ name: 'updated' }),
110
- })
111
- );
112
- });
113
-
114
- it('makes PATCH request with body', async () => {
115
- const mockResponse = {
116
- ok: true,
117
- json: jest.fn().mockResolvedValue({ success: true }),
118
- };
119
- fetch.mockResolvedValue(mockResponse);
120
-
121
- await BackendClient.request('PATCH', '/api/test', { name: 'patched' });
122
-
123
- expect(fetch).toHaveBeenCalledWith(
124
- expect.any(String),
125
- expect.objectContaining({
126
- method: 'PATCH',
127
- body: JSON.stringify({ name: 'patched' }),
128
- })
129
- );
130
- });
131
-
132
- it('does not include body for DELETE request', async () => {
133
- const mockResponse = {
134
- ok: true,
135
- json: jest.fn().mockResolvedValue({ deleted: true }),
136
- };
137
- fetch.mockResolvedValue(mockResponse);
138
-
139
- await BackendClient.request('DELETE', '/api/test', { id: '123' });
140
-
141
- const fetchCall = fetch.mock.calls[0][1];
142
- expect(fetchCall.body).toBeUndefined();
143
- });
144
-
145
- it('throws error on non-ok response', async () => {
146
- const mockResponse = {
147
- ok: false,
148
- status: 401,
149
- json: jest.fn().mockResolvedValue({ message: 'Unauthorized' }),
150
- };
151
- fetch.mockResolvedValue(mockResponse);
152
-
153
- await expect(BackendClient.request('GET', '/api/test')).rejects.toThrow('Unauthorized');
154
- });
155
-
156
- it('throws generic error when no message in response', async () => {
157
- const mockResponse = {
158
- ok: false,
159
- status: 500,
160
- json: jest.fn().mockResolvedValue({}),
161
- };
162
- fetch.mockResolvedValue(mockResponse);
163
-
164
- await expect(BackendClient.request('GET', '/api/test')).rejects.toThrow('API request failed: 500');
165
- });
166
-
167
- it('throws network error on fetch failure', async () => {
168
- fetch.mockRejectedValue(new Error('fetch failed: network error'));
169
-
170
- await expect(BackendClient.request('GET', '/api/test')).rejects.toThrow(
171
- 'Network error: Could not connect to backend'
172
- );
173
- });
174
-
175
- it('rethrows non-fetch errors', async () => {
176
- fetch.mockRejectedValue(new Error('Something else went wrong'));
177
-
178
- await expect(BackendClient.request('GET', '/api/test')).rejects.toThrow(
179
- 'Something else went wrong'
180
- );
181
- });
182
- });
183
-
184
- describe('validateSession', () => {
185
- it('returns response on success', async () => {
186
- const mockResponse = {
187
- ok: true,
188
- json: jest.fn().mockResolvedValue({ valid: true, userId: '123' }),
189
- };
190
- fetch.mockResolvedValue(mockResponse);
191
-
192
- const result = await BackendClient.validateSession();
193
-
194
- expect(result).toEqual({ valid: true, userId: '123' });
195
- expect(fetch).toHaveBeenCalledWith(
196
- expect.stringContaining('/api/v1/auth/cli/validate'),
197
- expect.any(Object)
198
- );
199
- });
200
-
201
- it('returns null on error', async () => {
202
- fetch.mockRejectedValue(new Error('Network error'));
203
-
204
- const result = await BackendClient.validateSession();
205
-
206
- expect(result).toBeNull();
207
- });
208
- });
209
-
210
- describe('refreshSession', () => {
211
- it('refreshes and updates session', async () => {
212
- configManager.getSession.mockReturnValue({ token: 'old-token' });
213
- const mockResponse = {
214
- ok: true,
215
- json: jest.fn().mockResolvedValue({
216
- token: 'new-token',
217
- expiresAt: Date.now() + 3600000,
218
- }),
219
- };
220
- fetch.mockResolvedValue(mockResponse);
221
-
222
- const result = await BackendClient.refreshSession();
223
-
224
- expect(result.token).toBe('new-token');
225
- expect(configManager.saveSession).toHaveBeenCalledWith(
226
- expect.objectContaining({ token: 'new-token' })
227
- );
228
- });
229
-
230
- it('throws error when no session exists', async () => {
231
- configManager.getSession.mockReturnValue(null);
232
-
233
- await expect(BackendClient.refreshSession()).rejects.toThrow('No session to refresh');
234
- });
235
-
236
- it('throws error when session has no token', async () => {
237
- configManager.getSession.mockReturnValue({ expiresAt: Date.now() });
238
-
239
- await expect(BackendClient.refreshSession()).rejects.toThrow('No session to refresh');
240
- });
241
-
242
- it('clears session on refresh failure', async () => {
243
- configManager.getSession.mockReturnValue({ token: 'old-token' });
244
- fetch.mockRejectedValue(new Error('Refresh failed'));
245
-
246
- await expect(BackendClient.refreshSession()).rejects.toThrow('Refresh failed');
247
- expect(configManager.clearSession).toHaveBeenCalled();
248
- });
249
- });
250
-
251
- describe('revokeSession', () => {
252
- it('calls revoke endpoint when session exists', async () => {
253
- configManager.getSession.mockReturnValue({ token: 'test-token' });
254
- const mockResponse = {
255
- ok: true,
256
- json: jest.fn().mockResolvedValue({ success: true }),
257
- };
258
- fetch.mockResolvedValue(mockResponse);
259
-
260
- const result = await BackendClient.revokeSession();
261
-
262
- expect(fetch).toHaveBeenCalledWith(
263
- expect.stringContaining('/api/v1/auth/cli/revoke'),
264
- expect.objectContaining({ method: 'POST' })
265
- );
266
- expect(result.success).toBe(true);
267
- });
268
-
269
- it('returns success when no session exists', async () => {
270
- configManager.getSession.mockReturnValue(null);
271
-
272
- const result = await BackendClient.revokeSession();
273
-
274
- expect(fetch).not.toHaveBeenCalled();
275
- expect(result.success).toBe(true);
276
- });
277
-
278
- it('returns success when session has no token', async () => {
279
- configManager.getSession.mockReturnValue({ expiresAt: Date.now() });
280
-
281
- const result = await BackendClient.revokeSession();
282
-
283
- expect(fetch).not.toHaveBeenCalled();
284
- expect(result.success).toBe(true);
285
- });
286
-
287
- it('returns failure but does not throw on error', async () => {
288
- configManager.getSession.mockReturnValue({ token: 'test-token' });
289
- fetch.mockRejectedValue(new Error('Revoke failed'));
290
-
291
- // Suppress console.error for this test
292
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
293
-
294
- const result = await BackendClient.revokeSession();
295
-
296
- expect(result.success).toBe(false);
297
- expect(result.error).toBe('Revoke failed');
298
-
299
- consoleSpy.mockRestore();
300
- });
301
- });
302
-
303
- describe('generateState', () => {
304
- it('generates a 64-character hex string', () => {
305
- const state = BackendClient.generateState();
306
-
307
- expect(state).toMatch(/^[a-f0-9]{64}$/);
308
- });
309
-
310
- it('generates unique values each time', () => {
311
- const state1 = BackendClient.generateState();
312
- const state2 = BackendClient.generateState();
313
-
314
- expect(state1).not.toBe(state2);
315
- });
316
- });
317
-
318
- describe('getLoginUrl', () => {
319
- it('returns provider selection URL with state when no provider specified', () => {
320
- const state = 'test-state-token';
321
- const url = BackendClient.getLoginUrl(state);
322
-
323
- // Login URL uses APP_URL (Next.js), not API_BASE_URL
324
- expect(url).toContain(APP_URL);
325
- expect(url).toContain('/auth/cli-login');
326
- expect(url).toContain('state=test-state-token');
327
- expect(url).toContain('callback=');
328
- });
329
-
330
- it('returns direct OAuth URL when provider specified', () => {
331
- const state = 'test-state-token';
332
- const url = BackendClient.getLoginUrl(state, 'google');
333
-
334
- expect(url).toContain(APP_URL);
335
- expect(url).toContain('/api/auth/oauth-signup');
336
- expect(url).toContain('provider=google');
337
- expect(url).toContain('sessionType=cli');
338
- expect(url).toContain('state=test-state-token');
339
- });
340
-
341
- it('includes encoded callback URL', () => {
342
- const state = 'test-state-token';
343
- const url = BackendClient.getLoginUrl(state, 'github');
344
-
345
- expect(url).toContain(encodeURIComponent('http://localhost:3333/callback'));
346
- });
347
- });
348
-
349
- describe('generateApiKey', () => {
350
- it('calls API to generate key', async () => {
351
- const mockResponse = {
352
- ok: true,
353
- json: jest.fn().mockResolvedValue({
354
- key: 'new-api-key',
355
- id: 'key-123',
356
- }),
357
- };
358
- fetch.mockResolvedValue(mockResponse);
359
-
360
- const result = await BackendClient.generateApiKey('org-123', 'My Key', ['read', 'write']);
361
-
362
- expect(fetch).toHaveBeenCalledWith(
363
- expect.stringContaining('/api/v1/auth/cli/api-keys'),
364
- expect.objectContaining({
365
- method: 'POST',
366
- body: JSON.stringify({
367
- organizationId: 'org-123',
368
- name: 'My Key',
369
- scopes: ['read', 'write'],
370
- }),
371
- })
372
- );
373
- expect(result.key).toBe('new-api-key');
374
- });
375
-
376
- it('uses default scopes when not provided', async () => {
377
- const mockResponse = {
378
- ok: true,
379
- json: jest.fn().mockResolvedValue({ key: 'key' }),
380
- };
381
- fetch.mockResolvedValue(mockResponse);
382
-
383
- await BackendClient.generateApiKey('org-123', 'My Key');
384
-
385
- expect(fetch).toHaveBeenCalledWith(
386
- expect.any(String),
387
- expect.objectContaining({
388
- body: JSON.stringify({
389
- organizationId: 'org-123',
390
- name: 'My Key',
391
- scopes: ['*'],
392
- }),
393
- })
394
- );
395
- });
396
- });
397
-
398
- describe('getOrganizations', () => {
399
- it('fetches organizations list', async () => {
400
- const mockResponse = {
401
- ok: true,
402
- json: jest.fn().mockResolvedValue({
403
- organizations: [{ id: '1', name: 'Org 1' }],
404
- }),
405
- };
406
- fetch.mockResolvedValue(mockResponse);
407
-
408
- const result = await BackendClient.getOrganizations();
409
-
410
- expect(fetch).toHaveBeenCalledWith(
411
- expect.stringContaining('/api/v1/auth/cli/organizations'),
412
- expect.objectContaining({ method: 'GET' })
413
- );
414
- expect(result.organizations).toHaveLength(1);
415
- });
416
- });
417
-
418
- describe('createOrganization', () => {
419
- it('creates organization with name', async () => {
420
- const mockResponse = {
421
- ok: true,
422
- json: jest.fn().mockResolvedValue({
423
- id: 'new-org-123',
424
- name: 'New Org',
425
- }),
426
- };
427
- fetch.mockResolvedValue(mockResponse);
428
-
429
- const result = await BackendClient.createOrganization('New Org');
430
-
431
- expect(fetch).toHaveBeenCalledWith(
432
- expect.stringContaining('/api/v1/auth/cli/organizations'),
433
- expect.objectContaining({
434
- method: 'POST',
435
- body: JSON.stringify({ name: 'New Org' }),
436
- })
437
- );
438
- expect(result.name).toBe('New Org');
439
- });
440
- });
441
-
442
- // ============================================
443
- // Connected Applications API Tests (Convex HTTP)
444
- // ============================================
445
-
446
- describe('checkExistingApplication', () => {
447
- it('returns found=true when application exists', async () => {
448
- const mockResponse = {
449
- ok: true,
450
- json: jest.fn().mockResolvedValue({
451
- found: true,
452
- application: {
453
- id: 'app-123',
454
- name: 'My App',
455
- },
456
- }),
457
- };
458
- fetch.mockResolvedValue(mockResponse);
459
-
460
- const result = await BackendClient.checkExistingApplication('org-123', 'hash123');
461
-
462
- // Should use Convex URL, not main backend
463
- expect(fetch).toHaveBeenCalledWith(
464
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications/by-path?organizationId=org-123&hash=hash123',
465
- expect.objectContaining({ method: 'GET' })
466
- );
467
- expect(result.found).toBe(true);
468
- expect(result.application.id).toBe('app-123');
469
- });
470
-
471
- it('returns found=false when 404', async () => {
472
- const mockResponse = {
473
- ok: false,
474
- status: 404,
475
- json: jest.fn().mockResolvedValue({ error: 'Not found' }),
476
- };
477
- fetch.mockResolvedValue(mockResponse);
478
-
479
- const result = await BackendClient.checkExistingApplication('org-123', 'hash456');
480
-
481
- expect(result.found).toBe(false);
482
- });
483
-
484
- it('throws error on non-404 errors', async () => {
485
- const mockResponse = {
486
- ok: false,
487
- status: 500,
488
- json: jest.fn().mockResolvedValue({ message: 'Server error' }),
489
- };
490
- fetch.mockResolvedValue(mockResponse);
491
-
492
- await expect(BackendClient.checkExistingApplication('org-123', 'hash789'))
493
- .rejects.toThrow('Server error');
494
- });
495
- });
496
-
497
- describe('registerApplication', () => {
498
- it('registers new application via Convex URL', async () => {
499
- const mockResponse = {
500
- ok: true,
501
- json: jest.fn().mockResolvedValue({
502
- applicationId: 'app-new-123',
503
- backendUrl: 'https://api.l4yercak3.com',
504
- }),
505
- };
506
- fetch.mockResolvedValue(mockResponse);
507
-
508
- const registrationData = {
509
- organizationId: 'org-123',
510
- name: 'My New App',
511
- source: {
512
- type: 'cli',
513
- projectPathHash: 'hash123',
514
- framework: 'nextjs',
515
- },
516
- connection: {
517
- features: ['crm', 'events'],
518
- },
519
- };
520
-
521
- const result = await BackendClient.registerApplication(registrationData);
522
-
523
- // Should use Convex URL, not main backend
524
- expect(fetch).toHaveBeenCalledWith(
525
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications',
526
- expect.objectContaining({
527
- method: 'POST',
528
- body: JSON.stringify(registrationData),
529
- })
530
- );
531
- expect(result.applicationId).toBe('app-new-123');
532
- });
533
- });
534
-
535
- describe('updateApplication', () => {
536
- it('updates existing application via Convex URL', async () => {
537
- const mockResponse = {
538
- ok: true,
539
- json: jest.fn().mockResolvedValue({
540
- success: true,
541
- applicationId: 'app-123',
542
- }),
543
- };
544
- fetch.mockResolvedValue(mockResponse);
545
-
546
- const updates = {
547
- connection: {
548
- features: ['crm', 'events', 'invoicing'],
549
- },
550
- };
551
-
552
- const result = await BackendClient.updateApplication('app-123', updates);
553
-
554
- expect(fetch).toHaveBeenCalledWith(
555
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications/app-123',
556
- expect.objectContaining({
557
- method: 'PATCH',
558
- body: JSON.stringify(updates),
559
- })
560
- );
561
- expect(result.success).toBe(true);
562
- });
563
- });
564
-
565
- describe('getApplication', () => {
566
- it('fetches application details via Convex URL', async () => {
567
- const mockResponse = {
568
- ok: true,
569
- json: jest.fn().mockResolvedValue({
570
- id: 'app-123',
571
- name: 'My App',
572
- status: 'active',
573
- }),
574
- };
575
- fetch.mockResolvedValue(mockResponse);
576
-
577
- const result = await BackendClient.getApplication('app-123');
578
-
579
- expect(fetch).toHaveBeenCalledWith(
580
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications/app-123',
581
- expect.objectContaining({ method: 'GET' })
582
- );
583
- expect(result.id).toBe('app-123');
584
- expect(result.status).toBe('active');
585
- });
586
- });
587
-
588
- describe('listApplications', () => {
589
- it('lists applications for organization via Convex URL', async () => {
590
- const mockResponse = {
591
- ok: true,
592
- json: jest.fn().mockResolvedValue({
593
- applications: [
594
- { id: 'app-1', name: 'App One' },
595
- { id: 'app-2', name: 'App Two' },
596
- ],
597
- }),
598
- };
599
- fetch.mockResolvedValue(mockResponse);
600
-
601
- const result = await BackendClient.listApplications('org-123');
602
-
603
- expect(fetch).toHaveBeenCalledWith(
604
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications?organizationId=org-123',
605
- expect.objectContaining({ method: 'GET' })
606
- );
607
- expect(result.applications).toHaveLength(2);
608
- });
609
- });
610
-
611
- describe('syncApplication', () => {
612
- it('syncs application data via Convex URL', async () => {
613
- const mockResponse = {
614
- ok: true,
615
- json: jest.fn().mockResolvedValue({
616
- success: true,
617
- syncedRecords: 42,
618
- }),
619
- };
620
- fetch.mockResolvedValue(mockResponse);
621
-
622
- const syncData = {
623
- direction: 'bidirectional',
624
- models: ['contacts', 'organizations'],
625
- };
626
-
627
- const result = await BackendClient.syncApplication('app-123', syncData);
628
-
629
- expect(fetch).toHaveBeenCalledWith(
630
- 'https://agreeable-lion-828.convex.site/api/v1/cli/applications/app-123/sync',
631
- expect.objectContaining({
632
- method: 'POST',
633
- body: JSON.stringify(syncData),
634
- })
635
- );
636
- expect(result.success).toBe(true);
637
- expect(result.syncedRecords).toBe(42);
638
- });
639
- });
640
- });