@agility/management-sdk 0.1.22 → 0.1.23

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.
@@ -0,0 +1,65 @@
1
+ # Agility CMS Management SDK Test Suite Plan
2
+
3
+ ## Setup
4
+
5
+ * [x] Choose and install a test runner (Suggesting Jest).
6
+ * [x] Configure test scripts in `package.json`.
7
+ * [x] Set up test environment configuration (handling API keys, GUIDs etc., likely via environment variables).
8
+ * Using `.env` file for configuration.
9
+ * Implemented Azure Table Storage refresh token flow in `src/tests/authHelper.ts`.
10
+
11
+ ## Core Functionality Tests
12
+
13
+ * [x] Test SDK client initialization (`ApiClient` class).
14
+ * Tested via `src/tests/authHelper.ts` integration in `src/tests/sdk.test.ts`.
15
+ * [ ] Test basic read operations (e.g., getting models, locales).
16
+
17
+ ## CRUD Operation Tests (Integration Tests)
18
+
19
+ * **Content Items**
20
+ * [ ] Get Content List
21
+ * [ ] Get Content Item by ID
22
+ * [ ] Create Content Item
23
+ * [ ] Update Content Item
24
+ * [ ] Delete Content Item
25
+ * [ ] Publish Content Item
26
+ * [ ] Unpublish Content Item
27
+ * [ ] Request Content Approval
28
+ * **Content Models**
29
+ * [ ] Get Models List
30
+ * [ ] Get Model by ID
31
+ * [ ] Save Model (Create/Update)
32
+ * [ ] Delete Model
33
+ * **Assets**
34
+ * [ ] Get Assets List
35
+ * [ ] Upload Asset
36
+ * [ ] Get Asset by ID
37
+ * [ ] Delete Asset
38
+ * **Containers**
39
+ * [ ] Get Containers List
40
+ * [ ] Get Container by ID
41
+ * [ ] Save Container (Create/Update)
42
+ * [ ] Delete Container
43
+ * **Pages**
44
+ * [ ] Get Pages List
45
+ * [ ] Get Page by ID
46
+ * [ ] Create Page
47
+ * [ ] Update Page
48
+ * [ ] Delete Page
49
+ * [ ] Publish Page
50
+ * [ ] Unpublish Page
51
+ * [ ] Request Page Approval
52
+ * **Sync/Batch Operations**
53
+ * [ ] Test Sync Endpoints
54
+ * [ ] Test Batch Endpoints
55
+ * **Other Endpoints**
56
+ * [ ] Test URL Redirection endpoints
57
+ * [ ] Test Site Map endpoints
58
+ * [ ] Test Webhook endpoints
59
+
60
+ ## Refinement
61
+
62
+ * [ ] Organize tests logically (e.g., by SDK module/feature).
63
+ * [ ] Ensure tests clean up created resources (delete items, models, etc.).
64
+ * [ ] Add tests for error handling scenarios.
65
+ * [ ] Review structure for Turborepo compatibility (e.g., tests in a `src/__tests__` or root `tests` folder).
@@ -0,0 +1,155 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Agility CMS Management SDK Rules Overview
7
+
8
+ ## Introduction
9
+ This document serves as the central reference for all Agility CMS Management SDK rules. These rules are designed to help developers implement the SDK effectively, securely, and efficiently.
10
+
11
+ ## Rule Categories
12
+
13
+ ### 1. Core Functionality
14
+ - [Setup and Authentication](mdc:setup_and_auth.mdc)
15
+ - Authentication flow
16
+ - Token management
17
+ - SDK initialization
18
+ - Best practices
19
+
20
+ - [Content Management](mdc:content_management.mdc)
21
+ - Content operations
22
+ - Publishing workflow
23
+ - Content retrieval
24
+ - Batch operations
25
+
26
+ - [Page Management](mdc:page_management.mdc)
27
+ - Page operations
28
+ - Template management
29
+ - Sitemap handling
30
+ - Publishing workflow
31
+
32
+ - [Asset Management](mdc:asset_management.mdc)
33
+ - File uploads
34
+ - Folder management
35
+ - Asset retrieval
36
+ - Gallery operations
37
+
38
+ - [Webhook Management](mdc:webhook_management.mdc)
39
+ - Webhook setup
40
+ - Event handling
41
+ - Security considerations
42
+ - Best practices
43
+
44
+ ### 2. Project Structure
45
+ - [Configuration](mdc:configuration.mdc)
46
+ - Environment setup
47
+ - SDK initialization
48
+ - Error handling
49
+ - Logging
50
+
51
+ - [Common Patterns](mdc:common_patterns.mdc)
52
+ - Content caching
53
+ - Batch operations
54
+ - Page hierarchy
55
+ - Asset optimization
56
+ - Webhook patterns
57
+
58
+ - [Testing and Debugging](mdc:testing_and_debugging.mdc)
59
+ - Unit testing
60
+ - Integration testing
61
+ - Debugging tools
62
+ - Performance testing
63
+
64
+ - [Security](mdc:security.mdc)
65
+ - Authentication security
66
+ - API security
67
+ - Data security
68
+ - Webhook security
69
+
70
+ ## Getting Started
71
+
72
+ ### Quick Start
73
+ 1. Set up your environment variables (see [Configuration](mdc:configuration.mdc))
74
+ 2. Initialize the SDK (see [Setup and Authentication](mdc:setup_and_auth.mdc))
75
+ 3. Start implementing your features using the appropriate rule files
76
+
77
+ ### Best Practices
78
+ 1. Always follow security guidelines (see [Security](mdc:security.mdc))
79
+ 2. Implement proper error handling (see [Configuration](mdc:configuration.mdc))
80
+ 3. Use common patterns for efficiency (see [Common Patterns](mdc:common_patterns.mdc))
81
+ 4. Write comprehensive tests (see [Testing and Debugging](mdc:testing_and_debugging.mdc))
82
+
83
+ ## Implementation Guide
84
+
85
+ ### Content Management
86
+ ```typescript
87
+ // See content_management.mdc for details
88
+ const content = await apiClient.contentMethods.getContentItem(contentID, guid, locale);
89
+ ```
90
+
91
+ ### Page Management
92
+ ```typescript
93
+ // See page_management.mdc for details
94
+ const page = await apiClient.pageMethods.getPage(pageID, guid, locale);
95
+ ```
96
+
97
+ ### Asset Management
98
+ ```typescript
99
+ // See asset_management.mdc for details
100
+ await apiClient.assetMethods.upload(formData, path, guid, groupingID);
101
+ ```
102
+
103
+ ### Webhook Setup
104
+ ```typescript
105
+ // See webhook_management.mdc for details
106
+ const webhook = await apiClient.webhookMethods.saveWebhook(guid, webhookConfig);
107
+ ```
108
+
109
+ ## Common Scenarios
110
+
111
+ ### 1. Content Publishing Workflow
112
+ 1. Create content (see [Content Management](mdc:content_management.mdc))
113
+ 2. Request approval
114
+ 3. Publish content
115
+ 4. Monitor status
116
+
117
+ ### 2. Page Management
118
+ 1. Create page template (see [Page Management](mdc:page_management.mdc))
119
+ 2. Create page
120
+ 3. Add content
121
+ 4. Publish page
122
+
123
+ ### 3. Asset Management
124
+ 1. Create folder structure (see [Asset Management](mdc:asset_management.mdc))
125
+ 2. Upload assets
126
+ 3. Organize in galleries
127
+ 4. Link to content
128
+
129
+ ### 4. Webhook Implementation
130
+ 1. Set up webhook (see [Webhook Management](mdc:webhook_management.mdc))
131
+ 2. Implement handlers
132
+ 3. Test integration
133
+ 4. Monitor events
134
+
135
+ ## Troubleshooting
136
+ - Check [Testing and Debugging](mdc:testing_and_debugging.mdc) for debugging tools
137
+ - Review [Common Patterns](mdc:common_patterns.mdc) for known issues
138
+ - Consult [Security](mdc:security.mdc) for security-related issues
139
+
140
+ ## Additional Resources
141
+ - [Agility CMS Documentation](mdc:https:/help.agilitycms.com/hc/en-us)
142
+ - [TypeScript Documentation](mdc:https:/www.typescriptlang.org/docs)
143
+ - [Community Forums](mdc:https:/help.agilitycms.com/hc/en-us/community/topics)
144
+
145
+ ## Contributing
146
+ If you have additional rules or improvements to suggest:
147
+ 1. Create a new rule file
148
+ 2. Update this central reference
149
+ 3. Submit a pull request
150
+
151
+ ## Version History
152
+ - v1.0.0: Initial release
153
+ - v1.1.0: Added security rules
154
+ - v1.2.0: Added common patterns
155
+ - v1.3.0: Added testing and debugging rules
@@ -0,0 +1,97 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Agility CMS Asset Management Rules
7
+
8
+ ## Asset Operations
9
+ - Always provide required parameters: guid, mediaID
10
+ - Use appropriate methods for different asset operations
11
+ - Handle file uploads and management properly
12
+
13
+ ## File Upload
14
+ 1. Upload single file:
15
+ ```typescript
16
+ const form = new FormData();
17
+ form.append('files', file, fileName);
18
+ await apiClient.assetMethods.upload(form, agilityFolderPath, guid, groupingID);
19
+ ```
20
+
21
+ 2. Upload multiple files:
22
+ ```typescript
23
+ const form = new FormData();
24
+ files.forEach(file => {
25
+ form.append('files', file, file.name);
26
+ });
27
+ await apiClient.assetMethods.upload(form, agilityFolderPath, guid, groupingID);
28
+ ```
29
+
30
+ ## Folder Management
31
+ 1. Create folder:
32
+ ```typescript
33
+ await apiClient.assetMethods.createFolder(originKey, guid);
34
+ ```
35
+
36
+ 2. Delete folder:
37
+ ```typescript
38
+ await apiClient.assetMethods.deleteFolder(originKey, guid, mediaID);
39
+ ```
40
+
41
+ 3. Rename folder:
42
+ ```typescript
43
+ await apiClient.assetMethods.renameFolder(folderName, newFolderName, guid, mediaID);
44
+ ```
45
+
46
+ ## File Operations
47
+ 1. Delete file:
48
+ ```typescript
49
+ await apiClient.assetMethods.deleteFile(mediaID, guid);
50
+ ```
51
+
52
+ 2. Move file:
53
+ ```typescript
54
+ await apiClient.assetMethods.moveFile(mediaID, newFolder, guid);
55
+ ```
56
+
57
+ ## Asset Retrieval
58
+ 1. Get media list:
59
+ ```typescript
60
+ const mediaList = await apiClient.assetMethods.getMediaList(pageSize, recordOffset, guid);
61
+ ```
62
+
63
+ 2. Get asset by ID:
64
+ ```typescript
65
+ const asset = await apiClient.assetMethods.getAssetByID(mediaID, guid);
66
+ ```
67
+
68
+ 3. Get asset by URL:
69
+ ```typescript
70
+ const asset = await apiClient.assetMethods.getAssetByUrl(url, guid);
71
+ ```
72
+
73
+ ## Gallery Management
74
+ 1. Get gallery by ID:
75
+ ```typescript
76
+ const gallery = await apiClient.assetMethods.getGalleryById(guid, id);
77
+ ```
78
+
79
+ 2. Get gallery by name:
80
+ ```typescript
81
+ const gallery = await apiClient.assetMethods.getGalleryByName(guid, galleryName);
82
+ ```
83
+
84
+ 3. Save gallery:
85
+ ```typescript
86
+ await apiClient.assetMethods.saveGallery(guid, gallery);
87
+ ```
88
+
89
+ ## Best Practices
90
+ - Validate file types before upload
91
+ - Implement proper error handling
92
+ - Use appropriate folder structure
93
+ - Optimize file sizes before upload
94
+ - Use descriptive file names
95
+ - Implement proper access control
96
+ - Monitor storage usage
97
+ - Use appropriate file formats
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,5 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
@@ -0,0 +1,61 @@
1
+ ---
2
+ description:
3
+ globs:
4
+ alwaysApply: false
5
+ ---
6
+ # Agility CMS Webhook Management Rules
7
+
8
+ ## Webhook Operations
9
+ - Always provide required parameters: guid, webhookID
10
+ - Use appropriate methods for different webhook operations
11
+ - Handle webhook events properly
12
+
13
+ ## Webhook Management
14
+ 1. List webhooks:
15
+ ```typescript
16
+ const webhooks = await apiClient.webhookMethods.webhookList(guid, take, skip);
17
+ ```
18
+
19
+ 2. Create webhook:
20
+ ```typescript
21
+ const webhook = new Webhook();
22
+ // Set required properties
23
+ await apiClient.webhookMethods.saveWebhook(guid, webhook);
24
+ ```
25
+
26
+ 3. Get webhook:
27
+ ```typescript
28
+ const webhook = await apiClient.webhookMethods.getWebhook(guid, webhookID);
29
+ ```
30
+
31
+ 4. Delete webhook:
32
+ ```typescript
33
+ await apiClient.webhookMethods.deleteWebhook(guid, webhookID);
34
+ ```
35
+
36
+ ## Webhook Configuration
37
+ 1. Required properties:
38
+ - URL endpoint
39
+ - Event types to listen for
40
+ - Authentication if required
41
+ - Retry policy
42
+ - Payload format
43
+
44
+ 2. Event types:
45
+ - Content changes
46
+ - Page changes
47
+ - Asset changes
48
+ - User changes
49
+ - System events
50
+
51
+ ## Best Practices
52
+ - Implement proper error handling
53
+ - Use HTTPS endpoints
54
+ - Validate webhook payloads
55
+ - Implement retry logic
56
+ - Monitor webhook delivery
57
+ - Secure webhook endpoints
58
+ - Log webhook events
59
+ - Handle rate limiting
60
+ - Use appropriate authentication
61
+ - Test webhook endpoints
package/.env ADDED
@@ -0,0 +1,11 @@
1
+ AGILITY_GUID=f3866b86-u
2
+ AGILITY_API_KEY=defaultpreview.2672a9e1f5f8fade023029763b540c64eabfab48f92e693fa01081d845783dca
3
+ AGILITY_LOCALES=en-us
4
+ AGILITY_SITEMAP=website
5
+ AGILITY_API_ISPREVIEW=true
6
+
7
+ AGILITY_MANAGEMENT_API_BASE_URL=https://mgmt.aglty.io
8
+ TEST_ENV=dev
9
+ STORAGE_ACCOUNT=agilitydevstorage
10
+ STORAGE_ACCOUNT_KEY=0gMvadhiKgr04J0u0dlui8gaH6rY8kRo46vNvG/JmGAmzhMqsQ7V+bonmZOVgqMOo9STt0xyEToHBpJFjVeR/w==
11
+ STORAGE_ACCOUNT_TABLE=TokenInfo
package/README.md CHANGED
@@ -12,8 +12,82 @@
12
12
  ### Prerequisites
