@techextensor/tab-sdk 0.0.3 → 0.0.6

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 (47) hide show
  1. package/esm2022/lib/app/analytics.service.mjs +51 -0
  2. package/esm2022/lib/app/app.service.mjs +145 -0
  3. package/esm2022/lib/app/file.service.mjs +41 -0
  4. package/esm2022/lib/app/release.service.mjs +38 -0
  5. package/esm2022/lib/app/report.service.mjs +48 -0
  6. package/esm2022/lib/app/translator.service.mjs +77 -0
  7. package/esm2022/lib/auth/auth.service.mjs +95 -0
  8. package/esm2022/lib/crud/crud.service.mjs +161 -0
  9. package/esm2022/lib/enum/store.enum.mjs +6 -0
  10. package/esm2022/lib/enum/ui.enum.mjs +13 -0
  11. package/esm2022/lib/http/http.service.mjs +58 -0
  12. package/esm2022/lib/interface/http.interface.mjs +2 -0
  13. package/esm2022/lib/interface/ui.interface.mjs +2 -0
  14. package/esm2022/lib/store/store.service.mjs +719 -0
  15. package/esm2022/lib/tab-sdk.service.mjs +52 -18
  16. package/esm2022/lib/ui/form.service.mjs +58 -76
  17. package/esm2022/lib/ui/ui.service.mjs +297 -2
  18. package/esm2022/lib/util/util.service.mjs +53 -0
  19. package/esm2022/lib/workflow/transition.service.mjs +40 -0
  20. package/fesm2022/techextensor-tab-sdk.mjs +1855 -341
  21. package/fesm2022/techextensor-tab-sdk.mjs.map +1 -1
  22. package/lib/app/analytics.service.d.ts +28 -0
  23. package/lib/app/app.service.d.ts +81 -0
  24. package/lib/app/file.service.d.ts +22 -0
  25. package/lib/app/release.service.d.ts +23 -0
  26. package/lib/app/report.service.d.ts +28 -0
  27. package/lib/app/translator.service.d.ts +49 -0
  28. package/lib/auth/auth.service.d.ts +58 -0
  29. package/lib/crud/crud.service.d.ts +88 -0
  30. package/lib/enum/store.enum.d.ts +4 -0
  31. package/lib/enum/ui.enum.d.ts +10 -0
  32. package/lib/http/http.service.d.ts +35 -0
  33. package/lib/interface/http.interface.d.ts +8 -0
  34. package/lib/interface/ui.interface.d.ts +24 -0
  35. package/lib/store/store.service.d.ts +406 -0
  36. package/lib/tab-sdk.service.d.ts +24 -8
  37. package/lib/ui/form.service.d.ts +35 -44
  38. package/lib/ui/ui.service.d.ts +154 -0
  39. package/lib/util/util.service.d.ts +14 -0
  40. package/lib/workflow/transition.service.d.ts +21 -0
  41. package/package.json +2 -2
  42. package/esm2022/lib/common/utils.service.mjs +0 -163
  43. package/esm2022/lib/core/auth.service.mjs +0 -48
  44. package/esm2022/lib/data/data.service.mjs +0 -81
  45. package/lib/common/utils.service.d.ts +0 -58
  46. package/lib/core/auth.service.d.ts +0 -28
  47. package/lib/data/data.service.d.ts +0 -36
@@ -1,56 +1,47 @@
1
+ import { BuildFormComponentType, CommonApiResponse, GetScreenConfig, ProcessRequestPayload, TemplateParsePayload } from '@techextensor/tab-core-utility';
1
2
  import * as i0 from "@angular/core";
2
3
  export declare class FormService {
3
- private readonly _helperFunctionService;
4
+ private readonly _tabFormioService;
5
+ private readonly _templateHelper;
4
6
  /**
5
- * Processes form components with individual actions in a single pass
6
- *
7
- * @example
8
- * // Process multiple components with different actions in one pass
9
- * sdk.form.processComponents(
10
- * screenParameters.rendererInstance.form.components,
11
- * [
12
- * {
13
- * keys: 'documentDetails', // Single key
14
- * action: (component) => component.hidden = true,
15
- * type: 'columns' // Optional type filter
16
- * },
17
- * {
18
- * keys: 'documentPreview,documentComments', // Multiple keys as comma-separated string
19
- * action: (component) => component.hidden = false
20
- * }
21
- * ]
22
- * );
23
- */
24
- processComponents(components: any[], processors: Array<{
25
- keys: string;
26
- type?: string;
27
- action: (component: any) => void;
28
- }>): void;
7
+ * Retrieves a screen by its ID.
8
+ *
9
+ * @param screenId The ID of the screen to retrieve.
10
+ * @param config Optional configuration object for the request.
11
+ * @returns A promise of the response from the server.
12
+ */
13
+ getScreen(screenId: string, config?: GetScreenConfig): Promise<CommonApiResponse>;
14
+ /**
15
+ * Retrieves the data for a screen by its ID.
16
+ *
17
+ * @param screenId The ID of the screen to retrieve the data for.
18
+ * @param requestPayload The request payload to send to the server.
19
+ * @returns A promise of the response from the server.
20
+ */
21
+ getScreenData(screenId: string, requestPayload: any): Promise<CommonApiResponse>;
22
+ /**
23
+ * Processes a request using the provided request payload.
24
+ *
25
+ * @param requestPayload The payload to be processed.
26
+ * @returns A promise of the response from the server.
27
+ */
28
+ processRequest(requestPayload: ProcessRequestPayload): Promise<CommonApiResponse>;
29
29
  /**
30
- * Updates visibility of multiple form components at once
30
+ * Builds Form.io components for the specified app object ID and type.
31
31
  *
32
- * @example
33
- * sdk.form.setComponentsVisibility(
34
- * screenParameters.rendererInstance.form.components,
35
- * {
36
- * 'documentDetails': false,
37
- * 'documentComments': true
38
- * }
39
- * );
32
+ * @param appObjectId The ID of the app object to build the components for.
33
+ * @param type The type of components to build.
34
+ * @returns A promise of the response from the server.
40
35
  */
41
- setComponentsVisibility(components: any[], visibilityMap: Record<string, boolean>): void;
36
+ buildFormIOComponents(appObjectId: string, type: BuildFormComponentType): Promise<CommonApiResponse>;
42
37
  /**
43
- * Finds components by key and returns them in a structured object
38
+ * Parses a template using the provided request payload.
44
39
  *
45
- * @example
46
- * const components = sdk.form.findComponentsByKeys(
47
- * form.components,
48
- * ['documentDetails', 'documentPreview', 'documentComments']
49
- * );
40
+ * @param requestPayload The payload containing the template to be parsed.
41
+ * @param onFailedParseOnServer If the parsing should be done on the server.
42
+ * @returns A promise of the response from the server.
50
43
  */
51
- findComponentsByKeys(components: any[], keys: string[], options?: {
52
- type?: string;
53
- }): Record<string, any>;
44
+ parseTemplate(requestPayload: TemplateParsePayload, onFailedParseOnServer?: boolean): Promise<CommonApiResponse>;
54
45
  static ɵfac: i0.ɵɵFactoryDeclaration<FormService, never>;
55
46
  static ɵprov: i0.ɵɵInjectableDeclaration<FormService>;
56
47
  }
