@seliseblocks/cli-os 0.1.3 → 0.1.5

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 (391) hide show
  1. package/AI_USAGE_GUIDE.md +328 -58
  2. package/README.md +83 -46
  3. package/dist/commands/auth/client-credentials/delete.d.ts +1 -0
  4. package/dist/commands/auth/client-credentials/delete.js +23 -0
  5. package/dist/commands/auth/client-credentials/list.d.ts +1 -0
  6. package/dist/commands/auth/client-credentials/list.js +14 -0
  7. package/dist/commands/auth/client-credentials/save.d.ts +1 -0
  8. package/dist/commands/auth/client-credentials/save.js +41 -0
  9. package/dist/commands/auth/config/get.d.ts +1 -0
  10. package/dist/commands/auth/config/get.js +14 -0
  11. package/dist/commands/auth/config/save.d.ts +1 -0
  12. package/dist/commands/auth/config/save.js +37 -0
  13. package/dist/commands/auth/idp/create.d.ts +1 -0
  14. package/dist/commands/auth/idp/create.js +46 -0
  15. package/dist/commands/auth/idp/delete.d.ts +1 -0
  16. package/dist/commands/auth/idp/delete.js +23 -0
  17. package/dist/commands/auth/idp/get.d.ts +1 -0
  18. package/dist/commands/auth/idp/get.js +16 -0
  19. package/dist/commands/auth/idp/list.d.ts +1 -0
  20. package/dist/commands/auth/idp/list.js +14 -0
  21. package/dist/commands/auth/idp/status.d.ts +1 -0
  22. package/dist/commands/auth/idp/status.js +27 -0
  23. package/dist/commands/auth/idp/update.d.ts +7 -0
  24. package/dist/commands/auth/idp/update.js +45 -0
  25. package/dist/commands/auth/oidc-clients/delete.d.ts +1 -0
  26. package/dist/commands/auth/oidc-clients/delete.js +23 -0
  27. package/dist/commands/auth/oidc-clients/get.d.ts +1 -0
  28. package/dist/commands/auth/oidc-clients/get.js +16 -0
  29. package/dist/commands/auth/oidc-clients/list.d.ts +1 -0
  30. package/dist/commands/auth/oidc-clients/list.js +14 -0
  31. package/dist/commands/auth/oidc-clients/rotate-secret.d.ts +1 -0
  32. package/dist/commands/auth/oidc-clients/rotate-secret.js +23 -0
  33. package/dist/commands/auth/oidc-clients/save.d.ts +2 -0
  34. package/dist/commands/auth/oidc-clients/save.js +57 -0
  35. package/dist/commands/auth/refresh.js +1 -1
  36. package/dist/commands/data/config/create.d.ts +1 -0
  37. package/dist/commands/data/config/create.js +38 -0
  38. package/dist/commands/data/config/get.d.ts +1 -0
  39. package/dist/commands/data/config/get.js +14 -0
  40. package/dist/commands/data/config/update.d.ts +1 -0
  41. package/dist/commands/data/config/update.js +41 -0
  42. package/dist/commands/data/files/create-folder.d.ts +1 -0
  43. package/dist/commands/data/files/create-folder.js +34 -0
  44. package/dist/commands/data/files/delete-folder.d.ts +1 -0
  45. package/dist/commands/data/files/delete-folder.js +25 -0
  46. package/dist/commands/data/files/delete.d.ts +1 -0
  47. package/dist/commands/data/files/delete.js +28 -0
  48. package/dist/commands/data/files/dms-list.d.ts +1 -0
  49. package/dist/commands/data/files/dms-list.js +27 -0
  50. package/dist/commands/data/files/dms-upload.d.ts +6 -0
  51. package/dist/commands/data/files/dms-upload.js +41 -0
  52. package/dist/commands/data/files/get-many.d.ts +1 -0
  53. package/dist/commands/data/files/get-many.js +24 -0
  54. package/dist/commands/data/files/get.d.ts +1 -0
  55. package/dist/commands/data/files/get.js +21 -0
  56. package/dist/commands/data/files/info.d.ts +1 -0
  57. package/dist/commands/data/files/info.js +30 -0
  58. package/dist/commands/data/files/presigned-upload-url.d.ts +6 -0
  59. package/dist/commands/data/files/presigned-upload-url.js +34 -0
  60. package/dist/commands/data/files/update-additional-info.d.ts +1 -0
  61. package/dist/commands/data/files/update-additional-info.js +26 -0
  62. package/dist/commands/data/files/upload-to-local-storage.d.ts +5 -0
  63. package/dist/commands/data/files/upload-to-local-storage.js +55 -0
  64. package/dist/commands/data/files/upload-to-url.d.ts +8 -0
  65. package/dist/commands/data/files/upload-to-url.js +36 -0
  66. package/dist/commands/data/files/upload.d.ts +7 -0
  67. package/dist/commands/data/files/upload.js +145 -0
  68. package/dist/commands/data/rules/policy/delete.d.ts +1 -0
  69. package/dist/commands/data/rules/policy/delete.js +24 -0
  70. package/dist/commands/data/rules/policy/get.d.ts +1 -0
  71. package/dist/commands/data/rules/policy/get.js +17 -0
  72. package/dist/commands/data/schema/aggregation.d.ts +1 -0
  73. package/dist/commands/data/schema/aggregation.js +26 -0
  74. package/dist/commands/data/schema/change-logs.d.ts +1 -0
  75. package/dist/commands/data/schema/change-logs.js +14 -0
  76. package/dist/commands/data/schema/delete.d.ts +1 -0
  77. package/dist/commands/data/schema/delete.js +24 -0
  78. package/dist/commands/data/schema/fields.d.ts +5 -0
  79. package/dist/commands/data/schema/fields.js +39 -0
  80. package/dist/commands/data/schema/get-by-name.d.ts +1 -0
  81. package/dist/commands/data/schema/get-by-name.js +17 -0
  82. package/dist/commands/data/schema/get.d.ts +1 -0
  83. package/dist/commands/data/schema/get.js +17 -0
  84. package/dist/commands/data/schema/info/list.d.ts +1 -0
  85. package/dist/commands/data/schema/info/list.js +15 -0
  86. package/dist/commands/data/schema/info/save.d.ts +1 -0
  87. package/dist/commands/data/schema/info/save.js +34 -0
  88. package/dist/commands/data/schema/info/update.d.ts +1 -0
  89. package/dist/commands/data/schema/info/update.js +35 -0
  90. package/dist/commands/data/sync.d.ts +7 -0
  91. package/dist/commands/data/sync.js +46 -0
  92. package/dist/commands/data/validation/by-schema-field.d.ts +1 -0
  93. package/dist/commands/data/validation/by-schema-field.js +18 -0
  94. package/dist/commands/data/validation/by-schema.d.ts +1 -0
  95. package/dist/commands/data/validation/by-schema.js +17 -0
  96. package/dist/commands/data/validation/delete.d.ts +1 -0
  97. package/dist/commands/data/validation/delete.js +24 -0
  98. package/dist/commands/data/validation/get.d.ts +1 -0
  99. package/dist/commands/data/validation/get.js +17 -0
  100. package/dist/commands/data/validation/list.d.ts +1 -0
  101. package/dist/commands/data/validation/list.js +25 -0
  102. package/dist/commands/data/validation/save.d.ts +6 -0
  103. package/dist/commands/data/validation/save.js +44 -0
  104. package/dist/commands/deselect.d.ts +1 -0
  105. package/dist/commands/deselect.js +31 -0
  106. package/dist/commands/iam/email/available.d.ts +1 -0
  107. package/dist/commands/iam/email/available.js +17 -0
  108. package/dist/commands/iam/organizations/config-get.d.ts +1 -0
  109. package/dist/commands/iam/organizations/config-get.js +14 -0
  110. package/dist/commands/iam/organizations/config-save.d.ts +1 -0
  111. package/dist/commands/iam/organizations/config-save.js +34 -0
  112. package/dist/commands/iam/organizations/create.d.ts +1 -0
  113. package/dist/commands/iam/organizations/create.js +37 -0
  114. package/dist/commands/iam/organizations/get.d.ts +1 -0
  115. package/dist/commands/iam/organizations/get.js +16 -0
  116. package/dist/commands/iam/organizations/list.d.ts +1 -0
  117. package/dist/commands/iam/organizations/list.js +26 -0
  118. package/dist/commands/iam/organizations/my.d.ts +1 -0
  119. package/dist/commands/iam/organizations/my.js +14 -0
  120. package/dist/commands/iam/organizations/update.d.ts +1 -0
  121. package/dist/commands/iam/organizations/update.js +39 -0
  122. package/dist/commands/iam/permissions/by-severity.d.ts +1 -0
  123. package/dist/commands/iam/permissions/by-severity.js +14 -0
  124. package/dist/commands/iam/permissions/create.d.ts +1 -0
  125. package/dist/commands/iam/permissions/create.js +39 -0
  126. package/dist/commands/iam/permissions/get.d.ts +1 -0
  127. package/dist/commands/iam/permissions/get.js +16 -0
  128. package/dist/commands/iam/permissions/list.d.ts +1 -0
  129. package/dist/commands/iam/permissions/list.js +41 -0
  130. package/dist/commands/iam/permissions/update.d.ts +1 -0
  131. package/dist/commands/iam/permissions/update.js +40 -0
  132. package/dist/commands/iam/resources/features.d.ts +1 -0
  133. package/dist/commands/iam/resources/features.js +19 -0
  134. package/dist/commands/iam/resources/groups.d.ts +1 -0
  135. package/dist/commands/iam/resources/groups.js +14 -0
  136. package/dist/commands/iam/roles/assign-permissions.d.ts +1 -0
  137. package/dist/commands/iam/roles/assign-permissions.js +33 -0
  138. package/dist/commands/iam/roles/assignable.d.ts +1 -0
  139. package/dist/commands/iam/roles/assignable.js +14 -0
  140. package/dist/commands/iam/roles/create.d.ts +1 -0
  141. package/dist/commands/iam/roles/create.js +35 -0
  142. package/dist/commands/iam/roles/get.d.ts +1 -0
  143. package/dist/commands/iam/roles/get.js +16 -0
  144. package/dist/commands/iam/roles/list.d.ts +1 -0
  145. package/dist/commands/iam/roles/list.js +34 -0
  146. package/dist/commands/iam/roles/update.d.ts +1 -0
  147. package/dist/commands/iam/roles/update.js +35 -0
  148. package/dist/commands/iam/signup-settings/get.d.ts +1 -0
  149. package/dist/commands/iam/signup-settings/get.js +14 -0
  150. package/dist/commands/iam/signup-settings/save.d.ts +1 -0
  151. package/dist/commands/iam/signup-settings/save.js +32 -0
  152. package/dist/commands/iam/users/access-grant.d.ts +1 -0
  153. package/dist/commands/iam/users/access-grant.js +32 -0
  154. package/dist/commands/iam/users/access-revoke.d.ts +1 -0
  155. package/dist/commands/iam/users/access-revoke.js +24 -0
  156. package/dist/commands/iam/users/activate.d.ts +1 -0
  157. package/dist/commands/iam/users/activate.js +24 -0
  158. package/dist/commands/iam/users/create.d.ts +1 -0
  159. package/dist/commands/iam/users/create.js +39 -0
  160. package/dist/commands/iam/users/deactivate.d.ts +1 -0
  161. package/dist/commands/iam/users/deactivate.js +24 -0
  162. package/dist/commands/iam/users/exists.d.ts +1 -0
  163. package/dist/commands/iam/users/exists.js +17 -0
  164. package/dist/commands/iam/users/get.d.ts +1 -0
  165. package/dist/commands/iam/users/get.js +17 -0
  166. package/dist/commands/iam/users/list.d.ts +1 -0
  167. package/dist/commands/iam/users/list.js +34 -0
  168. package/dist/commands/iam/users/update.d.ts +1 -0
  169. package/dist/commands/iam/users/update.js +35 -0
  170. package/dist/commands/init.js +0 -12
  171. package/dist/commands/localization/assistant/translation-suggestion.d.ts +1 -0
  172. package/dist/commands/localization/assistant/translation-suggestion.js +35 -0
  173. package/dist/commands/localization/config/get-webhook.d.ts +1 -0
  174. package/dist/commands/localization/config/get-webhook.js +14 -0
  175. package/dist/commands/localization/config/save-webhook.d.ts +1 -0
  176. package/dist/commands/localization/config/save-webhook.js +47 -0
  177. package/dist/commands/localization/glossary/delete.d.ts +1 -0
  178. package/dist/commands/localization/glossary/delete.js +24 -0
  179. package/dist/commands/localization/glossary/get.d.ts +1 -0
  180. package/dist/commands/localization/glossary/get.js +17 -0
  181. package/dist/commands/localization/glossary/list.d.ts +1 -0
  182. package/dist/commands/localization/glossary/list.js +22 -0
  183. package/dist/commands/localization/glossary/save.d.ts +1 -0
  184. package/dist/commands/localization/glossary/save.js +38 -0
  185. package/dist/commands/localization/glossary/suggested.d.ts +1 -0
  186. package/dist/commands/localization/glossary/suggested.js +20 -0
  187. package/dist/commands/localization/key/delete-keys.d.ts +1 -0
  188. package/dist/commands/localization/key/delete-keys.js +28 -0
  189. package/dist/commands/localization/key/delete.d.ts +1 -0
  190. package/dist/commands/localization/key/delete.js +24 -0
  191. package/dist/commands/localization/key/generate-uilm-file.d.ts +1 -0
  192. package/dist/commands/localization/key/generate-uilm-file.js +29 -0
  193. package/dist/commands/localization/key/get-by-names.d.ts +1 -0
  194. package/dist/commands/localization/key/get-by-names.js +24 -0
  195. package/dist/commands/localization/key/get-language-file-generation-history.d.ts +1 -0
  196. package/dist/commands/localization/key/get-language-file-generation-history.js +19 -0
  197. package/dist/commands/localization/key/get-localization-timeline.d.ts +1 -0
  198. package/dist/commands/localization/key/get-localization-timeline.js +28 -0
  199. package/dist/commands/localization/key/get-timeline-by-operation-id.d.ts +1 -0
  200. package/dist/commands/localization/key/get-timeline-by-operation-id.js +21 -0
  201. package/dist/commands/localization/key/get-timeline.d.ts +1 -0
  202. package/dist/commands/localization/key/get-timeline.js +25 -0
  203. package/dist/commands/localization/key/get-uilm-exported-files.d.ts +1 -0
  204. package/dist/commands/localization/key/get-uilm-exported-files.js +22 -0
  205. package/dist/commands/localization/key/get-uilm-file.d.ts +1 -0
  206. package/dist/commands/localization/key/get-uilm-file.js +18 -0
  207. package/dist/commands/localization/key/get.d.ts +1 -0
  208. package/dist/commands/localization/key/get.js +17 -0
  209. package/dist/commands/localization/key/list.d.ts +1 -0
  210. package/dist/commands/localization/key/list.js +39 -0
  211. package/dist/commands/localization/key/rollback.d.ts +1 -0
  212. package/dist/commands/localization/key/rollback.js +24 -0
  213. package/dist/commands/localization/key/save.d.ts +1 -0
  214. package/dist/commands/localization/key/save.js +44 -0
  215. package/dist/commands/localization/key/translate-all.d.ts +1 -0
  216. package/dist/commands/localization/key/translate-all.js +30 -0
  217. package/dist/commands/localization/key/translate-and-export.d.ts +7 -0
  218. package/dist/commands/localization/key/translate-and-export.js +132 -0
  219. package/dist/commands/localization/key/translate-key.d.ts +1 -0
  220. package/dist/commands/localization/key/translate-key.js +27 -0
  221. package/dist/commands/localization/key/translate-keys.d.ts +1 -0
  222. package/dist/commands/localization/key/translate-keys.js +31 -0
  223. package/dist/commands/localization/key/uilm-export.d.ts +1 -0
  224. package/dist/commands/localization/key/uilm-export.js +33 -0
  225. package/dist/commands/localization/key/uilm-import.d.ts +1 -0
  226. package/dist/commands/localization/key/uilm-import.js +26 -0
  227. package/dist/commands/localization/language/delete.d.ts +1 -0
  228. package/dist/commands/localization/language/delete.js +24 -0
  229. package/dist/commands/localization/language/list-for-tenant.d.ts +1 -0
  230. package/dist/commands/localization/language/list-for-tenant.js +14 -0
  231. package/dist/commands/localization/language/list.d.ts +1 -0
  232. package/dist/commands/localization/language/list.js +14 -0
  233. package/dist/commands/localization/language/save.d.ts +1 -0
  234. package/dist/commands/localization/language/save.js +36 -0
  235. package/dist/commands/localization/language/set-default.d.ts +1 -0
  236. package/dist/commands/localization/language/set-default.js +24 -0
  237. package/dist/commands/localization/module/list-for-tenant.d.ts +1 -0
  238. package/dist/commands/localization/module/list-for-tenant.js +14 -0
  239. package/dist/commands/localization/module/list.d.ts +1 -0
  240. package/dist/commands/localization/module/list.js +14 -0
  241. package/dist/commands/localization/module/save.d.ts +1 -0
  242. package/dist/commands/localization/module/save.js +32 -0
  243. package/dist/commands/localization/module/tag-glossary.d.ts +1 -0
  244. package/dist/commands/localization/module/tag-glossary.js +28 -0
  245. package/dist/commands/mail/config/delete.d.ts +1 -0
  246. package/dist/commands/mail/config/delete.js +24 -0
  247. package/dist/commands/mail/config/duplicate.d.ts +1 -0
  248. package/dist/commands/mail/config/duplicate.js +24 -0
  249. package/dist/commands/mail/config/get.d.ts +1 -0
  250. package/dist/commands/mail/config/get.js +17 -0
  251. package/dist/commands/mail/config/list.d.ts +1 -0
  252. package/dist/commands/mail/config/list.js +14 -0
  253. package/dist/commands/mail/config/save.d.ts +1 -0
  254. package/dist/commands/mail/config/save.js +44 -0
  255. package/dist/commands/mail/mailbox/get.d.ts +1 -0
  256. package/dist/commands/mail/mailbox/get.js +17 -0
  257. package/dist/commands/mail/mailbox/list.d.ts +1 -0
  258. package/dist/commands/mail/mailbox/list.js +24 -0
  259. package/dist/commands/mail/send.d.ts +1 -0
  260. package/dist/commands/mail/send.js +40 -0
  261. package/dist/commands/mail/sendtoany.d.ts +1 -0
  262. package/dist/commands/mail/sendtoany.js +41 -0
  263. package/dist/commands/mail/template/clone.d.ts +1 -0
  264. package/dist/commands/mail/template/clone.js +33 -0
  265. package/dist/commands/mail/template/delete.d.ts +1 -0
  266. package/dist/commands/mail/template/delete.js +24 -0
  267. package/dist/commands/mail/template/get.d.ts +1 -0
  268. package/dist/commands/mail/template/get.js +17 -0
  269. package/dist/commands/mail/template/list.d.ts +1 -0
  270. package/dist/commands/mail/template/list.js +24 -0
  271. package/dist/commands/mail/template/save.d.ts +1 -0
  272. package/dist/commands/mail/template/save.js +37 -0
  273. package/dist/commands/mfa/backup-codes/generate.d.ts +1 -0
  274. package/dist/commands/mfa/backup-codes/generate.js +22 -0
  275. package/dist/commands/mfa/backup-codes/list.d.ts +1 -0
  276. package/dist/commands/mfa/backup-codes/list.js +14 -0
  277. package/dist/commands/mfa/backup-codes/use.d.ts +1 -0
  278. package/dist/commands/mfa/backup-codes/use.js +18 -0
  279. package/dist/commands/mfa/config-get.d.ts +1 -0
  280. package/dist/commands/mfa/config-get.js +14 -0
  281. package/dist/commands/mfa/config-save.d.ts +1 -0
  282. package/dist/commands/mfa/config-save.js +36 -0
  283. package/dist/commands/mfa/disable.d.ts +1 -0
  284. package/dist/commands/mfa/disable.js +22 -0
  285. package/dist/commands/mfa/generate.d.ts +1 -0
  286. package/dist/commands/mfa/generate.js +22 -0
  287. package/dist/commands/mfa/method-set.d.ts +1 -0
  288. package/dist/commands/mfa/method-set.js +20 -0
  289. package/dist/commands/mfa/resend.d.ts +1 -0
  290. package/dist/commands/mfa/resend.js +20 -0
  291. package/dist/commands/mfa/totp-enable.d.ts +10 -0
  292. package/dist/commands/mfa/totp-enable.js +52 -0
  293. package/dist/commands/mfa/totp-setup.d.ts +1 -0
  294. package/dist/commands/mfa/totp-setup.js +15 -0
  295. package/dist/commands/mfa/totp-verify-setup.d.ts +1 -0
  296. package/dist/commands/mfa/totp-verify-setup.js +17 -0
  297. package/dist/commands/mfa/verify.d.ts +1 -0
  298. package/dist/commands/mfa/verify.js +26 -0
  299. package/dist/commands/new/web.js +115 -15
  300. package/dist/commands/notification/delete.d.ts +1 -0
  301. package/dist/commands/notification/delete.js +24 -0
  302. package/dist/commands/notification/get.d.ts +1 -0
  303. package/dist/commands/notification/get.js +17 -0
  304. package/dist/commands/notification/list.d.ts +1 -0
  305. package/dist/commands/notification/list.js +22 -0
  306. package/dist/commands/notification/save.d.ts +1 -0
  307. package/dist/commands/notification/save.js +34 -0
  308. package/dist/commands/notifier/list.d.ts +1 -0
  309. package/dist/commands/notifier/list.js +23 -0
  310. package/dist/commands/notifier/mark-all-read.d.ts +1 -0
  311. package/dist/commands/notifier/mark-all-read.js +23 -0
  312. package/dist/commands/notifier/mark-read.d.ts +1 -0
  313. package/dist/commands/notifier/mark-read.js +24 -0
  314. package/dist/commands/notifier/notify.d.ts +1 -0
  315. package/dist/commands/notifier/notify.js +39 -0
  316. package/dist/commands/notifier/unread.d.ts +1 -0
  317. package/dist/commands/notifier/unread.js +25 -0
  318. package/dist/commands/projects/get.js +16 -14
  319. package/dist/commands/projects/list.js +2 -7
  320. package/dist/commands/release/builds/list.js +22 -2
  321. package/dist/commands/release/deploy.js +122 -29
  322. package/dist/commands/release/status.js +4 -2
  323. package/dist/commands/sdk/client.d.ts +1 -0
  324. package/dist/commands/sdk/client.js +99 -0
  325. package/dist/commands/secrets/get.d.ts +1 -0
  326. package/dist/commands/secrets/get.js +21 -0
  327. package/dist/commands/secrets/save.d.ts +1 -0
  328. package/dist/commands/secrets/save.js +51 -0
  329. package/dist/commands/skill/add.d.ts +1 -0
  330. package/dist/commands/skill/add.js +19 -0
  331. package/dist/commands/skill/list.d.ts +1 -0
  332. package/dist/commands/skill/list.js +15 -0
  333. package/dist/commands/skill/show.d.ts +1 -0
  334. package/dist/commands/skill/show.js +15 -0
  335. package/dist/commands/storage/config/delete.d.ts +1 -0
  336. package/dist/commands/storage/config/delete.js +24 -0
  337. package/dist/commands/storage/config/get.d.ts +1 -0
  338. package/dist/commands/storage/config/get.js +17 -0
  339. package/dist/commands/storage/config/list.d.ts +1 -0
  340. package/dist/commands/storage/config/list.js +14 -0
  341. package/dist/commands/storage/config/save.d.ts +1 -0
  342. package/dist/commands/storage/config/save.js +49 -0
  343. package/dist/index.js +959 -143
  344. package/dist/lib/api.d.ts +1 -1
  345. package/dist/lib/api.js +39 -21
  346. package/dist/lib/args.d.ts +3 -0
  347. package/dist/lib/args.js +15 -0
  348. package/dist/lib/auth.d.ts +5 -2
  349. package/dist/lib/auth.js +23 -35
  350. package/dist/lib/config.js +7 -7
  351. package/dist/lib/json-flag.d.ts +17 -0
  352. package/dist/lib/json-flag.js +55 -0
  353. package/dist/lib/project-info.d.ts +33 -0
  354. package/dist/lib/project-info.js +39 -0
  355. package/dist/lib/prompt.d.ts +2 -0
  356. package/dist/lib/prompt.js +28 -0
  357. package/dist/lib/scaffold-web/dashboard.js +1 -1
  358. package/dist/lib/scaffold-web/root-files.js +1 -1
  359. package/dist/lib/secret-store.js +7 -7
  360. package/dist/lib/skills.d.ts +17 -0
  361. package/dist/lib/skills.js +69 -0
  362. package/dist/lib/token.d.ts +2 -0
  363. package/dist/lib/token.js +12 -0
  364. package/dist/lib/workspace.d.ts +1 -4
  365. package/dist/lib/workspace.js +18 -2
  366. package/dist/skills/blocks-data-gateway-configuration/SKILL.md +204 -0
  367. package/dist/skills/blocks-data-gateway-crud/SKILL.md +223 -0
  368. package/dist/skills/blocks-data-storage/SKILL.md +161 -0
  369. package/dist/skills/blocks-frontend-local-https/SKILL.md +100 -0
  370. package/dist/skills/blocks-iam-access-control/SKILL.md +49 -0
  371. package/dist/skills/blocks-iam-access-control/flows/feature-gating.md +38 -0
  372. package/dist/skills/blocks-iam-access-control/flows/manage-roles-permissions.md +109 -0
  373. package/dist/skills/blocks-iam-account/SKILL.md +169 -0
  374. package/dist/skills/blocks-iam-mfa/SKILL.md +124 -0
  375. package/dist/skills/blocks-iam-organizations/SKILL.md +43 -0
  376. package/dist/skills/blocks-iam-organizations/flows/admin-mutations.md +89 -0
  377. package/dist/skills/blocks-iam-organizations/flows/read-and-switch.md +57 -0
  378. package/dist/skills/blocks-iam-sso-oidc-configuration/SKILL.md +89 -0
  379. package/dist/skills/blocks-iam-sso-oidc-implementation/SKILL.md +80 -0
  380. package/dist/skills/blocks-iam-users/SKILL.md +131 -0
  381. package/dist/skills/blocks-localization-configuration/SKILL.md +149 -0
  382. package/dist/skills/blocks-localization-implementation/SKILL.md +63 -0
  383. package/dist/skills/blocks-mail/SKILL.md +95 -0
  384. package/dist/skills/blocks-notification/SKILL.md +69 -0
  385. package/dist/skills/blocks-notifier/SKILL.md +107 -0
  386. package/dist/skills/blocks-onboarding/SKILL.md +78 -0
  387. package/dist/skills/blocks-release-deployment/SKILL.md +81 -0
  388. package/dist/skills/blocks-secrets/SKILL.md +81 -0
  389. package/dist/skills/blocks-storage-configuration/SKILL.md +93 -0
  390. package/dist/skills/lint.mjs +168 -0
  391. package/package.json +4 -4