13
13
  1. Clone the repository agility-cms-management-sdk-typescript.
14
14
  2. Import the index file to make use of the Options class.
15
- 3. Create an object of the Options class to provide values of -
16
- - token -> Bearer token to authenticate a Rest Request to perform an operation.
15
+ 3. You will need valid Agility CMS credentials to authenticate and obtain an access token.
16
+
17
+ ### Authentication
18
+ Before using the SDK, you must authenticate against the Agility Management API to obtain a valid access token. This token is required for all subsequent API requests.
19
+
20
+ The authentication process uses OAuth 2.0 and requires multiple steps:
21
+
22
+ 1. First, initiate the authorization flow by making a GET request to the authorization endpoint:
23
+ ```javascript
24
+ const authUrl = 'https://mgmt.aglty.io/oauth/authorize';
25
+ const params = new URLSearchParams({
26
+ response_type: 'code',
27
+ redirect_uri: 'YOUR_REDIRECT_URI',
28
+ state: 'YOUR_STATE',
29
+ scope: 'openid profile email offline_access'
30
+ });
31
+
32
+ // Redirect the user to the authorization URL
33
+ window.location.href = `${authUrl}?${params.toString()}`;
34
+ ```
35
+
36
+ 2. After successful authentication, you'll receive an authorization code at your redirect URI. Use this code to obtain an access token:
37
+ ```javascript
38
+ const response = await fetch('https://mgmt.aglty.io/oauth/token', {
39
+ method: 'POST',
40
+ headers: {
41
+ 'Content-Type': 'application/x-www-form-urlencoded'
42
+ },
43
+ body: new URLSearchParams({
44
+ code: 'YOUR_AUTHORIZATION_CODE'
45
+ })
46
+ });
47
+
48
+ const { access_token, refresh_token, expires_in } = await response.json();
49
+ ```
50
+
51
+ 3. Use the obtained token to initialize the SDK:
52
+ ```javascript
53
+ import * as mgmtApi from "./index";
54
+
55
+ // Initialize the Options Class with your authentication token
56
+ let options = new mgmtApi.Options();
57
+ options.token = access_token; // Use the token obtained from authentication
58
+
59
+ // Initialize the APIClient Class
60
+ let apiClient = new mgmtApi.ApiClient(options);
61
+
62
+ let guid = "<<Provide the Guid of the Website>>";
63
+ let locale = "<<Provide the locale of the Website>>"; // Example: en-us
64
+
65
+ // Now you can make authenticated requests
66
+ var contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
67
+ console.log(JSON.stringify(contentItem));
68
+ ```
69
+
70
+ 4. When the access token expires, use the refresh token to obtain a new access token:
71
+ ```javascript
72
+ const response = await fetch('https://mgmt.aglty.io/oauth/refresh', {
73
+ method: 'POST',
74
+ headers: {
75
+ 'Content-Type': 'application/json'
76
+ },
77
+ body: JSON.stringify({
78
+ refresh_token: 'YOUR_REFRESH_TOKEN'
79
+ })
80
+ });
81
+
82
+ const { access_token, refresh_token, expires_in } = await response.json();
83
+ ```
84
+
85
+ Note:
86
+ - The access token has a limited lifetime (typically 1 hour)
87
+ - The refresh token can be used to obtain new access tokens
88
+ - Store refresh tokens securely and never expose them in client-side code
89
+ - Implement proper error handling for authentication failures
90
+
17
91
  4. Create an object of Method class(es), which can be used to create and perform operations. Following is the description of Classes and their respective methods -