@@ -1,5 +1,159 @@
1
+ import { ScreenOpenOptions, NavigationOptions, BaseScreenOptions, NavigateToSubdomainOptions } from '../interface/ui.interface';
2
+ import { BaseNotificationOptions, ConfirmationOptions, NotificationOptions } from '@techextensor/tab-core-utility';
1
3
  import * as i0 from "@angular/core";
2
4
  export declare class UiService {
5
+ private readonly _notificationService;
6
+ private readonly _confirmationService;
7
+ /**
8
+ * Open a screen with the given options. The mode determines how the screen is
9
+ * displayed.
10
+ *
11
+ * @param options The options for opening the screen.
12
+ */
13
+ openScreen(options: ScreenOpenOptions): void;
14
+ /**
15
+ * Opens a screen in a sidebar.
16
+ *
17
+ * @param options The options for opening the sidebar.
18
+ */
19
+ showSidebar(options: BaseScreenOptions): void;
20
+ /**
21
+ * Opens a screen in a popup dialog.
22
+ *
23
+ * @param options The options for opening the dialog.
24
+ */
25
+ showDialog(options: BaseScreenOptions): void;
26
+ /**
27
+ * Navigates to a screen within the same tab.
28
+ *
29
+ * @param options - The options for navigation, including screenId and optional reqtokens.
30
+ */
31
+ navigateTo(options: NavigationOptions): void;
32
+ /**
33
+ * Navigates to a screen in a new tab.
34
+ *
35
+ * @param options The options for navigation, including screenId and optional reqtokens.
36
+ */
37
+ openInNewTab(options: NavigationOptions): void;
38
+ /**
39
+ * Navigates to the specified URL.
40
+ *
41
+ * @param url - The URL to navigate to.
42
+ */
43
+ navigateToUrl(url: string): void;
44
+ /**
45
+ * Navigates to a specified subdomain using the provided options.
46
+ *
47
+ * @param options - The options for navigation, including subDomain, appCode, and url.
48
+ */
49
+ navigateToSubdomain(options: NavigateToSubdomainOptions): void;
50
+ /**
51
+ * Retrieves the active screen ID from the current URL.
52
+ *
53
+ * @returns The screen ID if present in the URL, otherwise undefined.
54
+ */
55
+ getActiveUrlScreenId(): string | undefined;
56
+ /**
57
+ * Show a notification to the user.
58
+ *
59
+ * @param options The options for the notification.
60
+ */
61
+ notify(options: NotificationOptions): void;
62
+ /**
63
+ * Displays a success notification to the user.
64
+ *
65
+ * @param options - The options for the notification, including message, title, and configuration.
66
+ */
67
+ showSuccess(options: BaseNotificationOptions): void;
68
+ /**
69
+ * Displays a warning notification to the user.
70
+ *
71
+ * @param options - The options for the notification, including message, title, and configuration.
72
+ */
73
+ showWarning(options: BaseNotificationOptions): void;
74
+ /**
75
+ * Displays an info notification to the user.
76
+ *
77
+ * @param options - The options for the notification, including message, title, and configuration.
78
+ */
79
+ showInfo(options: BaseNotificationOptions): void;
80
+ /**
81
+ * Displays an error notification to the user.
82
+ *
83
+ * @param options - The options for the notification, including message, title, and configuration.
84
+ */
85
+ showError(options: BaseNotificationOptions): void;
86
+ /**
87
+ * Displays a confirmation dialog to the user and returns a promise that resolves
88
+ * to a boolean indicating whether the user confirmed the action.
89
+ *
90
+ * @param options - The options for the confirmation dialog, including title, message,
91
+ * confirmText, cancelText, and visibility of buttons.
92
+ * @returns A promise that resolves to true if the user confirms, false otherwise.
93
+ */
94
+ confirm(options?: ConfirmationOptions): Promise<boolean>;
95
+ /**
96
+ * Displays a confirmation dialog to the user with a title and message that indicates
97
+ * the user is about to delete an item. The confirmation dialog has a "Delete" and "Cancel"
98
+ * button.
99
+ *
100
+ * @param options - The options for the confirmation dialog, including the item name and
101
+ * optional message.
102
+ * @returns A promise that resolves to true if the user confirms, false otherwise.
103
+ */
104
+ confirmDelete(options?: ConfirmationOptions): Promise<boolean>;
105
+ /**
106
+ * Displays a confirmation dialog to the user with a title and message that indicates
107
+ * the user is about to discard changes to an item. The confirmation dialog has a "Discard"
108
+ * and "Cancel" button.
109
+ *
110
+ * @param options - The options for the confirmation dialog, including the item name and
111
+ * optional message.
112
+ * @returns A promise that resolves to true if the user confirms, false otherwise.
113
+ */
114
+ confirmDiscard(options?: ConfirmationOptions): Promise<boolean>;
115
+ /**
116
+ * Closes the confirmation dialog.
117
+ *
118
+ * This method can be used to manually close the confirmation dialog.
119
+ */
120
+ closeConfirmationDialog(): void;
121
+ /**
122
+ * Retrieves the confirmation emitter from the confirmation service.
123
+ *
124
+ * @returns The confirmation emitter used for emitting confirmation events.
125
+ */
126
+ getConformationEmitter(): import("@angular/core").EventEmitter<boolean>;
127
+ /**
128
+ * Retrieves the dialog emitter from the confirmation service.
129
+ *
130
+ * The dialog emitter is an RxJS Subject that emits whenever a confirmation dialog is
131
+ * opened or closed. The value emitted is a boolean indicating whether a dialog is
132
+ * currently open.
133
+ *
134
+ * @returns The dialog emitter used for emitting confirmation dialog events.
135
+ */
136
+ getDialogEmitter(): import("@angular/core").EventEmitter<ConfirmationOptions>;
137
+ /**
138
+ * Retrieves the remove emitter from the confirmation service.
139
+ *
140
+ * The remove emitter is an RxJS Subject that emits whenever a removal confirmation
141
+ * dialog is opened or closed. The value emitted is a boolean indicating whether a
142
+ * removal dialog is currently open.
143
+ *
144
+ * @returns The remove emitter used for emitting removal confirmation dialog events.
145
+ */
146
+ getRemoveEmitter(): import("@angular/core").EventEmitter<boolean>;
147
+ /**
148
+ * Copies the provided text to the clipboard and displays a success notification.
149
+ *
150
+ * @param text - The text to be copied to the clipboard.
151
+ */
152
+ copyToClipboard(text: string): void;
153
+ /**
154
+ * Copies the current URL to the clipboard and displays a success notification.
155
+ */
156
+ copyCurrentUrlToClipboard(): void;
3
157
  static ɵfac: i0.ɵɵFactoryDeclaration<UiService, never>;
4
158
  static ɵprov: i0.ɵɵInjectableDeclaration<UiService>;
5
159
  }
