hacklab 0.22.3 → 26.921.1

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 (259) hide show
  1. package/README.md +23 -430
  2. package/dist/index.js +132 -23
  3. package/package.json +20 -42
  4. package/LICENSE +0 -21
  5. package/dist/agent-handoff.d.ts +0 -51
  6. package/dist/agent-handoff.d.ts.map +0 -1
  7. package/dist/agent-handoff.js +0 -91
  8. package/dist/agent-handoff.js.map +0 -1
  9. package/dist/api-client.d.ts +0 -18
  10. package/dist/api-client.d.ts.map +0 -1
  11. package/dist/api-client.js +0 -40
  12. package/dist/api-client.js.map +0 -1
  13. package/dist/belt.d.ts +0 -25
  14. package/dist/belt.d.ts.map +0 -1
  15. package/dist/belt.js +0 -113
  16. package/dist/belt.js.map +0 -1
  17. package/dist/card.d.ts +0 -66
  18. package/dist/card.d.ts.map +0 -1
  19. package/dist/card.js +0 -151
  20. package/dist/card.js.map +0 -1
  21. package/dist/cli.d.ts +0 -2
  22. package/dist/cli.d.ts.map +0 -1
  23. package/dist/cli.js +0 -238
  24. package/dist/cli.js.map +0 -1
  25. package/dist/commands/book.d.ts +0 -14
  26. package/dist/commands/book.d.ts.map +0 -1
  27. package/dist/commands/book.js +0 -90
  28. package/dist/commands/book.js.map +0 -1
  29. package/dist/commands/chat.d.ts +0 -36
  30. package/dist/commands/chat.d.ts.map +0 -1
  31. package/dist/commands/chat.js +0 -642
  32. package/dist/commands/chat.js.map +0 -1
  33. package/dist/commands/config.d.ts +0 -2
  34. package/dist/commands/config.d.ts.map +0 -1
  35. package/dist/commands/config.js +0 -84
  36. package/dist/commands/config.js.map +0 -1
  37. package/dist/commands/daemon.d.ts +0 -19
  38. package/dist/commands/daemon.d.ts.map +0 -1
  39. package/dist/commands/daemon.js +0 -72
  40. package/dist/commands/daemon.js.map +0 -1
  41. package/dist/commands/drop.d.ts +0 -12
  42. package/dist/commands/drop.d.ts.map +0 -1
  43. package/dist/commands/drop.js +0 -103
  44. package/dist/commands/drop.js.map +0 -1
  45. package/dist/commands/drops.d.ts +0 -9
  46. package/dist/commands/drops.d.ts.map +0 -1
  47. package/dist/commands/drops.js +0 -96
  48. package/dist/commands/drops.js.map +0 -1
  49. package/dist/commands/essay.d.ts +0 -40
  50. package/dist/commands/essay.d.ts.map +0 -1
  51. package/dist/commands/essay.js +0 -651
  52. package/dist/commands/essay.js.map +0 -1
  53. package/dist/commands/hackathon.d.ts +0 -2
  54. package/dist/commands/hackathon.d.ts.map +0 -1
  55. package/dist/commands/hackathon.js +0 -893
  56. package/dist/commands/hackathon.js.map +0 -1
  57. package/dist/commands/hacker.d.ts +0 -2
  58. package/dist/commands/hacker.d.ts.map +0 -1
  59. package/dist/commands/hacker.js +0 -87
  60. package/dist/commands/hacker.js.map +0 -1
  61. package/dist/commands/jobs.d.ts +0 -18
  62. package/dist/commands/jobs.d.ts.map +0 -1
  63. package/dist/commands/jobs.js +0 -138
  64. package/dist/commands/jobs.js.map +0 -1
  65. package/dist/commands/keys.d.ts +0 -2
  66. package/dist/commands/keys.d.ts.map +0 -1
  67. package/dist/commands/keys.js +0 -138
  68. package/dist/commands/keys.js.map +0 -1
  69. package/dist/commands/login.d.ts +0 -83
  70. package/dist/commands/login.d.ts.map +0 -1
  71. package/dist/commands/login.js +0 -236
  72. package/dist/commands/login.js.map +0 -1
  73. package/dist/commands/logout.d.ts +0 -2
  74. package/dist/commands/logout.d.ts.map +0 -1
  75. package/dist/commands/logout.js +0 -22
  76. package/dist/commands/logout.js.map +0 -1
  77. package/dist/commands/org-jobs.d.ts +0 -50
  78. package/dist/commands/org-jobs.d.ts.map +0 -1
  79. package/dist/commands/org-jobs.js +0 -383
  80. package/dist/commands/org-jobs.js.map +0 -1
  81. package/dist/commands/org.d.ts +0 -67
  82. package/dist/commands/org.d.ts.map +0 -1
  83. package/dist/commands/org.js +0 -1244
  84. package/dist/commands/org.js.map +0 -1
  85. package/dist/commands/ping.d.ts +0 -2
  86. package/dist/commands/ping.d.ts.map +0 -1
  87. package/dist/commands/ping.js +0 -50
  88. package/dist/commands/ping.js.map +0 -1
  89. package/dist/commands/profile.d.ts +0 -72
  90. package/dist/commands/profile.d.ts.map +0 -1
  91. package/dist/commands/profile.js +0 -672
  92. package/dist/commands/profile.js.map +0 -1
  93. package/dist/commands/project.d.ts +0 -2
  94. package/dist/commands/project.d.ts.map +0 -1
  95. package/dist/commands/project.js +0 -583
  96. package/dist/commands/project.js.map +0 -1
  97. package/dist/commands/referral.d.ts +0 -6
  98. package/dist/commands/referral.d.ts.map +0 -1
  99. package/dist/commands/referral.js +0 -93
  100. package/dist/commands/referral.js.map +0 -1
  101. package/dist/commands/rtfm.d.ts +0 -9
  102. package/dist/commands/rtfm.d.ts.map +0 -1
  103. package/dist/commands/rtfm.js +0 -114
  104. package/dist/commands/rtfm.js.map +0 -1
  105. package/dist/commands/scan.d.ts +0 -13
  106. package/dist/commands/scan.d.ts.map +0 -1
  107. package/dist/commands/scan.js +0 -286
  108. package/dist/commands/scan.js.map +0 -1
  109. package/dist/commands/scout.d.ts +0 -18
  110. package/dist/commands/scout.d.ts.map +0 -1
  111. package/dist/commands/scout.js +0 -232
  112. package/dist/commands/scout.js.map +0 -1
  113. package/dist/commands/setup-rail.d.ts +0 -58
  114. package/dist/commands/setup-rail.d.ts.map +0 -1
  115. package/dist/commands/setup-rail.js +0 -135
  116. package/dist/commands/setup-rail.js.map +0 -1
  117. package/dist/commands/setup.d.ts +0 -29
  118. package/dist/commands/setup.d.ts.map +0 -1
  119. package/dist/commands/setup.js +0 -442
  120. package/dist/commands/setup.js.map +0 -1
  121. package/dist/commands/sync.d.ts +0 -9
  122. package/dist/commands/sync.d.ts.map +0 -1
  123. package/dist/commands/sync.js +0 -345
  124. package/dist/commands/sync.js.map +0 -1
  125. package/dist/commands/update.d.ts +0 -2
  126. package/dist/commands/update.d.ts.map +0 -1
  127. package/dist/commands/update.js +0 -92
  128. package/dist/commands/update.js.map +0 -1
  129. package/dist/commands/whoami.d.ts +0 -2
  130. package/dist/commands/whoami.d.ts.map +0 -1
  131. package/dist/commands/whoami.js +0 -41
  132. package/dist/commands/whoami.js.map +0 -1
  133. package/dist/config.d.ts +0 -78
  134. package/dist/config.d.ts.map +0 -1
  135. package/dist/config.js +0 -93
  136. package/dist/config.js.map +0 -1
  137. package/dist/daily-sync.d.ts +0 -150
  138. package/dist/daily-sync.d.ts.map +0 -1
  139. package/dist/daily-sync.js +0 -665
  140. package/dist/daily-sync.js.map +0 -1
  141. package/dist/dossier.d.ts +0 -73
  142. package/dist/dossier.d.ts.map +0 -1
  143. package/dist/dossier.js +0 -141
  144. package/dist/dossier.js.map +0 -1
  145. package/dist/field-normalize.d.ts +0 -4
  146. package/dist/field-normalize.d.ts.map +0 -1
  147. package/dist/field-normalize.js +0 -8
  148. package/dist/field-normalize.js.map +0 -1
  149. package/dist/index.d.ts +0 -3
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/index.js.map +0 -1
  152. package/dist/job-fields.d.ts +0 -47
  153. package/dist/job-fields.d.ts.map +0 -1
  154. package/dist/job-fields.js +0 -148
  155. package/dist/job-fields.js.map +0 -1
  156. package/dist/machine.d.ts +0 -15
  157. package/dist/machine.d.ts.map +0 -1
  158. package/dist/machine.js +0 -64
  159. package/dist/machine.js.map +0 -1
  160. package/dist/org-fields.d.ts +0 -57
  161. package/dist/org-fields.d.ts.map +0 -1
  162. package/dist/org-fields.js +0 -167
  163. package/dist/org-fields.js.map +0 -1
  164. package/dist/posthog.d.ts +0 -38
  165. package/dist/posthog.d.ts.map +0 -1
  166. package/dist/posthog.js +0 -224
  167. package/dist/posthog.js.map +0 -1
  168. package/dist/project-fields.d.ts +0 -40
  169. package/dist/project-fields.d.ts.map +0 -1
  170. package/dist/project-fields.js +0 -79
  171. package/dist/project-fields.js.map +0 -1
  172. package/dist/prompt-consent.d.ts +0 -73
  173. package/dist/prompt-consent.d.ts.map +0 -1
  174. package/dist/prompt-consent.js +0 -191
  175. package/dist/prompt-consent.js.map +0 -1
  176. package/dist/prompt-stats.d.ts +0 -226
  177. package/dist/prompt-stats.d.ts.map +0 -1
  178. package/dist/prompt-stats.js +0 -561
  179. package/dist/prompt-stats.js.map +0 -1
  180. package/dist/referral.d.ts +0 -14
  181. package/dist/referral.d.ts.map +0 -1
  182. package/dist/referral.js +0 -28
  183. package/dist/referral.js.map +0 -1
  184. package/dist/registry.d.ts +0 -15
  185. package/dist/registry.d.ts.map +0 -1
  186. package/dist/registry.js +0 -180
  187. package/dist/registry.js.map +0 -1
  188. package/dist/resolve-command.d.ts +0 -20
  189. package/dist/resolve-command.d.ts.map +0 -1
  190. package/dist/resolve-command.js +0 -21
  191. package/dist/resolve-command.js.map +0 -1
  192. package/dist/scanners/antigravity.d.ts +0 -41
  193. package/dist/scanners/antigravity.d.ts.map +0 -1
  194. package/dist/scanners/antigravity.js +0 -210
  195. package/dist/scanners/antigravity.js.map +0 -1
  196. package/dist/scanners/github-copilot-telemetry.d.ts +0 -23
  197. package/dist/scanners/github-copilot-telemetry.d.ts.map +0 -1
  198. package/dist/scanners/github-copilot-telemetry.js +0 -220
  199. package/dist/scanners/github-copilot-telemetry.js.map +0 -1
  200. package/dist/scanners/github-copilot.d.ts +0 -68
  201. package/dist/scanners/github-copilot.d.ts.map +0 -1
  202. package/dist/scanners/github-copilot.js +0 -262
  203. package/dist/scanners/github-copilot.js.map +0 -1
  204. package/dist/scanners/incremental.d.ts +0 -282
  205. package/dist/scanners/incremental.d.ts.map +0 -1
  206. package/dist/scanners/incremental.js +0 -788
  207. package/dist/scanners/incremental.js.map +0 -1
  208. package/dist/scanners/index.d.ts +0 -116
  209. package/dist/scanners/index.d.ts.map +0 -1
  210. package/dist/scanners/index.js +0 -726
  211. package/dist/scanners/index.js.map +0 -1
  212. package/dist/scanners/sqlite.d.ts +0 -18
  213. package/dist/scanners/sqlite.d.ts.map +0 -1
  214. package/dist/scanners/sqlite.js +0 -63
  215. package/dist/scanners/sqlite.js.map +0 -1
  216. package/dist/scanners/util.d.ts +0 -112
  217. package/dist/scanners/util.d.ts.map +0 -1
  218. package/dist/scanners/util.js +0 -167
  219. package/dist/scanners/util.js.map +0 -1
  220. package/dist/session.d.ts +0 -106
  221. package/dist/session.d.ts.map +0 -1
  222. package/dist/session.js +0 -191
  223. package/dist/session.js.map +0 -1
  224. package/dist/share-card-colors.d.ts +0 -19
  225. package/dist/share-card-colors.d.ts.map +0 -1
  226. package/dist/share-card-colors.js +0 -36
  227. package/dist/share-card-colors.js.map +0 -1
  228. package/dist/share-card.d.ts +0 -31
  229. package/dist/share-card.d.ts.map +0 -1
  230. package/dist/share-card.js +0 -380
  231. package/dist/share-card.js.map +0 -1
  232. package/dist/share.d.ts +0 -17
  233. package/dist/share.d.ts.map +0 -1
  234. package/dist/share.js +0 -75
  235. package/dist/share.js.map +0 -1
  236. package/dist/sync.d.ts +0 -100
  237. package/dist/sync.d.ts.map +0 -1
  238. package/dist/sync.js +0 -304
  239. package/dist/sync.js.map +0 -1
  240. package/dist/ui.d.ts +0 -33
  241. package/dist/ui.d.ts.map +0 -1
  242. package/dist/ui.js +0 -127
  243. package/dist/ui.js.map +0 -1
  244. package/dist/utils/npmGlobal.d.ts +0 -30
  245. package/dist/utils/npmGlobal.d.ts.map +0 -1
  246. package/dist/utils/npmGlobal.js +0 -69
  247. package/dist/utils/npmGlobal.js.map +0 -1
  248. package/dist/utils/openBrowser.d.ts +0 -14
  249. package/dist/utils/openBrowser.d.ts.map +0 -1
  250. package/dist/utils/openBrowser.js +0 -47
  251. package/dist/utils/openBrowser.js.map +0 -1
  252. package/dist/utils/updateCheck.d.ts +0 -16
  253. package/dist/utils/updateCheck.d.ts.map +0 -1
  254. package/dist/utils/updateCheck.js +0 -111
  255. package/dist/utils/updateCheck.js.map +0 -1
  256. package/dist/utils/waitForEnter.d.ts +0 -12
  257. package/dist/utils/waitForEnter.d.ts.map +0 -1
  258. package/dist/utils/waitForEnter.js +0 -43
  259. package/dist/utils/waitForEnter.js.map +0 -1