18
92
 
19
93
  ### Making a Request
@@ -662,6 +736,14 @@ Returns: An object with the requested Webhook.
662
736
  | `guid` | `string` | Current website guid.|
663
737
  | `webhookID` | `string` | The webhookID of the requested webhook.|
664
738
 
739
+ ## Class Instance
740
+
741
+ ### getLocales
742
+ | Parameter | Type | Description |
743
+ | :-------- | :------- | :------------------------- |
744
+ | `guid` | `string` | Current website guid.|
745
+
746
+ Returns: An array of locales. ex. ['en-us','fr-ca']
665
747
 
666
748
  ## Running the SDK Locally
667
749
 
@@ -12,6 +12,6 @@ export declare class ContainerMethods {
12
12
  getContainerSecurity(id: number, guid: string): Promise<Container>;
13
13
  getContainerList(guid: string): Promise<Container[]>;
14
14
  getNotificationList(id: number, guid: string): Promise<Notification[]>;
15
- saveContainer(container: Container, guid: string): Promise<Container>;
15
+ saveContainer(container: Container, guid: string, forceReferenceName?: boolean): Promise<Container>;
16
16
  deleteContainer(id: number, guid: string): Promise<string>;
17
17
  }
@@ -164,14 +164,15 @@ var ContainerMethods = /** @class */ (function () {
164
164
  });