@@ -0,0 +1,14 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class UtilService {
3
+ private _context;
4
+ private _initialized;
5
+ /**
6
+ * Initializes the UtilService with context that contains service references
7
+ *
8
+ * @param context The context object containing service references
9
+ * @returns A proxy that intercepts and delegates method calls to the appropriate service
10
+ */
11
+ init(context: any): any;
12
+ static ɵfac: i0.ɵɵFactoryDeclaration<UtilService, never>;
13
+ static ɵprov: i0.ɵɵInjectableDeclaration<UtilService>;
14
+ }
@@ -0,0 +1,21 @@
1
+ import { CommonApiResponse, NextStatusPayload, UpdateStatusPayload } from '@techextensor/tab-core-utility';
2
+ import * as i0 from "@angular/core";
3
+ export declare class TransitionService {
4
+ private readonly _tabBlueprintService;
5
+ /**
6
+ * Retrieves the next status based on the provided payload.
7
+ *
8
+ * @param payload - The payload containing information to determine the next status.
9
+ * @returns A promise that resolves to the common API response.
10
+ */
11
+ getNextStatus(payload: NextStatusPayload): Promise<CommonApiResponse>;
12
+ /**
13
+ * Updates the status of an entity based on the provided payload.
14
+ *
15
+ * @param payload - The payload containing information to update the status.
16
+ * @returns A promise that resolves to the common API response.
17
+ */
18
+ updateStatus(payload: UpdateStatusPayload): Promise<any>;
19
+ static ɵfac: i0.ɵɵFactoryDeclaration<TransitionService, never>;
20
+ static ɵprov: i0.ɵɵInjectableDeclaration<TransitionService>;
21
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@techextensor/tab-sdk",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^17.3.0",
6
6
  "@angular/core": "^17.3.0",
7
- "@techextensor/tab-core-utility": "^2.2.135"
7
+ "@techextensor/tab-core-utility": "^2.2.149"
8
8
  },
