@datalayer/core 0.0.12 → 0.0.13

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 (237) hide show
  1. package/README.md +2 -2
  2. package/lib/api/DatalayerApi.d.ts +38 -26
  3. package/lib/api/DatalayerApi.js +35 -8
  4. package/lib/api/iam/authentication.d.ts +8 -7
  5. package/lib/api/iam/authentication.js +14 -15
  6. package/lib/api/iam/healthz.d.ts +3 -2
  7. package/lib/api/iam/healthz.js +5 -3
  8. package/lib/api/iam/index.d.ts +9 -4
  9. package/lib/api/iam/index.js +9 -4
  10. package/lib/api/iam/oauth2.d.ts +115 -0
  11. package/lib/api/iam/oauth2.js +309 -0
  12. package/lib/api/iam/profile.d.ts +8 -1
  13. package/lib/api/iam/profile.js +17 -2
  14. package/lib/api/iam/usage.d.ts +56 -0
  15. package/lib/api/iam/usage.js +39 -0
  16. package/lib/api/index.d.ts +6 -5
  17. package/lib/api/index.js +6 -5
  18. package/lib/api/runtimes/environments.js +3 -2
  19. package/lib/api/runtimes/healthz.d.ts +3 -13
  20. package/lib/api/runtimes/healthz.js +4 -3
  21. package/lib/api/runtimes/index.d.ts +3 -2
  22. package/lib/api/runtimes/index.js +3 -2
  23. package/lib/api/runtimes/runtimes.js +17 -6
  24. package/lib/api/runtimes/snapshots.js +3 -2
  25. package/lib/api/spacer/documents.d.ts +12 -0
  26. package/lib/api/spacer/documents.js +43 -0
  27. package/lib/api/spacer/healthz.d.ts +3 -13
  28. package/lib/api/spacer/healthz.js +4 -3
  29. package/lib/api/spacer/index.d.ts +4 -2
  30. package/lib/api/spacer/index.js +4 -2
  31. package/lib/api/spacer/items.d.ts +9 -1
  32. package/lib/api/spacer/items.js +17 -2
  33. package/lib/api/spacer/lexicals.js +3 -2
  34. package/lib/api/spacer/notebooks.js +3 -2
  35. package/lib/api/spacer/spaces.js +3 -2
  36. package/lib/api/spacer/users.js +3 -2
  37. package/lib/api/types/common.d.ts +64 -0
  38. package/lib/api/types/iam.d.ts +88 -65
  39. package/lib/api/types/index.d.ts +4 -2
  40. package/lib/api/types/index.js +4 -2
  41. package/lib/api/types/runtimes.d.ts +9 -39
  42. package/lib/api/types/spacer.d.ts +37 -65
  43. package/lib/api/utils/validation.d.ts +24 -1
  44. package/lib/api/utils/validation.js +62 -1
  45. package/lib/client/base.d.ts +75 -0
  46. package/lib/client/base.js +199 -0
  47. package/lib/client/constants.d.ts +22 -0
  48. package/lib/client/constants.js +22 -0
  49. package/lib/client/index.d.ts +108 -0
  50. package/lib/client/index.js +79 -0
  51. package/lib/client/mixins/IAMMixin.d.ts +54 -0
  52. package/lib/client/mixins/IAMMixin.js +181 -0
  53. package/lib/client/mixins/RuntimesMixin.d.ts +93 -0
  54. package/lib/client/mixins/RuntimesMixin.js +229 -0
  55. package/lib/client/mixins/SpacerMixin.d.ts +111 -0
  56. package/lib/client/mixins/SpacerMixin.js +340 -0
  57. package/lib/client/models/Credits.d.ts +91 -0
  58. package/lib/client/models/Credits.js +130 -0
  59. package/lib/client/models/Environment.d.ts +73 -0
  60. package/lib/client/models/Environment.js +88 -0
  61. package/lib/client/models/HealthCheck.d.ts +72 -0
  62. package/lib/client/models/HealthCheck.js +107 -0
  63. package/lib/client/models/Item.d.ts +69 -0
  64. package/lib/client/models/Item.js +191 -0
  65. package/lib/client/models/Lexical.d.ts +83 -0
  66. package/lib/client/models/Lexical.js +152 -0
  67. package/lib/client/models/Notebook.d.ts +87 -0
  68. package/lib/client/models/Notebook.js +153 -0
  69. package/lib/client/models/Runtime.d.ts +122 -0
  70. package/lib/client/models/Runtime.js +204 -0
  71. package/lib/client/models/Snapshot.d.ts +92 -0
  72. package/lib/client/models/Snapshot.js +139 -0
  73. package/lib/client/models/Space.d.ts +135 -0
  74. package/lib/client/models/Space.js +234 -0
  75. package/lib/client/models/User.d.ts +64 -0
  76. package/lib/client/models/User.js +83 -0
  77. package/lib/client/models/index.d.ts +26 -0
  78. package/lib/client/models/index.js +25 -0
  79. package/lib/client/utils/mixins.d.ts +12 -0
  80. package/lib/{sdk/client → client}/utils/mixins.js +0 -28
  81. package/lib/client/utils/spacerUtils.d.ts +18 -0
  82. package/lib/client/utils/spacerUtils.js +32 -0
  83. package/lib/collaboration/DatalayerCollaboration.d.ts +6 -1
  84. package/lib/collaboration/DatalayerCollaboration.js +2 -2
  85. package/lib/collaboration/DatalayerCollaborationProvider.d.ts +5 -0
  86. package/lib/collaboration/DatalayerCollaborationProvider.js +10 -9
  87. package/lib/components/progress/CreditsIndicator.d.ts +1 -1
  88. package/lib/components/runtimes/RuntimeCellVariablesDialog.js +1 -1
  89. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +1 -1
  90. package/lib/components/runtimes/RuntimePickerBase.d.ts +1 -1
  91. package/lib/components/runtimes/RuntimePickerBase.js +1 -1
  92. package/lib/components/runtimes/RuntimePickerCell.js +2 -2
  93. package/lib/components/runtimes/RuntimePickerNotebook.d.ts +1 -1
  94. package/lib/components/runtimes/RuntimePickerNotebook.js +1 -1
  95. package/lib/components/runtimes/RuntimeTransfer.d.ts +1 -1
  96. package/lib/components/runtimes/RuntimeUtils.d.ts +1 -1
  97. package/lib/components/snapshots/RuntimeSnapshotMenu.d.ts +1 -1
  98. package/lib/components/snapshots/RuntimeSnapshotMenu.js +27 -20
  99. package/lib/config/Configuration.d.ts +8 -0
  100. package/lib/hooks/useDatalayer.js +1 -1
  101. package/lib/hooks/useRuntimes.js +1 -1
  102. package/lib/hooks/useToast.js +1 -1
  103. package/lib/index.d.ts +2 -2
  104. package/lib/index.js +4 -2
  105. package/lib/sdk/index.d.ts +5 -4
  106. package/lib/sdk/index.js +6 -5
  107. package/lib/services/DatalayerServiceManager.js +1 -1
  108. package/lib/state/substates/CoreState.js +2 -0
  109. package/lib/state/substates/RuntimesState.d.ts +1 -1
  110. package/lib/state/substates/RuntimesState.js +1 -1
  111. package/lib/{sdk/stateful → stateful}/index.d.ts +1 -1
  112. package/lib/{sdk/stateful → stateful}/index.js +1 -1
  113. package/lib/{sdk/stateful → stateful}/jupyter/exec/Snippets.d.ts +1 -41
  114. package/lib/{sdk/stateful → stateful}/jupyter/exec/Snippets.js +1 -20
  115. package/lib/{sdk/stateful → stateful}/runtimes/actions.d.ts +3 -3
  116. package/lib/{sdk/stateful → stateful}/runtimes/actions.js +8 -8
  117. package/lib/{sdk/stateful → stateful}/runtimes/apis.d.ts +8 -8
  118. package/lib/stateful/runtimes/apis.js +5 -0
  119. package/package.json +12 -10
  120. package/lib/__tests__/hooks.test.d.ts +0 -1
  121. package/lib/__tests__/hooks.test.js +0 -19
  122. package/lib/__tests__/index.test.d.ts +0 -1
  123. package/lib/__tests__/index.test.js +0 -27
  124. package/lib/__tests__/integration.test.d.ts +0 -1
  125. package/lib/__tests__/integration.test.js +0 -57
  126. package/lib/__tests__/shared/cleanup-shared.d.ts +0 -4
  127. package/lib/__tests__/shared/cleanup-shared.js +0 -228
  128. package/lib/__tests__/shared/test-config.d.ts +0 -51
  129. package/lib/__tests__/shared/test-config.js +0 -110
  130. package/lib/__tests__/shared/test-constants.d.ts +0 -66
  131. package/lib/__tests__/shared/test-constants.js +0 -79
  132. package/lib/__tests__/utils.test.d.ts +0 -1
  133. package/lib/__tests__/utils.test.js +0 -59
  134. package/lib/api/__tests__/iam.authentication.integration.test.d.ts +0 -1
  135. package/lib/api/__tests__/iam.authentication.integration.test.js +0 -247
  136. package/lib/api/__tests__/iam.healthz.integration.test.d.ts +0 -1
  137. package/lib/api/__tests__/iam.healthz.integration.test.js +0 -63
  138. package/lib/api/__tests__/iam.profile.integration.test.d.ts +0 -1
  139. package/lib/api/__tests__/iam.profile.integration.test.js +0 -252
  140. package/lib/api/__tests__/runtimes.environments.integration.test.d.ts +0 -1
  141. package/lib/api/__tests__/runtimes.environments.integration.test.js +0 -122
  142. package/lib/api/__tests__/runtimes.healthz.integration.test.d.ts +0 -1
  143. package/lib/api/__tests__/runtimes.healthz.integration.test.js +0 -50
  144. package/lib/api/__tests__/runtimes.integration.test.d.ts +0 -1
  145. package/lib/api/__tests__/runtimes.integration.test.js +0 -369
  146. package/lib/api/__tests__/spacer.healthz.integration.test.d.ts +0 -1
  147. package/lib/api/__tests__/spacer.healthz.integration.test.js +0 -50
  148. package/lib/api/__tests__/spacer.integration.test.d.ts +0 -1
  149. package/lib/api/__tests__/spacer.integration.test.js +0 -519
  150. package/lib/api/iam/__tests__/authentication.unit.test.d.ts +0 -1
  151. package/lib/api/iam/__tests__/authentication.unit.test.js +0 -63
  152. package/lib/api/iam/__tests__/healthz.unit.test.d.ts +0 -1
  153. package/lib/api/iam/__tests__/healthz.unit.test.js +0 -60
  154. package/lib/api/iam/__tests__/profile.unit.test.d.ts +0 -1
  155. package/lib/api/iam/__tests__/profile.unit.test.js +0 -57
  156. package/lib/api/runtimes/__tests__/environments.unit.test.d.ts +0 -1
  157. package/lib/api/runtimes/__tests__/environments.unit.test.js +0 -77
  158. package/lib/api/runtimes/__tests__/healthz.unit.test.d.ts +0 -1
  159. package/lib/api/runtimes/__tests__/healthz.unit.test.js +0 -57
  160. package/lib/api/runtimes/__tests__/runtimes.unit.test.d.ts +0 -1
  161. package/lib/api/runtimes/__tests__/runtimes.unit.test.js +0 -139
  162. package/lib/api/runtimes/__tests__/snapshots.unit.test.d.ts +0 -1
  163. package/lib/api/runtimes/__tests__/snapshots.unit.test.js +0 -96
  164. package/lib/api/spacer/__tests__/healthz.unit.test.d.ts +0 -1
  165. package/lib/api/spacer/__tests__/healthz.unit.test.js +0 -57
  166. package/lib/api/spacer/__tests__/items.unit.test.d.ts +0 -1
  167. package/lib/api/spacer/__tests__/items.unit.test.js +0 -165
  168. package/lib/api/spacer/__tests__/lexicals.unit.test.d.ts +0 -1
  169. package/lib/api/spacer/__tests__/lexicals.unit.test.js +0 -323
  170. package/lib/api/spacer/__tests__/notebooks.unit.test.d.ts +0 -1
  171. package/lib/api/spacer/__tests__/notebooks.unit.test.js +0 -224
  172. package/lib/api/spacer/__tests__/users.unit.test.d.ts +0 -1
  173. package/lib/api/spacer/__tests__/users.unit.test.js +0 -132
  174. package/lib/api/utils/__tests__/validation.test.d.ts +0 -1
  175. package/lib/api/utils/__tests__/validation.test.js +0 -109
  176. package/lib/sdk/client/__tests__/sdk.health.integration.test.d.ts +0 -1
  177. package/lib/sdk/client/__tests__/sdk.health.integration.test.js +0 -110
  178. package/lib/sdk/client/__tests__/sdk.iam.integration.test.d.ts +0 -1
  179. package/lib/sdk/client/__tests__/sdk.iam.integration.test.js +0 -179
  180. package/lib/sdk/client/__tests__/sdk.models.integration.test.d.ts +0 -1
  181. package/lib/sdk/client/__tests__/sdk.models.integration.test.js +0 -376
  182. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.d.ts +0 -1
  183. package/lib/sdk/client/__tests__/sdk.runtimes.integration.test.js +0 -276
  184. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.d.ts +0 -1
  185. package/lib/sdk/client/__tests__/sdk.spacer.integration.test.js +0 -361
  186. package/lib/sdk/client/base.d.ts +0 -88
  187. package/lib/sdk/client/base.js +0 -112
  188. package/lib/sdk/client/index.d.ts +0 -192
  189. package/lib/sdk/client/index.js +0 -128
  190. package/lib/sdk/client/mixins/HealthMixin.d.ts +0 -100
  191. package/lib/sdk/client/mixins/HealthMixin.js +0 -133
  192. package/lib/sdk/client/mixins/IAMMixin.d.ts +0 -59
  193. package/lib/sdk/client/mixins/IAMMixin.js +0 -83
  194. package/lib/sdk/client/mixins/RuntimesMixin.d.ts +0 -134
  195. package/lib/sdk/client/mixins/RuntimesMixin.js +0 -221
  196. package/lib/sdk/client/mixins/SpacerMixin.d.ts +0 -184
  197. package/lib/sdk/client/mixins/SpacerMixin.js +0 -278
  198. package/lib/sdk/client/models/Lexical.d.ts +0 -156
  199. package/lib/sdk/client/models/Lexical.js +0 -275
  200. package/lib/sdk/client/models/Notebook.d.ts +0 -174
  201. package/lib/sdk/client/models/Notebook.js +0 -311
  202. package/lib/sdk/client/models/Runtime.d.ts +0 -221
  203. package/lib/sdk/client/models/Runtime.js +0 -341
  204. package/lib/sdk/client/models/Snapshot.d.ts +0 -156
  205. package/lib/sdk/client/models/Snapshot.js +0 -244
  206. package/lib/sdk/client/models/Space.d.ts +0 -182
  207. package/lib/sdk/client/models/Space.js +0 -276
  208. package/lib/sdk/client/models/__tests__/Lexical.test.d.ts +0 -1
  209. package/lib/sdk/client/models/__tests__/Lexical.test.js +0 -288
  210. package/lib/sdk/client/models/__tests__/Notebook.test.d.ts +0 -1
  211. package/lib/sdk/client/models/__tests__/Notebook.test.js +0 -206
  212. package/lib/sdk/client/models/__tests__/Runtime.test.d.ts +0 -1
  213. package/lib/sdk/client/models/__tests__/Runtime.test.js +0 -133
  214. package/lib/sdk/client/models/__tests__/Snapshot.test.d.ts +0 -1
  215. package/lib/sdk/client/models/__tests__/Snapshot.test.js +0 -244
  216. package/lib/sdk/client/models/__tests__/Space.test.d.ts +0 -1
  217. package/lib/sdk/client/models/__tests__/Space.test.js +0 -334
  218. package/lib/sdk/client/models/index.d.ts +0 -30
  219. package/lib/sdk/client/models/index.js +0 -30
  220. package/lib/sdk/client/utils/mixins.d.ts +0 -42
  221. /package/lib/{sdk/stateful/runtimes/apis.js → api/types/common.js} +0 -0
  222. /package/lib/{sdk/stateful → stateful}/jupyter/exec/Python.d.ts +0 -0
  223. /package/lib/{sdk/stateful → stateful}/jupyter/exec/Python.js +0 -0
  224. /package/lib/{sdk/stateful → stateful}/jupyter/exec/index.d.ts +0 -0
  225. /package/lib/{sdk/stateful → stateful}/jupyter/exec/index.js +0 -0
  226. /package/lib/{sdk/stateful → stateful}/jupyter/index.d.ts +0 -0
  227. /package/lib/{sdk/stateful → stateful}/jupyter/index.js +0 -0
  228. /package/lib/{sdk/stateful → stateful}/jupyter/kernelsHandler.d.ts +0 -0
  229. /package/lib/{sdk/stateful → stateful}/jupyter/kernelsHandler.js +0 -0
  230. /package/lib/{sdk/stateful → stateful}/runtimes/index.d.ts +0 -0
  231. /package/lib/{sdk/stateful → stateful}/runtimes/index.js +0 -0
  232. /package/lib/{sdk/stateful → stateful}/runtimes/settings.d.ts +0 -0
  233. /package/lib/{sdk/stateful → stateful}/runtimes/settings.js +0 -0
  234. /package/lib/{sdk/stateful → stateful}/runtimes/snapshots.d.ts +0 -0
  235. /package/lib/{sdk/stateful → stateful}/runtimes/snapshots.js +0 -0
  236. /package/lib/{sdk/stateful → stateful}/runtimes/utils.d.ts +0 -0
  237. /package/lib/{sdk/stateful → stateful}/runtimes/utils.js +0 -0