165
165
  });
166
166
  };
167
- ContainerMethods.prototype.saveContainer = function (container, guid) {
168
- return __awaiter(this, void 0, void 0, function () {
167
+ ContainerMethods.prototype.saveContainer = function (container_1, guid_1) {
168
+ return __awaiter(this, arguments, void 0, function (container, guid, forceReferenceName) {
169
169
  var apiPath, resp, err_7;
170
+ if (forceReferenceName === void 0) { forceReferenceName = false; }
170
171
  return __generator(this, function (_a) {
171
172
  switch (_a.label) {
172
173
  case 0:
173
174
  _a.trys.push([0, 2, , 3]);
174
- apiPath = "container";
175
+ apiPath = "container".concat(forceReferenceName ? '?forceReferenceName=true' : '');
175
176
  return [4 /*yield*/, this._clientInstance.executePost(apiPath, guid, this._options.token, container)];
176
177
  case 1:
177
178
  resp = _a.sent();
@@ -18,8 +18,8 @@ export declare class ContentMethods {
18
18
  approveContent(contentID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
19
19
  declineContent(contentID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
20
20
  deleteContent(contentID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
21
- saveContentItem(contentItem: ContentItem, guid: string, locale: string): Promise<number[]>;
22
- saveContentItems(contentItems: ContentItem[], guid: string, locale: string): Promise<number[]>;
21
+ saveContentItem(contentItem: ContentItem, guid: string, locale: string): Promise<import("..").Batch | number[]>;
22
+ saveContentItems(contentItems: ContentItem[], guid: string, locale: string): Promise<import("..").Batch | number[]>;
23
23
  getContentItems(referenceName: string, guid: string, locale: string, listParams: ListParams): Promise<ContentList>;
24
24
  getContentList(referenceName: string, guid: string, locale: string, listParams: ListParams, filterObject?: ContentListFilterModel): Promise<ContentList>;
25
25
  getContentHistory(locale: string, guid: string, contentID: number, take?: number, skip?: number): Promise<ContentItemHistory>;
@@ -285,6 +285,10 @@ var ContentMethods = /** @class */ (function () {
285
285
  }); }); })];
286
286
  case 2:
287
287
  batch = _a.sent();
288
+ // Aaaron May 1 2025 - if the batch has error data, return the batch not just the -1 contentID
289
+ if (batch.errorData) {
290
+ return [2 /*return*/, batch];
291
+ }
288
292
  contentIDs_7 = [];
289
293
  batch.items.forEach(function (element) { return contentIDs_7.push(element.itemID); });
290
294
  return [2 /*return*/, contentIDs_7];
@@ -317,6 +321,10 @@ var ContentMethods = /** @class */ (function () {
317
321
  }); }); })];
318
322
  case 2:
319
323
  batch = _a.sent();
324
+ // Aaaron May 1 2025 - if the batch has error data, return the batch not just the -1 contentID
325
+ if (batch.errorData) {
326
+ return [2 /*return*/, batch];
327
+ }
320
328
  contentIDs_8 = [];
321
329
  batch.items.forEach(function (element) { return contentIDs_8.push(element.itemID); });
322
330
  return [2 /*return*/, contentIDs_8];
@@ -26,7 +26,7 @@ export declare class PageMethods {
26
26
  approvePage(pageID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
27
27
  declinePage(pageID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
28
28
  deletePage(pageID: number, guid: string, locale: string, comments?: string): Promise<number[]>;
29
- savePage(pageItem: PageItem, guid: string, locale: string, parentPageID?: number, placeBeforePageItemID?: number): Promise<number[]>;
29
+ savePage(pageItem: PageItem, guid: string, locale: string, parentPageID?: number, placeBeforePageItemID?: number): Promise<import("..").Batch | number[]>;
30
30
  getPageHistory(locale: string, guid: string, pageID: number, take?: number, skip?: number): Promise<PageHistory>;
31
31
  getPageComments(locale: string, guid: string, pageID: number, take?: number, skip?: number): Promise<ItemComments>;
32
32
  }
@@ -430,6 +430,10 @@ var PageMethods = /** @class */ (function () {
430
430
  }); }); })];