@@ -1,57 +0,0 @@
1
- export type OrgFieldType = 'text' | 'url' | 'number' | 'boolean' | 'list';
2
- export type OrgFieldSpec = {
3
- /** API key sent to /api/cli/org. */
4
- key: string;
5
- /** CLI-facing name (`hacklab org set <name> …`). */
6
- name: string;
7
- /** Label shown in the interactive editor. */
8
- label: string;
9
- type: OrgFieldType;
10
- };
11
- export declare const ORG_FIELDS: OrgFieldSpec[];
12
- export declare const ORG_FIELD_NAMES: string[];
13
- export type OrgValue = string | number | boolean | string[] | null;
14
- export type NormalizedOrgValue = {
15
- ok: true;
16
- value: OrgValue;
17
- } | {
18
- ok: false;
19
- error: string;
20
- };
21
- /**
22
- * Shape one raw CLI string into the value the API expects. Empty clears the
23
- * field (except name/slug, which are required). URLs get https:// prepended
24
- * when the scheme is missing; lists split on commas. Real validation (slug
25
- * pattern, lengths, URL syntax) stays server-side.
26
- */
27
- export declare function normalizeOrgFieldValue(spec: OrgFieldSpec, raw: string): NormalizedOrgValue;
28
- /**
29
- * Map a parsed yaml/json document to API fields for `org apply`. Keys may be
30
- * CLI names (`long-description`, `hiring`) or API keys (`longDescription`,
31
- * `isHiring`); unknown keys fail loudly so a typo can't silently drop a field.
32
- * Lists accept real arrays or comma-separated strings.
33
- */
34
- export declare function parseOrgDocument(doc: unknown): {
35
- ok: true;
36
- fields: Record<string, OrgValue>;
37
- } | {
38
- ok: false;
39
- error: string;
40
- };
41
- /**
42
- * Pick the org a view/set/apply targets. `--org <slug>` wins; with no flag,
43
- * exactly one managed org is the target, zero or several is a typed error the
44
- * caller renders (JSON gets the code, humans get the message — which always
45
- * names the way out).
46
- */
47
- export declare function resolveTargetOrg<T extends {
48
- slug: string;
49
- }>(organizations: T[], slugFlag: string | undefined): {
50
- ok: true;
51
- org: T;
52
- } | {
53
- ok: false;
54
- code: 'no_org' | 'ambiguous_org' | 'not_found';
55
- error: string;
56
- };
57
- //# sourceMappingURL=org-fields.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"org-fields.d.ts","sourceRoot":"","sources":["../src/org-fields.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;AAEzE,MAAM,MAAM,YAAY,GAAG;IACzB,oCAAoC;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAA;IACZ,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,YAAY,CAAA;CACnB,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,YAAY,EA4BpC,CAAA;AAED,eAAO,MAAM,eAAe,UAAgC,CAAA;AAK5D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;AAElE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAShC;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,YAAY,EAClB,GAAG,EAAE,MAAM,GACV,kBAAkB,CA+BpB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GACzC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;CAAE,GAC9C;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd,CAqDJ;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EACzD,aAAa,EAAE,CAAC,EAAE,EAClB,QAAQ,EAAE,MAAM,GAAG,SAAS,GAE1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,CAAC,CAAA;CAAE,GACpB;IACE,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,QAAQ,GAAG,eAAe,GAAG,WAAW,CAAA;IAC9C,KAAK,EAAE,MAAM,CAAA;CACd,CA+BJ"}
@@ -1,167 +0,0 @@
1
- import { ensureScheme, FALSE_WORDS, TRUE_WORDS } from './field-normalize.js';
2
- export const ORG_FIELDS = [
3
- { key: 'name', name: 'name', label: 'Name', type: 'text' },
4
- { key: 'slug', name: 'slug', label: 'Slug (URL handle)', type: 'text' },
5
- { key: 'logoUrl', name: 'logo', label: 'Logo URL', type: 'url' },
6
- { key: 'website', name: 'website', label: 'Website', type: 'url' },
7
- {
8
- key: 'description',
9
- name: 'description',
10
- label: 'Short description',
11
- type: 'text',
12
- },
13
- {
14
- key: 'longDescription',
15
- name: 'long-description',
16
- label: 'Long description',
17
- type: 'text',
18
- },
19
- { key: 'ycBatch', name: 'yc-batch', label: 'YC batch', type: 'text' },
20
- { key: 'ycSlug', name: 'yc-slug', label: 'YC slug', type: 'text' },
21
- { key: 'ycUrl', name: 'yc-url', label: 'YC URL', type: 'url' },
22
- { key: 'waasUrl', name: 'waas', label: 'WaaS URL', type: 'url' },
23
- { key: 'teamSize', name: 'team-size', label: 'Team size', type: 'number' },
24
- { key: 'status', name: 'status', label: 'Status', type: 'text' },
25
- { key: 'stage', name: 'stage', label: 'Stage', type: 'text' },
26
- { key: 'isHiring', name: 'hiring', label: 'Hiring?', type: 'boolean' },
27
- { key: 'industries', name: 'industries', label: 'Industries', type: 'list' },
28
- { key: 'tags', name: 'tags', label: 'Tags', type: 'list' },
29
- { key: 'locations', name: 'locations', label: 'Locations', type: 'list' },
30
- ];
31
- export const ORG_FIELD_NAMES = ORG_FIELDS.map((f) => f.name);
32
- // name and slug are notNull columns — a blank must fail loudly, not clear.
33
- const REQUIRED_KEYS = new Set(['name', 'slug']);
34
- function splitList(raw) {
35
- return raw
36
- .split(',')
37
- .map((s) => s.trim())
38
- .filter(Boolean);
39
- }
40
- /**
41
- * Shape one raw CLI string into the value the API expects. Empty clears the
42
- * field (except name/slug, which are required). URLs get https:// prepended
43
- * when the scheme is missing; lists split on commas. Real validation (slug
44
- * pattern, lengths, URL syntax) stays server-side.
45
- */
46
- export function normalizeOrgFieldValue(spec, raw) {
47
- const trimmed = raw.trim();
48
- if (!trimmed) {
49
- if (REQUIRED_KEYS.has(spec.key)) {
50
- return { ok: false, error: `${spec.name} can't be empty` };
51
- }
52
- return { ok: true, value: null };
53
- }
54
- if (spec.type === 'boolean') {
55
- const word = trimmed.toLowerCase();
56
- if (TRUE_WORDS.has(word))
57
- return { ok: true, value: true };
58
- if (FALSE_WORDS.has(word))
59
- return { ok: true, value: false };
60
- return { ok: false, error: `${spec.name} must be yes or no` };
61
- }
62
- if (spec.type === 'number') {
63
- if (!/^\d+$/.test(trimmed)) {
64
- return { ok: false, error: `${spec.name} must be a whole number` };
65
- }
66
- return { ok: true, value: Number(trimmed) };
67
- }
68
- if (spec.type === 'list') {
69
- const items = splitList(trimmed);
70
- return { ok: true, value: items.length ? items : null };
71
- }
72
- if (spec.type === 'url')
73
- return { ok: true, value: ensureScheme(trimmed) };
74
- return { ok: true, value: trimmed };
75
- }
76
- /**
77
- * Map a parsed yaml/json document to API fields for `org apply`. Keys may be
78
- * CLI names (`long-description`, `hiring`) or API keys (`longDescription`,
79
- * `isHiring`); unknown keys fail loudly so a typo can't silently drop a field.
80
- * Lists accept real arrays or comma-separated strings.
81
- */
82
- export function parseOrgDocument(doc) {
83
- if (typeof doc !== 'object' || doc === null || Array.isArray(doc)) {
84
- return { ok: false, error: 'expected a mapping of fields to values' };
85
- }
86
- const fields = {};
87
- for (const [rawKey, rawValue] of Object.entries(doc)) {
88
- const spec = ORG_FIELDS.find((f) => f.name === rawKey || f.key === rawKey);
89
- if (!spec) {
90
- return {
91
- ok: false,
92
- error: `unknown field "${rawKey}" (fields: ${ORG_FIELD_NAMES.join(', ')})`,
93
- };
94
- }
95
- if (rawValue === null) {
96
- if (REQUIRED_KEYS.has(spec.key)) {
97
- return { ok: false, error: `${spec.name} can't be empty` };
98
- }
99
- fields[spec.key] = null;
100
- continue;
101
- }
102
- if (typeof rawValue === 'boolean') {
103
- if (spec.type !== 'boolean') {
104
- return { ok: false, error: `${spec.name}: expected a string value` };
105
- }
106
- fields[spec.key] = rawValue;
107
- continue;
108
- }
109
- if (Array.isArray(rawValue)) {
110
- if (spec.type !== 'list') {
111
- return { ok: false, error: `${spec.name}: expected a single value` };
112
- }
113
- const items = rawValue.map((v) => String(v).trim()).filter(Boolean);
114
- fields[spec.key] = items.length ? items : null;
115
- continue;
116
- }
117
- if (typeof rawValue !== 'string' && typeof rawValue !== 'number') {
118
- return { ok: false, error: `${spec.name}: expected a string value` };
119
- }
120
- const normalized = normalizeOrgFieldValue(spec, String(rawValue));
121
- if (!normalized.ok)
122
- return normalized;
123
- fields[spec.key] = normalized.value;
124
- }
125
- if (Object.keys(fields).length === 0) {
126
- return { ok: false, error: 'no fields to apply' };
127
- }
128
- return { ok: true, fields };
129
- }
130
- /**
131
- * Pick the org a view/set/apply targets. `--org <slug>` wins; with no flag,
132
- * exactly one managed org is the target, zero or several is a typed error the
133
- * caller renders (JSON gets the code, humans get the message — which always
134
- * names the way out).
135
- */
136
- export function resolveTargetOrg(organizations, slugFlag) {
137
- if (slugFlag) {
138
- const found = organizations.find((o) => o.slug === slugFlag);
139
- if (found)
140
- return { ok: true, org: found };
141
- const yours = organizations.map((o) => o.slug).join(', ');
142
- return {
143
- ok: false,
144
- code: 'not_found',
145
- error: organizations.length
146
- ? `you don't manage "${slugFlag}" (you manage: ${yours})`
147
- : `you don't manage "${slugFlag}" — claim or create it first`,
148
- };
149
- }
150
- if (organizations.length === 0) {
151
- return {
152
- ok: false,
153
- code: 'no_org',
154
- error: "you don't manage a company yet — run `hacklab org claim <slug>` or `hacklab org create`",
155
- };
156
- }
157
- if (organizations.length > 1) {
158
- const slugs = organizations.map((o) => o.slug).join(', ');
159
- return {
160
- ok: false,
161
- code: 'ambiguous_org',
162
- error: `you manage ${organizations.length} companies — pass --org <slug> (${slugs})`,
163
- };
164
- }
165
- return { ok: true, org: organizations[0] };
166
- }
167
- //# sourceMappingURL=org-fields.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"org-fields.js","sourceRoot":"","sources":["../src/org-fields.ts"],"names":[],"mappings":"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"}
package/dist/posthog.d.ts DELETED
@@ -1,38 +0,0 @@
1
- /**
2
- * Telemetry is opt-OUT. It's off when the user sets `HACKLAB_NO_TELEMETRY`
3
- * (mirrors `HACKLAB_NO_UPDATE_CHECK`) or the cross-tool `DO_NOT_TRACK` standard
4
- * (https://consoledonottrack.com). Checked at every entry point, so a disabled
5
- * CLI never constructs a client, phones home, or installs exception handlers.
6
- */
7
- export declare function isTelemetryDisabled(): boolean;
8
- /**
9
- * Capture an event and flush it. Falls back to the anonymous device id when no
10
- * handle is given, so pre-auth usage is still counted (and later stitched onto
11
- * the user via `identifyUser`). Fire-and-forget: gated on opt-out, wrapped so it
12
- * can never slow down or break the command that called it.
13
- */
14
- export declare function captureEvent(distinctId: string | undefined, event: string, properties?: Record<string, unknown>): Promise<void>;
15
- /**
16
- * Identify the logged-in user and merge any anonymous pre-login history onto
17
- * them. `properties` is passed straight through (callers set `$set` /
18
- * `$set_once`). Opt-out gated and fully wrapped.
19
- */
20
- export declare function identifyUser(handle: string, properties: Record<string, unknown>): Promise<void>;
21
- /** Report an unhandled error to PostHog. Opt-out gated and wrapped. */
22
- export declare function captureException(error: unknown, distinctId?: string): Promise<void>;
23
- /**
24
- * Final drain before the process exits. No-op if telemetry never initialized.
25
- * Uses flush(), not shutdown(): shutdown() routes a failed flush to a hardcoded
26
- * console.error (a network stack trace in the user's terminal), whereas flush()
27
- * rejects into our own catch and stays silent. There are no background timers to
28
- * clear (flushInterval is 0), so flush() is a complete drain here.
29
- */
30
- export declare function shutdownTelemetry(): Promise<void>;
31
- /**
32
- * One-time, one-line notice that the CLI collects anonymous usage, with the
33
- * opt-out. Interactive only (never in pipes / CI / the quiet daily run), shown
34
- * once per machine (flagged in telemetry.json). Mirrors the update-check nudge:
35
- * stderr, TTY-gated, and wrapped so it can never break or delay a command.
36
- */
37
- export declare function maybePrintTelemetryNotice(): Promise<void>;
38
- //# sourceMappingURL=posthog.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"posthog.d.ts","sourceRoot":"","sources":["../src/posthog.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAI7C;AAgGD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,MAAM,EACb,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,uEAAuE;AACvE,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAOvD;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmB/D"}
package/dist/posthog.js DELETED
@@ -1,224 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { promises as fs } from 'node:fs';
3
- import { createRequire } from 'node:module';
4
- import { dirname, join } from 'node:path';
5
- import { PostHog } from 'posthog-node';
6
- import { envNameForUrl, getSessionPath, resolveAppUrl } from './session.js';
7
- import { dim } from './ui.js';
8
- // Single source of the published version (one level up from this module in both
9
- // `dist/` and `src/`), tagged onto every event so we can slice by CLI version.
10
- const require = createRequire(import.meta.url);
11
- const { version: CLI_VERSION } = require('../package.json');
12
- // The PostHog *project* API key for the CLI's own project (id 226792, separate
13
- // from the web app's project 226288). It's a publishable client key (phc_…,
14
- // write-only) that ships inside the published npm package regardless, so
15
- // committing it here is fine. `POSTHOG_API_KEY` overrides it for dev/testing.
16
- // The CLI never reads Vercel env (it runs on users' machines), so its key lives
17
- // here, not in Vercel.
18
- const PROJECT_API_KEY = process.env.POSTHOG_API_KEY ??
19
- 'phc_oCCCCjjTXkmknHh5gjEhsqJNuJ77BqsZUU96MRtAHoYQ';
20
- const HOST = process.env.POSTHOG_HOST ?? 'https://eu.i.posthog.com';
21
- // Telemetry state (anon id + one-time-notice flag) lives next to the session
22
- // file, so it honors HACKLAB_SESSION_PATH exactly like the update-check cache.
23
- function telemetryPath() {
24
- return join(dirname(getSessionPath()), 'telemetry.json');
25
- }
26
- /**
27
- * Telemetry is opt-OUT. It's off when the user sets `HACKLAB_NO_TELEMETRY`
28
- * (mirrors `HACKLAB_NO_UPDATE_CHECK`) or the cross-tool `DO_NOT_TRACK` standard
29
- * (https://consoledonottrack.com). Checked at every entry point, so a disabled
30
- * CLI never constructs a client, phones home, or installs exception handlers.
31
- */
32
- export function isTelemetryDisabled() {
33
- if (process.env.HACKLAB_NO_TELEMETRY)
34
- return true;
35
- const dnt = process.env.DO_NOT_TRACK;
36
- return dnt === '1' || dnt === 'true';
37
- }
38
- async function readState() {
39
- try {
40
- return JSON.parse(await fs.readFile(telemetryPath(), 'utf8'));
41
- }
42
- catch {
43
- return {};
44
- }
45
- }
46
- async function writeState(state) {
47
- try {
48
- await fs.mkdir(dirname(telemetryPath()), { recursive: true });
49
- await fs.writeFile(telemetryPath(), `${JSON.stringify(state, null, 2)}\n`, 'utf8');
50
- }
51
- catch {
52
- // Best-effort: a failed write just means a fresh anon id / re-shown notice.
53
- }
54
- }
55
- /**
56
- * A stable anonymous device id for events that fire before (or without) login.
57
- * Generated once and persisted; on login we `alias` it to the real handle so
58
- * PostHog stitches the anonymous history onto the identified user.
59
- */
60
- async function getAnonymousId() {
61
- const state = await readState();
62
- if (state.anonymousId)
63
- return state.anonymousId;
64
- const anonymousId = `anon_${randomUUID()}`;
65
- await writeState({ ...state, anonymousId });
66
- return anonymousId;
67
- }
68
- let client = null;
69
- function getClient() {
70
- if (!client) {
71
- client = new PostHog(PROJECT_API_KEY, {
72
- host: HOST,
73
- // We flush explicitly after every capture (and on shutdown), so disable
74
- // both of posthog-node's background-flush triggers: the count trigger
75
- // (flushAt — set high enough that a single CLI run never hits it) and the
76
- // timer (flushInterval: 0). This matters because a background flush routes
77
- // its failure to a hardcoded console.error we can't intercept — it would
78
- // dump a network stack trace into the user's terminal on a flaky
79
- // connection. Our explicit flush rejects into our own try/catch instead,
80
- // so a telemetry failure stays silent.
81
- flushAt: 1000,
82
- flushInterval: 0,
83
- // Best-effort telemetry: don't retry a failed send. The default is 3
84
- // retries with a 3s backoff, and that backoff timer is what keeps a
85
- // one-shot CLI alive for ~10s after the command visibly finished when the
86
- // network is down. No retries → fail fast → the process exits promptly.
87
- fetchRetryCount: 0,
88
- // Tighter than the 10s default so a black-holed connection gives up fast.
89
- requestTimeout: 3000,
90
- enableExceptionAutocapture: true,
91
- });
92
- }
93
- return client;
94
- }
95
- /**
96
- * Properties attached to every CLI event. CLI and web now live in separate
97
- * PostHog projects, but we still tag `source: 'cli'` as a cheap, explicit
98
- * discriminator — handy if the two datasets are ever combined, and it costs
99
- * nothing to keep.
100
- */
101
- function defaultProperties() {
102
- return {
103
- source: 'cli',
104
- cli_version: CLI_VERSION,
105
- os: process.platform,
106
- arch: process.arch,
107
- node_version: process.versions.node,
108
- environment: envNameForUrl(resolveAppUrl()) ?? 'unknown',
109
- };
110
- }
111
- // Never let a stuck network hold up the CLI: cap any send at a couple seconds
112
- // and move on. The timer is unref'd so it can't by itself keep the process
113
- // alive after the real work is done.
114
- async function withTimeout(p, ms = 2000) {
115
- await Promise.race([
116
- p.catch(() => undefined),
117
- new Promise((resolve) => {
118
- const t = setTimeout(resolve, ms);
119
- t.unref?.();
120
- }),
121
- ]);
122
- }
123
- /**
124
- * Capture an event and flush it. Falls back to the anonymous device id when no
125
- * handle is given, so pre-auth usage is still counted (and later stitched onto
126
- * the user via `identifyUser`). Fire-and-forget: gated on opt-out, wrapped so it
127
- * can never slow down or break the command that called it.
128
- */
129
- export async function captureEvent(distinctId, event, properties) {
130
- if (isTelemetryDisabled())
131
- return;
132
- try {
133
- const id = distinctId ?? (await getAnonymousId());
134
- const ph = getClient();
135
- ph.capture({
136
- distinctId: id,
137
- event,
138
- properties: { ...defaultProperties(), ...properties },
139
- });
140
- await withTimeout(ph.flush());
141
- }
142
- catch {
143
- // Telemetry must never break a command. Swallow everything.
144
- }
145
- }
146
- /**
147
- * Identify the logged-in user and merge any anonymous pre-login history onto
148
- * them. `properties` is passed straight through (callers set `$set` /
149
- * `$set_once`). Opt-out gated and fully wrapped.
150
- */
151
- export async function identifyUser(handle, properties) {
152
- if (isTelemetryDisabled())
153
- return;
154
- try {
155
- const ph = getClient();
156
- const { anonymousId } = await readState();
157
- if (anonymousId && anonymousId !== handle) {
158
- ph.alias({ distinctId: handle, alias: anonymousId });
159
- }
160
- ph.identify({ distinctId: handle, properties });
161
- await withTimeout(ph.flush());
162
- }
163
- catch {
164
- // Identification is best-effort — never break login over it.
165
- }
166
- }
167
- /** Report an unhandled error to PostHog. Opt-out gated and wrapped. */
168
- export async function captureException(error, distinctId) {
169
- if (isTelemetryDisabled())
170
- return;
171
- try {
172
- const ph = getClient();
173
- const id = distinctId ?? (await getAnonymousId());
174
- ph.captureException(error, id, defaultProperties());
175
- await withTimeout(ph.flush());
176
- }
177
- catch {
178
- // Swallow — a telemetry failure must not mask the original error.
179
- }
180
- }
181
- /**
182
- * Final drain before the process exits. No-op if telemetry never initialized.
183
- * Uses flush(), not shutdown(): shutdown() routes a failed flush to a hardcoded
184
- * console.error (a network stack trace in the user's terminal), whereas flush()
185
- * rejects into our own catch and stays silent. There are no background timers to
186
- * clear (flushInterval is 0), so flush() is a complete drain here.
187
- */
188
- export async function shutdownTelemetry() {
189
- if (!client)
190
- return;
191
- try {
192
- await withTimeout(client.flush());
193
- }
194
- catch {
195
- // Best-effort final flush.
196
- }
197
- }
198
- /**
199
- * One-time, one-line notice that the CLI collects anonymous usage, with the
200
- * opt-out. Interactive only (never in pipes / CI / the quiet daily run), shown
201
- * once per machine (flagged in telemetry.json). Mirrors the update-check nudge:
202
- * stderr, TTY-gated, and wrapped so it can never break or delay a command.
203
- */
204
- export async function maybePrintTelemetryNotice() {
205
- try {
206
- if (isTelemetryDisabled())
207
- return;
208
- if (!process.stdout.isTTY)
209
- return;
210
- const state = await readState();
211
- if (state.noticeShownAt)
212
- return;
213
- await writeState({
214
- ...state,
215
- anonymousId: state.anonymousId ?? `anon_${randomUUID()}`,
216
- noticeShownAt: new Date().toISOString(),
217
- });
218
- process.stderr.write(`${dim('hacklab collects anonymous usage analytics to improve the CLI — opt out with HACKLAB_NO_TELEMETRY=1 (or DO_NOT_TRACK=1).')}\n`);
219
- }
220
- catch {
221
- // A notice must never break or delay the actual command.
222
- }
223
- }
224
- //# sourceMappingURL=posthog.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"posthog.js","sourceRoot":"","sources":["../src/posthog.ts"],"names":[],"mappings":"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"}
@@ -1,40 +0,0 @@
1
- export type RepoRemote = {
2
- /** Canonical https URL, no trailing `.git`. */
3
- url: string;
4
- /** `owner/name` host path when it parses, e.g. `acme/hacklab`. */
5
- owner: string | null;
6
- name: string;
7
- };
8
- export type ProjectFields = {
9
- slug: string;
10
- title: string;
11
- description: string | null;
12
- tags: string[];
13
- repoUrl: string | null;
14
- liveUrl: string | null;
15
- /** Repo was private/inaccessible at add time; web hides its link + stats. */
16
- private: boolean;
17
- /** Long-form markdown, the project page's content. */
18
- content: string | null;
19
- };
20
- /** True when `url` points at a github.com repo — decides repoUrl vs liveUrl. */
21
- export declare function isGithubRepoUrl(url: string): boolean;
22
- /**
23
- * Best-effort visibility check for a github.com repo. An unauthenticated GET
24
- * returns 200 for a public repo and 404 for a private (or missing) one — GitHub
25
- * hides a private repo's existence. Returns true only on a definitive 404.
26
- * Fails open to `false` on any network error/timeout or non-github URL: a dead
27
- * link to a private repo is harmless, but false-hiding a public project is not.
28
- * Our OAuth is identity-only (no repo scope), so this probe stays unauthenticated.
29
- */
30
- export declare function probeRepoPrivate(repoUrl: string | null | undefined): Promise<boolean>;
31
- /**
32
- * Normalize any common git remote spelling to a canonical https URL.
33
- * `git@github.com:acme/hacklab.git`, `ssh://git@github.com/acme/hacklab.git`,
34
- * and `https://github.com/acme/hacklab.git` all become
35
- * `https://github.com/acme/hacklab`.
36
- */
37
- export declare function normalizeRepoUrl(remote: string): RepoRemote | null;
38
- /** Name-derived slug matching the server's PROJECT_SLUG_PATTERN. */
39
- export declare function slugFromName(name: string): string;
40
- //# sourceMappingURL=project-fields.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-fields.d.ts","sourceRoot":"","sources":["../src/project-fields.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG;IACvB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAA;IACX,kEAAkE;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAA;IAChB,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB,CAAA;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOpD;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACjC,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAwBlE;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASjD"}
@@ -1,79 +0,0 @@
1
- // Pure helpers shared by the `hacklab project` command: repo-URL
2
- // normalization, slug derivation, and the GitHub privacy probe. Everything
3
- // here is best-effort and offline except `probeRepoPrivate`, which owns the
4
- // one network call.
5
- /** True when `url` points at a github.com repo — decides repoUrl vs liveUrl. */
6
- export function isGithubRepoUrl(url) {
7
- try {
8
- const host = new URL(url).host.toLowerCase();
9
- return host === 'github.com' || host === 'www.github.com';
10
- }
11
- catch {
12
- return false;
13
- }
14
- }
15
- /**
16
- * Best-effort visibility check for a github.com repo. An unauthenticated GET
17
- * returns 200 for a public repo and 404 for a private (or missing) one — GitHub
18
- * hides a private repo's existence. Returns true only on a definitive 404.
19
- * Fails open to `false` on any network error/timeout or non-github URL: a dead
20
- * link to a private repo is harmless, but false-hiding a public project is not.
21
- * Our OAuth is identity-only (no repo scope), so this probe stays unauthenticated.
22
- */
23
- export async function probeRepoPrivate(repoUrl) {
24
- if (!repoUrl || !isGithubRepoUrl(repoUrl))
25
- return false;
26
- try {
27
- const res = await fetch(repoUrl, {
28
- method: 'HEAD',
29
- redirect: 'follow',
30
- signal: AbortSignal.timeout(6000),
31
- headers: { 'User-Agent': 'HacklabCLI (+https://hacklab.so)' },
32
- });
33
- return res.status === 404;
34
- }
35
- catch {
36
- return false;
37
- }
38
- }
39
- /**
40
- * Normalize any common git remote spelling to a canonical https URL.
41
- * `git@github.com:acme/hacklab.git`, `ssh://git@github.com/acme/hacklab.git`,
42
- * and `https://github.com/acme/hacklab.git` all become
43
- * `https://github.com/acme/hacklab`.
44
- */
45
- export function normalizeRepoUrl(remote) {
46
- const trimmed = remote.trim();
47
- if (!trimmed)
48
- return null;
49
- const scp = trimmed.match(/^(?:[\w.-]+@)?([\w.-]+):(?!\/\/)(.+)$/);
50
- const url = trimmed.match(/^(?:https?|ssh|git):\/\/(?:[\w.-]+@)?([\w.-]+)(?::\d+)?\/(.+)$/);
51
- const host = url?.[1] ?? scp?.[1];
52
- let path = url?.[2] ?? scp?.[2];
53
- if (!host || !path)
54
- return null;
55
- path = path.replace(/\.git$/i, '').replace(/\/+$/, '');
56
- if (!path)
57
- return null;
58
- const segments = path.split('/');
59
- const name = segments.at(-1);
60
- if (!name)
61
- return null;
62
- return {
63
- url: `https://${host}/${path}`,
64
- owner: segments.at(-2) ?? null,
65
- name,
66
- };
67
- }
68
- /** Name-derived slug matching the server's PROJECT_SLUG_PATTERN. */
69
- export function slugFromName(name) {
70
- const slug = name
71
- .trim()
72
- .toLowerCase()
73
- .replace(/[^a-z0-9]+/g, '-')
74
- .replace(/^-+|-+$/g, '')
75
- .slice(0, 100)
76
- .replace(/-+$/, '');
77
- return slug || 'project';
78
- }
79
- //# sourceMappingURL=project-fields.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-fields.js","sourceRoot":"","sources":["../src/project-fields.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,2EAA2E;AAC3E,4EAA4E;AAC5E,oBAAoB;AAuBpB,gFAAgF;AAChF,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAA;QAC5C,OAAO,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,gBAAgB,CAAA;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAkC;IAElC,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE;YAC/B,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;YACjC,OAAO,EAAE,EAAE,YAAY,EAAE,kCAAkC,EAAE;SAC9D,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,MAAM,KAAK,GAAG,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAA;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAA;IAClE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CACvB,gEAAgE,CACjE,CAAA;IACD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IACjC,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAE/B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IACtD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5B,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IAEtB,OAAO;QACL,GAAG,EAAE,WAAW,IAAI,IAAI,IAAI,EAAE;QAC9B,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI;QAC9B,IAAI;KACL,CAAA;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,IAAI,GAAG,IAAI;SACd,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;SACb,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACrB,OAAO,IAAI,IAAI,SAAS,CAAA;AAC1B,CAAC"}