@objectstack/cli 4.0.4 → 4.0.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 (241) hide show
  1. package/README.md +12 -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/compile.d.ts +3 -0
  7. package/dist/commands/compile.d.ts.map +1 -1
  8. package/dist/commands/compile.js +128 -6
  9. package/dist/commands/compile.js.map +1 -1
  10. package/dist/commands/create.js +1 -1
  11. package/dist/commands/data/create.js +2 -2
  12. package/dist/commands/data/create.js.map +1 -1
  13. package/dist/commands/data/delete.js +2 -2
  14. package/dist/commands/data/delete.js.map +1 -1
  15. package/dist/commands/data/get.js +2 -2
  16. package/dist/commands/data/get.js.map +1 -1
  17. package/dist/commands/data/query.js +2 -2
  18. package/dist/commands/data/query.js.map +1 -1
  19. package/dist/commands/data/update.js +2 -2
  20. package/dist/commands/data/update.js.map +1 -1
  21. package/dist/commands/dev.d.ts +3 -0
  22. package/dist/commands/dev.d.ts.map +1 -1
  23. package/dist/commands/dev.js +48 -19
  24. package/dist/commands/dev.js.map +1 -1
  25. package/dist/commands/generate.js +9 -9
  26. package/dist/commands/generate.js.map +1 -1
  27. package/dist/commands/i18n/check.d.ts +18 -0
  28. package/dist/commands/i18n/check.d.ts.map +1 -0
  29. package/dist/commands/i18n/check.js +153 -0
  30. package/dist/commands/i18n/check.js.map +1 -0
  31. package/dist/commands/init.js +2 -2
  32. package/dist/commands/lint.d.ts +3 -0
  33. package/dist/commands/lint.d.ts.map +1 -1
  34. package/dist/commands/lint.js +24 -0
  35. package/dist/commands/lint.js.map +1 -1
  36. package/dist/commands/login.d.ts +17 -0
  37. package/dist/commands/login.d.ts.map +1 -0
  38. package/dist/commands/login.js +313 -0
  39. package/dist/commands/login.js.map +1 -0
  40. package/dist/commands/logout.d.ts.map +1 -0
  41. package/dist/commands/{auth/logout.js → logout.js} +14 -2
  42. package/dist/commands/logout.js.map +1 -0
  43. package/dist/commands/meta/delete.js +2 -2
  44. package/dist/commands/meta/delete.js.map +1 -1
  45. package/dist/commands/meta/get.js +2 -2
  46. package/dist/commands/meta/get.js.map +1 -1
  47. package/dist/commands/meta/list.js +2 -2
  48. package/dist/commands/meta/list.js.map +1 -1
  49. package/dist/commands/meta/register.js +2 -2
  50. package/dist/commands/meta/register.js.map +1 -1
  51. package/dist/commands/projects/bind.d.ts +30 -0
  52. package/dist/commands/projects/bind.d.ts.map +1 -0
  53. package/dist/commands/projects/bind.js +132 -0
  54. package/dist/commands/projects/bind.js.map +1 -0
  55. package/dist/commands/projects/create.d.ts +28 -0
  56. package/dist/commands/projects/create.d.ts.map +1 -0
  57. package/dist/commands/projects/create.js +120 -0
  58. package/dist/commands/projects/create.js.map +1 -0
  59. package/dist/commands/projects/list.d.ts +21 -0
  60. package/dist/commands/projects/list.d.ts.map +1 -0
  61. package/dist/commands/projects/list.js +79 -0
  62. package/dist/commands/projects/list.js.map +1 -0
  63. package/dist/commands/projects/projects.test.d.ts +2 -0
  64. package/dist/commands/projects/projects.test.d.ts.map +1 -0
  65. package/dist/commands/projects/projects.test.js +56 -0
  66. package/dist/commands/projects/projects.test.js.map +1 -0
  67. package/dist/commands/projects/show.d.ts +21 -0
  68. package/dist/commands/projects/show.d.ts.map +1 -0
  69. package/dist/commands/projects/show.js +72 -0
  70. package/dist/commands/projects/show.js.map +1 -0
  71. package/dist/commands/projects/switch.d.ts +24 -0
  72. package/dist/commands/projects/switch.d.ts.map +1 -0
  73. package/dist/commands/projects/switch.js +64 -0
  74. package/dist/commands/projects/switch.js.map +1 -0
  75. package/dist/commands/publish.d.ts +14 -0
  76. package/dist/commands/publish.d.ts.map +1 -0
  77. package/dist/commands/publish.js +91 -0
  78. package/dist/commands/publish.js.map +1 -0
  79. package/dist/commands/{auth/login.d.ts → register.d.ts} +3 -2
  80. package/dist/commands/register.d.ts.map +1 -0
  81. package/dist/commands/{auth/login.js → register.js} +44 -61
  82. package/dist/commands/register.js.map +1 -0
  83. package/dist/commands/serve.d.ts +8 -0
  84. package/dist/commands/serve.d.ts.map +1 -1
  85. package/dist/commands/serve.js +606 -44
  86. package/dist/commands/serve.js.map +1 -1
  87. package/dist/commands/start.d.ts +11 -0
  88. package/dist/commands/start.d.ts.map +1 -0
  89. package/dist/commands/start.js +43 -0
  90. package/dist/commands/start.js.map +1 -0
  91. package/dist/commands/whoami.d.ts.map +1 -0
  92. package/dist/commands/{auth/whoami.js → whoami.js} +5 -5
  93. package/dist/commands/whoami.js.map +1 -0
  94. package/dist/index.d.ts +7 -4
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +8 -5
  97. package/dist/index.js.map +1 -1
  98. package/dist/utils/account.d.ts +31 -0
  99. package/dist/utils/account.d.ts.map +1 -0
  100. package/dist/utils/account.js +154 -0
  101. package/dist/utils/account.js.map +1 -0
  102. package/dist/utils/api-client.d.ts +10 -4
  103. package/dist/utils/api-client.d.ts.map +1 -1
  104. package/dist/utils/api-client.js +13 -7
  105. package/dist/utils/api-client.js.map +1 -1
  106. package/dist/utils/auth-config.d.ts +6 -0
  107. package/dist/utils/auth-config.d.ts.map +1 -1
  108. package/dist/utils/auth-config.js.map +1 -1
  109. package/dist/utils/build-runtime.d.ts +45 -0
  110. package/dist/utils/build-runtime.d.ts.map +1 -0
  111. package/dist/utils/build-runtime.js +154 -0
  112. package/dist/utils/build-runtime.js.map +1 -0
  113. package/dist/utils/config.d.ts.map +1 -1
  114. package/dist/utils/config.js +17 -2
  115. package/dist/utils/config.js.map +1 -1
  116. package/dist/utils/console.d.ts +32 -0
  117. package/dist/utils/console.d.ts.map +1 -0
  118. package/dist/utils/console.js +169 -0
  119. package/dist/utils/console.js.map +1 -0
  120. package/dist/utils/extract-hook-body.d.ts +13 -0
  121. package/dist/utils/extract-hook-body.d.ts.map +1 -0
  122. package/dist/utils/extract-hook-body.js +175 -0
  123. package/dist/utils/extract-hook-body.js.map +1 -0
  124. package/dist/utils/format.d.ts +8 -0
  125. package/dist/utils/format.d.ts.map +1 -1
  126. package/dist/utils/format.js +15 -2
  127. package/dist/utils/format.js.map +1 -1
  128. package/dist/utils/i18n-coverage.d.ts +61 -0
  129. package/dist/utils/i18n-coverage.d.ts.map +1 -0
  130. package/dist/utils/i18n-coverage.js +176 -0
  131. package/dist/utils/i18n-coverage.js.map +1 -0
  132. package/dist/utils/lower-callables.d.ts +17 -0
  133. package/dist/utils/lower-callables.d.ts.map +1 -0
  134. package/dist/utils/lower-callables.js +181 -0
  135. package/dist/utils/lower-callables.js.map +1 -0
  136. package/dist/utils/plugin-detection.d.ts +1 -0
  137. package/dist/utils/plugin-detection.d.ts.map +1 -1
  138. package/dist/utils/plugin-detection.js +41 -0
  139. package/dist/utils/plugin-detection.js.map +1 -1
  140. package/dist/utils/studio.d.ts +1 -0
  141. package/dist/utils/studio.d.ts.map +1 -1
  142. package/dist/utils/studio.js +25 -9
  143. package/dist/utils/studio.js.map +1 -1
  144. package/package.json +55 -21
  145. package/.turbo/turbo-build.log +0 -4
  146. package/CHANGELOG.md +0 -821
  147. package/bin/run-dev.js +0 -5
  148. package/dist/commands/auth/login.d.ts.map +0 -1
  149. package/dist/commands/auth/login.js.map +0 -1
  150. package/dist/commands/auth/logout.d.ts.map +0 -1
  151. package/dist/commands/auth/logout.js.map +0 -1
  152. package/dist/commands/auth/whoami.d.ts.map +0 -1
  153. package/dist/commands/auth/whoami.js.map +0 -1
  154. package/dist/commands/codemod/v2-to-v3.d.ts +0 -10
  155. package/dist/commands/codemod/v2-to-v3.d.ts.map +0 -1
  156. package/dist/commands/codemod/v2-to-v3.js +0 -145
  157. package/dist/commands/codemod/v2-to-v3.js.map +0 -1
  158. package/dist/commands/plugin/add.d.ts +0 -22
  159. package/dist/commands/plugin/add.d.ts.map +0 -1
  160. package/dist/commands/plugin/add.js +0 -93
  161. package/dist/commands/plugin/add.js.map +0 -1
  162. package/dist/commands/plugin/build.d.ts +0 -29
  163. package/dist/commands/plugin/build.d.ts.map +0 -1
  164. package/dist/commands/plugin/build.js +0 -170
  165. package/dist/commands/plugin/build.js.map +0 -1
  166. package/dist/commands/plugin/info.d.ts +0 -10
  167. package/dist/commands/plugin/info.d.ts.map +0 -1
  168. package/dist/commands/plugin/info.js +0 -65
  169. package/dist/commands/plugin/info.js.map +0 -1
  170. package/dist/commands/plugin/list.d.ts +0 -13
  171. package/dist/commands/plugin/list.d.ts.map +0 -1
  172. package/dist/commands/plugin/list.js +0 -78
  173. package/dist/commands/plugin/list.js.map +0 -1
  174. package/dist/commands/plugin/publish.d.ts +0 -27
  175. package/dist/commands/plugin/publish.d.ts.map +0 -1
  176. package/dist/commands/plugin/publish.js +0 -152
  177. package/dist/commands/plugin/publish.js.map +0 -1
  178. package/dist/commands/plugin/remove.d.ts +0 -20
  179. package/dist/commands/plugin/remove.d.ts.map +0 -1
  180. package/dist/commands/plugin/remove.js +0 -79
  181. package/dist/commands/plugin/remove.js.map +0 -1
  182. package/dist/commands/plugin/validate.d.ts +0 -23
  183. package/dist/commands/plugin/validate.d.ts.map +0 -1
  184. package/dist/commands/plugin/validate.js +0 -251
  185. package/dist/commands/plugin/validate.js.map +0 -1
  186. package/src/bin.ts +0 -13
  187. package/src/commands/auth/login.ts +0 -188
  188. package/src/commands/auth/logout.ts +0 -51
  189. package/src/commands/auth/whoami.ts +0 -85
  190. package/src/commands/codemod/v2-to-v3.ts +0 -171
  191. package/src/commands/compile.ts +0 -114
  192. package/src/commands/create.ts +0 -281
  193. package/src/commands/data/create.ts +0 -110
  194. package/src/commands/data/delete.ts +0 -84
  195. package/src/commands/data/get.ts +0 -84
  196. package/src/commands/data/query.ts +0 -127
  197. package/src/commands/data/update.ts +0 -114
  198. package/src/commands/dev.ts +0 -83
  199. package/src/commands/diff.ts +0 -294
  200. package/src/commands/doctor.ts +0 -572
  201. package/src/commands/explain.ts +0 -412
  202. package/src/commands/generate.ts +0 -924
  203. package/src/commands/info.ts +0 -124
  204. package/src/commands/init.ts +0 -327
  205. package/src/commands/lint.ts +0 -315
  206. package/src/commands/meta/delete.ts +0 -79
  207. package/src/commands/meta/get.ts +0 -73
  208. package/src/commands/meta/list.ts +0 -105
  209. package/src/commands/meta/register.ts +0 -97
  210. package/src/commands/plugin/add.ts +0 -112
  211. package/src/commands/plugin/build.ts +0 -193
  212. package/src/commands/plugin/info.ts +0 -79
  213. package/src/commands/plugin/list.ts +0 -93
  214. package/src/commands/plugin/publish.ts +0 -176
  215. package/src/commands/plugin/remove.ts +0 -97
  216. package/src/commands/plugin/validate.ts +0 -268
  217. package/src/commands/serve.ts +0 -411
  218. package/src/commands/studio.ts +0 -52
  219. package/src/commands/test.ts +0 -135
  220. package/src/commands/validate.ts +0 -143
  221. package/src/index.ts +0 -22
  222. package/src/utils/api-client.ts +0 -88
  223. package/src/utils/auth-config.ts +0 -107
  224. package/src/utils/config.ts +0 -80
  225. package/src/utils/format.ts +0 -267
  226. package/src/utils/output-formatter.ts +0 -91
  227. package/src/utils/plugin-detection.ts +0 -16
  228. package/src/utils/plugin-helpers.ts +0 -37
  229. package/src/utils/studio.ts +0 -350
  230. package/test/commands.test.ts +0 -128
  231. package/test/create.test.ts +0 -25
  232. package/test/plugin-commands.test.ts +0 -44
  233. package/test/plugin.test.ts +0 -169
  234. package/test/remote-api-commands.test.ts +0 -188
  235. package/test/remote-api-utils.test.ts +0 -196
  236. package/test/serve-host-config.test.ts +0 -77
  237. package/tsconfig.build.json +0 -20
  238. package/tsconfig.json +0 -25
  239. package/tsup.config.ts +0 -23
  240. /package/dist/commands/{auth/logout.d.ts → logout.d.ts} +0 -0
  241. /package/dist/commands/{auth/whoami.d.ts → whoami.d.ts} +0 -0
