@objectstack/cli 4.0.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/README.md +44 -25
  2. package/dist/commands/build.d.ts +5 -0
  3. package/dist/commands/build.d.ts.map +1 -0
  4. package/dist/commands/build.js +6 -0
  5. package/dist/commands/build.js.map +1 -0
  6. package/dist/commands/cloud/login.d.ts +16 -0
  7. package/dist/commands/cloud/login.d.ts.map +1 -0
  8. package/dist/commands/cloud/login.js +166 -0
  9. package/dist/commands/cloud/login.js.map +1 -0
  10. package/dist/commands/cloud/logout.d.ts +15 -0
  11. package/dist/commands/cloud/logout.d.ts.map +1 -0
  12. package/dist/commands/cloud/logout.js +51 -0
  13. package/dist/commands/cloud/logout.js.map +1 -0
  14. package/dist/commands/cloud/whoami.d.ts +15 -0
  15. package/dist/commands/cloud/whoami.d.ts.map +1 -0
  16. package/dist/commands/cloud/whoami.js +81 -0
  17. package/dist/commands/cloud/whoami.js.map +1 -0
  18. package/dist/commands/compile.d.ts +3 -0
  19. package/dist/commands/compile.d.ts.map +1 -1
  20. package/dist/commands/compile.js +128 -6
  21. package/dist/commands/compile.js.map +1 -1
  22. package/dist/commands/create.js +1 -1
  23. package/dist/commands/data/create.js +2 -2
  24. package/dist/commands/data/create.js.map +1 -1
  25. package/dist/commands/data/delete.js +2 -2
  26. package/dist/commands/data/delete.js.map +1 -1
  27. package/dist/commands/data/get.js +2 -2
  28. package/dist/commands/data/get.js.map +1 -1
  29. package/dist/commands/data/query.js +2 -2
  30. package/dist/commands/data/query.js.map +1 -1
  31. package/dist/commands/data/update.js +2 -2
  32. package/dist/commands/data/update.js.map +1 -1
  33. package/dist/commands/dev.d.ts +9 -0
  34. package/dist/commands/dev.d.ts.map +1 -1
  35. package/dist/commands/dev.js +116 -22
  36. package/dist/commands/dev.js.map +1 -1
  37. package/dist/commands/generate.js +9 -9
  38. package/dist/commands/generate.js.map +1 -1
  39. package/dist/commands/i18n/check.d.ts +18 -0
  40. package/dist/commands/i18n/check.d.ts.map +1 -0
  41. package/dist/commands/i18n/check.js +153 -0
  42. package/dist/commands/i18n/check.js.map +1 -0
  43. package/dist/commands/init.js +2 -2
  44. package/dist/commands/lint.d.ts +3 -0
  45. package/dist/commands/lint.d.ts.map +1 -1
  46. package/dist/commands/lint.js +24 -0
  47. package/dist/commands/lint.js.map +1 -1
  48. package/dist/commands/login.d.ts +17 -0
  49. package/dist/commands/login.d.ts.map +1 -0
  50. package/dist/commands/login.js +313 -0
  51. package/dist/commands/login.js.map +1 -0
  52. package/dist/commands/logout.d.ts.map +1 -0
  53. package/dist/commands/{auth/logout.js → logout.js} +14 -2
  54. package/dist/commands/logout.js.map +1 -0
  55. package/dist/commands/meta/delete.js +2 -2
  56. package/dist/commands/meta/delete.js.map +1 -1
  57. package/dist/commands/meta/get.js +2 -2
  58. package/dist/commands/meta/get.js.map +1 -1
  59. package/dist/commands/meta/list.js +2 -2
  60. package/dist/commands/meta/list.js.map +1 -1
  61. package/dist/commands/meta/register.js +2 -2
  62. package/dist/commands/meta/register.js.map +1 -1
  63. package/dist/commands/package/publish.d.ts +32 -0
  64. package/dist/commands/package/publish.d.ts.map +1 -0
  65. package/dist/commands/package/publish.js +324 -0
  66. package/dist/commands/package/publish.js.map +1 -0
  67. package/dist/commands/projects/bind.d.ts +30 -0
  68. package/dist/commands/projects/bind.d.ts.map +1 -0
  69. package/dist/commands/projects/bind.js +132 -0
  70. package/dist/commands/projects/bind.js.map +1 -0
  71. package/dist/commands/projects/create.d.ts +28 -0
  72. package/dist/commands/projects/create.d.ts.map +1 -0
  73. package/dist/commands/projects/create.js +120 -0
  74. package/dist/commands/projects/create.js.map +1 -0
  75. package/dist/commands/projects/list.d.ts +21 -0
  76. package/dist/commands/projects/list.d.ts.map +1 -0
  77. package/dist/commands/projects/list.js +79 -0
  78. package/dist/commands/projects/list.js.map +1 -0
  79. package/dist/commands/projects/projects.test.d.ts +2 -0
  80. package/dist/commands/projects/projects.test.d.ts.map +1 -0
  81. package/dist/commands/projects/projects.test.js +56 -0
  82. package/dist/commands/projects/projects.test.js.map +1 -0
  83. package/dist/commands/projects/show.d.ts +21 -0
  84. package/dist/commands/projects/show.d.ts.map +1 -0
  85. package/dist/commands/projects/show.js +72 -0
  86. package/dist/commands/projects/show.js.map +1 -0
  87. package/dist/commands/projects/switch.d.ts +24 -0
  88. package/dist/commands/projects/switch.d.ts.map +1 -0
  89. package/dist/commands/projects/switch.js +64 -0
  90. package/dist/commands/projects/switch.js.map +1 -0
  91. package/dist/commands/publish.d.ts +17 -0
  92. package/dist/commands/publish.d.ts.map +1 -0
  93. package/dist/commands/publish.js +135 -0
  94. package/dist/commands/publish.js.map +1 -0
  95. package/dist/commands/{auth/login.d.ts → register.d.ts} +3 -2
  96. package/dist/commands/register.d.ts.map +1 -0
  97. package/dist/commands/{auth/login.js → register.js} +44 -61
  98. package/dist/commands/register.js.map +1 -0
  99. package/dist/commands/rollback.d.ts +13 -0
  100. package/dist/commands/rollback.d.ts.map +1 -0
  101. package/dist/commands/rollback.js +77 -0
  102. package/dist/commands/rollback.js.map +1 -0
  103. package/dist/commands/serve.d.ts +22 -0
  104. package/dist/commands/serve.d.ts.map +1 -1
  105. package/dist/commands/serve.js +1173 -58
  106. package/dist/commands/serve.js.map +1 -1
  107. package/dist/commands/start.d.ts +18 -0
  108. package/dist/commands/start.d.ts.map +1 -0
  109. package/dist/commands/start.js +112 -0
  110. package/dist/commands/start.js.map +1 -0
  111. package/dist/commands/whoami.d.ts.map +1 -0
  112. package/dist/commands/{auth/whoami.js → whoami.js} +5 -5
  113. package/dist/commands/whoami.js.map +1 -0
  114. package/dist/index.d.ts +11 -4
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +14 -5
  117. package/dist/index.js.map +1 -1
  118. package/dist/utils/account.d.ts +31 -0
  119. package/dist/utils/account.d.ts.map +1 -0
  120. package/dist/utils/account.js +154 -0
  121. package/dist/utils/account.js.map +1 -0
  122. package/dist/utils/api-client.d.ts +10 -4
  123. package/dist/utils/api-client.d.ts.map +1 -1
  124. package/dist/utils/api-client.js +13 -7
  125. package/dist/utils/api-client.js.map +1 -1
  126. package/dist/utils/auth-config.d.ts +6 -0
  127. package/dist/utils/auth-config.d.ts.map +1 -1
  128. package/dist/utils/auth-config.js.map +1 -1
  129. package/dist/utils/auth-flows.d.ts +31 -0
  130. package/dist/utils/auth-flows.d.ts.map +1 -0
  131. package/dist/utils/auth-flows.js +151 -0
  132. package/dist/utils/auth-flows.js.map +1 -0
  133. package/dist/utils/build-runtime.d.ts +45 -0
  134. package/dist/utils/build-runtime.d.ts.map +1 -0
  135. package/dist/utils/build-runtime.js +154 -0
  136. package/dist/utils/build-runtime.js.map +1 -0
  137. package/dist/utils/cloud-config.d.ts +24 -0
  138. package/dist/utils/cloud-config.d.ts.map +1 -0
  139. package/dist/utils/cloud-config.js +75 -0
  140. package/dist/utils/cloud-config.js.map +1 -0
  141. package/dist/utils/config.d.ts.map +1 -1
  142. package/dist/utils/config.js +17 -2
  143. package/dist/utils/config.js.map +1 -1
  144. package/dist/utils/console.d.ts +33 -0
  145. package/dist/utils/console.d.ts.map +1 -0
  146. package/dist/utils/console.js +172 -0
  147. package/dist/utils/console.js.map +1 -0
  148. package/dist/utils/extract-hook-body.d.ts +13 -0
  149. package/dist/utils/extract-hook-body.d.ts.map +1 -0
  150. package/dist/utils/extract-hook-body.js +175 -0
  151. package/dist/utils/extract-hook-body.js.map +1 -0
  152. package/dist/utils/format.d.ts +8 -0
  153. package/dist/utils/format.d.ts.map +1 -1
  154. package/dist/utils/format.js +15 -2
  155. package/dist/utils/format.js.map +1 -1
  156. package/dist/utils/i18n-coverage.d.ts +61 -0
  157. package/dist/utils/i18n-coverage.d.ts.map +1 -0
  158. package/dist/utils/i18n-coverage.js +176 -0
  159. package/dist/utils/i18n-coverage.js.map +1 -0
  160. package/dist/utils/lower-callables.d.ts +17 -0
  161. package/dist/utils/lower-callables.d.ts.map +1 -0
  162. package/dist/utils/lower-callables.js +181 -0
  163. package/dist/utils/lower-callables.js.map +1 -0
  164. package/dist/utils/plugin-detection.d.ts +1 -0
  165. package/dist/utils/plugin-detection.d.ts.map +1 -1
  166. package/dist/utils/plugin-detection.js +41 -0
  167. package/dist/utils/plugin-detection.js.map +1 -1
  168. package/dist/utils/studio.d.ts +1 -0
  169. package/dist/utils/studio.d.ts.map +1 -1
  170. package/dist/utils/studio.js +24 -9
  171. package/dist/utils/studio.js.map +1 -1
  172. package/package.json +60 -22
  173. package/.turbo/turbo-build.log +0 -4
  174. package/CHANGELOG.md +0 -821
  175. package/bin/run-dev.js +0 -5
  176. package/dist/commands/auth/login.d.ts.map +0 -1
  177. package/dist/commands/auth/login.js.map +0 -1
  178. package/dist/commands/auth/logout.d.ts.map +0 -1
  179. package/dist/commands/auth/logout.js.map +0 -1
  180. package/dist/commands/auth/whoami.d.ts.map +0 -1
  181. package/dist/commands/auth/whoami.js.map +0 -1
  182. package/dist/commands/codemod/v2-to-v3.d.ts +0 -10
  183. package/dist/commands/codemod/v2-to-v3.d.ts.map +0 -1
  184. package/dist/commands/codemod/v2-to-v3.js +0 -145
  185. package/dist/commands/codemod/v2-to-v3.js.map +0 -1
  186. package/dist/commands/plugin/add.d.ts +0 -22
  187. package/dist/commands/plugin/add.d.ts.map +0 -1
  188. package/dist/commands/plugin/add.js +0 -93
  189. package/dist/commands/plugin/add.js.map +0 -1
  190. package/dist/commands/plugin/build.d.ts +0 -29
  191. package/dist/commands/plugin/build.d.ts.map +0 -1
  192. package/dist/commands/plugin/build.js +0 -170
  193. package/dist/commands/plugin/build.js.map +0 -1
  194. package/dist/commands/plugin/info.d.ts +0 -10
  195. package/dist/commands/plugin/info.d.ts.map +0 -1
  196. package/dist/commands/plugin/info.js +0 -65
  197. package/dist/commands/plugin/info.js.map +0 -1
  198. package/dist/commands/plugin/list.d.ts +0 -13
  199. package/dist/commands/plugin/list.d.ts.map +0 -1
  200. package/dist/commands/plugin/list.js +0 -78
  201. package/dist/commands/plugin/list.js.map +0 -1
  202. package/dist/commands/plugin/publish.d.ts +0 -27
  203. package/dist/commands/plugin/publish.d.ts.map +0 -1
  204. package/dist/commands/plugin/publish.js +0 -152
  205. package/dist/commands/plugin/publish.js.map +0 -1
  206. package/dist/commands/plugin/remove.d.ts +0 -20
  207. package/dist/commands/plugin/remove.d.ts.map +0 -1
  208. package/dist/commands/plugin/remove.js +0 -79
  209. package/dist/commands/plugin/remove.js.map +0 -1
  210. package/dist/commands/plugin/validate.d.ts +0 -23
  211. package/dist/commands/plugin/validate.d.ts.map +0 -1
  212. package/dist/commands/plugin/validate.js +0 -251
  213. package/dist/commands/plugin/validate.js.map +0 -1
  214. package/src/bin.ts +0 -13
  215. package/src/commands/auth/login.ts +0 -188
  216. package/src/commands/auth/logout.ts +0 -51
  217. package/src/commands/auth/whoami.ts +0 -85
  218. package/src/commands/codemod/v2-to-v3.ts +0 -171
  219. package/src/commands/compile.ts +0 -114
  220. package/src/commands/create.ts +0 -281
  221. package/src/commands/data/create.ts +0 -110
  222. package/src/commands/data/delete.ts +0 -84
  223. package/src/commands/data/get.ts +0 -84
  224. package/src/commands/data/query.ts +0 -127
  225. package/src/commands/data/update.ts +0 -114
  226. package/src/commands/dev.ts +0 -83
  227. package/src/commands/diff.ts +0 -294
  228. package/src/commands/doctor.ts +0 -572
  229. package/src/commands/explain.ts +0 -412
  230. package/src/commands/generate.ts +0 -924
  231. package/src/commands/info.ts +0 -124
  232. package/src/commands/init.ts +0 -327
  233. package/src/commands/lint.ts +0 -315
  234. package/src/commands/meta/delete.ts +0 -79
  235. package/src/commands/meta/get.ts +0 -73
  236. package/src/commands/meta/list.ts +0 -105
  237. package/src/commands/meta/register.ts +0 -97
  238. package/src/commands/plugin/add.ts +0 -112
  239. package/src/commands/plugin/build.ts +0 -193
  240. package/src/commands/plugin/info.ts +0 -79
  241. package/src/commands/plugin/list.ts +0 -93
  242. package/src/commands/plugin/publish.ts +0 -176
  243. package/src/commands/plugin/remove.ts +0 -97
  244. package/src/commands/plugin/validate.ts +0 -268
  245. package/src/commands/serve.ts +0 -411
  246. package/src/commands/studio.ts +0 -52
  247. package/src/commands/test.ts +0 -135
  248. package/src/commands/validate.ts +0 -143
  249. package/src/index.ts +0 -22
  250. package/src/utils/api-client.ts +0 -88
  251. package/src/utils/auth-config.ts +0 -107
  252. package/src/utils/config.ts +0 -80
  253. package/src/utils/format.ts +0 -267
  254. package/src/utils/output-formatter.ts +0 -91
  255. package/src/utils/plugin-detection.ts +0 -16
  256. package/src/utils/plugin-helpers.ts +0 -37
  257. package/src/utils/studio.ts +0 -350
  258. package/test/commands.test.ts +0 -128
  259. package/test/create.test.ts +0 -25
  260. package/test/plugin-commands.test.ts +0 -44
  261. package/test/plugin.test.ts +0 -169
  262. package/test/remote-api-commands.test.ts +0 -188
  263. package/test/remote-api-utils.test.ts +0 -196
  264. package/test/serve-host-config.test.ts +0 -77
  265. package/tsconfig.build.json +0 -20
  266. package/tsconfig.json +0 -25
  267. package/tsup.config.ts +0 -23
  268. /package/dist/commands/{auth/logout.d.ts → logout.d.ts} +0 -0
  269. /package/dist/commands/{auth/whoami.d.ts → whoami.d.ts} +0 -0
@@ -0,0 +1,75 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ /**
3
+ * Cloud credential store — separate from the runtime credential store at
4
+ * `~/.objectstack/credentials.json`.
5
+ *
6
+ * Why a second file?
7
+ * ------------------
8
+ * ObjectStack now has two distinct identities on a developer's machine:
9
+ *
10
+ * 1. **Runtime identity** — who you are inside your *own* ObjectOS
11
+ * instance (the CRM / Todo / app you're building). Stored in
12
+ * `credentials.json`, written by `os login`.
13
+ *
14
+ * 2. **Cloud identity** — who you are on the official ObjectStack Cloud
15
+ * package registry (`https://cloud.objectos.app`). Stored in
16
+ * `cloud.json`, written by `os cloud login`. Used to publish &
17
+ * install packages, browse the marketplace, etc.
18
+ *
19
+ * Keeping them in separate files makes it unambiguous which token a
20
+ * command is going to use, and makes it impossible to accidentally
21
+ * publish a package with a runtime-scoped token.
22
+ */
23
+ import { chmod, mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
24
+ import { homedir } from 'node:os';
25
+ import { join } from 'node:path';
26
+ /** Canonical hosted control plane. */
27
+ export const DEFAULT_CLOUD_URL = 'https://cloud.objectos.app';
28
+ export function getCloudCredentialsPath() {
29
+ return join(homedir(), '.objectstack', 'cloud.json');
30
+ }
31
+ export async function readCloudConfig() {
32
+ const path = getCloudCredentialsPath();
33
+ try {
34
+ const content = await readFile(path, 'utf-8');
35
+ return JSON.parse(content);
36
+ }
37
+ catch (error) {
38
+ if (error.code === 'ENOENT') {
39
+ throw new Error('Not logged in to ObjectStack Cloud. Run `os cloud login` first.');
40
+ }
41
+ throw new Error(`Failed to read cloud credentials: ${error.message}`);
42
+ }
43
+ }
44
+ export async function tryReadCloudConfig() {
45
+ try {
46
+ return await readCloudConfig();
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ }
52
+ export async function writeCloudConfig(config) {
53
+ const path = getCloudCredentialsPath();
54
+ const dir = join(homedir(), '.objectstack');
55
+ await mkdir(dir, { recursive: true });
56
+ await writeFile(path, JSON.stringify(config, null, 2), { mode: 0o600 });
57
+ try {
58
+ await chmod(path, 0o600);
59
+ }
60
+ catch {
61
+ // Platforms without chmod support — silently continue.
62
+ }
63
+ }
64
+ export async function deleteCloudConfig() {
65
+ const path = getCloudCredentialsPath();
66
+ try {
67
+ await unlink(path);
68
+ }
69
+ catch (error) {
70
+ if (error.code !== 'ENOENT') {
71
+ throw new Error(`Failed to delete cloud credentials: ${error.message}`);
72
+ }
73
+ }
74
+ }
75
+ //# sourceMappingURL=cloud-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-config.js","sourceRoot":"","sources":["../../src/utils/cloud-config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,sCAAsC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,4BAA4B,CAAC;AAmB9D,MAAM,UAAU,uBAAuB;IACrC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;QACrF,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,CAAC;QACH,OAAO,MAAM,eAAe,EAAE,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAmB;IACxD,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;IAE5C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA6BzD;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkBvE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAgC,GAAG,OAAO,CAE5E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CA6BzD;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCvE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAgC,GAAG,OAAO,CAE5E"}
@@ -47,10 +47,25 @@ export async function loadConfig(source) {
47
47
  const { mod } = await bundleRequire({
48
48
  filepath: absolutePath,
49
49
  });
50
- const config = mod.default || mod;
51
- if (!config) {
50
+ const baseConfig = mod.default || mod;
51
+ if (!baseConfig) {
52
52
  throw new Error(`No default export found in ${path.basename(absolutePath)}`);
53
53
  }
54
+ // Preserve named exports (e.g. `onEnable`, `onDisable` lifecycle hooks)
55
+ // alongside the default-exported stack. Module-namespace named exports are
56
+ // otherwise dropped when we unwrap `mod.default`, which prevents AppPlugin
57
+ // from invoking runtime hooks.
58
+ const config = (baseConfig === mod || mod.default == null)
59
+ ? baseConfig
60
+ : (() => {
61
+ const merged = { ...baseConfig };
62
+ for (const key of Object.keys(mod)) {
63
+ if (key === 'default' || key in merged)
64
+ continue;
65
+ merged[key] = mod[key];
66
+ }
67
+ return merged;
68
+ })();
54
69
  return {
55
70
  config,
56
71
  absolutePath,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzC;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAe;IAC/C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,UAAU,CAAC,0BAA0B,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC,CAAC;YAC/F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,cAAc;IACd,MAAM,UAAU,GAAG;QACjB,uBAAuB;QACvB,uBAAuB;QACvB,wBAAwB;KACzB,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;QACnD,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IACrC,CAAC;IAED,UAAU,CAAC,8DAA8D,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC,CAAC;IACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAe;IAC9C,MAAM,YAAY,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEzB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,aAAa,CAAC;QAClC,QAAQ,EAAE,YAAY;KACvB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO;QACL,MAAM;QACN,YAAY;QACZ,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;KAC7B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,uBAAuB;IACjE,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /** URL mount path for the Console portal inside the ObjectStack server */
2
+ export declare const CONSOLE_PATH = "/_console";
3
+ /**
4
+ * Resolve the filesystem path to the @objectstack/console package.
5
+ * Searches workspace locations first, then falls back to node_modules.
6
+ */
7
+ export declare function resolveConsolePath(): string | null;
8
+ /**
9
+ * Check whether the Console portal has a pre-built `dist/` directory.
10
+ */
11
+ export declare function hasConsoleDist(consolePath: string): boolean;
12
+ /**
13
+ * Create a lightweight kernel plugin that serves the pre-built Console
14
+ * portal static files at `/_console/*`.
15
+ *
16
+ * Identical SPA-fallback semantics to `createStudioStaticPlugin` and
17
+ * `createAccountStaticPlugin`:
18
+ * - `index.html` is read fresh on every fallback hit (so a rebuild
19
+ * producing new hashed asset names doesn't leave the browser
20
+ * pointing at stale URLs).
21
+ * - Hashed asset paths under `/_console/assets/*` never SPA-fallback —
22
+ * a real 404 surfaces a rebuild/deploy mismatch instead of the
23
+ * dreaded "asset returns text/html" silent failure.
24
+ */
25
+ export declare function createConsoleStaticPlugin(distPath: string, options?: {
26
+ isDev?: boolean;
27
+ rootRedirect?: boolean;
28
+ }): {
29
+ name: string;
30
+ init: () => Promise<void>;
31
+ start: (ctx: any) => Promise<void>;
32
+ };
33
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"AAwBA,0EAA0E;AAC1E,eAAO,MAAM,YAAY,cAAc,CAAC;AAIxC;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CA6ClD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE3D;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE;;;iBAM1F,GAAG;EAgEzB"}
@@ -0,0 +1,172 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ /**
3
+ * Console UI Integration Utilities
4
+ *
5
+ * Mirrors `studio.ts` / `account.ts` but for the opinionated, fork-ready
6
+ * runtime console (`@objectstack/console`). The Console SPA is mounted at
7
+ * `/_console/` by every deployment that opts in (CLI dev server,
8
+ * self-host, Vercel) — exactly the same convention as `_studio` and
9
+ * `_account`. The Console is built with `base: '/_console/'`, so its
10
+ * pre-built `dist/` is served verbatim.
11
+ *
12
+ * Note: this module was previously named `dashboard.ts` (and the SPA was
13
+ * `apps/dashboard`). It was renamed to disambiguate from the spec-level
14
+ * `Dashboard` metadata type — the Console *renders* dashboards, it is not
15
+ * itself a dashboard.
16
+ */
17
+ import path from 'path';
18
+ import fs from 'fs';
19
+ import { createRequire } from 'module';
20
+ import { pathToFileURL } from 'url';
21
+ // ─── Constants ──────────────────────────────────────────────────────
22
+ /** URL mount path for the Console portal inside the ObjectStack server */
23
+ export const CONSOLE_PATH = '/_console';
24
+ // ─── Path Resolution ────────────────────────────────────────────────
25
+ /**
26
+ * Resolve the filesystem path to the @objectstack/console package.
27
+ * Searches workspace locations first, then falls back to node_modules.
28
+ */
29
+ export function resolveConsolePath() {
30
+ const cwd = process.cwd();
31
+ // Workspace candidates (monorepo layouts)
32
+ const candidates = [
33
+ path.resolve(cwd, 'apps/console'),
34
+ path.resolve(cwd, '../../apps/console'),
35
+ path.resolve(cwd, '../apps/console'),
36
+ ];
37
+ for (const candidate of candidates) {
38
+ const pkgPath = path.join(candidate, 'package.json');
39
+ if (fs.existsSync(pkgPath)) {
40
+ try {
41
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
42
+ if (pkg.name === '@objectstack/console')
43
+ return candidate;
44
+ }
45
+ catch {
46
+ // Skip invalid package.json
47
+ }
48
+ }
49
+ }
50
+ // Fallback: resolve from node_modules via createRequire.
51
+ const resolutionBases = [
52
+ pathToFileURL(path.join(cwd, 'package.json')).href, // consumer workspace
53
+ import.meta.url, // CLI package itself
54
+ ];
55
+ for (const base of resolutionBases) {
56
+ try {
57
+ const req = createRequire(base);
58
+ const resolved = req.resolve('@objectstack/console/package.json');
59
+ return path.dirname(resolved);
60
+ }
61
+ catch {
62
+ // Not resolvable from this base — try next
63
+ }
64
+ }
65
+ // Last resort: direct filesystem check in cwd/node_modules
66
+ const directPath = path.join(cwd, 'node_modules', '@objectstack', 'console');
67
+ if (fs.existsSync(path.join(directPath, 'package.json'))) {
68
+ return directPath;
69
+ }
70
+ return null;
71
+ }
72
+ /**
73
+ * Check whether the Console portal has a pre-built `dist/` directory.
74
+ */
75
+ export function hasConsoleDist(consolePath) {
76
+ return fs.existsSync(path.join(consolePath, 'dist', 'index.html'));
77
+ }
78
+ // ─── Plugin Factory ─────────────────────────────────────────────────
79
+ /**
80
+ * Create a lightweight kernel plugin that serves the pre-built Console
81
+ * portal static files at `/_console/*`.
82
+ *
83
+ * Identical SPA-fallback semantics to `createStudioStaticPlugin` and
84
+ * `createAccountStaticPlugin`:
85
+ * - `index.html` is read fresh on every fallback hit (so a rebuild
86
+ * producing new hashed asset names doesn't leave the browser
87
+ * pointing at stale URLs).
88
+ * - Hashed asset paths under `/_console/assets/*` never SPA-fallback —
89
+ * a real 404 surfaces a rebuild/deploy mismatch instead of the
90
+ * dreaded "asset returns text/html" silent failure.
91
+ */
92
+ export function createConsoleStaticPlugin(distPath, options) {
93
+ return {
94
+ name: 'com.objectstack.console-static',
95
+ init: async () => { },
96
+ start: async (ctx) => {
97
+ const httpServer = ctx.getService?.('http.server');
98
+ if (!httpServer?.getRawApp) {
99
+ ctx.logger?.warn?.('Console static: http.server service not found — skipping');
100
+ return;
101
+ }
102
+ const app = httpServer.getRawApp();
103
+ const absoluteDist = path.resolve(distPath);
104
+ const indexPath = path.join(absoluteDist, 'index.html');
105
+ if (!fs.existsSync(indexPath)) {
106
+ ctx.logger?.warn?.(`Console static: dist not found at ${absoluteDist}`);
107
+ return;
108
+ }
109
+ const readIndexHtml = () => fs.readFileSync(indexPath, 'utf-8');
110
+ // The Console is the default end-user surface — root `/` redirects
111
+ // here whenever the Console is mounted (`rootRedirect !== false`).
112
+ // Mirrors the studio plugin's `rootRedirect` option. The CLI's
113
+ // serve.ts gates whether the Console mounts at all via `--no-console`
114
+ // / `OS_DISABLE_CONSOLE=1`; once mounted, claiming `/` is the
115
+ // intended behaviour in both dev and production deployments.
116
+ if (options?.rootRedirect !== false) {
117
+ app.get('/', (c) => c.redirect(`${CONSOLE_PATH}/`));
118
+ }
119
+ // Redirect bare path to trailing-slash (SPA convention)
120
+ app.get(CONSOLE_PATH, (c) => c.redirect(`${CONSOLE_PATH}/`));
121
+ // Serve static files with SPA fallback
122
+ app.get(`${CONSOLE_PATH}/*`, async (c) => {
123
+ const reqPath = c.req.path.substring(CONSOLE_PATH.length) || '/';
124
+ const filePath = path.join(absoluteDist, reqPath);
125
+ // Security: prevent path traversal
126
+ if (!filePath.startsWith(absoluteDist)) {
127
+ return c.text('Forbidden', 403);
128
+ }
129
+ // Try serving the exact file
130
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
131
+ const content = fs.readFileSync(filePath);
132
+ return new Response(content, {
133
+ headers: { 'content-type': mimeType(filePath) },
134
+ });
135
+ }
136
+ // Hashed-asset paths must never SPA-fallback.
137
+ if (reqPath.startsWith('/assets/')) {
138
+ return c.text('Not Found', 404);
139
+ }
140
+ // SPA fallback
141
+ return new Response(readIndexHtml(), {
142
+ headers: { 'content-type': 'text/html; charset=utf-8' },
143
+ });
144
+ });
145
+ // Suppress unused-parameter lint when isDev isn't needed.
146
+ void options;
147
+ },
148
+ };
149
+ }
150
+ // ─── Helpers ────────────────────────────────────────────────────────
151
+ const MIME_TYPES = {
152
+ '.html': 'text/html; charset=utf-8',
153
+ '.js': 'application/javascript; charset=utf-8',
154
+ '.mjs': 'application/javascript; charset=utf-8',
155
+ '.css': 'text/css; charset=utf-8',
156
+ '.json': 'application/json; charset=utf-8',
157
+ '.svg': 'image/svg+xml',
158
+ '.png': 'image/png',
159
+ '.jpg': 'image/jpeg',
160
+ '.jpeg': 'image/jpeg',
161
+ '.gif': 'image/gif',
162
+ '.ico': 'image/x-icon',
163
+ '.woff': 'font/woff',
164
+ '.woff2': 'font/woff2',
165
+ '.ttf': 'font/ttf',
166
+ '.map': 'application/json',
167
+ };
168
+ function mimeType(filePath) {
169
+ const ext = path.extname(filePath).toLowerCase();
170
+ return MIME_TYPES[ext] || 'application/octet-stream';
171
+ }
172
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/utils/console.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface ExtractedBody {
2
+ /** Pure function-body source (without the surrounding `(ctx) => {...}`). */
3
+ source: string;
4
+ /** Inferred capability tokens — may be merged with explicit `// @capabilities` line. */
5
+ capabilities: Array<'api.read' | 'api.write' | 'crypto.uuid' | 'crypto.hash' | 'log'>;
6
+ /** True when source is a single expression (arrow with implicit return). */
7
+ isExpression: boolean;
8
+ }
9
+ /**
10
+ * Extract the body source from a callable. Throws on forbidden patterns.
11
+ */
12
+ export declare function extractHookBody(fn: (...a: unknown[]) => unknown, originLabel: string): ExtractedBody;
13
+ //# sourceMappingURL=extract-hook-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-hook-body.d.ts","sourceRoot":"","sources":["../../src/utils/extract-hook-body.ts"],"names":[],"mappings":"AAgDA,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,aAAa,GAAG,KAAK,CAAC,CAAC;IACtF,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,CAmDpG"}
@@ -0,0 +1,175 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ /**
3
+ * Extract a metadata-only `HookBody` from an inline JS function.
4
+ *
5
+ * The CLI's `lowerCallables` pass already has direct access to every
6
+ * `handler: (ctx) => {...}` value the user wrote in their `defineStack({...})`
7
+ * config. After tsx/esbuild has loaded the config, those callables are real
8
+ * runtime functions whose `.toString()` returns the compiled source — that
9
+ * source is exactly what we want to ship as `body.source` so the runtime can
10
+ * re-evaluate it inside the QuickJS sandbox without needing the .mjs side
11
+ * channel.
12
+ *
13
+ * For v1 we apply a deliberately simple **regex allow-list** over the
14
+ * extracted body — full TypeScript AST analysis is deferred to v2. Anything
15
+ * the regex rejects (top-level `import`, `require(`, `fetch(`, `process.*`,
16
+ * `globalThis.*`, `eval`, `new Function`) makes the build **fail**. There is
17
+ * no silent fallback to the L3 .mjs path because that path is being closed.
18
+ *
19
+ * Capability inference: we scan the body for known `ctx.api.*`, `ctx.log.*`,
20
+ * `ctx.crypto.*` access patterns and add the matching capability tokens to
21
+ * `body.capabilities` automatically. Authors can still override by setting
22
+ * `// @capabilities api.read api.write` as the first line of the function.
23
+ */
24
+ const FORBIDDEN_PATTERNS = [
25
+ { rx: /\bimport\s*[\(\*\{]/, reason: 'dynamic `import()` and ES imports are not allowed in hook/action bodies — declare a Connector recipe instead' },
26
+ { rx: /\brequire\s*\(/, reason: '`require()` is not allowed in hook/action bodies' },
27
+ { rx: /\bfetch\s*\(/, reason: '`fetch()` is not allowed in hook/action bodies — declare a Connector recipe instead' },
28
+ { rx: /\bprocess\s*\./, reason: '`process` access is not allowed in hook/action bodies' },
29
+ { rx: /\bglobalThis\s*\./, reason: '`globalThis` access is not allowed in hook/action bodies' },
30
+ { rx: /\beval\s*\(/, reason: '`eval()` is not allowed in hook/action bodies' },
31
+ { rx: /\bnew\s+Function\s*\(/, reason: '`new Function()` is not allowed in hook/action bodies' },
32
+ ];
33
+ const CAPABILITY_PATTERNS = [
34
+ // Match `ctx.api.object(...)` directly OR a local alias like
35
+ // `const api = ctx.api;` then `api.object(...)`. We accept any
36
+ // identifier (or chain) ending in `.object(...)` followed by a known
37
+ // read/write method — over-inclusive but safe (false-positive caps
38
+ // get rejected at the runtime by the sandbox if not actually granted).
39
+ { rx: /\.object\s*\([^)]+\)\s*\.\s*(?:find|findOne|count|aggregate|get|list)\b/, cap: 'api.read' },
40
+ { rx: /\.object\s*\([^)]+\)\s*\.\s*(?:insert|update|upsert|delete|patch|remove|create)\b/, cap: 'api.write' },
41
+ { rx: /ctx\.crypto\.randomUUID\b/, cap: 'crypto.uuid' },
42
+ { rx: /ctx\.crypto\.hash\b/, cap: 'crypto.hash' },
43
+ { rx: /ctx\.log\.(?:info|warn|error|debug)\b/, cap: 'log' },
44
+ ];
45
+ /**
46
+ * Extract the body source from a callable. Throws on forbidden patterns.
47
+ */
48
+ export function extractHookBody(fn, originLabel) {
49
+ const raw = String(fn);
50
+ // Strip leading function/arrow header and trailing closing brace so the
51
+ // result is a pure block body suitable for `new Function('ctx', body)`.
52
+ const block = peelToBlockBody(raw);
53
+ if (!block) {
54
+ throw new Error(`[hook-body-extract] could not parse the body of ${originLabel}; ` +
55
+ `please rewrite the handler as a single arrow function or named function expression`);
56
+ }
57
+ // Reject any forbidden token before we ship the source as metadata.
58
+ for (const { rx, reason } of FORBIDDEN_PATTERNS) {
59
+ if (rx.test(block.source)) {
60
+ throw new Error(`[hook-body-extract] ${originLabel}: ${reason}\n` +
61
+ `--- offending body source ---\n${block.source.slice(0, 400)}${block.source.length > 400 ? '…' : ''}`);
62
+ }
63
+ }
64
+ // Infer capabilities from API surface usage.
65
+ const inferred = new Set();
66
+ for (const { rx, cap } of CAPABILITY_PATTERNS) {
67
+ if (rx.test(block.source))
68
+ inferred.add(cap);
69
+ }
70
+ // Honour an explicit override: `// @capabilities api.read api.write`.
71
+ const overrideMatch = block.source.match(/^[\s\n]*\/\/\s*@capabilities\s+([a-z.\s]+)/m);
72
+ if (overrideMatch) {
73
+ const tokens = overrideMatch[1].split(/\s+/).filter(Boolean);
74
+ for (const t of tokens) {
75
+ if (t === 'api.read' ||
76
+ t === 'api.write' ||
77
+ t === 'crypto.uuid' ||
78
+ t === 'crypto.hash' ||
79
+ t === 'log') {
80
+ inferred.add(t);
81
+ }
82
+ }
83
+ }
84
+ return {
85
+ source: block.source,
86
+ capabilities: [...inferred].sort(),
87
+ isExpression: block.isExpression,
88
+ };
89
+ }
90
+ /**
91
+ * Remove the parameter list and outermost braces from a function string,
92
+ * yielding the bare statements (or expression for shorthand arrows).
93
+ */
94
+ function peelToBlockBody(raw) {
95
+ // Try arrow forms first since they're the dominant authoring style.
96
+ // Match the parameter list followed by `=>` and either `{...}` or expr.
97
+ // We rely on a manual brace scan rather than a single regex so braces
98
+ // inside string/template literals don't confuse us.
99
+ const arrowIdx = findTopLevelArrow(raw);
100
+ if (arrowIdx >= 0) {
101
+ const after = raw.slice(arrowIdx + 2).trimStart();
102
+ if (after.startsWith('{')) {
103
+ const body = sliceBalanced(after, '{', '}');
104
+ if (body)
105
+ return { source: body.inner, isExpression: false };
106
+ }
107
+ else {
108
+ // Implicit-return arrow — wrap as `return ...;`
109
+ const expr = after.replace(/[;\s]+$/g, '');
110
+ return { source: `return (${expr});`, isExpression: true };
111
+ }
112
+ }
113
+ // function () { ... } / async function () { ... }
114
+ const fnIdx = raw.search(/\bfunction\b/);
115
+ if (fnIdx >= 0) {
116
+ const braceIdx = raw.indexOf('{', fnIdx);
117
+ if (braceIdx > 0) {
118
+ const body = sliceBalanced(raw.slice(braceIdx), '{', '}');
119
+ if (body)
120
+ return { source: body.inner, isExpression: false };
121
+ }
122
+ }
123
+ // Method shorthand inside an object literal: `name(ctx) { ... }`.
124
+ const braceIdx = raw.indexOf('{');
125
+ if (braceIdx > 0) {
126
+ const body = sliceBalanced(raw.slice(braceIdx), '{', '}');
127
+ if (body)
128
+ return { source: body.inner, isExpression: false };
129
+ }
130
+ return null;
131
+ }
132
+ function findTopLevelArrow(s) {
133
+ // Skip past balanced parameter list `(...)` then expect `=>`.
134
+ // We scan looking for `(` not preceded by an identifier char and
135
+ // immediately matched by a balanced `)` then optional whitespace then `=>`.
136
+ let i = 0;
137
+ const len = s.length;
138
+ while (i < len) {
139
+ if (s[i] === '(') {
140
+ const closing = matchBalancedIndex(s, i, '(', ')');
141
+ if (closing < 0)
142
+ return -1;
143
+ let j = closing + 1;
144
+ while (j < len && /\s/.test(s[j]))
145
+ j++;
146
+ if (s[j] === '=' && s[j + 1] === '>')
147
+ return j;
148
+ i = closing + 1;
149
+ continue;
150
+ }
151
+ i++;
152
+ }
153
+ return -1;
154
+ }
155
+ function matchBalancedIndex(s, start, open, close) {
156
+ let depth = 0;
157
+ for (let i = start; i < s.length; i++) {
158
+ const c = s[i];
159
+ if (c === open)
160
+ depth++;
161
+ else if (c === close) {
162
+ depth--;
163
+ if (depth === 0)
164
+ return i;
165
+ }
166
+ }
167
+ return -1;
168
+ }
169
+ function sliceBalanced(s, open, close) {
170
+ const end = matchBalancedIndex(s, 0, open, close);
171
+ if (end < 0)
172
+ return null;
173
+ return { inner: s.slice(1, end) };
174
+ }
175
+ //# sourceMappingURL=extract-hook-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-hook-body.js","sourceRoot":"","sources":["../../src/utils/extract-hook-body.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,14 @@ export interface ServerReadyOptions {
46
46
  pluginNames?: string[];
47
47
  uiEnabled?: boolean;
48
48
  studioPath?: string;
49
+ accountPath?: string;
50
+ consolePath?: string;
51
+ /** Resolved storage driver display name (e.g. "MongoDBDriver", "SqlDriver(pg)"). */
52
+ driverLabel?: string;
53
+ /** Resolved DB URL with credentials redacted. */
54
+ databaseUrl?: string;
55
+ /** Whether the SecurityPlugin was wired in multi-tenant mode (default true). */
56
+ multiTenant?: boolean;
49
57
  }
50
58
  export declare function printServerReady(opts: ServerReadyOptions): void;
51
59
  export declare function printMetadataStats(stats: MetadataStats): void;
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGpC,eAAO,MAAM,QAAQ,gBAAgB,CAAC;AACtC,eAAO,MAAM,SAAS,OAAO,CAAC;AAI9B,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAM1C;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,QAGxC;AAID,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,QAGzE;AAID,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,QAEvC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,QAEvC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,QAErC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,QAEpC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,QAEpC;AAID,wBAAgB,WAAW;;;EAM1B;AAID,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,QAwC9C;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,CAwC/D;AAID,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,QAmBxD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,QAwDtD"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGpC,eAAO,MAAM,QAAQ,gBAAgB,CAAC;AACtC,eAAO,MAAM,SAAS,OAAO,CAAC;AAI9B,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,QAM1C;AAID,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,QAGxC;AAID,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,QAGzE;AAID,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,QAEvC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,QAEvC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,QAErC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,QAEpC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,QAEpC;AAID,wBAAgB,WAAW;;;EAM1B;AAID,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,QAwC9C;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,CAwC/D;AAID,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,QAgCxD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,QAwDtD"}
@@ -127,13 +127,26 @@ export function printServerReady(opts) {
127
127
  console.log('');
128
128
  console.log(chalk.bold.green(' ✓ Server is ready'));
129
129
  console.log('');
130
- console.log(chalk.cyan(' ➜') + chalk.bold(' API: ') + chalk.cyan(base + '/'));
130
+ console.log(chalk.cyan(' ➜') + chalk.bold(' API: ') + chalk.cyan(base + '/'));
131
131
  if (opts.uiEnabled && opts.studioPath) {
132
- console.log(chalk.cyan(' ➜') + chalk.bold(' Studio: ') + chalk.cyan(base + opts.studioPath + '/'));
132
+ console.log(chalk.cyan(' ➜') + chalk.bold(' Studio: ') + chalk.cyan(base + opts.studioPath + '/'));
133
+ }
134
+ if (opts.uiEnabled && opts.accountPath) {
135
+ console.log(chalk.cyan(' ➜') + chalk.bold(' Account: ') + chalk.cyan(base + opts.accountPath + '/'));
136
+ }
137
+ if (opts.uiEnabled && opts.consolePath) {
138
+ console.log(chalk.cyan(' ➜') + chalk.bold(' Console: ') + chalk.cyan(base + opts.consolePath + '/'));
133
139
  }
134
140
  console.log('');
135
141
  console.log(chalk.dim(` Config: ${opts.configFile}`));
136
142
  console.log(chalk.dim(` Mode: ${opts.isDev ? 'development' : 'production'}`));
143
+ if (opts.driverLabel) {
144
+ const dbInfo = opts.databaseUrl ? `${opts.driverLabel} ${chalk.dim('→')} ${opts.databaseUrl}` : opts.driverLabel;
145
+ console.log(chalk.dim(` Driver: ${dbInfo}`));
146
+ }
147
+ if (opts.multiTenant !== undefined) {
148
+ console.log(chalk.dim(` Tenancy: ${opts.multiTenant ? 'multi-tenant' : 'single-tenant'}`));
149
+ }
137
150
  console.log(chalk.dim(` Plugins: ${opts.pluginCount} loaded`));
138
151
  if (opts.pluginNames && opts.pluginNames.length > 0) {
139
152
  console.log(chalk.dim(` ${opts.pluginNames.join(', ')}`));