9
9
  "dependencies": {
10
10
  "tslib": "^2.3.0"
@@ -1,163 +0,0 @@
1
- import { inject, Injectable } from "@angular/core";
2
- import { AuthService } from "../core/auth.service";
3
- import { TabSdk } from "../tab-sdk.service";
4
- import * as i0 from "@angular/core";
5
- export class UtilsService {
6
- _authService = inject(AuthService);
7
- _helperFunctionService = TabSdk.context?.HelperFunctionService;
8
- /**
9
- * Extracts the event name from various event parameter structures
10
- *
11
- * @example
12
- * const eventName = sdk.utils.extractEventName(screenParameters.event);
13
- * if (eventName === 'deleteDocument') {
14
- * // Handle delete document event
15
- * }
16
- */
17
- extractEventName(event) {
18
- if (!event)
19
- return '';
20
- // Check common patterns for event names
21
- return event.event?.component?.configuration?.configScreen?.componentValue?.eventName ??
22
- event.detail?.type ??
23
- event.type ??
24
- event.name ??
25
- '';
26
- }
27
- /**
28
- * Builds an application URL with the specified path and parameters
29
- *
30
- * @example
31
- * // Get full URL with protocol
32
- * const fullUrl = sdk.utils.buildAppUrl('screen/12345', { id: '12345' });
33
- */
34
- buildAppUrl(path, parameters, includeProtocol = true) {
35
- const appCode = this._authService.getAppCode();
36
- const params = new URLSearchParams();
37
- // Add parameters to the URL
38
- if (parameters) {
39
- Object.entries(parameters).forEach(([key, value]) => {
40
- if (value !== undefined && value !== null) {
41
- params.append(key, String(value));
42
- }
43
- });
44
- }
45
- // Build query string
46
- const queryString = params.toString() ? `?${params.toString()}` : '';
47
- // Build URL
48
- if (includeProtocol) {
49
- const host = window.location.host;
50
- return `http://${host}/${appCode}/${path}${queryString}`;
51
- }
52
- else {
53
- return `/${appCode}/${path}${queryString}`;
54
- }
55
- }
56
- /**
57
- * Generates and copies a screen URL to the clipboard
58
- *
59
- * @example
60
- * // Copy URL to clipboard
61
- * sdk.utils.copyScreenLink('12345', { id: '12345' });
62
- */
63
- copyScreenLinkToClipboard(screenId, parameters) {
64
- const url = this.buildAppUrl(`screen/${screenId}`, parameters);
65
- return this._helperFunctionService.copyToClipboard(url);
66
- }
67
- /**
68
- * Downloads a blob as a file
69
- *
70
- * @example
71
- * // Download a blob as 'report.pdf'
72
- * const pdfBlob = new Blob([pdfContent], { type: 'application/pdf' });
73
- * sdk.utils.downloadBlob(pdfBlob, 'report.pdf');
74
- */
75
- downloadBlob(blob, filename) {
76
- // Create object URL
77
- const url = URL.createObjectURL(blob);
78
- // Create download link
79
- const downloadLink = document.createElement('a');
80
- downloadLink.href = url;
81
- downloadLink.download = filename;
82
- // Append to body, click, and remove
83
- document.body.appendChild(downloadLink);
84
- downloadLink.click();
85
- document.body.removeChild(downloadLink);
86
- // Release object URL after a short delay to ensure download starts
87
- setTimeout(() => URL.revokeObjectURL(url), 100);
88
- }
89
- /**
90
- * Exports HTML content as a Word document (.doc)
91
- *
92
- * @example
93
- * // Export editor content as Word document
94
- * sdk.utils.exportAsWord(editorContent, 'report');
95
- */
96
- exportAsWord(content, filename = 'document') {
97
- // Format content with Word-compatible namespaces
98
- const docContent = `
99
- <html xmlns:o="urn:schemas-microsoft-com:office:office"
100
- xmlns:w="urn:schemas-microsoft-com:office:word"
101
- xmlns="http://www.w3.org/TR/REC-html40">
102
- <head>
103
- <meta charset="utf-8">
104
- <title>${filename}</title>
105
- </head>
106
- <body>${content}</body>
107
- </html>`;
108
- // Create blob with BOM for Word compatibility
109
- const blob = new Blob(['\ufeff', docContent], {
110
- type: 'application/msword'
111
- });
112
- // Use the downloadBlob utility
113
- this.downloadBlob(blob, `${filename}.doc`);
114
- }
115
- /**
116
- * Exports HTML content as PDF using browser print functionality
117
- *
118
- * @example
119
- * // Export content as PDF
120
- * sdk.utils.exportAsPdf(documentContent, 'Invoice');
121
- */
122
- exportAsPdf(content, title = 'Document') {
123
- // Open new window
124
- const printWindow = window.open('', '', 'width=800,height=600');
125
- // Add content with basic styling
126
- printWindow.document?.write(`
127
- <html>
128
- <head>
129
- <title>${title}</title>
130
- <style>
131
- body { font-family: Arial, sans-serif; margin: 20px; }
132
- @media print {
133
- body { margin: 0mm; }
134
- }
135
- </style>
136
- </head>
137
- <body>
138
- ${content}
139
- </body>
140
- </html>
141
- `);
142
- // Prepare for printing
143
- printWindow.document.close();
144
- printWindow.focus();
145
- // Use timeout to ensure content is rendered before printing
146
- setTimeout(() => {
147
- printWindow.print();
148
- // Close window after print dialog is closed or printing is complete
149
- printWindow.addEventListener('afterprint', () => {
150
- printWindow.close();
151
- });
152
- }, 300);
153
- }
154
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
155
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, providedIn: 'root' });
156
- }
157
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UtilsService, decorators: [{
158
- type: Injectable,
159
- args: [{
160
- providedIn: 'root'
161
- }]
162
- }] });
163
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhYi1zZGsvc3JjL2xpYi9jb21tb24vdXRpbHMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDOztBQUs1QyxNQUFNLE9BQU8sWUFBWTtJQUNKLFlBQVksR0FBZ0IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ2hELHNCQUFzQixHQUFRLE1BQU0sQ0FBQyxPQUFPLEVBQUUscUJBQXFCLENBQUM7SUFHckY7Ozs7Ozs7O09BUUc7SUFDSCxnQkFBZ0IsQ0FBQyxLQUFVO1FBQ3ZCLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFFdEIsd0NBQXdDO1FBQ3hDLE9BQU8sS0FBSyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsU0FBUztZQUNqRixLQUFLLENBQUMsTUFBTSxFQUFFLElBQUk7WUFDbEIsS0FBSyxDQUFDLElBQUk7WUFDVixLQUFLLENBQUMsSUFBSTtZQUNWLEVBQUUsQ0FBQztJQUNYLENBQUM7SUFHRDs7Ozs7O09BTUc7SUFDSCxXQUFXLENBQ1AsSUFBWSxFQUNaLFVBQWdDLEVBQ2hDLGtCQUEyQixJQUFJO1FBRS9CLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDL0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUVyQyw0QkFBNEI7UUFDNUIsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNiLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFB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LEtBQUssQ0FBQzs7O3lCQUdYLEtBQUs7Ozs7Ozs7OztrQkFTWixPQUFPOzs7U0FHaEIsQ0FBQyxDQUFDO1FBRUgsdUJBQXVCO1FBQ3ZCLFdBQVcsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDN0IsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRXBCLDREQUE0RDtRQUM1RCxVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ1osV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLG9FQUFvRTtZQUNwRSxXQUFXLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtnQkFDNUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3hCLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ1osQ0FBQzt3R0EvS1EsWUFBWTs0R0FBWixZQUFZLGNBRlQsTUFBTTs7NEZBRVQsWUFBWTtrQkFIeEIsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tIFwiLi4vY29yZS9hdXRoLnNlcnZpY2VcIjtcbmltcG9ydCB7IFRhYlNkayB9IGZyb20gXCIuLi90YWItc2RrLnNlcnZpY2VcIjtcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBVdGlsc1NlcnZpY2Uge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX2F1dGhTZXJ2aWNlOiBBdXRoU2VydmljZSA9IGluamVjdChBdXRoU2VydmljZSk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfaGVscGVyRnVuY3Rpb25TZXJ2aWNlOiBhbnkgPSBUYWJTZGsuY29udGV4dD8uSGVscGVyRnVuY3Rpb25TZXJ2aWNlO1xuICAgIFxuXG4gICAgLyoqXG4gICAgICogRXh0cmFjdHMgdGhlIGV2ZW50IG5hbWUgZnJvbSB2YXJpb3VzIGV2ZW50IHBhcmFtZXRlciBzdHJ1Y3R1cmVzXG4gICAgICogXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBjb25zdCBldmVudE5hbWUgPSBzZGsudXRpbHMuZXh0cmFjdEV2ZW50TmFtZShzY3JlZW5QYXJhbWV0ZXJzLmV2ZW50KTtcbiAgICAgKiBpZiAoZXZlbnROYW1lID09PSAnZGVsZXRlRG9jdW1lbnQnKSB7XG4gICAgICogICAvLyBIYW5kbGUgZGVsZXRlIGRvY3VtZW50IGV2ZW50XG4gICAgICogfVxuICAgICAqL1xuICAgIGV4dHJhY3RFdmVudE5hbWUoZXZlbnQ6IGFueSk6IHN0cmluZyB7XG4gICAgICAgIGlmICghZXZlbnQpIHJldHVybiAnJztcblxuICAgICAgICAvLyBDaGVjayBjb21tb24gcGF0dGVybnMgZm9yIGV2ZW50IG5hbWVzXG4gICAgICAgIHJldHVybiBldmVudC5ldmVudD8uY29tcG9uZW50Py5jb25maWd1cmF0aW9uPy5jb25maWdTY3JlZW4/LmNvbXBvbmVudFZhbHVlPy5ldmVudE5hbWUgPz9cbiAgICAgICAgICAgIGV2ZW50LmRldGFpbD8udHlwZSA/P1xuICAgICAgICAgICAgZXZlbnQudHlwZSA/P1xuICAgICAgICAgICAgZXZlbnQubmFtZSA/P1xuICAgICAgICAgICAgJyc7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBCdWlsZHMgYW4gYXBwbGljYXRpb24gVVJMIHdpdGggdGhlIHNwZWNpZmllZCBwYXRoIGFuZCBwYXJhbWV0ZXJzXG4gICAgICogXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAvLyBHZXQgZnVsbCBVUkwgd2l0aCBwcm90b2NvbFxuICAgICAqIGNvbnN0IGZ1bGxVcmwgPSBzZGsudXRpbHMuYnVpbGRBcHBVcmwoJ3NjcmVlbi8xMjM0NScsIHsgaWQ6ICcxMjM0NScgfSk7XG4gICAgICovXG4gICAgYnVpbGRBcHBVcmwoXG4gICAgICAgIHBhdGg6IHN0cmluZyxcbiAgICAgICAgcGFyYW1ldGVycz86IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgICAgIGluY2x1ZGVQcm90b2NvbDogYm9vbGVhbiA9IHRydWVcbiAgICApOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBhcHBDb2RlID0gdGhpcy5fYXV0aFNlcnZpY2UuZ2V0QXBwQ29kZSgpO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKCk7XG5cbiAgICAgICAgLy8gQWRkIHBhcmFtZXRlcnMgdG8gdGhlIFVSTFxuICAgICAgICBpZiAocGFyYW1ldGVycykge1xuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocGFyYW1ldGVycykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmFwcGVuZChrZXksIFN0cmluZyh2YWx1ZSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnVpbGQgcXVlcnkgc3RyaW5nXG4gICAgICAgIGNvbnN0IHF1ZXJ5U3RyaW5nID0gcGFyYW1zLnRvU3RyaW5nKCkgPyBgPyR7cGFyYW1zLnRvU3RyaW5nKCl9YCA6ICcnO1xuXG4gICAgICAgIC8vIEJ1aWxkIFVSTFxuICAgICAgICBpZiAoaW5jbHVkZVByb3RvY29sKSB7XG4gICAgICAgICAgICBjb25zdCBob3N0ID0gd2luZG93LmxvY2F0aW9uLmhvc3Q7XG4gICAgICAgICAgICByZXR1cm4gYGh0dHA6Ly8ke2hvc3R9LyR7YXBwQ29kZX0vJHtwYXRofSR7cXVlcnlTdHJpbmd9YDtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGAvJHthcHBDb2RlfS8ke3BhdGh9JHtxdWVyeVN0cmluZ31gO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGVzIGFuZCBjb3BpZXMgYSBzY3JlZW4gVVJMIHRvIHRoZSBjbGlwYm9hcmRcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIC8vIENvcHkgVVJMIHRvIGNsaXBib2FyZFxuICAgICAqIHNkay51dGlscy5jb3B5U2NyZWVuTGluaygnMTIzNDUnLCB7IGlkOiAnMTIzNDUnIH0pO1xuICAgICAqL1xuICAgIGNvcHlTY3JlZW5MaW5rVG9DbGlwYm9hcmQoXG4gICAgICAgIHNjcmVlbklkOiBzdHJpbmcsXG4gICAgICAgIHBhcmFtZXRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICAgKTogYW55IHtcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy5idWlsZEFwcFVybChgc2NyZWVuLyR7c2NyZWVuSWR9YCwgcGFyYW1ldGVycyk7ICAgICAgICBcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlbHBlckZ1bmN0aW9uU2VydmljZS5jb3B5VG9DbGlwYm9hcmQodXJsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEb3dubG9hZHMgYSBibG9iIGFzIGEgZmlsZVxuICAgICAqIFxuICAgICAqIEBleGFtcGxlXG4gICAgICogLy8gRG93bmxvYWQgYSBibG9iIGFzICdyZXBvcnQucGRmJ1xuICAgICAqIGNvbnN0IHBkZkJsb2IgPSBuZXcgQmxvYihbcGRmQ29udGVudF0sIHsgdHlwZTogJ2FwcGxpY2F0aW9uL3BkZicgfSk7XG4gICAgICogc2RrLnV0aWxzLmRvd25sb2FkQmxvYihwZGZCbG9iLCAncmVwb3J0LnBkZicpO1xuICAgICAqL1xuICAgIGRvd25sb2FkQmxvYihibG9iOiBCbG9iLCBmaWxlbmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIC8vIENyZWF0ZSBvYmplY3QgVVJMXG4gICAgICAgIGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGRvd25sb2FkIGxpbmtcbiAgICAgICAgY29uc3QgZG93bmxvYWRMaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICBkb3dubG9hZExpbmsuaHJlZiA9IHVybDtcbiAgICAgICAgZG93bmxvYWRMaW5rLmRvd25sb2FkID0gZmlsZW5hbWU7XG5cbiAgICAgICAgLy8gQXBwZW5kIHRvIGJvZHksIGNsaWNrLCBhbmQgcmVtb3ZlXG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZG93bmxvYWRMaW5rKTtcbiAgICAgICAgZG93bmxvYWRMaW5rLmNsaWNrKCk7XG4gICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZG93bmxvYWRMaW5rKTtcblxuICAgICAgICAvLyBSZWxlYXNlIG9iamVjdCBVUkwgYWZ0ZXIgYSBzaG9ydCBkZWxheSB0byBlbnN1cmUgZG93bmxvYWQgc3RhcnRzXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4gVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpLCAxMDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cG9ydHMgSFRNTCBjb250ZW50IGFzIGEgV29yZCBkb2N1bWVudCAoLmRvYylcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIC8vIEV4cG9ydCBlZGl0b3IgY29udGVudCBhcyBXb3JkIGRvY3VtZW50XG4gICAgICogc2RrLnV0aWxzLmV4cG9ydEFzV29yZChlZGl0b3JDb250ZW50LCAncmVwb3J0Jyk7XG4gICAgICovXG4gICAgZXhwb3J0QXNXb3JkKGNvbnRlbnQ6IHN0cmluZywgZmlsZW5hbWU6IHN0cmluZyA9ICdkb2N1bWVudCcpOiB2b2lkIHtcbiAgICAgICAgLy8gRm9ybWF0IGNvbnRlbnQgd2l0aCBXb3JkLWNvbXBhdGlibGUgbmFtZXNwYWNlc1xuICAgICAgICBjb25zdCBkb2NDb250ZW50ID0gYFxuICAgICAgICA8aHRtbCB4bWxuczpvPVwidXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6b2ZmaWNlXCIgXG4gICAgICAgICAgICB4bWxuczp3PVwidXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZFwiIFxuICAgICAgICAgICAgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy9UUi9SRUMtaHRtbDQwXCI+XG4gICAgICAgIDxoZWFkPlxuICAgICAgICAgICAgPG1ldGEgY2hhcnNldD1cInV0Zi04XCI+XG4gICAgICAgICAgICA8dGl0bGU+JHtmaWxlbmFtZX08L3RpdGxlPlxuICAgICAgICA8L2hlYWQ+XG4gICAgICAgIDxib2R5PiR7Y29udGVudH08L2JvZHk+XG4gICAgICAgIDwvaHRtbD5gO1xuXG4gICAgICAgIC8vIENyZWF0ZSBibG9iIHdpdGggQk9NIGZvciBXb3JkIGNvbXBhdGliaWxpdHlcbiAgICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFsnXFx1ZmVmZicsIGRvY0NvbnRlbnRdLCB7XG4gICAgICAgICAgICB0eXBlOiAnYXBwbGljYXRpb24vbXN3b3JkJ1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBVc2UgdGhlIGRvd25sb2FkQmxvYiB1dGlsaXR5XG4gICAgICAgIHRoaXMuZG93bmxvYWRCbG9iKGJsb2IsIGAke2ZpbGVuYW1lfS5kb2NgKTtcbiAgICB9XG5cblxuICAgIC8qKlxuICAgICAqIEV4cG9ydHMgSFRNTCBjb250ZW50IGFzIFBERiB1c2luZyBicm93c2VyIHByaW50IGZ1bmN0aW9uYWxpdHlcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIC8vIEV4cG9ydCBjb250ZW50IGFzIFBERlxuICAgICAqIHNkay51dGlscy5leHBvcnRBc1BkZihkb2N1bWVudENvbnRlbnQsICdJbnZvaWNlJyk7XG4gICAgICovXG4gICAgZXhwb3J0QXNQZGYoY29udGVudDogc3RyaW5nLCB0aXRsZTogc3RyaW5nID0gJ0RvY3VtZW50Jyk6IHZvaWQge1xuICAgICAgICAvLyBPcGVuIG5ldyB3aW5kb3dcbiAgICAgICAgY29uc3QgcHJpbnRXaW5kb3c6IGFueSA9IHdpbmRvdy5vcGVuKCcnLCAnJywgJ3dpZHRoPTgwMCxoZWlnaHQ9NjAwJyk7XG5cbiAgICAgICAgLy8gQWRkIGNvbnRlbnQgd2l0aCBiYXNpYyBzdHlsaW5nXG4gICAgICAgIHByaW50V2luZG93LmRvY3VtZW50Py53cml0ZShgXG4gICAgICAgICAgICA8aHRtbD5cbiAgICAgICAgICAgIDxoZWFkPlxuICAgICAgICAgICAgICAgIDx0aXRsZT4ke3RpdGxlfTwvdGl0bGU+XG4gICAgICAgICAgICAgICAgPHN0eWxlPlxuICAgICAgICAgICAgICAgIGJvZHkgeyBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7IG1hcmdpbjogMjBweDsgfVxuICAgICAgICAgICAgICAgIEBtZWRpYSBwcmludCB7XG4gICAgICAgICAgICAgICAgICAgIGJvZHkgeyBtYXJnaW46IDBtbTsgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L3N0eWxlPlxuICAgICAgICAgICAgPC9oZWFkPlxuICAgICAgICAgICAgPGJvZHk+XG4gICAgICAgICAgICAgICAgJHtjb250ZW50fVxuICAgICAgICAgICAgPC9ib2R5PlxuICAgICAgICAgICAgPC9odG1sPlxuICAgICAgICBgKTtcblxuICAgICAgICAvLyBQcmVwYXJlIGZvciBwcmludGluZ1xuICAgICAgICBwcmludFdpbmRvdy5kb2N1bWVudC5jbG9zZSgpO1xuICAgICAgICBwcmludFdpbmRvdy5mb2N1cygpO1xuXG4gICAgICAgIC8vIFVzZSB0aW1lb3V0IHRvIGVuc3VyZSBjb250ZW50IGlzIHJlbmRlcmVkIGJlZm9yZSBwcmludGluZ1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHByaW50V2luZG93LnByaW50KCk7XG4gICAgICAgICAgICAvLyBDbG9zZSB3aW5kb3cgYWZ0ZXIgcHJpbnQgZGlhbG9nIGlzIGNsb3NlZCBvciBwcmludGluZyBpcyBjb21wbGV0ZVxuICAgICAgICAgICAgcHJpbnRXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignYWZ0ZXJwcmludCcsICgpID0+IHtcbiAgICAgICAgICAgICAgICBwcmludFdpbmRvdy5jbG9zZSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIDMwMCk7XG4gICAgfVxufSJdfQ==
@@ -1,48 +0,0 @@
1
- import { inject, Injectable } from "@angular/core";
2
- import { LocalStorageService, SessionStorageService, StorageConstants } from "@techextensor/tab-core-utility";
3
- import * as i0 from "@angular/core";
4
- export class AuthService {
5
- _sessionStorageService = inject(SessionStorageService);
6
- _localStorageService = inject(LocalStorageService);
7
- /**
8
- * Get the current application code/identifier
9
- *
10
- * @example
11
- * const appCode = sdk.config.getAppCode();
12
- */
13
- getAppCode() {
14
- return this._sessionStorageService.getSessionStorage(StorageConstants.applicationCode) ?? '';
15
- }
16
- /**
17
- * Get the current user ID
18
- *
19
- * @example
20
- * const userId = sdk.auth.getCurrentUserId();
21
- */
22
- getCurrentUserId() {
23
- const userInfo = this.getCurrentUser();
24
- return userInfo?.user?.Id ?? '';
25
- }
26
- /**
27
- * Get the current user information
28
- *
29
- * @example
30
- * const user = sdk.auth.getCurrentUser();
31
- */
32
- getCurrentUser() {
33
- const userInfoStr = this._localStorageService.getLocalStorage(StorageConstants.userInfo);
34
- if (userInfoStr) {
35
- return JSON.parse(userInfoStr);
36
- }
37
- return null;
38
- }
39
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
40
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, providedIn: 'root' });
41
- }
42
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AuthService, decorators: [{
43
- type: Injectable,
44
- args: [{
45
- providedIn: 'root'
46
- }]
47
- }] });
48
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFiLXNkay9zcmMvbGliL2NvcmUvYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDOztBQUs5RyxNQUFNLE9BQU8sV0FBVztJQUNILHNCQUFzQixHQUEwQixNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUM5RSxvQkFBb0IsR0FBd0IsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFekY7Ozs7O09BS0c7SUFDSCxVQUFVO1FBQ04sT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2pHLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGdCQUFnQjtRQUNaLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QyxPQUFPLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxjQUFjO1FBQ1YsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6RixJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2QsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ25DLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO3dHQXRDUSxXQUFXOzRHQUFYLFdBQVcsY0FGUixNQUFNOzs0RkFFVCxXQUFXO2tCQUh2QixVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBMb2NhbFN0b3JhZ2VTZXJ2aWNlLCBTZXNzaW9uU3RvcmFnZVNlcnZpY2UsIFN0b3JhZ2VDb25zdGFudHMgfSBmcm9tIFwiQHRlY2hleHRlbnNvci90YWItY29yZS11dGlsaXR5XCI7XG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFNlcnZpY2Uge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3Nlc3Npb25TdG9yYWdlU2VydmljZTogU2Vzc2lvblN0b3JhZ2VTZXJ2aWNlID0gaW5qZWN0KFNlc3Npb25TdG9yYWdlU2VydmljZSk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfbG9jYWxTdG9yYWdlU2VydmljZTogTG9jYWxTdG9yYWdlU2VydmljZSA9IGluamVjdChMb2NhbFN0b3JhZ2VTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBhcHBsaWNhdGlvbiBjb2RlL2lkZW50aWZpZXJcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGNvbnN0IGFwcENvZGUgPSBzZGsuY29uZmlnLmdldEFwcENvZGUoKTtcbiAgICAgKi9cbiAgICBnZXRBcHBDb2RlKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXNzaW9uU3RvcmFnZVNlcnZpY2UuZ2V0U2Vzc2lvblN0b3JhZ2UoU3RvcmFnZUNvbnN0YW50cy5hcHBsaWNhdGlvbkNvZGUpID8/ICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCB1c2VyIElEXG4gICAgICogXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBjb25zdCB1c2VySWQgPSBzZGsuYXV0aC5nZXRDdXJyZW50VXNlcklkKCk7XG4gICAgICovXG4gICAgZ2V0Q3VycmVudFVzZXJJZCgpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCB1c2VySW5mbyA9IHRoaXMuZ2V0Q3VycmVudFVzZXIoKTtcbiAgICAgICAgcmV0dXJuIHVzZXJJbmZvPy51c2VyPy5JZCA/PyAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGN1cnJlbnQgdXNlciBpbmZvcm1hdGlvblxuICAgICAqIFxuICAgICAqIEBleGFtcGxlXG4gICAgICogY29uc3QgdXNlciA9IHNkay5hdXRoLmdldEN1cnJlbnRVc2VyKCk7XG4gICAgICovXG4gICAgZ2V0Q3VycmVudFVzZXIoKTogYW55IHtcbiAgICAgICAgY29uc3QgdXNlckluZm9TdHIgPSB0aGlzLl9sb2NhbFN0b3JhZ2VTZXJ2aWNlLmdldExvY2FsU3RvcmFnZShTdG9yYWdlQ29uc3RhbnRzLnVzZXJJbmZvKTtcbiAgICAgICAgaWYgKHVzZXJJbmZvU3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZSh1c2VySW5mb1N0cik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG59Il19
@@ -1,81 +0,0 @@
1
- import { inject, Injectable } from "@angular/core";
2
- import { TabDeleteService, TabInsertService, TabUpdateService } from '@techextensor/tab-core-utility';
3
- import * as i0 from "@angular/core";
4
- export class DataService {
5
- _tabInsertService = inject(TabInsertService);
6
- _tabUpdateService = inject(TabUpdateService);
7
- _tabDeleteService = inject(TabDeleteService);
8
- /**
9
- * Insert a new record
10
- *
11
- * @example
12
- * const newRecord = await sdk.data.insert('123456', {
13
- * name: 'ACME Corp',
14
- * email: 'contact@acme.com'
15
- * });
16
- */
17
- insert(objectId, data) {
18
- return new Promise((resolve, reject) => {
19
- this._tabInsertService.insertByObjectId(objectId, { data })
20
- ?.subscribe((response) => {
21
- if (response?.StatusCode == 200 && response?.Result) {
22
- resolve(response.Result);
23
- }
24
- else {
25
- reject(new Error('Failed to insert record'));
26
- }
27
- });
28
- });
29
- }
30
- /**
31
- * Update an existing record
32
- *
33
- * @example
34
- * await sdk.data.update('12345', {
35
- * Id: '12345',
36
- * name: 'ACME Corporation',
37
- * status: 'active'
38
- * });
39
- */
40
- update(objectId, data) {
41
- return new Promise((resolve, reject) => {
42
- this._tabUpdateService.updateByObjectId(objectId, { data })
43
- ?.subscribe((response) => {
44
- if (response?.StatusCode == 200 && response?.Result) {
45
- resolve(response.Result);
46
- }
47
- else {
48
- reject(new Error('Failed to update record'));
49
- }
50
- });
51
- });
52
- }
53
- /**
54
- * Delete a record
55
- *
56
- * @example
57
- * await sdk.data.delete('12345', {Id: '12345'});
58
- */
59
- delete(objectId, data) {
60
- return new Promise((resolve, reject) => {
61
- this._tabDeleteService.deleteRecord('', { data }, objectId)
62
- ?.subscribe((response) => {
63
- if (response?.StatusCode == 200) {
64
- resolve();
65
- }
66
- else {
67
- reject(new Error('Failed to delete record'));
68
- }
69
- });
70
- });
71
- }
72
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
73
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataService, providedIn: 'root' });
74
- }
75
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DataService, decorators: [{
76
- type: Injectable,
77
- args: [{
78
- providedIn: 'root'
79
- }]
80
- }] });
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFiLXNkay9zcmMvbGliL2RhdGEvZGF0YS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDOztBQUt0RyxNQUFNLE9BQU8sV0FBVztJQUNILGlCQUFpQixHQUFxQixNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUMvRCxpQkFBaUIsR0FBcUIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDL0QsaUJBQWlCLEdBQXFCLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRWhGOzs7Ozs7OztPQVFHO0lBQ0gsTUFBTSxDQUFDLFFBQWdCLEVBQUUsSUFBUztRQUM5QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQztnQkFDdkQsRUFBRSxTQUFTLENBQUMsQ0FBQyxRQUFhLEVBQUUsRUFBRTtnQkFDMUIsSUFBSSxRQUFRLEVBQUUsVUFBVSxJQUFJLEdBQUcsSUFBSSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUM7b0JBQ2xELE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzdCLENBQUM7cUJBQU0sQ0FBQztvQkFDSixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxNQUFNLENBQUMsUUFBZ0IsRUFBRSxJQUFTO1FBQzlCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDbkMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDO2dCQUN2RCxFQUFFLFNBQVMsQ0FBQyxDQUFDLFFBQWEsRUFBRSxFQUFFO2dCQUMxQixJQUFJLFFBQVEsRUFBRSxVQUFVLElBQUksR0FBRyxJQUFJLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQztvQkFDbEQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDN0IsQ0FBQztxQkFBTSxDQUFDO29CQUNKLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pELENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNYLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsTUFBTSxDQUFDLFFBQWdCLEVBQUUsSUFBUztRQUM5QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLEVBQUMsSUFBSSxFQUFDLEVBQUUsUUFBUSxDQUFDO2dCQUNyRCxFQUFFLFNBQVMsQ0FBQyxDQUFDLFFBQWEsRUFBRSxFQUFFO2dCQUMxQixJQUFJLFFBQVEsRUFBRSxVQUFVLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQzlCLE9BQU8sRUFBRSxDQUFDO2dCQUNkLENBQUM7cUJBQU0sQ0FBQztvQkFDSixNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDO2dCQUNqRCxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDWCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7d0dBbkVRLFdBQVc7NEdBQVgsV0FBVyxjQUZSLE1BQU07OzRGQUVULFdBQVc7a0JBSHZCLFVBQVU7bUJBQUM7b0JBQ1IsVUFBVSxFQUFFLE1BQU07aUJBQ3JCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IFRhYkRlbGV0ZVNlcnZpY2UsIFRhYkluc2VydFNlcnZpY2UsIFRhYlVwZGF0ZVNlcnZpY2UgfSBmcm9tICdAdGVjaGV4dGVuc29yL3RhYi1jb3JlLXV0aWxpdHknO1xuXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIERhdGFTZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF90YWJJbnNlcnRTZXJ2aWNlOiBUYWJJbnNlcnRTZXJ2aWNlID0gaW5qZWN0KFRhYkluc2VydFNlcnZpY2UpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX3RhYlVwZGF0ZVNlcnZpY2U6IFRhYlVwZGF0ZVNlcnZpY2UgPSBpbmplY3QoVGFiVXBkYXRlU2VydmljZSk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfdGFiRGVsZXRlU2VydmljZTogVGFiRGVsZXRlU2VydmljZSA9IGluamVjdChUYWJEZWxldGVTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqIEluc2VydCBhIG5ldyByZWNvcmRcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGNvbnN0IG5ld1JlY29yZCA9IGF3YWl0IHNkay5kYXRhLmluc2VydCgnMTIzNDU2Jywge1xuICAgICAqICAgbmFtZTogJ0FDTUUgQ29ycCcsXG4gICAgICogICBlbWFpbDogJ2NvbnRhY3RAYWNtZS5jb20nXG4gICAgICogfSk7XG4gICAgICovXG4gICAgaW5zZXJ0KG9iamVjdElkOiBzdHJpbmcsIGRhdGE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fdGFiSW5zZXJ0U2VydmljZS5pbnNlcnRCeU9iamVjdElkKG9iamVjdElkLCB7IGRhdGEgfSlcbiAgICAgICAgICAgICAgICA/LnN1YnNjcmliZSgocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2U/LlN0YXR1c0NvZGUgPT0gMjAwICYmIHJlc3BvbnNlPy5SZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUocmVzcG9uc2UuUmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0ZhaWxlZCB0byBpbnNlcnQgcmVjb3JkJykpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSBhbiBleGlzdGluZyByZWNvcmRcbiAgICAgKiBcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGF3YWl0IHNkay5kYXRhLnVwZGF0ZSgnMTIzNDUnLCB7XG4gICAgICogICBJZDogJzEyMzQ1JyxcbiAgICAgKiAgIG5hbWU6ICdBQ01FIENvcnBvcmF0aW9uJyxcbiAgICAgKiAgIHN0YXR1czogJ2FjdGl2ZSdcbiAgICAgKiB9KTtcbiAgICAgKi9cbiAgICB1cGRhdGUob2JqZWN0SWQ6IHN0cmluZywgZGF0YTogYW55KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl90YWJVcGRhdGVTZXJ2aWNlLnVwZGF0ZUJ5T2JqZWN0SWQob2JqZWN0SWQsIHsgZGF0YSB9KVxuICAgICAgICAgICAgICAgID8uc3Vic2NyaWJlKChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZT8uU3RhdHVzQ29kZSA9PSAyMDAgJiYgcmVzcG9uc2U/LlJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShyZXNwb25zZS5SZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRmFpbGVkIHRvIHVwZGF0ZSByZWNvcmQnKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVsZXRlIGEgcmVjb3JkXG4gICAgICogXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBhd2FpdCBzZGsuZGF0YS5kZWxldGUoJzEyMzQ1Jywge0lkOiAnMTIzNDUnfSk7XG4gICAgICovXG4gICAgZGVsZXRlKG9iamVjdElkOiBzdHJpbmcsIGRhdGE6IGFueSk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fdGFiRGVsZXRlU2VydmljZS5kZWxldGVSZWNvcmQoJycsIHtkYXRhfSwgb2JqZWN0SWQpXG4gICAgICAgICAgICAgICAgPy5zdWJzY3JpYmUoKHJlc3BvbnNlOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlPy5TdGF0dXNDb2RlID09IDIwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRmFpbGVkIHRvIGRlbGV0ZSByZWNvcmQnKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxufSJdfQ==