@managespace/sdk 0.1.157 → 0.1.158-extensions

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 (70) hide show
  1. package/README.md +723 -2
  2. package/dist/extensibility/functions/project/billing.d.ts +12 -19
  3. package/dist/extensibility/functions/project/billing.d.ts.map +1 -1
  4. package/dist/extensibility/functions/project/billing.js +0 -5
  5. package/dist/extensibility/types/control.d.ts +1 -1
  6. package/dist/extensibility/types/control.d.ts.map +1 -1
  7. package/dist/extensions/host-bridge.d.ts +166 -0
  8. package/dist/extensions/host-bridge.d.ts.map +1 -0
  9. package/dist/extensions/host-bridge.js +259 -0
  10. package/dist/extensions/index.d.ts +40 -0
  11. package/dist/extensions/index.d.ts.map +1 -0
  12. package/dist/extensions/index.js +55 -0
  13. package/dist/extensions/types.d.ts +111 -0
  14. package/dist/extensions/types.d.ts.map +1 -0
  15. package/dist/extensions/types.js +2 -0
  16. package/dist/generated/apis/default-api.d.ts +1 -9
  17. package/dist/generated/apis/default-api.d.ts.map +1 -1
  18. package/dist/generated/apis/default-api.js +0 -28
  19. package/dist/generated/apis/extensions-api.d.ts +98 -0
  20. package/dist/generated/apis/extensions-api.d.ts.map +1 -0
  21. package/dist/generated/apis/extensions-api.js +295 -0
  22. package/dist/generated/apis/index.d.ts +1 -0
  23. package/dist/generated/apis/index.d.ts.map +1 -1
  24. package/dist/generated/apis/index.js +1 -0
  25. package/dist/generated/models/contact.d.ts +1 -1
  26. package/dist/generated/models/contact.d.ts.map +1 -1
  27. package/dist/generated/models/contact.js +3 -3
  28. package/dist/generated/models/customer.d.ts +1 -1
  29. package/dist/generated/models/customer.d.ts.map +1 -1
  30. package/dist/generated/models/customer.js +3 -3
  31. package/dist/generated/models/extension-org.d.ts +64 -0
  32. package/dist/generated/models/extension-org.d.ts.map +1 -0
  33. package/dist/generated/models/extension-org.js +70 -0
  34. package/dist/generated/models/extension.d.ts +106 -0
  35. package/dist/generated/models/extension.d.ts.map +1 -0
  36. package/dist/generated/models/extension.js +98 -0
  37. package/dist/generated/models/index.d.ts +2 -1
  38. package/dist/generated/models/index.d.ts.map +1 -1
  39. package/dist/generated/models/index.js +2 -1
  40. package/dist/generated/models/subscription-preview.d.ts +1 -1
  41. package/dist/generated/models/subscription-preview.d.ts.map +1 -1
  42. package/dist/generated/models/subscription-preview.js +3 -3
  43. package/dist/generated/models/subscription.d.ts +1 -1
  44. package/dist/generated/models/subscription.d.ts.map +1 -1
  45. package/dist/generated/models/subscription.js +3 -3
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -0
  49. package/package.json +7 -3
  50. package/src/extensibility/functions/project/billing.ts +12 -18
  51. package/src/extensibility/types/control.ts +0 -1
  52. package/src/extensions/host-bridge.ts +272 -0
  53. package/src/extensions/index.ts +40 -0
  54. package/src/extensions/types.ts +120 -0
  55. package/src/generated/.openapi-generator/FILES +3 -1
  56. package/src/generated/apis/default-api.ts +0 -37
  57. package/src/generated/apis/extensions-api.ts +362 -0
  58. package/src/generated/apis/index.ts +1 -0
  59. package/src/generated/models/contact.ts +4 -4
  60. package/src/generated/models/customer.ts +4 -4
  61. package/src/generated/models/extension-org.ts +119 -0
  62. package/src/generated/models/extension.ts +182 -0
  63. package/src/generated/models/index.ts +2 -1
  64. package/src/generated/models/subscription-preview.ts +4 -4
  65. package/src/generated/models/subscription.ts +4 -4
  66. package/src/index.ts +1 -0
  67. package/dist/generated/models/payment-gateway-client-token-response.d.ts +0 -47
  68. package/dist/generated/models/payment-gateway-client-token-response.d.ts.map +0 -1
  69. package/dist/generated/models/payment-gateway-client-token-response.js +0 -63
  70. package/src/generated/models/payment-gateway-client-token-response.ts +0 -87