package/dist/lib/api.d.ts CHANGED
@@ -6,7 +6,7 @@ type RequestOptions = {
6
6
  impersonatedProjectAuth?: boolean;
7
7
  method?: string;
8
8
  projectTenantId?: string;
9
- query?: Record<string, string | number | boolean | undefined>;
9
+ query?: Record<string, string | number | boolean | string[] | undefined>;
10
10
  };
11
11
  export declare function blocksRequest<T>(path: string, options?: RequestOptions): Promise<T>;
12
12
  export {};
package/dist/lib/api.js CHANGED
@@ -6,31 +6,49 @@ export async function blocksRequest(path, options = {}) {
6
6
  const baseUrl = options.apiUrl ?? profile.apiUrl;
7
7
  const url = buildUrl(baseUrl, path);
8
8
  for (const [key, value] of Object.entries(options.query ?? {})) {
9
- if (value !== undefined)
10
- url.searchParams.set(key, String(value));
9
+ if (value === undefined)
10
+ continue;
11
+ if (Array.isArray(value)) {
12
+ for (const item of value)
13
+ url.searchParams.append(key, item);
14
+ continue;
15
+ }
16
+ url.searchParams.set(key, String(value));
11
17
  }
12
- const headers = {
18
+ const isFormData = options.body instanceof FormData;
19
+ const baseHeaders = {
13
20
  Accept: "application/json"
14
21
  };
15
- if (options.body !== undefined)
16
- headers["Content-Type"] = "application/json";
17
- if (options.accountAuth) {
18
- const account = await getAccountSession(options.accountName);
19
- headers.Authorization = `Bearer ${account.accessToken}`;
20
- headers["x-blocks-key"] = account.accountTenant;
21
- }
22
- if (options.impersonatedProjectAuth) {
23
- const project = await getImpersonatedProjectSession(options.accountName, options.projectTenantId);
24
- headers.Authorization = `Bearer ${project.accessToken}`;
25
- headers["x-blocks-key"] = project.accountTenant;
22
+ if (options.body !== undefined && !isFormData)
23
+ baseHeaders["Content-Type"] = "application/json";
24
+ const send = async (forceRefresh) => {
25
+ const headers = { ...baseHeaders };
26
+ if (options.accountAuth) {
27
+ const account = await getAccountSession(options.accountName, { forceRefresh });
28
+ headers.Authorization = `Bearer ${account.accessToken}`;
29
+ headers["x-blocks-key"] = account.accountTenant;
30
+ }
31
+ if (options.impersonatedProjectAuth) {
32
+ const project = await getImpersonatedProjectSession(options.accountName, options.projectTenantId, { forceRefresh });
33
+ headers.Authorization = `Bearer ${project.accessToken}`;
34
+ headers["x-blocks-key"] = project.accountTenant;
35
+ }
36
+ return fetch(url, {
37
+ body: options.body === undefined ? undefined : isFormData ? options.body : JSON.stringify(options.body),
38
+ headers,
39
+ method: options.method ?? (options.body === undefined ? "GET" : "POST")
40
+ }).catch((error) => {
41
+ throw new Error(`Blocks API request failed for ${url.origin}${url.pathname}: ${error.message}`);
42
+ });
43
+ };
44
+ let response = await send(false);
45
+ if (response.status === 401 && (options.accountAuth || options.impersonatedProjectAuth)) {
46
+ // The locally cached expiry said the token was still good, but the server
47
+ // rejected it anyway (early revocation, clock skew, forced logout server-side).
48
+ // Force one refresh-and-retry before giving up -- this is what actually
49
+ // prevents a spurious 're-run blocks login' when the refresh token is still valid.
50
+ response = await send(true);
26
51
  }
27
- const response = await fetch(url, {
28
- body: options.body === undefined ? undefined : JSON.stringify(options.body),
29
- headers,
30
- method: options.method ?? (options.body === undefined ? "GET" : "POST")
31
- }).catch((error) => {
32
- throw new Error(`Blocks API request failed for ${url.origin}${url.pathname}: ${error.message}`);
33
- });
34
52
  const text = await response.text();
35
53
  const data = parseJson(text);
36
54
  if (!response.ok) {
@@ -9,3 +9,6 @@ export declare function stringFlag(flags: Record<string, string | boolean>, name
9
9
  }): string;
10
10
  export declare function integerFlag(flags: Record<string, string | boolean>, name: string, defaultValue: number): number;
11
11
  export declare function booleanFlag(flags: Record<string, string | boolean>, name: string): boolean;
12
+ export declare function optionalIntegerFlag(flags: Record<string, string | boolean>, name: string): number | undefined;
13
+ /** Unlike `booleanFlag`, distinguishes "not passed" (undefined) from an explicit `--flag=false`. */
14
+ export declare function optionalBooleanFlag(flags: Record<string, string | boolean>, name: string): boolean | undefined;
package/dist/lib/args.js CHANGED
@@ -42,3 +42,18 @@ export function integerFlag(flags, name, defaultValue) {
42
42
  export function booleanFlag(flags, name) {
43
43
  return flags[name] === true || flags[name] === "true";
44
44
  }
45
+ export function optionalIntegerFlag(flags, name) {
46
+ const value = flags[name];
47
+ if (value === undefined || value === true)
48
+ return undefined;
49
+ const parsed = Number(value);
50
+ if (!Number.isInteger(parsed))
51
+ throw new Error(`--${name} must be an integer`);
52
+ return parsed;
53
+ }
54
+ /** Unlike `booleanFlag`, distinguishes "not passed" (undefined) from an explicit `--flag=false`. */
55
+ export function optionalBooleanFlag(flags, name) {
56
+ if (!(name in flags))
57
+ return undefined;
58
+ return booleanFlag(flags, name);
59
+ }
@@ -12,6 +12,9 @@ export type ProjectSession = {
12
12
  accountTenant: string;
13
13
  tenantId: string;
14
14
  };
15
+ export type SessionOptions = {
16
+ forceRefresh?: boolean;
17
+ };
15
18
  export type DeviceAuthorizationResponse = {
16
19
  device_code: string;
17
20
  expires_in: number;
@@ -25,7 +28,7 @@ export type DevicePollingOptions = {
25
28
  };
26
29
  export declare function requestDeviceAuthorization(profile: AccountProfile): Promise<DeviceAuthorizationResponse>;
27
30
  export declare function pollDeviceToken(profile: AccountProfile, device: DeviceAuthorizationResponse, options?: DevicePollingOptions): Promise<TokenResponse>;
28
- export declare function getAccountSession(accountOverride?: string): Promise<AccountSession>;
31
+ export declare function getAccountSession(accountOverride?: string, options?: SessionOptions): Promise<AccountSession>;
29
32
  export declare function selectProject(tenantId: string): Promise<void>;
30
- export declare function getImpersonatedProjectSession(accountOverride?: string, tenantOverride?: string): Promise<ProjectSession>;
33
+ export declare function getImpersonatedProjectSession(accountOverride?: string, tenantOverride?: string, options?: SessionOptions): Promise<ProjectSession>;
31
34
  export declare function revokeCurrentSession(accountOverride?: string): Promise<void>;
package/dist/lib/auth.js CHANGED
@@ -4,7 +4,6 @@ import { readTokenStore, writeTokenStore } from "./token-store.js";
4
4
  import { getClientSecret } from "./secret-store.js";
5
5
  import { CliActionableError } from "./errors.js";
6
6
  const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
7
- const FALLBACK_IMPERSONATION_CLIENT_ID = "57214b67-aa9c-4307-92ab-a25e35180fac";
8
7
  const MAX_CONSECUTIVE_TRANSIENT_ERRORS = 3;
9
8
  export async function requestDeviceAuthorization(profile) {
10
9
  const rootTenantId = await resolveRootTenantForDevice(profile);
@@ -81,33 +80,33 @@ export async function pollDeviceToken(profile, device, options = {}) {
81
80
  continue;
82
81
  }
83
82
  if (response.error === "access_denied") {
84
- throw new CliActionableError("Device authorization was denied.", "device_login_denied", "blocks-os login");
83
+ throw new CliActionableError("Device authorization was denied.", "device_login_denied", "blocks login");
85
84
  }
86
85
  if (response.error === "expired_token") {
87
- throw new CliActionableError("Device login expired before approval.", "device_login_expired", "blocks-os login");
86
+ throw new CliActionableError("Device login expired before approval.", "device_login_expired", "blocks login");
88
87
  }
89
88
  if (response.error) {
90
- throw new CliActionableError(response.error_description ?? response.error, "device_login_failed", "blocks-os login");
89
+ throw new CliActionableError(response.error_description ?? response.error, "device_login_failed", "blocks login");
91
90
  }
92
91
  return response;
93
92
  }
94
- throw new CliActionableError("Device login expired before approval.", "device_login_expired", "blocks-os login");
93
+ throw new CliActionableError("Device login expired before approval.", "device_login_expired", "blocks login");
95
94
  }
96
95
  function throwIfTooManyTransientErrors(count, cause) {
97
96
  if (count <= MAX_CONSECUTIVE_TRANSIENT_ERRORS)
98
97
  return;
99
98
  const detail = cause instanceof Error ? cause.message : String(cause);
100
- throw new CliActionableError(`Could not reach the identity provider while waiting for device approval (${detail}).`, "device_login_network_error", "Check your network connection and run 'blocks-os login' again.");
99
+ throw new CliActionableError(`Could not reach the identity provider while waiting for device approval (${detail}).`, "device_login_network_error", "Check your network connection and run 'blocks login' again.");
101
100
  }
102
- export async function getAccountSession(accountOverride) {
101
+ export async function getAccountSession(accountOverride, options = {}) {
103
102
  let config = await readConfig();
104
103
  let store = await readTokenStore();
105
104
  const { name, profile } = getAccountProfile(config, accountOverride);
106
105
  const token = store.accounts[name]?.account;
107
106
  if (!token?.accessToken || !token.accountTenant) {
108
- throw new Error(`Account '${name}' is not logged in. Run 'blocks-os login' first.`);
107
+ throw new Error(`Account '${name}' is not logged in. Run 'blocks login' first.`);
109
108
  }
110
- if (!isExpiring(token.expiresAt)) {
109
+ if (!options.forceRefresh && !isExpiring(token.expiresAt)) {
111
110
  return {
112
111
  accessToken: token.accessToken,
113
112
  account: name,
@@ -116,7 +115,7 @@ export async function getAccountSession(accountOverride) {
116
115
  };
117
116
  }
118
117
  if (!token.refreshToken) {
119
- throw new Error(`Account '${name}' token expired and no refresh token is available. Run 'blocks-os login' again.`);
118
+ throw new Error(`Account '${name}' token expired and no refresh token is available. Run 'blocks login' again.`);
120
119
  }
121
120
  const refreshed = await refreshToken(profile.oidcUrl, profile.clientId, token.refreshToken, await getClientSecret(name), profile.rootTenantId ?? token.accountTenant);
122
121
  const next = applyAccountToken(config, store, name, profile.clientId, refreshed);
@@ -142,16 +141,16 @@ export async function selectProject(tenantId) {
142
141
  }
143
142
  });
144
143
  }
145
- export async function getImpersonatedProjectSession(accountOverride, tenantOverride) {
144
+ export async function getImpersonatedProjectSession(accountOverride, tenantOverride, options = {}) {
146
145
  let config = await readConfig();
147
146
  let store = await readTokenStore();
148
147
  const { name, profile } = getAccountProfile(config, accountOverride);
149
148
  const tenantId = tenantOverride ?? config.selectedProject?.tenantId;
150
149
  if (!tenantId) {
151
- throw new Error("No project selected. Run 'blocks-os use <tenantId>' first.");
150
+ throw new Error("No project selected. Run 'blocks use <tenantId>' first.");
152
151
  }
153
152
  const projectToken = store.accounts[name]?.projects?.[tenantId];
154
- if (projectToken?.accessToken && !isExpiring(projectToken.expiresAt)) {
153
+ if (!options.forceRefresh && projectToken?.accessToken && !isExpiring(projectToken.expiresAt)) {
155
154
  return {
156
155
  accessToken: projectToken.accessToken,
157
156
  account: name,
@@ -168,12 +167,12 @@ export async function getImpersonatedProjectSession(accountOverride, tenantOverr
168
167
  await writeTokenStore(store);
169
168
  return projectSessionFromToken(name, tenantId, store.accounts[name].projects[tenantId], store.accounts[name]?.account?.accountTenant ?? profile.rootTenantId);
170
169
  }
171
- const account = await getAccountSession(name);
170
+ const account = await getAccountSession(name, options);
172
171
  config = await readConfig();
173
172
  store = await readTokenStore();
174
173
  const rootRefresh = store.accounts[name]?.account?.refreshToken;
175
174
  if (!rootRefresh) {
176
- throw new Error(`Project impersonation needs a fresh account refresh token. Run 'blocks-os login' again.`);
175
+ throw new Error(`Project impersonation needs a fresh account refresh token. Run 'blocks login' again.`);
177
176
  }
178
177
  const data = await impersonateProject({
179
178
  accessToken: account.accessToken,
@@ -236,7 +235,7 @@ async function refreshToken(oidcUrl, clientId, refreshToken, clientSecret, rootT
236
235
  // The OIDC server's exact wording for an expired/revoked refresh token
237
236
  // varies (invalid_grant, blank description, etc.) -- don't depend on it.
238
237
  // Always surface a clear, consistent next step instead.
239
- throw new CliActionableError(`Refresh token was rejected by the identity provider (${error.message}).`, "refresh_token_rejected", "blocks-os login");
238
+ throw new CliActionableError(`Refresh token was rejected by the identity provider (${error.message}).`, "refresh_token_rejected", "blocks login");
240
239
  }
241
240
  // fetch() itself failed (DNS, connection refused, TLS, etc.) -- the
242
241
  // refresh token may still be valid, so don't tell the user to log in.
@@ -245,22 +244,9 @@ async function refreshToken(oidcUrl, clientId, refreshToken, clientSecret, rootT
245
244
  }
246
245
  }
247
246
  async function impersonateProject(args) {
248
- const first = await postImpersonate(args, args.clientId);
249
- if (first.ok)
250
- return first.data;
251
- const message = first.data.error_description ?? first.data.error ?? "";
252
- if (args.clientId !== FALLBACK_IMPERSONATION_CLIENT_ID && /invalid_client|client configuration/i.test(message)) {
253
- const fallback = await postImpersonate(args, FALLBACK_IMPERSONATION_CLIENT_ID);
254
- if (fallback.ok)
255
- return fallback.data;
256
- throw new Error(fallback.data.error_description ?? fallback.data.error ?? `Impersonation failed with HTTP ${fallback.status}`);
257
- }
258
- throw new Error(first.data.error_description ?? first.data.error ?? `Impersonation failed with HTTP ${first.status}`);
259
- }
260
- async function postImpersonate(args, clientId) {
261
247
  const response = await fetch(new URL("/iam/v4/auth/impersonate", args.apiUrl), {
262
248
  body: JSON.stringify({
263
- client_id: clientId,
249
+ client_id: args.clientId,
264
250
  refresh_token: args.refreshToken,
265
251
  targeted_tenant_id: args.tenantId
266
252
  }),
@@ -273,11 +259,13 @@ async function postImpersonate(args, clientId) {
273
259
  method: "POST"
274
260
  });
275
261
  const data = parseJson(await response.text());
276
- return {
277
- data,
278
- ok: response.ok && !data.error,
279
- status: response.status
280
- };
262
+ if (response.ok && !data.error)
263
+ return data;
264
+ const message = data.error_description ?? data.error ?? "";
265
+ if (/invalid_client|client configuration/i.test(message)) {
266
+ throw new CliActionableError(`Impersonation failed: the account's OIDC client ('${args.clientId}') is not registered for impersonation (${message}).`, "impersonation_invalid_client", "Check the client_id in 'blocks auth config get', then contact an admin to register it for impersonation.");
267
+ }
268
+ throw new Error(message || `Impersonation failed with HTTP ${response.status}`);
281
269
  }
282
270
  // Thrown only once we have an actual response from the identity provider
283
271
  // that rejects the request (bad grant, bad client, etc.) -- as opposed to
@@ -1,11 +1,11 @@
1
1
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
2
  import { homedir, platform } from "node:os";
3
3
  import { dirname, join } from "node:path";
4
- const BAD_GATEWAY_OS_URL = "https://api.seliseblocks.com/os/v4";
5
- const DEFAULT_API_URL = "https://os.seliseblocks.com";
4
+ const BAD_GATEWAY_OS_URL = "https://os.seliseblocks.com";
5
+ const DEFAULT_API_URL = "https://api.seliseblocks.com";
6
6
  const DEFAULT_OS_CLIENT_ID = "4a633b13-1108-4fbf-84fd-b196c9dcdee2";
7
7
  const DEFAULT_OIDC_URL = "https://iam.seliseblocks.com";
8
- const DEFAULT_OS_URL = "https://os.seliseblocks.com";
8
+ const DEFAULT_OS_URL = "https://api.seliseblocks.com";
9
9
  const DEFAULT_PROFILE_TIMESTAMP = "2026-01-01T00:00:00.000Z";
10
10
  const DEFAULT_ROOT_TENANT_ID = "d7e5554c758541db8a18694b64ef423d";
11
11
  const DEFAULT_SCOPE = "openid profile offline_access";
@@ -20,16 +20,16 @@ export function defaults() {
20
20
  };
21
21
  }
22
22
  export function configDir() {
23
- const override = nonEmptyEnv("BLOCKS_OS_CONFIG_DIR");
23
+ const override = nonEmptyEnv("BLOCKS_CONFIG_DIR");
24
24
  if (override)
25
25
  return override;
26
26
  if (platform() === "win32") {
27
- return join(nonEmptyEnv("APPDATA") ?? join(homedir(), "AppData", "Roaming"), "seliseblocks", "cli-os");
27
+ return join(nonEmptyEnv("APPDATA") ?? join(homedir(), "AppData", "Roaming"), "seliseblocks", "cli");
28
28
  }
29
29
  if (platform() === "darwin") {
30
- return join(homedir(), "Library", "Application Support", "seliseblocks", "cli-os");
30
+ return join(homedir(), "Library", "Application Support", "seliseblocks", "cli");
31
31
  }
32
- return join(nonEmptyEnv("XDG_CONFIG_HOME") ?? join(homedir(), ".config"), "seliseblocks", "cli-os");
32
+ return join(nonEmptyEnv("XDG_CONFIG_HOME") ?? join(homedir(), ".config"), "seliseblocks", "cli");
33
33
  }
34
34
  export function configPath() {
35
35
  return join(configDir(), "config.json");
@@ -0,0 +1,17 @@
1
+ type Flags = Record<string, string | boolean>;
2
+ /**
3
+ * Reads a JSON object payload from `--body '<json>'` or `--file <path.json>`.
4
+ * Rich IAM/MFA/Auth-admin payloads have far more optional fields than are
5
+ * worth turning into individual flags; this is the escape hatch every
6
+ * create/update command layers convenience flags on top of.
7
+ */
8
+ export declare function jsonBodyFlag(flags: Flags, options?: {
9
+ required?: boolean;
10
+ }): Promise<Record<string, unknown>>;
11
+ /** Splits a comma-separated flag value (e.g. `--roles admin,editor`) into a trimmed string array. */
12
+ export declare function listFlag(flags: Flags, name: string): string[] | undefined;
13
+ /** Parses a single named flag as an arbitrary JSON value (object or array), e.g. `--attachments '["a.pdf"]'`. */
14
+ export declare function jsonFlag(flags: Flags, name: string): unknown;
15
+ /** Drops `undefined` values so unset convenience flags never overwrite a `--body`/`--file` payload's fields. */
16
+ export declare function compact<T extends object>(obj: T): Partial<T>;
17
+ export {};
@@ -0,0 +1,55 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { stringFlag } from "./args.js";
3
+ /**
4
+ * Reads a JSON object payload from `--body '<json>'` or `--file <path.json>`.
5
+ * Rich IAM/MFA/Auth-admin payloads have far more optional fields than are
6
+ * worth turning into individual flags; this is the escape hatch every
7
+ * create/update command layers convenience flags on top of.
8
+ */
9
+ export async function jsonBodyFlag(flags, options = {}) {
10
+ const inline = stringFlag(flags, "body");
11
+ if (inline)
12
+ return parseJsonObject(inline, "--body");
13
+ const file = stringFlag(flags, "file");
14
+ if (file)
15
+ return parseJsonObject(await readFile(file, "utf8"), `--file ${file}`);
16
+ if (options.required)
17
+ throw new Error("Provide --body '<json>' or --file <path.json> with the request payload.");
18
+ return {};
19
+ }
20
+ /** Splits a comma-separated flag value (e.g. `--roles admin,editor`) into a trimmed string array. */
21
+ export function listFlag(flags, name) {
22
+ const value = flags[name];
23
+ if (typeof value !== "string" || !value)
24
+ return undefined;
25
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
26
+ }
27
+ /** Parses a single named flag as an arbitrary JSON value (object or array), e.g. `--attachments '["a.pdf"]'`. */
28
+ export function jsonFlag(flags, name) {
29
+ const raw = stringFlag(flags, name);
30
+ if (!raw)
31
+ return undefined;
32
+ try {
33
+ return JSON.parse(raw);
34
+ }
35
+ catch (error) {
36
+ throw new Error(`Could not parse JSON from --${name}: ${error.message}`);
37
+ }
38
+ }
39
+ /** Drops `undefined` values so unset convenience flags never overwrite a `--body`/`--file` payload's fields. */
40
+ export function compact(obj) {
41
+ return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
42
+ }
43
+ function parseJsonObject(text, source) {
44
+ let value;
45
+ try {
46
+ value = JSON.parse(text);
47
+ }
48
+ catch (error) {
49
+ throw new Error(`Could not parse JSON from ${source}: ${error.message}`);
50
+ }
51
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
52
+ throw new Error(`${source} must be a JSON object.`);
53
+ }
54
+ return value;
55
+ }
@@ -0,0 +1,33 @@
1
+ export type ProjectRecord = {
2
+ applications?: Array<{
3
+ domain?: string;
4
+ }>;
5
+ environment?: string;
6
+ name?: string;
7
+ tenantId?: string;
8
+ } & Record<string, unknown>;
9
+ export type ProjectGroupRecord = {
10
+ name?: string;
11
+ projects?: ProjectRecord[];
12
+ tenantGroupId?: string;
13
+ } & Record<string, unknown>;
14
+ export type TenantAssetResponse = {
15
+ assets?: {
16
+ resources?: Array<{
17
+ link?: string;
18
+ name?: string;
19
+ resourceId?: string;
20
+ }>;
21
+ };
22
+ };
23
+ export declare function listProjectGroups(flags: Record<string, string | boolean>): Promise<ProjectGroupRecord[]>;
24
+ export declare function findProjectByTenantId(tenantId: string, flags: Record<string, string | boolean>): Promise<{
25
+ group: ProjectGroupRecord;
26
+ project: ProjectRecord;
27
+ }>;
28
+ export declare function resolveSelectedProject(flags: Record<string, string | boolean>): Promise<{
29
+ group: ProjectGroupRecord;
30
+ project: ProjectRecord;
31
+ tenantId: string;
32
+ }>;
33
+ export declare function getProjectAssets(tenantGroupId: string, flags: Record<string, string | boolean>): Promise<TenantAssetResponse>;
@@ -0,0 +1,39 @@
1
+ import { blocksRequest } from "./api.js";
2
+ import { requestContext } from "./request-context.js";
3
+ import { selectedProject } from "./workspace.js";
4
+ // Project metadata (Project/Gets, Project/GetAsset) always uses the account
5
+ // token, never the impersonated project token -- these endpoints operate at
6
+ // the account/tenant-group level, above any single project's own API surface.
7
+ export async function listProjectGroups(flags) {
8
+ return blocksRequest("/os/v4/Project/Gets", {
9
+ accountAuth: true,
10
+ query: { page: 0, pageSize: 100, tenantGroupId: "" },
11
+ ...requestContext(flags)
12
+ });
13
+ }
14
+ export async function findProjectByTenantId(tenantId, flags) {
15
+ const groups = await listProjectGroups(flags);
16
+ for (const group of groups) {
17
+ const project = (group.projects ?? []).find((item) => item.tenantId === tenantId);
18
+ if (project)
19
+ return { group, project };
20
+ }
21
+ throw new Error(`Project '${tenantId}' was not found in Project/Gets.`);
22
+ }
23
+ // Resolves the CLI's currently selected project (blocks.json, --project flag,
24
+ // or 'blocks use') and looks it up via Project/Gets. Throws the same
25
+ // actionable "No project selected" error as selectedProject() when nothing
26
+ // is selected -- callers should not catch that error, letting it surface to
27
+ // the user with the "run blocks use <tenantId>" next step intact.
28
+ export async function resolveSelectedProject(flags) {
29
+ const tenantId = await selectedProject(flags);
30
+ const { group, project } = await findProjectByTenantId(tenantId, flags);
31
+ return { group, project, tenantId };
32
+ }
33
+ export async function getProjectAssets(tenantGroupId, flags) {
34
+ return blocksRequest("/os/v4/Project/GetAsset", {
35
+ accountAuth: true,
36
+ query: { page: 0, pageSize: 100, tenantGroupId },
37
+ ...requestContext(flags)
38
+ });
39
+ }
@@ -0,0 +1,2 @@
1
+ export declare function promptText(message: string): Promise<string>;
2
+ export declare function selectFromList(message: string, options: string[]): Promise<number>;
@@ -0,0 +1,28 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { stdin as input, stdout as output } from "node:process";
3
+ export async function promptText(message) {
4
+ const rl = createInterface({ input, output });
5
+ try {
6
+ return (await rl.question(message)).trim();
7
+ }
8
+ finally {
9
+ rl.close();
10
+ }
11
+ }
12
+ export async function selectFromList(message, options) {
13
+ const rl = createInterface({ input, output });
14
+ try {
15
+ console.log(message);
16
+ options.forEach((option, index) => console.log(` ${index + 1}) ${option}`));
17
+ while (true) {
18
+ const answer = (await rl.question(`Choose 1-${options.length}: `)).trim();
19
+ const choice = Number(answer);
20
+ if (Number.isInteger(choice) && choice >= 1 && choice <= options.length)
21
+ return choice - 1;
22
+ console.log(`Enter a number between 1 and ${options.length}.`);
23
+ }
24
+ }
25
+ finally {
26
+ rl.close();
27
+ }
28
+ }
@@ -55,7 +55,7 @@ export async function writeDashboard(root) {
55
55
  " </li>",
56
56
  " <li>",
57
57
  " <Languages size={18} />",
58
- " <span>Edit <code>blocks/localization/*.en.json</code>, then run <code>blocks-os localization:push</code> to sync copy to Blocks.</span>",
58
+ " <span>Edit <code>blocks/localization/*.en.json</code>, then run <code>blocks localization push</code> to sync copy to Blocks.</span>",
59
59
  " </li>",
60
60
  " </ul>",
61
61
  " </div>",
@@ -122,7 +122,7 @@ export async function writeRootFiles(root, options) {
122
122
  "- `/login/callback` — completes the hosted IAM callback via `blocksClient.auth.idp.callback()`, then returns to the page you started from.",
123
123
  "- `/` and `/profile` — protected; redirect to `/login` when signed out.",
124
124
  "- Sidebar + topbar shell matching the `@seliseblocks/blocks-kit` look (icon-only rail on narrow screens, avatar dropdown, notifications menu, active-item accent bar).",
125
- "- `blocks/localization/*.en.json` local i18n seed files for AI or human edits. Sync them through `blocks-os localization:validate` and `blocks-os localization:push`; the runtime app reads Localization service data through `blocksClient.localization`.",
125
+ "- `blocks/localization/*.en.json` local i18n seed files for AI or human edits. Sync them through `blocks localization validate` and `blocks localization push`; the runtime app reads Localization service data through `blocksClient.localization`.",
126
126
  "",
127
127
  "IAM's hosted login sets the session as a **Secure, httpOnly** cookie by default -- this app never reads, stores, or refreshes a token itself. \"Signed in\" is determined by calling `blocksClient.auth.userInfo()` (`GET /iam/v4/auth/me`), which the browser's cookie authenticates automatically; this is different from `blocksClient.iam.me()`, the full IAM profile call used on the Profile page. Logging out calls `blocksClient.auth.logout()` so IAM ends the session server-side. A cached bearer token (and `blocksClient.auth.oidc.refreshToken()` to refresh it) is only used if a tenant's OIDC config explicitly returns tokens in the response body instead of a cookie.",
128
128
  ""
@@ -5,7 +5,7 @@ import { dirname, join } from "node:path";
5
5
  import { promisify } from "node:util";
6
6
  import { configDir } from "./config.js";
7
7
  const execFileAsync = promisify(execFile);
8
- const SERVICE = "seliseblocks-cli-os";
8
+ const SERVICE = "seliseblocks-cli";
9
9
  export function secretPath() {
10
10
  return join(configDir(), "secrets.json");
11
11
  }
@@ -138,7 +138,7 @@ function normalizeSecretStore(store) {
138
138
  };
139
139
  }
140
140
  async function resolveBackend() {
141
- if (process.env.BLOCKS_OS_SECRET_STORE === "file")
141
+ if (process.env.BLOCKS_SECRET_STORE === "file")
142
142
  return "file";
143
143
  if (platform() === "win32")
144
144
  return "windows-dpapi";
@@ -162,9 +162,9 @@ async function protectWindowsSecret(secret) {
162
162
  "-NoProfile",
163
163
  "-NonInteractive",
164
164
  "-Command",
165
- "$secure = ConvertTo-SecureString $env:BLOCKS_OS_SECRET_INPUT -AsPlainText -Force; $secure | ConvertFrom-SecureString"
165
+ "$secure = ConvertTo-SecureString $env:BLOCKS_SECRET_INPUT -AsPlainText -Force; $secure | ConvertFrom-SecureString"
166
166
  ], {
167
- env: { ...process.env, BLOCKS_OS_SECRET_INPUT: secret }
167
+ env: { ...process.env, BLOCKS_SECRET_INPUT: secret }
168
168
  });
169
169
  return stdout.trim();
170
170
  }
@@ -174,9 +174,9 @@ async function unprotectWindowsSecret(secret) {
174
174
  "-NoProfile",
175
175
  "-NonInteractive",
176
176
  "-Command",
177
- "$secure = ConvertTo-SecureString $env:BLOCKS_OS_SECRET_INPUT; $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure); try { [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { if ($bstr -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) } }"
177
+ "$secure = ConvertTo-SecureString $env:BLOCKS_SECRET_INPUT; $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure); try { [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) } finally { if ($bstr -ne [IntPtr]::Zero) { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) } }"
178
178
  ], {
179
- env: { ...process.env, BLOCKS_OS_SECRET_INPUT: secret }
179
+ env: { ...process.env, BLOCKS_SECRET_INPUT: secret }
180
180
  });
181
181
  return stdout.trim() || undefined;
182
182
  }
@@ -202,7 +202,7 @@ async function removeMacSecret(account) {
202
202
  await execFileAsync("security", ["delete-generic-password", "-a", account, "-s", SERVICE]);
203
203
  }
204
204
  async function setLinuxSecret(account, secret) {
205
- await spawnWithInput("secret-tool", ["store", "--label", `Blocks OS CLI ${account}`, "service", SERVICE, "account", account], secret);
205
+ await spawnWithInput("secret-tool", ["store", "--label", `Blocks CLI ${account}`, "service", SERVICE, "account", account], secret);
206
206
  }
207
207
  async function getLinuxSecret(account) {
208
208
  try {
@@ -0,0 +1,17 @@
1
+ export type SkillSummary = {
2
+ description: string;
3
+ name: string;
4
+ path: string;
5
+ };
6
+ export type SkillDetail = SkillSummary & {
7
+ content: string;
8
+ };
9
+ export declare const SKILLS_REPO_URL = "https://github.com/SELISEdigitalplatforms/blocks-cli/tree/main/blocks-skills";
10
+ export declare function resolveSkillsDir(): string;
11
+ export declare function parseFrontmatter(raw: string): {
12
+ body: string;
13
+ description?: string;
14
+ name?: string;
15
+ };
16
+ export declare function listSkills(): Promise<SkillSummary[]>;
17
+ export declare function readSkill(name: string): Promise<SkillDetail>;