@@ -1,169 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import PluginList from '../src/commands/plugin/list';
3
- import PluginInfo from '../src/commands/plugin/info';
4
- import PluginAdd from '../src/commands/plugin/add';
5
- import PluginRemove from '../src/commands/plugin/remove';
6
- import fs from 'fs';
7
- import path from 'path';
8
- import os from 'os';
9
-
10
- describe('Plugin Commands (oclif)', () => {
11
- it('should have plugin list command', () => {
12
- expect(PluginList.description).toContain('List');
13
- });
14
-
15
- it('should have plugin list alias', () => {
16
- expect(PluginList.aliases).toContain('plugin ls');
17
- });
18
-
19
- it('should have plugin info command', () => {
20
- expect(PluginInfo.description).toContain('information');
21
- });
22
-
23
- it('should have plugin add command', () => {
24
- expect(PluginAdd.description).toContain('Add');
25
- });
26
-
27
- it('should have plugin remove command', () => {
28
- expect(PluginRemove.description).toContain('Remove');
29
- });
30
-
31
- it('should have plugin remove alias', () => {
32
- expect(PluginRemove.aliases).toContain('plugin rm');
33
- });
34
- });
35
-
36
- describe('Plugin Config Manipulation', () => {
37
- let tmpDir: string;
38
- let configPath: string;
39
-
40
- beforeEach(() => {
41
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'os-plugin-test-'));
42
- configPath = path.join(tmpDir, 'objectstack.config.ts');
43
- });
44
-
45
- afterEach(() => {
46
- fs.rmSync(tmpDir, { recursive: true, force: true });
47
- });
48
-
49
- describe('addPluginToConfig (via file manipulation)', () => {
50
- it('should add plugin import and entry to config with existing plugins array', () => {
51
- fs.writeFileSync(configPath, `import { defineStack } from '@objectstack/spec';
52
-
53
- export default defineStack({
54
- manifest: {
55
- name: 'test-app',
56
- version: '1.0.0',
57
- },
58
- plugins: [
59
- ],
60
- });
61
- `);
62
-
63
- // Simulate what the add command does
64
- let content = fs.readFileSync(configPath, 'utf-8');
65
- const packageName = '@objectstack/plugin-auth';
66
- const varName = 'authPlugin';
67
- const importLine = `import ${varName} from '${packageName}';\n`;
68
-
69
- // Add import after last import
70
- const importRegex = /^import .+$/gm;
71
- let lastImportEnd = 0;
72
- let match: RegExpExecArray | null;
73
- while ((match = importRegex.exec(content)) !== null) {
74
- lastImportEnd = match.index + match[0].length;
75
- }
76
- content = content.slice(0, lastImportEnd) + '\n' + importLine + content.slice(lastImportEnd);
77
-
78
- // Add to plugins array
79
- content = content.replace(
80
- /(plugins\s*:\s*\[)/,
81
- `$1\n ${varName},`
82
- );
83
-
84
- fs.writeFileSync(configPath, content);
85
-
86
- const result = fs.readFileSync(configPath, 'utf-8');
87
- expect(result).toContain("import authPlugin from '@objectstack/plugin-auth'");
88
- expect(result).toContain('authPlugin,');
89
- });
90
-
91
- it('should add plugin to config without existing plugins array', () => {
92
- fs.writeFileSync(configPath, `import { defineStack } from '@objectstack/spec';
93
-
94
- export default defineStack({
95
- manifest: {
96
- name: 'test-app',
97
- version: '1.0.0',
98
- },
99
- });
100
- `);
101
-
102
- let content = fs.readFileSync(configPath, 'utf-8');
103
- const packageName = '@objectstack/plugin-security';
104
- const varName = 'securityPlugin';
105
- const importLine = `import ${varName} from '${packageName}';\n`;
106
-
107
- // Add import
108
- const importRegex = /^import .+$/gm;
109
- let lastImportEnd = 0;
110
- let match: RegExpExecArray | null;
111
- while ((match = importRegex.exec(content)) !== null) {
112
- lastImportEnd = match.index + match[0].length;
113
- }
114
- content = content.slice(0, lastImportEnd) + '\n' + importLine + content.slice(lastImportEnd);
115
-
116
- // Add plugins array
117
- if (!/plugins\s*:\s*\[/.test(content)) {
118
- content = content.replace(
119
- /(defineStack\(\{[\s\S]*?)(}\s*\))/,
120
- `$1 plugins: [\n ${varName},\n ],\n$2`
121
- );
122
- }
123
-
124
- fs.writeFileSync(configPath, content);
125
-
126
- const result = fs.readFileSync(configPath, 'utf-8');
127
- expect(result).toContain("import securityPlugin from '@objectstack/plugin-security'");
128
- expect(result).toContain('plugins: [');
129
- expect(result).toContain('securityPlugin,');
130
- });
131
- });
132
-
133
- describe('removePluginFromConfig (via file manipulation)', () => {
134
- it('should remove plugin import and entry from config', () => {
135
- fs.writeFileSync(configPath, `import { defineStack } from '@objectstack/spec';
136
- import authPlugin from '@objectstack/plugin-auth';
137
-
138
- export default defineStack({
139
- manifest: {
140
- name: 'test-app',
141
- version: '1.0.0',
142
- },
143
- plugins: [
144
- authPlugin,
145
- ],
146
- });
147
- `);
148
-
149
- let content = fs.readFileSync(configPath, 'utf-8');
150
- const packageName = '@objectstack/plugin-auth';
151
-
152
- // Remove import
153
- const importRegex = new RegExp(`^import .+['"]${packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"].*$\\n?`, 'gm');
154
- content = content.replace(importRegex, '');
155
-
156
- // Remove from plugins array
157
- content = content.replace(/\s*authPlugin,?\n?/g, '\n');
158
-
159
- fs.writeFileSync(configPath, content);
160
-
161
- const result = fs.readFileSync(configPath, 'utf-8');
162
- expect(result).not.toContain('@objectstack/plugin-auth');
163
- expect(result).not.toContain('authPlugin');
164
- // The rest of the config should remain intact
165
- expect(result).toContain("import { defineStack } from '@objectstack/spec'");
166
- expect(result).toContain('manifest');
167
- });
168
- });
169
- });
@@ -1,188 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import AuthLogin from '../src/commands/auth/login';
3
- import AuthLogout from '../src/commands/auth/logout';
4
- import AuthWhoami from '../src/commands/auth/whoami';
5
- import DataQuery from '../src/commands/data/query';
6
- import DataGet from '../src/commands/data/get';
7
- import DataCreate from '../src/commands/data/create';
8
- import DataUpdate from '../src/commands/data/update';
9
- import DataDelete from '../src/commands/data/delete';
10
- import MetaList from '../src/commands/meta/list';
11
- import MetaGet from '../src/commands/meta/get';
12
- import MetaRegister from '../src/commands/meta/register';
13
- import MetaDelete from '../src/commands/meta/delete';
14
-
15
- describe('Remote API Commands (oclif)', () => {
16
- describe('Auth Commands', () => {
17
- it('should have auth login command', () => {
18
- expect(AuthLogin.description).toContain('Authenticate');
19
- expect(AuthLogin.flags).toHaveProperty('url');
20
- expect(AuthLogin.flags).toHaveProperty('email');
21
- expect(AuthLogin.flags).toHaveProperty('password');
22
- expect(AuthLogin.flags).toHaveProperty('json');
23
- });
24
-
25
- it('should have auth logout command', () => {
26
- expect(AuthLogout.description).toContain('Clear');
27
- expect(AuthLogout.flags).toHaveProperty('json');
28
- });
29
-
30
- it('should have auth whoami command', () => {
31
- expect(AuthWhoami.description).toContain('session');
32
- expect(AuthWhoami.flags).toHaveProperty('url');
33
- expect(AuthWhoami.flags).toHaveProperty('token');
34
- expect(AuthWhoami.flags).toHaveProperty('format');
35
- });
36
-
37
- it('auth commands should have examples', () => {
38
- expect(AuthLogin.examples).toBeDefined();
39
- expect(AuthLogin.examples.length).toBeGreaterThan(0);
40
- expect(AuthLogout.examples).toBeDefined();
41
- expect(AuthWhoami.examples).toBeDefined();
42
- });
43
- });
44
-
45
- describe('Data Commands', () => {
46
- it('should have data query command', () => {
47
- expect(DataQuery.description).toContain('Query');
48
- expect(DataQuery.args).toHaveProperty('object');
49
- expect(DataQuery.flags).toHaveProperty('filter');
50
- expect(DataQuery.flags).toHaveProperty('fields');
51
- expect(DataQuery.flags).toHaveProperty('sort');
52
- expect(DataQuery.flags).toHaveProperty('limit');
53
- expect(DataQuery.flags).toHaveProperty('offset');
54
- expect(DataQuery.flags).toHaveProperty('format');
55
- });
56
-
57
- it('should have data get command', () => {
58
- expect(DataGet.description).toContain('single record');
59
- expect(DataGet.args).toHaveProperty('object');
60
- expect(DataGet.args).toHaveProperty('id');
61
- expect(DataGet.flags).toHaveProperty('format');
62
- });
63
-
64
- it('should have data create command', () => {
65
- expect(DataCreate.description).toContain('Create');
66
- expect(DataCreate.args).toHaveProperty('object');
67
- expect(DataCreate.flags).toHaveProperty('data');
68
- expect(DataCreate.flags).toHaveProperty('format');
69
- });
70
-
71
- it('should have data update command', () => {
72
- expect(DataUpdate.description).toContain('Update');
73
- expect(DataUpdate.args).toHaveProperty('object');
74
- expect(DataUpdate.args).toHaveProperty('id');
75
- expect(DataUpdate.flags).toHaveProperty('data');
76
- expect(DataUpdate.flags).toHaveProperty('format');
77
- });
78
-
79
- it('should have data delete command', () => {
80
- expect(DataDelete.description).toContain('Delete');
81
- expect(DataDelete.args).toHaveProperty('object');
82
- expect(DataDelete.args).toHaveProperty('id');
83
- expect(DataDelete.flags).toHaveProperty('format');
84
- });
85
-
86
- it('data commands should support common flags', () => {
87
- const commands = [DataQuery, DataGet, DataCreate, DataUpdate, DataDelete];
88
- commands.forEach(cmd => {
89
- expect(cmd.flags).toHaveProperty('url');
90
- expect(cmd.flags).toHaveProperty('token');
91
- });
92
- });
93
-
94
- it('data commands should have examples', () => {
95
- expect(DataQuery.examples).toBeDefined();
96
- expect(DataQuery.examples.length).toBeGreaterThan(0);
97
- expect(DataGet.examples).toBeDefined();
98
- expect(DataCreate.examples).toBeDefined();
99
- expect(DataUpdate.examples).toBeDefined();
100
- expect(DataDelete.examples).toBeDefined();
101
- });
102
- });
103
-
104
- describe('Metadata Commands', () => {
105
- it('should have meta list command', () => {
106
- expect(MetaList.description).toContain('List metadata');
107
- expect(MetaList.args).toHaveProperty('type');
108
- expect(MetaList.flags).toHaveProperty('format');
109
- });
110
-
111
- it('should have meta get command', () => {
112
- expect(MetaGet.description).toContain('Get');
113
- expect(MetaGet.args).toHaveProperty('type');
114
- expect(MetaGet.args).toHaveProperty('name');
115
- expect(MetaGet.flags).toHaveProperty('format');
116
- });
117
-
118
- it('should have meta register command', () => {
119
- expect(MetaRegister.description).toContain('Register');
120
- expect(MetaRegister.args).toHaveProperty('type');
121
- expect(MetaRegister.flags).toHaveProperty('data');
122
- expect(MetaRegister.flags).toHaveProperty('format');
123
- });
124
-
125
- it('should have meta delete command', () => {
126
- expect(MetaDelete.description).toContain('Delete');
127
- expect(MetaDelete.args).toHaveProperty('type');
128
- expect(MetaDelete.args).toHaveProperty('name');
129
- expect(MetaDelete.flags).toHaveProperty('format');
130
- });
131
-
132
- it('meta commands should support common flags', () => {
133
- const commands = [MetaList, MetaGet, MetaRegister, MetaDelete];
134
- commands.forEach(cmd => {
135
- expect(cmd.flags).toHaveProperty('url');
136
- expect(cmd.flags).toHaveProperty('token');
137
- });
138
- });
139
-
140
- it('meta commands should have examples', () => {
141
- expect(MetaList.examples).toBeDefined();
142
- expect(MetaList.examples.length).toBeGreaterThan(0);
143
- expect(MetaGet.examples).toBeDefined();
144
- expect(MetaRegister.examples).toBeDefined();
145
- expect(MetaDelete.examples).toBeDefined();
146
- });
147
- });
148
-
149
- describe('Command Conventions', () => {
150
- it('all remote commands should support --url flag with OBJECTSTACK_URL env var', () => {
151
- const commands = [
152
- AuthLogin, AuthWhoami,
153
- DataQuery, DataGet, DataCreate, DataUpdate, DataDelete,
154
- MetaList, MetaGet, MetaRegister, MetaDelete
155
- ];
156
-
157
- commands.forEach(cmd => {
158
- expect(cmd.flags).toHaveProperty('url');
159
- expect(cmd.flags.url).toHaveProperty('env', 'OBJECTSTACK_URL');
160
- });
161
- });
162
-
163
- it('authenticated commands should support --token flag with OBJECTSTACK_TOKEN env var', () => {
164
- const commands = [
165
- AuthWhoami,
166
- DataQuery, DataGet, DataCreate, DataUpdate, DataDelete,
167
- MetaList, MetaGet, MetaRegister, MetaDelete
168
- ];
169
-
170
- commands.forEach(cmd => {
171
- expect(cmd.flags).toHaveProperty('token');
172
- expect(cmd.flags.token).toHaveProperty('env', 'OBJECTSTACK_TOKEN');
173
- });
174
- });
175
-
176
- it('all commands should support output formatting', () => {
177
- const commands = [
178
- AuthWhoami,
179
- DataQuery, DataGet, DataCreate, DataUpdate, DataDelete,
180
- MetaList, MetaGet, MetaRegister, MetaDelete
181
- ];
182
-
183
- commands.forEach(cmd => {
184
- expect(cmd.flags).toHaveProperty('format');
185
- });
186
- });
187
- });
188
- });
@@ -1,196 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createApiClient, requireAuth } from '../src/utils/api-client';
3
- import { readAuthConfig, writeAuthConfig, deleteAuthConfig, getCredentialsPath } from '../src/utils/auth-config';
4
- import { formatOutput } from '../src/utils/output-formatter';
5
- import * as fs from 'node:fs/promises';
6
-
7
- // Mock fs module
8
- vi.mock('node:fs/promises');
9
-
10
- describe('API Client Utilities', () => {
11
- describe('createApiClient', () => {
12
- it('should use provided URL and token', async () => {
13
- const { client, token } = await createApiClient({
14
- url: 'https://test.example.com',
15
- token: 'test-token',
16
- });
17
-
18
- expect(client).toBeDefined();
19
- expect((client as any).baseUrl).toBe('https://test.example.com');
20
- expect(token).toBe('test-token');
21
- });
22
-
23
- it('should default to localhost when no URL provided', async () => {
24
- const { client } = await createApiClient({});
25
-
26
- expect(client).toBeDefined();
27
- expect((client as any).baseUrl).toBe('http://localhost:3000');
28
- });
29
-
30
- it('should use environment variables if no options provided', async () => {
31
- const originalUrl = process.env.OBJECTSTACK_URL;
32
- const originalToken = process.env.OBJECTSTACK_TOKEN;
33
-
34
- process.env.OBJECTSTACK_URL = 'https://env.example.com';
35
- process.env.OBJECTSTACK_TOKEN = 'env-token';
36
-
37
- const { client, token } = await createApiClient({});
38
-
39
- expect((client as any).baseUrl).toBe('https://env.example.com');
40
- expect(token).toBe('env-token');
41
-
42
- // Restore
43
- process.env.OBJECTSTACK_URL = originalUrl;
44
- process.env.OBJECTSTACK_TOKEN = originalToken;
45
- });
46
- });
47
-
48
- describe('requireAuth', () => {
49
- it('should not throw when token is provided', () => {
50
- expect(() => requireAuth('valid-token')).not.toThrow();
51
- });
52
-
53
- it('should throw when token is missing', () => {
54
- expect(() => requireAuth(undefined)).toThrow(/Authentication required/);
55
- });
56
-
57
- it('should throw when token is empty string', () => {
58
- expect(() => requireAuth('')).toThrow(/Authentication required/);
59
- });
60
- });
61
- });
62
-
63
- describe('Auth Config Utilities', () => {
64
- beforeEach(() => {
65
- vi.clearAllMocks();
66
- });
67
-
68
- describe('getCredentialsPath', () => {
69
- it('should return path to credentials file', () => {
70
- const path = getCredentialsPath();
71
- expect(path).toContain('.objectstack');
72
- expect(path).toContain('credentials.json');
73
- });
74
- });
75
-
76
- describe('writeAuthConfig', () => {
77
- it('should write credentials to file with correct permissions', async () => {
78
- const mockMkdir = vi.mocked(fs.mkdir);
79
- const mockWriteFile = vi.mocked(fs.writeFile);
80
-
81
- const config = {
82
- url: 'https://test.example.com',
83
- token: 'test-token',
84
- email: 'user@example.com',
85
- createdAt: '2024-01-01T00:00:00.000Z',
86
- };
87
-
88
- await writeAuthConfig(config);
89
-
90
- expect(mockMkdir).toHaveBeenCalledWith(
91
- expect.stringContaining('.objectstack'),
92
- { recursive: true }
93
- );
94
-
95
- expect(mockWriteFile).toHaveBeenCalledWith(
96
- expect.stringContaining('credentials.json'),
97
- expect.stringContaining('test-token'),
98
- { mode: 0o600 }
99
- );
100
- });
101
- });
102
-
103
- describe('readAuthConfig', () => {
104
- it('should read and parse credentials file', async () => {
105
- const mockConfig = {
106
- url: 'https://test.example.com',
107
- token: 'test-token',
108
- email: 'user@example.com',
109
- createdAt: '2024-01-01T00:00:00.000Z',
110
- };
111
-
112
- const mockReadFile = vi.mocked(fs.readFile);
113
- mockReadFile.mockResolvedValue(JSON.stringify(mockConfig));
114
-
115
- const config = await readAuthConfig();
116
-
117
- expect(config).toEqual(mockConfig);
118
- });
119
-
120
- it('should throw helpful error when file does not exist', async () => {
121
- const mockReadFile = vi.mocked(fs.readFile);
122
- mockReadFile.mockRejectedValue({ code: 'ENOENT' });
123
-
124
- await expect(readAuthConfig()).rejects.toThrow(/No stored credentials/);
125
- });
126
- });
127
-
128
- describe('deleteAuthConfig', () => {
129
- it('should delete credentials file', async () => {
130
- const mockUnlink = vi.mocked(fs.unlink);
131
- mockUnlink.mockResolvedValue(undefined as any);
132
-
133
- await deleteAuthConfig();
134
-
135
- expect(mockUnlink).toHaveBeenCalled();
136
- expect(mockUnlink).toHaveBeenCalledWith(
137
- expect.stringContaining('credentials.json')
138
- );
139
- });
140
-
141
- it('should not throw if file does not exist', async () => {
142
- const mockUnlink = vi.mocked(fs.unlink);
143
- mockUnlink.mockRejectedValue({ code: 'ENOENT' } as any);
144
-
145
- await expect(deleteAuthConfig()).resolves.not.toThrow();
146
- expect(mockUnlink).toHaveBeenCalled();
147
- });
148
- });
149
- });
150
-
151
- describe('Output Formatter Utilities', () => {
152
- beforeEach(() => {
153
- // Spy on console.log
154
- vi.spyOn(console, 'log').mockImplementation(() => {});
155
- });
156
-
157
- it('should format JSON output', () => {
158
- const data = { name: 'test', value: 123 };
159
- formatOutput(data, 'json');
160
-
161
- expect(console.log).toHaveBeenCalledWith(
162
- expect.stringContaining('"name": "test"')
163
- );
164
- });
165
-
166
- it('should format YAML output', () => {
167
- const data = { name: 'test', value: 123 };
168
- formatOutput(data, 'yaml');
169
-
170
- expect(console.log).toHaveBeenCalled();
171
- });
172
-
173
- it('should format table output for arrays', () => {
174
- const data = [
175
- { name: 'item1', value: 1 },
176
- { name: 'item2', value: 2 },
177
- ];
178
- formatOutput(data, 'table');
179
-
180
- expect(console.log).toHaveBeenCalled();
181
- });
182
-
183
- it('should format table output for single object', () => {
184
- const data = { name: 'test', value: 123 };
185
- formatOutput(data, 'table');
186
-
187
- expect(console.log).toHaveBeenCalled();
188
- });
189
-
190
- it('should handle empty arrays', () => {
191
- const data: any[] = [];
192
- formatOutput(data, 'table');
193
-
194
- expect(console.log).toHaveBeenCalled();
195
- });
196
- });
@@ -1,77 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { isHostConfig } from '../src/utils/plugin-detection';
3
-
4
- /**
5
- * Tests for the host config detection logic used in serve.ts
6
- *
7
- * When the root config is a host/aggregator (i.e. its `plugins` array
8
- * contains already-instantiated Plugin objects), the CLI must NOT wrap
9
- * it again with AppPlugin, as that would cause duplicate registration
10
- * and a `plugin.app.<id> failed to start` error.
11
- */
12
- describe('Host config detection', () => {
13
-
14
- it('should detect host config with instantiated plugins', () => {
15
- const config = {
16
- manifest: { id: 'dev-workspace', name: 'dev_workspace' },
17
- plugins: [
18
- { name: 'objectql', init: async () => {}, start: async () => {} },
19
- { name: 'driver', init: async () => {}, start: async () => {} },
20
- ],
21
- };
22
- expect(isHostConfig(config)).toBe(true);
23
- });
24
-
25
- it('should NOT detect pure app bundle config (no plugins)', () => {
26
- const config = {
27
- manifest: { id: 'my-app', name: 'my_app' },
28
- objects: [{ name: 'task', fields: [] }],
29
- };
30
- expect(isHostConfig(config)).toBe(false);
31
- });
32
-
33
- it('should NOT detect config with empty plugins array', () => {
34
- const config = {
35
- manifest: { id: 'my-app', name: 'my_app' },
36
- objects: [{ name: 'task', fields: [] }],
37
- plugins: [],
38
- };
39
- expect(isHostConfig(config)).toBe(false);
40
- });
41
-
42
- it('should NOT detect config with string plugin references', () => {
43
- const config = {
44
- manifest: { id: 'my-app', name: 'my_app' },
45
- plugins: ['@objectstack/plugin-auth', '@objectstack/objectql'],
46
- };
47
- expect(isHostConfig(config)).toBe(false);
48
- });
49
-
50
- it('should NOT detect config with plain object plugins (no init method)', () => {
51
- const config = {
52
- manifest: { id: 'my-app', name: 'my_app' },
53
- plugins: [
54
- { name: 'some-plugin', version: '1.0.0' },
55
- ],
56
- };
57
- expect(isHostConfig(config)).toBe(false);
58
- });
59
-
60
- it('should detect if at least one plugin has init method', () => {
61
- const config = {
62
- manifest: { id: 'dev-workspace' },
63
- plugins: [
64
- { name: 'plain-bundle', version: '1.0.0' },
65
- { name: 'real-plugin', init: async () => {}, start: async () => {} },
66
- ],
67
- };
68
- expect(isHostConfig(config)).toBe(true);
69
- });
70
-
71
- it('should handle config without plugins property', () => {
72
- const config = {
73
- manifest: { id: 'my-app', name: 'my_app' },
74
- };
75
- expect(isHostConfig(config)).toBe(false);
76
- });
77
- });
@@ -1,20 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
- "ignoreDeprecations": "6.0",
8
- "strict": true,
9
- "esModuleInterop": true,
10
- "skipLibCheck": true,
11
- "forceConsistentCasingInFileNames": true,
12
- "outDir": "dist",
13
- "rootDir": "src",
14
- "declaration": true,
15
- "declarationMap": true,
16
- "sourceMap": true,
17
- "types": ["node"]
18
- },
19
- "include": ["src"]
20
- }
package/tsconfig.json DELETED
@@ -1,25 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": [
7
- "ES2022",
8
- "DOM",
9
- "DOM.Iterable"
10
- ],
11
- "strict": true,
12
- "esModuleInterop": true,
13
- "skipLibCheck": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "outDir": "dist",
16
- "rootDir": "src",
17
- "types": [
18
- "node"
19
- ],
20
- "ignoreDeprecations": "6.0"
21
- },
22
- "include": [
23
- "src"
24
- ]
25
- }