431
431
  case 2:
432
432
  batch = _a.sent();
433
+ // Aaaron May 1 2025 - if the batch has error data, return the batch not just the -1 pageID
434
+ if (batch.errorData) {
435
+ return [2 /*return*/, batch];
436
+ }
433
437
  pageIDs_7 = [];
434
438
  batch.items.forEach(function (element) { return pageIDs_7.push(element.itemID); });
435
439
  return [2 /*return*/, pageIDs_7];
@@ -0,0 +1,11 @@
1
+ export declare class TokenResponseData {
2
+ partitionKey: string;
3
+ rowKey: string;
4
+ access_token: string;
5
+ refresh_token: string;
6
+ token_type?: string;
7
+ expires_in?: number;
8
+ timestamp?: Date;
9
+ etag?: string;
10
+ constructor(partitionKey: string, rowKey: string);
11
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenResponseData = void 0;
4
+ var TokenResponseData = /** @class */ (function () {
5
+ function TokenResponseData(partitionKey, rowKey) {
6
+ this.access_token = '';
7
+ this.refresh_token = '';
8
+ this.partitionKey = partitionKey;
9
+ this.rowKey = rowKey;
10
+ }
11
+ return TokenResponseData;
12
+ }());
13
+ exports.TokenResponseData = TokenResponseData;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var authHelper_1 = require("./authHelper"); // Import the new helper
40
+ describe('Instance Methods', function () {
41
+ var apiClient;
42
+ var guid;
43
+ // Use jest.setTimeout for potentially longer async setup
44
+ jest.setTimeout(30000); // 30 seconds timeout for auth
45
+ beforeAll(function () { return __awaiter(void 0, void 0, void 0, function () {
46
+ var authResult, error_1;
47
+ return __generator(this, function (_a) {
48
+ switch (_a.label) {
49
+ case 0:
50
+ _a.trys.push([0, 2, , 3]);
51
+ console.log("Setting up Instance Methods tests...");
52
+ return [4 /*yield*/, (0, authHelper_1.getApiClientWithAuth)()];
53
+ case 1:
54
+ authResult = _a.sent();
55
+ apiClient = authResult.apiClient;
56
+ guid = authResult.guid; // Get guid from the helper result
57
+ if (!apiClient || !guid) {
58
+ throw new Error("Failed to initialize authenticated API client for tests.");
59
+ }
60
+ console.log("Authenticated client ready for Instance Methods tests.");
61
+ return [3 /*break*/, 3];
62
+ case 2:
63
+ error_1 = _a.sent();
64
+ console.error("FATAL: Error during test setup (beforeAll):", error_1);
65
+ // Rethrow or process.exit to prevent tests running without auth
66
+ throw error_1;
67
+ case 3: return [2 /*return*/];
68
+ }
69
+ });
70
+ }); });
71
+ it('should get locales for the instance', function () { return __awaiter(void 0, void 0, void 0, function () {
72
+ var locales, error_2;
73
+ return __generator(this, function (_a) {
74
+ switch (_a.label) {
75
+ case 0:
76
+ expect(apiClient.instanceMethods).toBeDefined();
77
+ _a.label = 1;
78
+ case 1:
79
+ _a.trys.push([1, 3, , 4]);
80
+ return [4 /*yield*/, apiClient.instanceMethods.getLocales(guid)];
81
+ case 2:
82
+ locales = _a.sent();
83
+ expect(locales).toBeDefined();
84
+ expect(Array.isArray(locales)).toBe(true);
85
+ expect(locales.length).toBeGreaterThan(0);
86
+ // Check the type of the first locale code
87
+ expect(typeof locales[0]).toBe('string');
88
+ console.log("Found ".concat(locales.length, " locales. First locale code: ").concat(locales[0]));
89
+ return [3 /*break*/, 4];
90
+ case 3:
91
+ error_2 = _a.sent();
92
+ console.error("Error fetching locales:", error_2);
93
+ throw error_2; // Re-throw to fail the test
94
+ case 4: return [2 /*return*/];
95
+ }
96
+ });
97
+ }); });
98
+ // Add more tests for other instanceMethods here
99
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var authHelper_1 = require("./authHelper");
40
+ var apiClient_1 = require("../apiClient");
41
+ describe('Authentication Helper', function () {
42
+ // Increase timeout for auth process
43
+ jest.setTimeout(30000);
44
+ it('should get an authenticated API client without errors', function () { return __awaiter(void 0, void 0, void 0, function () {
45
+ var _a, apiClient, guid, error_1;
46
+ var _b;
47
+ return __generator(this, function (_c) {
48
+ switch (_c.label) {
49
+ case 0:
50
+ _c.trys.push([0, 2, , 3]);
51
+ console.log("Testing getApiClientWithAuth...");
52
+ return [4 /*yield*/, (0, authHelper_1.getApiClientWithAuth)()];
53
+ case 1:
54
+ _a = _c.sent(), apiClient = _a.apiClient, guid = _a.guid;
55
+ expect(apiClient).toBeDefined();
56
+ expect(apiClient).toBeInstanceOf(apiClient_1.ApiClient);
57
+ expect(guid).toBeDefined();
58
+ expect(typeof guid).toBe('string');
59
+ expect(guid.length).toBeGreaterThan(0);
60
+ // Check that the client has options and a token/baseUrl from the auth helper
61
+ expect(apiClient._options).toBeDefined();
62
+ expect(apiClient._options.token).toBeDefined();
63
+ expect(apiClient._options.token.length).toBeGreaterThan(0);
64
+ expect(apiClient._options.baseUrl).toBeDefined();
65
+ expect((_b = apiClient._options.baseUrl) === null || _b === void 0 ? void 0 : _b.startsWith('http')).toBe(true);
66
+ console.log("Successfully obtained authenticated client via helper for GUID: ".concat(guid));
67
+ console.log("Token starts with: ".concat(apiClient._options.token.substring(0, 10), "..."));
68
+ console.log("Base URL: ".concat(apiClient._options.baseUrl));
69
+ return [3 /*break*/, 3];
70
+ case 2:
71
+ error_1 = _c.sent();
72
+ console.error("Error testing getApiClientWithAuth:", error_1);
73
+ throw error_1; // Fail the test if auth helper fails
74
+ case 3: return [2 /*return*/];
75
+ }
76
+ });
77
+ }); });
78
+ });
@@ -0,0 +1,12 @@
1
+ # Agility CMS Test Environment Variables
2
+ # Copy this file to .env and fill in your actual values.
3
+
4
+ # Required for API calls
5
+ AGILITY_GUID=
6
+
7
+ # Required for Authentication via Azure Table Storage Refresh Token Flow
8
+ STORAGE_ACCOUNT=
9
+ STORAGE_ACCOUNT_KEY=
10
+ STORAGE_ACCOUNT_TABLE=
11
+ AGILITY_MANAGEMENT_API_BASE_URL= # e.g., https://mgmt.aglty.io or https://mgmt-dev.aglty.io
12
+ TEST_ENV=prod # Optional: set to 'dev' if using dev refresh token rowKey, otherwise defaults to 'prod' rowKey
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agility/management-sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "Agility CMS Tyescript SDK for Management API.",
5
5
  "repository": {
6
6
  "type": "git",