@@ -1,224 +0,0 @@
1
- /*
2
- * Copyright (c) 2023-2025 Datalayer, Inc.
3
- * Distributed under the terms of the Modified BSD License.
4
- */
5
- import { describe, it, expect, vi, beforeEach } from 'vitest';
6
- import { notebooks } from '..';
7
- import * as DatalayerApi from '../../DatalayerApi';
8
- import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../../constants';
9
- import { MOCK_JWT_TOKEN } from '../../../__tests__/shared/test-constants';
10
- // Mock the DatalayerApi module
11
- vi.mock('../../DatalayerApi', () => ({
12
- requestDatalayerAPI: vi.fn(),
13
- }));
14
- describe('Spacer Notebooks Unit Tests', () => {
15
- beforeEach(() => {
16
- vi.clearAllMocks();
17
- });
18
- describe('create', () => {
19
- const mockCreateResponse = {
20
- success: true,
21
- message: 'Notebook created successfully',
22
- notebook: {
23
- id: 'notebook-123',
24
- uid: 'uid-notebook-123',
25
- name: 'Test Notebook',
26
- path: '/notebooks/test-notebook',
27
- space_id: 'space-456',
28
- owner_id: 'user-789',
29
- created_at: '2024-01-01T00:00:00Z',
30
- },
31
- };
32
- it('should successfully create a notebook with FormData', async () => {
33
- console.log('Testing notebook creation with FormData...');
34
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
35
- mockedRequest.mockResolvedValue(mockCreateResponse);
36
- const notebookData = {
37
- spaceId: 'space-456',
38
- notebookType: 'jupyter',
39
- name: 'Test Notebook',
40
- description: 'A test notebook',
41
- };
42
- const result = await notebooks.createNotebook(MOCK_JWT_TOKEN, notebookData, DEFAULT_SERVICE_URLS.SPACER);
43
- expect(mockedRequest).toHaveBeenCalledTimes(1);
44
- // Check that FormData was passed as the body
45
- const callArgs = mockedRequest.mock.calls[0][0];
46
- expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks`);
47
- expect(callArgs.method).toBe('POST');
48
- expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
49
- expect(callArgs.body).toBeInstanceOf(FormData);
50
- expect(result).toEqual(mockCreateResponse);
51
- expect(result.success).toBe(true);
52
- expect(result.notebook.name).toBe('Test Notebook');
53
- console.log('Notebook created successfully');
54
- });
55
- it('should handle FormData with file attachment', async () => {
56
- console.log('Testing notebook creation with file...');
57
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
58
- mockedRequest.mockResolvedValue(mockCreateResponse);
59
- const file = new File(['notebook content'], 'test.ipynb', {
60
- type: 'application/json',
61
- });
62
- const notebookData = {
63
- spaceId: 'space-456',
64
- notebookType: 'jupyter',
65
- name: 'Test Notebook',
66
- description: 'A test notebook',
67
- file,
68
- };
69
- await notebooks.createNotebook(MOCK_JWT_TOKEN, notebookData, DEFAULT_SERVICE_URLS.SPACER);
70
- const callArgs = mockedRequest.mock.calls[0][0];
71
- expect(callArgs.url).toBe(`${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks`);
72
- expect(callArgs.method).toBe('POST');
73
- expect(callArgs.token).toBe(MOCK_JWT_TOKEN);
74
- expect(callArgs.body).toBeInstanceOf(FormData);
75
- console.log('Notebook with file created successfully');
76
- });
77
- it('should handle API errors during creation', async () => {
78
- console.log('Testing notebook creation with API error...');
79
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
80
- mockedRequest.mockRejectedValue(new Error('API Error'));
81
- const formData = new FormData();
82
- formData.append('spaceId', 'space-456');
83
- formData.append('notebookType', 'jupyter');
84
- formData.append('name', 'Test Notebook');
85
- formData.append('description', 'A test notebook');
86
- await expect(notebooks.createNotebook(MOCK_JWT_TOKEN, formData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('API Error');
87
- console.log('API error handled correctly');
88
- });
89
- });
90
- describe('get', () => {
91
- const mockGetResponse = {
92
- success: true,
93
- message: 'Notebook retrieved successfully',
94
- notebook: {
95
- id: 'notebook-123',
96
- uid: 'uid-notebook-123',
97
- name: 'Test Notebook',
98
- path: '/notebooks/test-notebook',
99
- space_id: 'space-456',
100
- owner_id: 'user-789',
101
- created_at: '2024-01-01T00:00:00Z',
102
- updated_at: '2024-01-02T00:00:00Z',
103
- },
104
- };
105
- it('should successfully get a notebook by ID', async () => {
106
- console.log('Testing get notebook by ID...');
107
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
108
- mockedRequest.mockResolvedValue(mockGetResponse);
109
- const result = await notebooks.getNotebook(MOCK_JWT_TOKEN, 'notebook-123', DEFAULT_SERVICE_URLS.SPACER);
110
- expect(mockedRequest).toHaveBeenCalledTimes(1);
111
- expect(mockedRequest).toHaveBeenCalledWith({
112
- url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
113
- method: 'GET',
114
- token: MOCK_JWT_TOKEN,
115
- });
116
- expect(result).toEqual(mockGetResponse);
117
- expect(result.success).toBe(true);
118
- expect(result.notebook?.id).toBe('notebook-123');
119
- console.log('Notebook retrieved successfully');
120
- });
121
- it('should handle notebook not found (404)', async () => {
122
- console.log('Testing get notebook with 404...');
123
- const notFoundResponse = {
124
- success: false,
125
- message: 'Notebook not found',
126
- };
127
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
128
- mockedRequest.mockResolvedValue(notFoundResponse);
129
- const result = await notebooks.getNotebook(MOCK_JWT_TOKEN, 'nonexistent-notebook', DEFAULT_SERVICE_URLS.SPACER);
130
- expect(result).toEqual(notFoundResponse);
131
- expect(result.success).toBe(false);
132
- expect(result.notebook).toBeUndefined();
133
- console.log('404 response handled correctly');
134
- });
135
- it('should handle API errors during get', async () => {
136
- console.log('Testing get notebook with API error...');
137
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
138
- mockedRequest.mockRejectedValue(new Error('Network error'));
139
- await expect(notebooks.getNotebook(MOCK_JWT_TOKEN, 'notebook-123', DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Network error');
140
- console.log('API error handled correctly');
141
- });
142
- });
143
- describe('update', () => {
144
- const mockUpdateResponse = {
145
- success: true,
146
- message: 'Notebook updated successfully',
147
- notebook: {
148
- id: 'notebook-123',
149
- uid: 'uid-notebook-123',
150
- name: 'Updated Notebook',
151
- path: '/notebooks/updated-notebook',
152
- space_id: 'space-456',
153
- owner_id: 'user-789',
154
- created_at: '2024-01-01T00:00:00Z',
155
- updated_at: '2024-01-03T00:00:00Z',
156
- },
157
- };
158
- it('should successfully update a notebook name', async () => {
159
- console.log('Testing update notebook name...');
160
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
161
- mockedRequest.mockResolvedValue(mockUpdateResponse);
162
- const updateData = {
163
- name: 'Updated Notebook',
164
- };
165
- const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
166
- expect(mockedRequest).toHaveBeenCalledTimes(1);
167
- expect(mockedRequest).toHaveBeenCalledWith({
168
- url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
169
- method: 'PUT',
170
- token: MOCK_JWT_TOKEN,
171
- body: updateData,
172
- });
173
- expect(result).toEqual(mockUpdateResponse);
174
- expect(result.success).toBe(true);
175
- expect(result.notebook.name).toBe('Updated Notebook');
176
- console.log('Notebook name updated successfully');
177
- });
178
- it('should successfully update a notebook description', async () => {
179
- console.log('Testing update notebook description...');
180
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
181
- mockedRequest.mockResolvedValue(mockUpdateResponse);
182
- const updateData = {
183
- description: 'Updated description',
184
- };
185
- const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
186
- expect(mockedRequest).toHaveBeenCalledWith({
187
- url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
188
- method: 'PUT',
189
- token: MOCK_JWT_TOKEN,
190
- body: updateData,
191
- });
192
- expect(result.success).toBe(true);
193
- console.log('Notebook description updated successfully');
194
- });
195
- it('should successfully update both name and description', async () => {
196
- console.log('Testing update notebook name and description...');
197
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
198
- mockedRequest.mockResolvedValue(mockUpdateResponse);
199
- const updateData = {
200
- name: 'Updated Notebook',
201
- description: 'Updated description',
202
- };
203
- const result = await notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER);
204
- expect(mockedRequest).toHaveBeenCalledWith({
205
- url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/notebooks/notebook-123`,
206
- method: 'PUT',
207
- token: MOCK_JWT_TOKEN,
208
- body: updateData,
209
- });
210
- expect(result.success).toBe(true);
211
- console.log('Notebook name and description updated successfully');
212
- });
213
- it('should handle API errors during update', async () => {
214
- console.log('Testing update notebook with API error...');
215
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
216
- mockedRequest.mockRejectedValue(new Error('Update failed'));
217
- const updateData = {
218
- name: 'Updated Notebook',
219
- };
220
- await expect(notebooks.updateNotebook(MOCK_JWT_TOKEN, 'notebook-123', updateData, DEFAULT_SERVICE_URLS.SPACER)).rejects.toThrow('Update failed');
221
- console.log('API error handled correctly');
222
- });
223
- });
224
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,132 +0,0 @@
1
- /*
2
- * Copyright (c) 2023-2025 Datalayer, Inc.
3
- * Distributed under the terms of the Modified BSD License.
4
- */
5
- import { describe, it, expect, vi, beforeEach } from 'vitest';
6
- import { users } from '..';
7
- import * as DatalayerApi from '../../DatalayerApi';
8
- import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../../constants';
9
- import { MOCK_JWT_TOKEN } from '../../../__tests__/shared/test-constants';
10
- // Mock the DatalayerApi module
11
- vi.mock('../../DatalayerApi', () => ({
12
- requestDatalayerAPI: vi.fn(),
13
- }));
14
- describe('Spacer Users Unit Tests', () => {
15
- beforeEach(() => {
16
- vi.clearAllMocks();
17
- });
18
- describe('getMySpaces', () => {
19
- const mockSpacesResponse = {
20
- success: true,
21
- message: 'Spaces retrieved successfully',
22
- spaces: [
23
- {
24
- id: 'space-1',
25
- uid: 'uid-space-1',
26
- name: 'My First Space',
27
- description: 'A test space',
28
- owner_id: 'user-123',
29
- created_at: '2024-01-01T00:00:00Z',
30
- updated_at: '2024-01-02T00:00:00Z',
31
- },
32
- {
33
- id: 'space-2',
34
- uid: 'uid-space-2',
35
- name: 'My Second Space',
36
- description: 'Another test space',
37
- owner_id: 'user-123',
38
- created_at: '2024-01-03T00:00:00Z',
39
- updated_at: '2024-01-04T00:00:00Z',
40
- },
41
- ],
42
- };
43
- it('should successfully get user spaces', async () => {
44
- console.log('Testing getMySpaces with valid token...');
45
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
46
- mockedRequest.mockResolvedValue(mockSpacesResponse);
47
- const result = await users.getMySpaces(MOCK_JWT_TOKEN);
48
- expect(mockedRequest).toHaveBeenCalledTimes(1);
49
- expect(mockedRequest).toHaveBeenCalledWith({
50
- url: `${DEFAULT_SERVICE_URLS.SPACER}${API_BASE_PATHS.SPACER}/spaces/users/me`,
51
- method: 'GET',
52
- token: MOCK_JWT_TOKEN,
53
- });
54
- expect(result).toEqual(mockSpacesResponse);
55
- expect(result.spaces).toHaveLength(2);
56
- console.log('Successfully retrieved user spaces');
57
- });
58
- it('should use custom base URL when provided', async () => {
59
- console.log('Testing getMySpaces with custom base URL...');
60
- const customUrl = 'https://custom.spacer.api';
61
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
62
- mockedRequest.mockResolvedValue(mockSpacesResponse);
63
- await users.getMySpaces(MOCK_JWT_TOKEN, customUrl);
64
- expect(mockedRequest).toHaveBeenCalledWith({
65
- url: `${customUrl}${API_BASE_PATHS.SPACER}/spaces/users/me`,
66
- method: 'GET',
67
- token: MOCK_JWT_TOKEN,
68
- });
69
- console.log('Custom base URL used correctly');
70
- });
71
- it('should handle empty spaces list', async () => {
72
- console.log('Testing getMySpaces with empty response...');
73
- const emptyResponse = {
74
- success: true,
75
- message: 'No spaces found for user',
76
- spaces: [],
77
- };
78
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
79
- mockedRequest.mockResolvedValue(emptyResponse);
80
- const result = await users.getMySpaces(MOCK_JWT_TOKEN);
81
- expect(result).toEqual(emptyResponse);
82
- expect(result.spaces).toHaveLength(0);
83
- console.log('Empty spaces list handled correctly');
84
- });
85
- it('should fail when token is missing', async () => {
86
- console.log('Testing getMySpaces with missing token...');
87
- await expect(
88
- // @ts-expect-error Testing undefined token
89
- users.getMySpaces(undefined)).rejects.toThrow('Authentication token is required');
90
- console.log('Correctly rejected missing token');
91
- });
92
- it('should fail when token is empty', async () => {
93
- console.log('Testing getMySpaces with empty token...');
94
- await expect(users.getMySpaces('')).rejects.toThrow('Authentication token is required');
95
- console.log('Correctly rejected empty token');
96
- });
97
- it('should fail when token is only whitespace', async () => {
98
- console.log('Testing getMySpaces with whitespace token...');
99
- await expect(users.getMySpaces(' ')).rejects.toThrow('Authentication token is required');
100
- console.log('Correctly rejected whitespace token');
101
- });
102
- it('should fail when token is null', async () => {
103
- console.log('Testing getMySpaces with null token...');
104
- await expect(
105
- // @ts-expect-error Testing null token
106
- users.getMySpaces(null)).rejects.toThrow('Authentication token is required');
107
- console.log('Correctly rejected null token');
108
- });
109
- it('should handle API errors gracefully', async () => {
110
- console.log('Testing getMySpaces with API error...');
111
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
112
- mockedRequest.mockRejectedValue(new Error('Network error'));
113
- await expect(users.getMySpaces(MOCK_JWT_TOKEN)).rejects.toThrow('Network error');
114
- console.log('API error handled correctly');
115
- });
116
- it('should handle malformed response', async () => {
117
- console.log('Testing getMySpaces with malformed response...');
118
- const malformedResponse = {
119
- success: false,
120
- message: 'Invalid response format',
121
- // spaces array is missing
122
- };
123
- const mockedRequest = vi.mocked(DatalayerApi.requestDatalayerAPI);
124
- mockedRequest.mockResolvedValue(malformedResponse);
125
- const result = await users.getMySpaces(MOCK_JWT_TOKEN);
126
- expect(result).toEqual(malformedResponse);
127
- // Should not throw, but spaces will be undefined
128
- expect(result.spaces).toBeUndefined();
129
- console.log('Malformed response handled gracefully');
130
- });
131
- });
132
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,109 +0,0 @@
1
- /*
2
- * Copyright (c) 2023-2025 Datalayer, Inc.
3
- * Distributed under the terms of the Modified BSD License.
4
- */
5
- import { describe, it, expect } from 'vitest';
6
- import { validateToken, validateRequired, validateRequiredString, } from '../validation';
7
- describe('validation utilities', () => {
8
- describe('validateToken', () => {
9
- const validToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjk5OTk5OTk5OTl9.Vg30C57s3l90JNap_VgMhKZjfc-p7SoBXaSAy8c6BS8';
10
- it('should accept valid JWT tokens', () => {
11
- expect(() => validateToken(validToken)).not.toThrow();
12
- });
13
- it('should reject null or undefined tokens', () => {
14
- expect(() => validateToken(null)).toThrow('Authentication token is required');
15
- expect(() => validateToken(undefined)).toThrow('Authentication token is required');
16
- });
17
- it('should reject empty or whitespace tokens', () => {
18
- expect(() => validateToken('')).toThrow('Authentication token is required');
19
- expect(() => validateToken(' ')).toThrow('Authentication token is required');
20
- });
21
- it('should reject tokens without three parts', () => {
22
- expect(() => validateToken('part1.part2')).toThrow('Invalid token format: JWT must have three parts separated by dots');
23
- expect(() => validateToken('part1.part2.part3.part4')).toThrow('Invalid token format: JWT must have three parts separated by dots');
24
- expect(() => validateToken('singlepart')).toThrow('Invalid token format: JWT must have three parts separated by dots');
25
- });
26
- it('should reject tokens with empty parts', () => {
27
- expect(() => validateToken('.part2.part3')).toThrow('Invalid token format: Part 1 is empty');
28
- expect(() => validateToken('part1..part3')).toThrow('Invalid token format: Part 2 is empty');
29
- expect(() => validateToken('part1.part2.')).toThrow('Invalid token format: Part 3 is empty');
30
- });
31
- it('should reject tokens with invalid Base64URL characters', () => {
32
- const invalidCharToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWI!@#$.Vg30C57s3l90JNap_VgMhKZjfc-p7SoBXaSAy8c6BS8';
33
- expect(() => validateToken(invalidCharToken)).toThrow('Invalid token format: Part 2 contains invalid characters');
34
- });
35
- it('should reject tokens that are too short', () => {
36
- const shortToken = 'eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxIn0.signature';
37
- expect(() => validateToken(shortToken)).toThrow('Invalid token format: Token is too short to be a valid JWT');
38
- });
39
- it('should reject tokens that are too long', () => {
40
- const header = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9';
41
- const payload = 'a'.repeat(4000);
42
- const signature = 'b'.repeat(1000);
43
- const longToken = `${header}.${payload}.${signature}`;
44
- expect(() => validateToken(longToken)).toThrow('Invalid token format: Token exceeds maximum expected length');
45
- });
46
- it('should reject tokens with invalid JWT header', () => {
47
- const invalidHeaderToken = 'notbase64.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.signature123456789012345';
48
- expect(() => validateToken(invalidHeaderToken)).toThrow('Invalid token format: JWT header is not valid base64-encoded JSON');
49
- });
50
- it('should reject tokens with missing algorithm in header', () => {
51
- // This token has valid JSON header but missing 'alg' field
52
- const noAlgToken = 'eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjk5OTk5OTk5OTl9.signature123456789012345678901234567890';
53
- expect(() => validateToken(noAlgToken)).toThrow('Invalid token format: Missing algorithm in JWT header');
54
- });
55
- it('should reject tokens with invalid JWT payload', () => {
56
- // This token has enough length but invalid base64 in payload
57
- const invalidPayloadToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.notvalidbase64jsonbutlongenoughtopasslengthchecknotvalidbase64jsonbutlongenough.signature123456789012345678901234567890';
58
- expect(() => validateToken(invalidPayloadToken)).toThrow('Invalid token format: JWT payload is not valid base64-encoded JSON');
59
- });
60
- it('should reject expired tokens', () => {
61
- const expiredToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.4Adcj3UFYzPUVaVF43FmMab6RlaQD8A9V8wFzzht-KQ';
62
- expect(() => validateToken(expiredToken)).toThrow('Token has expired');
63
- });
64
- it('should reject tokens not yet valid (nbf claim)', () => {
65
- const futureToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJuYmYiOjk5OTk5OTk5OTl9.UGLFIRACvGl-MiFpZmAiDuVm7br9tBTxMOqb4sjN-jg';
66
- expect(() => validateToken(futureToken)).toThrow('Token is not yet valid');
67
- });
68
- it('should reject tokens with signature that is too short', () => {
69
- const shortSigToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.short';
70
- expect(() => validateToken(shortSigToken)).toThrow('Invalid token format: JWT signature is too short');
71
- });
72
- it('should trim whitespace from tokens', () => {
73
- const tokenWithWhitespace = ` ${validToken} `;
74
- expect(() => validateToken(tokenWithWhitespace)).not.toThrow();
75
- });
76
- });
77
- describe('validateRequired', () => {
78
- it('should accept valid values', () => {
79
- expect(() => validateRequired('value', 'param')).not.toThrow();
80
- expect(() => validateRequired(0, 'param')).not.toThrow();
81
- expect(() => validateRequired(false, 'param')).not.toThrow();
82
- expect(() => validateRequired('', 'param')).not.toThrow();
83
- });
84
- it('should reject null values', () => {
85
- expect(() => validateRequired(null, 'param')).toThrow('param is required');
86
- });
87
- it('should reject undefined values', () => {
88
- expect(() => validateRequired(undefined, 'param')).toThrow('param is required');
89
- });
90
- });
91
- describe('validateRequiredString', () => {
92
- it('should accept valid strings', () => {
93
- expect(() => validateRequiredString('value', 'param')).not.toThrow();
94
- expect(() => validateRequiredString(' value ', 'param')).not.toThrow();
95
- });
96
- it('should reject null values', () => {
97
- expect(() => validateRequiredString(null, 'param')).toThrow('param is required');
98
- });
99
- it('should reject undefined values', () => {
100
- expect(() => validateRequiredString(undefined, 'param')).toThrow('param is required');
101
- });
102
- it('should reject empty strings', () => {
103
- expect(() => validateRequiredString('', 'param')).toThrow('param is required');
104
- });
105
- it('should reject whitespace-only strings', () => {
106
- expect(() => validateRequiredString(' ', 'param')).toThrow('param is required');
107
- });
108
- });
109
- });
@@ -1,110 +0,0 @@
1
- /*
2
- * Copyright (c) 2023-2025 Datalayer, Inc.
3
- * Distributed under the terms of the Modified BSD License.
4
- */
5
- import { describe, it, expect, beforeAll } from 'vitest';
6
- import { DatalayerSDK } from '..';
7
- import { testConfig } from '../../../__tests__/shared/test-config';
8
- import { DEFAULT_SERVICE_URLS } from '../../../api/constants';
9
- /**
10
- * SDK Health Integration Tests
11
- *
12
- * Tests health check functionality across all Datalayer services
13
- * using the SDK client.
14
- */
15
- describe('SDK Health Integration Tests', () => {
16
- let sdk;
17
- beforeAll(() => {
18
- if (!testConfig.hasToken()) {
19
- return;
20
- }
21
- sdk = new DatalayerSDK({
22
- token: testConfig.getToken(),
23
- iamRunUrl: DEFAULT_SERVICE_URLS.IAM,
24
- runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
25
- spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
26
- });
27
- });
28
- describe.skipIf(!testConfig.hasToken())('health check methods', () => {
29
- describe('individual service health checks', () => {
30
- it('should check IAM service health', async () => {
31
- console.log('Testing IAM health check...');
32
- const isHealthy = await sdk.isIAMHealthy();
33
- expect(isHealthy).toBe(true);
34
- console.log(`IAM service is ${isHealthy ? 'healthy' : 'unhealthy'}`);
35
- });
36
- it('should check Runtimes service health', async () => {
37
- console.log('Testing Runtimes health check...');
38
- const isHealthy = await sdk.isRuntimesHealthy();
39
- expect(isHealthy).toBe(true);
40
- console.log(`Runtimes service is ${isHealthy ? 'healthy' : 'unhealthy'}`);
41
- });
42
- it('should check Spacer service health', async () => {
43
- console.log('Testing Spacer health check...');
44
- const isHealthy = await sdk.isSpacerHealthy();
45
- expect(isHealthy).toBe(true);
46
- console.log(`Spacer service is ${isHealthy ? 'healthy' : 'unhealthy'}`);
47
- });
48
- });
49
- describe('combined health checks', () => {
50
- it('should check all services health at once', async () => {
51
- console.log('Testing all services health check...');
52
- const allHealthy = await sdk.areAllServicesHealthy();
53
- expect(allHealthy).toBe(true);
54
- console.log(`All services are ${allHealthy ? 'healthy' : 'not all healthy'}`);
55
- });
56
- it('should get detailed health status for all services', async () => {
57
- console.log('Getting detailed health status...');
58
- const status = await sdk.getHealthStatus();
59
- expect(status).toBeDefined();
60
- expect(status.iam).toBeDefined();
61
- expect(status.runtimes).toBeDefined();
62
- expect(status.spacer).toBeDefined();
63
- expect(status.allHealthy).toBeDefined();
64
- console.log('Health Status:');
65
- console.log(` IAM: ${status.iam.healthy ? '✅' : '❌'}`);
66
- if (status.iam.version) {
67
- console.log(` Version: ${status.iam.version}`);
68
- }
69
- console.log(` Runtimes: ${status.runtimes.healthy ? '✅' : '❌'}`);
70
- if (status.runtimes.version) {
71
- console.log(` Version: ${status.runtimes.version}`);
72
- }
73
- console.log(` Spacer: ${status.spacer.healthy ? '✅' : '❌'}`);
74
- if (status.spacer.version) {
75
- console.log(` Version: ${status.spacer.version}`);
76
- }
77
- console.log(` Overall: ${status.allHealthy ? '✅ All Healthy' : '⚠️ Some Issues'}`);
78
- });
79
- });
80
- describe('error handling', () => {
81
- it('should handle network errors gracefully', async () => {
82
- console.log('Testing health check with invalid URL...');
83
- // Create SDK with invalid URL
84
- const badSdk = new DatalayerSDK({
85
- token: testConfig.getToken(),
86
- iamRunUrl: 'https://invalid.example.com',
87
- runtimesRunUrl: DEFAULT_SERVICE_URLS.RUNTIMES,
88
- spacerRunUrl: DEFAULT_SERVICE_URLS.SPACER,
89
- });
90
- const isHealthy = await badSdk.isIAMHealthy();
91
- expect(isHealthy).toBe(false);
92
- const status = await badSdk.getHealthStatus();
93
- expect(status.iam.healthy).toBe(false);
94
- expect(status.allHealthy).toBe(false);
95
- console.log('Network error handled correctly');
96
- });
97
- });
98
- describe('configuration validation', () => {
99
- it('should use configured service URLs', async () => {
100
- console.log('Verifying SDK uses configured URLs...');
101
- // The SDK should be using the URLs we configured
102
- const config = sdk.getConfig();
103
- expect(config.iamRunUrl).toBe(DEFAULT_SERVICE_URLS.IAM);
104
- expect(config.runtimesRunUrl).toBe(DEFAULT_SERVICE_URLS.RUNTIMES);
105
- expect(config.spacerRunUrl).toBe(DEFAULT_SERVICE_URLS.SPACER);
106
- console.log('SDK configuration verified');
107
- });
108
- });
109
- });
110
- });