@@ -0,0 +1,272 @@
1
+ import type {
2
+ EntityEvent,
3
+ EntityEventHandler,
4
+ ExtensionContext,
5
+ ExtensionMessage,
6
+ HostMessage,
7
+ } from './types';
8
+
9
+ let contextResolve: ((context: ExtensionContext) => void) | null = null;
10
+ let currentContext: ExtensionContext | null = null;
11
+ const entityEventHandlers: Set<EntityEventHandler> = new Set();
12
+
13
+ // Set up message listener when this module loads
14
+ if (typeof window !== 'undefined') {
15
+ window.addEventListener('message', (event: MessageEvent<HostMessage>) => {
16
+ if (!event.data?.type) return;
17
+
18
+ switch (event.data.type) {
19
+ case 'CONTEXT_INIT':
20
+ currentContext = event.data.payload;
21
+ if (contextResolve) {
22
+ contextResolve(event.data.payload);
23
+ contextResolve = null;
24
+ }
25
+ break;
26
+
27
+ case 'ENTITY_EVENT':
28
+ for (const handler of entityEventHandlers) {
29
+ try {
30
+ handler(event.data.payload);
31
+ } catch (error) {
32
+ console.error('Entity event handler error:', error);
33
+ }
34
+ }
35
+ break;
36
+ }
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Get the extension context from the ManageSpace host.
42
+ *
43
+ * This returns a promise that resolves when the context is received from the host.
44
+ * Call this early in your extension's lifecycle to get authentication and org context.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * import { getContext } from '@managespace/sdk/extensions';
49
+ *
50
+ * const context = await getContext();
51
+ * console.log('Org ID:', context.orgId);
52
+ * console.log('API URL:', context.apiBaseUrl);
53
+ * ```
54
+ */
55
+ export function getContext(): Promise<ExtensionContext> {
56
+ if (currentContext) {
57
+ return Promise.resolve(currentContext);
58
+ }
59
+
60
+ return new Promise((resolve) => {
61
+ contextResolve = resolve;
62
+ });
63
+ }
64
+
65
+ /**
66
+ * Get the current context synchronously.
67
+ *
68
+ * Returns null if the context has not yet been received from the host.
69
+ * Prefer using `getContext()` which waits for the context to be available.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * import { getCurrentContext } from '@managespace/sdk/extensions';
74
+ *
75
+ * const context = getCurrentContext();
76
+ * if (context) {
77
+ * console.log('Already have context:', context.orgId);
78
+ * }
79
+ * ```
80
+ */
81
+ export function getCurrentContext(): ExtensionContext | null {
82
+ return currentContext;
83
+ }
84
+
85
+ /**
86
+ * Navigate the ManageSpace host application to a specific path.
87
+ *
88
+ * Use this to navigate users to pages within ManageSpace, such as
89
+ * customer profiles, asset details, or other views.
90
+ *
91
+ * @param path - The path to navigate to (e.g., "/customer/123")
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * import { navigate } from '@managespace/sdk/extensions';
96
+ *
97
+ * // Navigate to a customer profile
98
+ * navigate('/customer/abc-123');
99
+ *
100
+ * // Navigate to the assets page
101
+ * navigate('/assets');
102
+ * ```
103
+ */
104
+ export function navigate(path: string): void {
105
+ const message: ExtensionMessage = {
106
+ type: 'NAVIGATE',
107
+ payload: { path },
108
+ };
109
+ window.parent.postMessage(message, '*');
110
+ }
111
+
112
+ /**
113
+ * Show a toast notification in the ManageSpace host application.
114
+ *
115
+ * Use this for user feedback after actions complete.
116
+ *
117
+ * @param message - The message to display
118
+ * @param variant - The toast type: 'success' or 'error' (default: 'success')
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * import { showToast } from '@managespace/sdk/extensions';
123
+ *
124
+ * // Success notification
125
+ * showToast('Customer updated successfully');
126
+ *
127
+ * // Error notification
128
+ * showToast('Failed to save changes', 'error');
129
+ * ```
130
+ */
131
+ export function showToast(message: string, variant: 'success' | 'error' = 'success'): void {
132
+ const msg: ExtensionMessage = {
133
+ type: 'SHOW_TOAST',
134
+ payload: { message, variant },
135
+ };
136
+ window.parent.postMessage(msg, '*');
137
+ }
138
+
139
+ /**
140
+ * Signal to the ManageSpace host that the extension is ready to receive context.
141
+ *
142
+ * Call this after your extension has loaded and set up its message listeners.
143
+ * The host will respond with a CONTEXT_INIT message containing the ExtensionContext.
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * import { signalReady, getContext } from '@managespace/sdk/extensions';
148
+ *
149
+ * // Signal ready and wait for context
150
+ * signalReady();
151
+ * const context = await getContext();
152
+ * ```
153
+ */
154
+ export function signalReady(): void {
155
+ const message: ExtensionMessage = { type: 'READY' };
156
+ window.parent.postMessage(message, '*');
157
+ }
158
+
159
+ /**
160
+ * Subscribe to entity events from the ManageSpace host.
161
+ *
162
+ * The host sends events when entities (customers, assets, etc.) are
163
+ * created, updated, or deleted. Use this to keep your extension in sync.
164
+ *
165
+ * @param handler - Callback function to handle entity events
166
+ * @returns Unsubscribe function to remove the handler
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * import { onEntityEvent } from '@managespace/sdk/extensions';
171
+ *
172
+ * const unsubscribe = onEntityEvent((event) => {
173
+ * if (event.entityType === 'customer' && event.action === 'updated') {
174
+ * console.log('Customer updated:', event.entityId);
175
+ * refreshCustomerData();
176
+ * }
177
+ * });
178
+ *
179
+ * // Later, to stop listening:
180
+ * unsubscribe();
181
+ * ```
182
+ */
183
+ export function onEntityEvent(handler: EntityEventHandler): () => void {
184
+ entityEventHandlers.add(handler);
185
+ return () => {
186
+ entityEventHandlers.delete(handler);
187
+ };
188
+ }
189
+
190
+ /**
191
+ * Create a configured fetch function for calling the ManageSpace API.
192
+ *
193
+ * This returns a fetch wrapper that automatically includes credentials
194
+ * and sets the correct headers for API calls.
195
+ *
196
+ * @param context - The extension context from getContext()
197
+ * @returns A fetch function configured for ManageSpace API calls
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * import { getContext, createApiFetch } from '@managespace/sdk/extensions';
202
+ *
203
+ * const context = await getContext();
204
+ * const apiFetch = createApiFetch(context);
205
+ *
206
+ * // Fetch customers
207
+ * const response = await apiFetch('/api/crm/customers/queries', {
208
+ * method: 'POST',
209
+ * body: JSON.stringify({
210
+ * pageOptions: { offset: 0, limit: 20 }
211
+ * })
212
+ * });
213
+ * const data = await response.json();
214
+ * ```
215
+ */
216
+ export function createApiFetch(
217
+ context: ExtensionContext,
218
+ ): (path: string, options?: RequestInit) => Promise<Response> {
219
+ return (path: string, options: RequestInit = {}) => {
220
+ const url = `${context.apiBaseUrl}${path}`;
221
+ return fetch(url, {
222
+ ...options,
223
+ credentials: 'include',
224
+ headers: {
225
+ 'Content-Type': 'application/json',
226
+ ...options.headers,
227
+ },
228
+ });
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Create a configured fetch function for calling your extension's BFF.
234
+ *
235
+ * This returns a fetch wrapper that forwards credentials to your BFF,
236
+ * allowing it to make authenticated calls to the ManageSpace API.
237
+ *
238
+ * @param context - The extension context from getContext()
239
+ * @returns A fetch function configured for BFF calls, or null if no BFF is configured
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * import { getContext, createBffFetch } from '@managespace/sdk/extensions';
244
+ *
245
+ * const context = await getContext();
246
+ * const bffFetch = createBffFetch(context);
247
+ *
248
+ * if (bffFetch) {
249
+ * const response = await bffFetch('/api/enriched-customers');
250
+ * const data = await response.json();
251
+ * }
252
+ * ```
253
+ */
254
+ export function createBffFetch(
255
+ context: ExtensionContext,
256
+ ): ((path: string, options?: RequestInit) => Promise<Response>) | null {
257
+ if (!context.bffUrl) {
258
+ return null;
259
+ }
260
+
261
+ return (path: string, options: RequestInit = {}) => {
262
+ const url = `${context.bffUrl}${path}`;
263
+ return fetch(url, {
264
+ ...options,
265
+ credentials: 'include',
266
+ headers: {
267
+ 'Content-Type': 'application/json',
268
+ ...options.headers,
269
+ },
270
+ });
271
+ };
272
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ManageSpace Extension SDK
3
+ *
4
+ * This module provides utilities for building extensions that run within
5
+ * the ManageSpace platform. Extensions are loaded in iframes and communicate
6
+ * with the host application via postMessage.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import {
11
+ * getContext,
12
+ * signalReady,
13
+ * navigate,
14
+ * showToast,
15
+ * createApiFetch,
16
+ * } from '@managespace/sdk/extensions';
17
+ *
18
+ * // Signal ready and get context
19
+ * signalReady();
20
+ * const context = await getContext();
21
+ *
22
+ * // Create API client
23
+ * const apiFetch = createApiFetch(context);
24
+ *
25
+ * // Fetch data
26
+ * const response = await apiFetch('/api/crm/customers/queries', {
27
+ * method: 'POST',
28
+ * body: JSON.stringify({ pageOptions: { offset: 0, limit: 20 } })
29
+ * });
30
+ *
31
+ * // Navigate and show feedback
32
+ * navigate('/customer/123');
33
+ * showToast('Customer loaded');
34
+ * ```
35
+ *
36
+ * @module extensions
37
+ */
38
+
39
+ export * from './types';
40
+ export * from './host-bridge';
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Extension context injected by the ManageSpace host application.
3
+ * This is received via postMessage when the extension loads.
4
+ */
5
+ export interface ExtensionContext {
6
+ /**
7
+ * Authentication token for API calls.
8
+ * Note: When calling the ManageSpace API, use `credentials: 'include'` instead
9
+ * of passing this token directly. The token is provided for BFF authentication.
10
+ */
11
+ token: string;
12
+
13
+ /** The organisation ID the user is currently viewing */
14
+ orgId: string;
15
+
16
+ /** The authenticated user's ID */
17
+ userId: string;
18
+
19
+ /** The site ID the user is currently viewing (may be empty if at org level) */
20
+ siteId: string;
21
+
22
+ /** List of permission strings the user has */
23
+ permissions: Array<string>;
24
+
25
+ /**
26
+ * Base URL for ManageSpace API calls.
27
+ * Example: "http://localhost:5173/gateway"
28
+ */
29
+ apiBaseUrl: string;
30
+
31
+ /**
32
+ * BFF URL from the extension manifest, if configured.
33
+ * Use this to call your extension's backend.
34
+ */
35
+ bffUrl?: string;
36
+ }
37
+
38
+ /**
39
+ * Messages sent from the ManageSpace host to the extension.
40
+ */
41
+ export type HostMessage =
42
+ | { type: 'CONTEXT_INIT'; payload: ExtensionContext }
43
+ | {
44
+ type: 'ENTITY_EVENT';
45
+ payload: {
46
+ entityType: string;
47
+ entityId: string;
48
+ action: 'created' | 'updated' | 'deleted';
49
+ };
50
+ };
51
+
52
+ /**
53
+ * Messages sent from the extension to the ManageSpace host.
54
+ */
55
+ export type ExtensionMessage =
56
+ | { type: 'NAVIGATE'; payload: { path: string } }
57
+ | { type: 'SHOW_TOAST'; payload: { message: string; variant: 'success' | 'error' } }
58
+ | { type: 'READY' };
59
+
60
+ /**
61
+ * Extension manifest format.
62
+ * This file (manifest.json) must be included in your extension bundle.
63
+ */
64
+ export interface ExtensionManifest {
65
+ /** Display name of the extension */
66
+ name: string;
67
+
68
+ /** Semantic version (e.g., "1.0.0") */
69
+ version: string;
70
+
71
+ /** Author or company name */
72
+ author: string;
73
+
74
+ /** Short description of what the extension does */
75
+ description?: string;
76
+
77
+ /** Label shown in the navigation menu */
78
+ navLabel: string;
79
+
80
+ /**
81
+ * Icon name for the navigation menu.
82
+ * Use Lucide icon names (e.g., "Users", "Settings", "BarChart")
83
+ */
84
+ navIcon: string;
85
+
86
+ /**
87
+ * Route path for the extension (e.g., "/extensions/my-extension").
88
+ * Must start with "/extensions/"
89
+ */
90
+ navRoute: string;
91
+
92
+ /** Entry point HTML file (usually "index.html") */
93
+ entryPoint: string;
94
+
95
+ /** Optional BFF (Backend for Frontend) configuration */
96
+ bff?: {
97
+ /** URL of the BFF server */
98
+ url: string;
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Entity event payload received when ManageSpace entities change.
104
+ * Subscribe to these events to react to changes in the host application.
105
+ */
106
+ export interface EntityEvent {
107
+ /** Type of entity (e.g., "customer", "asset", "subscription") */
108
+ entityType: string;
109
+
110
+ /** ID of the affected entity */
111
+ entityId: string;
112
+
113
+ /** What happened to the entity */
114
+ action: 'created' | 'updated' | 'deleted';
115
+ }
116
+
117
+ /**
118
+ * Callback type for entity event handlers.
119
+ */
120
+ export type EntityEventHandler = (event: EntityEvent) => void;
@@ -1,4 +1,5 @@
1
1
  apis/default-api.ts
2
+ apis/extensions-api.ts
2
3
  apis/index.ts
3
4
  index.ts
4
5
  models/accounts-receivable-report-filters.ts
@@ -103,6 +104,8 @@ models/extensibility-function-instance.ts
103
104
  models/extensibility-function-metadata.ts
104
105
  models/extensibility-repo.ts
105
106
  models/extensibility-status.ts
107
+ models/extension-org.ts
108
+ models/extension.ts
106
109
  models/field-area.ts
107
110
  models/field-preferences.ts
108
111
  models/field-type.ts
@@ -180,7 +183,6 @@ models/org.ts
180
183
  models/page-meta.ts
181
184
  models/paginated.ts
182
185
  models/past-due-balances-report-filters.ts
183
- models/payment-gateway-client-token-response.ts
184
186
  models/payment-method.ts
185
187
  models/payment-run-filter-condition.ts
186
188
  models/payment-run-filter-options.ts
@@ -152,7 +152,6 @@ import type {
152
152
  Org,
153
153
  PastDueBalancesReportFilters,
154
154
  Payment,
155
- PaymentGatewayClientTokenResponse,
156
155
  PaymentMethod,
157
156
  PaymentRun,
158
157
  PlanCustom,
@@ -489,8 +488,6 @@ import {
489
488
  PastDueBalancesReportFiltersToJSON,
490
489
  PaymentFromJSON,
491
490
  PaymentToJSON,
492
- PaymentGatewayClientTokenResponseFromJSON,
493
- PaymentGatewayClientTokenResponseToJSON,
494
491
  PaymentMethodFromJSON,
495
492
  PaymentMethodToJSON,
496
493
  PaymentRunFromJSON,
@@ -6388,40 +6385,6 @@ export class DefaultApi extends runtime.BaseAPI {
6388
6385
  return await response.value();
6389
6386
  }
6390
6387
 
6391
- /**
6392
- *
6393
- */
6394
- async getPaymentGatewayClientTokenRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaymentGatewayClientTokenResponse>> {
6395
- const queryParameters: any = {};
6396
-
6397
- const headerParameters: runtime.HTTPHeaders = {};
6398
-
6399
- if (this.configuration && this.configuration.accessToken) {
6400
- const token = this.configuration.accessToken;
6401
- const tokenString = await token("bearer", []);
6402
-
6403
- if (tokenString) {
6404
- headerParameters["Authorization"] = `Bearer ${tokenString}`;
6405
- }
6406
- }
6407
- const response = await this.request({
6408
- path: `/api/billing/client-token`,
6409
- method: 'GET',
6410
- headers: headerParameters,
6411
- query: queryParameters,
6412
- }, initOverrides);
6413
-
6414
- return new runtime.JSONApiResponse(response, (jsonValue) => PaymentGatewayClientTokenResponseFromJSON(jsonValue));
6415
- }
6416
-
6417
- /**
6418
- *
6419
- */
6420
- async getPaymentGatewayClientToken(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaymentGatewayClientTokenResponse> {
6421
- const response = await this.getPaymentGatewayClientTokenRaw(initOverrides);
6422
- return await response.value();
6423
- }
6424
-
6425
6388
  /**
6426
6389
  */
6427
6390
  async getPaymentMethodRaw(requestParameters: GetPaymentMethodRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaymentMethod>> {