@agility/management-sdk 0.1.35 → 0.1.37

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 (261) hide show
  1. package/README.md +371 -317
  2. package/dist/apiMethods/clientInstance.d.ts +2 -0
  3. package/dist/apiMethods/clientInstance.js +11 -2
  4. package/dist/apiMethods/containerMethods.d.ts +3 -0
  5. package/dist/apiMethods/containerMethods.js +43 -9
  6. package/dist/apiMethods/contentMethods.d.ts +12 -0
  7. package/dist/apiMethods/contentMethods.js +119 -48
  8. package/dist/apiMethods/pageMethods.d.ts +12 -0
  9. package/dist/apiMethods/pageMethods.js +88 -34
  10. package/dist/enums/contentViewType.d.ts +6 -0
  11. package/dist/enums/contentViewType.js +10 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +2 -0
  14. package/dist/models/pagedResult.d.ts +4 -0
  15. package/dist/models/pagedResult.js +2 -0
  16. package/dist/util/queryString.d.ts +8 -0
  17. package/dist/util/queryString.js +27 -0
  18. package/docs/asset-methods.md +381 -381
  19. package/docs/auth-component.md +360 -360
  20. package/docs/auth.md +593 -593
  21. package/docs/batch-methods.md +243 -243
  22. package/docs/cicd.md +606 -606
  23. package/docs/container-methods.md +267 -267
  24. package/docs/content-methods.md +491 -422
  25. package/docs/instance-methods.md +104 -104
  26. package/docs/instance-user-methods.md +230 -230
  27. package/docs/model-methods.md +433 -433
  28. package/docs/multi-instance-operations.md +191 -191
  29. package/docs/page-methods.md +737 -670
  30. package/docs/server-user-methods.md +279 -279
  31. package/docs/webhook-methods.md +451 -451
  32. package/license.txt +20 -20
  33. package/package.json +40 -40
  34. package/tsconfig.json +14 -14
  35. package/.cursor/api-coverage.md +0 -217
  36. package/.cursor/api-documentation-manifest.md +0 -275
  37. package/.cursor/api-functions-analysis.md +0 -111
  38. package/.cursor/breakout-manifest.md +0 -278
  39. package/.cursor/docs-final-check.md +0 -269
  40. package/.cursor/github-actions-improvements.md +0 -76
  41. package/.cursor/hardening.md +0 -271
  42. package/.cursor/linting-fix.md +0 -160
  43. package/.cursor/manifest.md +0 -243
  44. package/.cursor/mocks.md +0 -100
  45. package/.cursor/test-coverage.md +0 -841
  46. package/.env +0 -92
  47. package/coverage/base.css +0 -224
  48. package/coverage/block-navigation.js +0 -87
  49. package/coverage/coverage-summary.json +0 -43
  50. package/coverage/favicon.png +0 -0
  51. package/coverage/index.html +0 -161
  52. package/coverage/lcov-report/base.css +0 -224
  53. package/coverage/lcov-report/block-navigation.js +0 -87
  54. package/coverage/lcov-report/favicon.png +0 -0
  55. package/coverage/lcov-report/index.html +0 -161
  56. package/coverage/lcov-report/prettify.css +0 -1
  57. package/coverage/lcov-report/prettify.js +0 -2
  58. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  59. package/coverage/lcov-report/sorter.js +0 -210
  60. package/coverage/lcov-report/src/apiClient.ts.html +0 -199
  61. package/coverage/lcov-report/src/apiMethods/assetMethods.ts.html +0 -682
  62. package/coverage/lcov-report/src/apiMethods/batchMethods.ts.html +0 -736
  63. package/coverage/lcov-report/src/apiMethods/clientInstance.ts.html +0 -403
  64. package/coverage/lcov-report/src/apiMethods/containerMethods.ts.html +0 -460
  65. package/coverage/lcov-report/src/apiMethods/contentMethods.ts.html +0 -1183
  66. package/coverage/lcov-report/src/apiMethods/index.html +0 -266
  67. package/coverage/lcov-report/src/apiMethods/instanceMethods.ts.html +0 -160
  68. package/coverage/lcov-report/src/apiMethods/instanceUserMethods.ts.html +0 -268
  69. package/coverage/lcov-report/src/apiMethods/modelMethods.ts.html +0 -352
  70. package/coverage/lcov-report/src/apiMethods/pageMethods.ts.html +0 -1276
  71. package/coverage/lcov-report/src/apiMethods/serverUserMethods.ts.html +0 -196
  72. package/coverage/lcov-report/src/apiMethods/webhookMethods.ts.html +0 -271
  73. package/coverage/lcov-report/src/enums/batchItemType.ts.html +0 -106
  74. package/coverage/lcov-report/src/enums/batchOperationType.ts.html +0 -142
  75. package/coverage/lcov-report/src/enums/batchState..ts.html +0 -106
  76. package/coverage/lcov-report/src/enums/index.html +0 -161
  77. package/coverage/lcov-report/src/enums/workflowOperationType.ts.html +0 -175
  78. package/coverage/lcov-report/src/index.html +0 -116
  79. package/coverage/lcov-report/src/models/assetContainer.ts.html +0 -106
  80. package/coverage/lcov-report/src/models/assetGalleries.ts.html +0 -103
  81. package/coverage/lcov-report/src/models/assetMediaGrouping.ts.html +0 -136
  82. package/coverage/lcov-report/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  83. package/coverage/lcov-report/src/models/batch.ts.html +0 -178
  84. package/coverage/lcov-report/src/models/batchItem.ts.html +0 -127
  85. package/coverage/lcov-report/src/models/container.ts.html +0 -232
  86. package/coverage/lcov-report/src/models/contentDefinitionTypeID.ts.html +0 -142
  87. package/coverage/lcov-report/src/models/contentItem.ts.html +0 -202
  88. package/coverage/lcov-report/src/models/contentSectionDefaultModule.ts.html +0 -106
  89. package/coverage/lcov-report/src/models/contentSectionDefinition.ts.html +0 -196
  90. package/coverage/lcov-report/src/models/contentViewColumn.ts.html +0 -109
  91. package/coverage/lcov-report/src/models/exception.ts.html +0 -109
  92. package/coverage/lcov-report/src/models/index.html +0 -476
  93. package/coverage/lcov-report/src/models/instanceRole.ts.html +0 -106
  94. package/coverage/lcov-report/src/models/instanceUser.ts.html +0 -130
  95. package/coverage/lcov-report/src/models/locales.ts.html +0 -100
  96. package/coverage/lcov-report/src/models/media.ts.html +0 -178
  97. package/coverage/lcov-report/src/models/model.ts.html +0 -172
  98. package/coverage/lcov-report/src/models/notification.ts.html +0 -124
  99. package/coverage/lcov-report/src/models/options.ts.html +0 -109
  100. package/coverage/lcov-report/src/models/pageItem.ts.html +0 -268
  101. package/coverage/lcov-report/src/models/pageModel.ts.html +0 -130
  102. package/coverage/lcov-report/src/models/sharedModule.ts.html +0 -106
  103. package/coverage/lcov-report/src/models/sitemap.ts.html +0 -148
  104. package/coverage/lcov-report/src/models/websiteUser.ts.html +0 -157
  105. package/coverage/lcov.info +0 -1459
  106. package/coverage/prettify.css +0 -1
  107. package/coverage/prettify.js +0 -2
  108. package/coverage/sort-arrow-sprite.png +0 -0
  109. package/coverage/sorter.js +0 -210
  110. package/coverage/src/apiClient.ts.html +0 -199
  111. package/coverage/src/apiMethods/assetMethods.ts.html +0 -682
  112. package/coverage/src/apiMethods/batchMethods.ts.html +0 -736
  113. package/coverage/src/apiMethods/clientInstance.ts.html +0 -403
  114. package/coverage/src/apiMethods/containerMethods.ts.html +0 -460
  115. package/coverage/src/apiMethods/contentMethods.ts.html +0 -1183
  116. package/coverage/src/apiMethods/index.html +0 -266
  117. package/coverage/src/apiMethods/instanceMethods.ts.html +0 -160
  118. package/coverage/src/apiMethods/instanceUserMethods.ts.html +0 -268
  119. package/coverage/src/apiMethods/modelMethods.ts.html +0 -352
  120. package/coverage/src/apiMethods/pageMethods.ts.html +0 -1276
  121. package/coverage/src/apiMethods/serverUserMethods.ts.html +0 -196
  122. package/coverage/src/apiMethods/webhookMethods.ts.html +0 -271
  123. package/coverage/src/enums/batchItemType.ts.html +0 -106
  124. package/coverage/src/enums/batchOperationType.ts.html +0 -142
  125. package/coverage/src/enums/batchState..ts.html +0 -106
  126. package/coverage/src/enums/index.html +0 -161
  127. package/coverage/src/enums/workflowOperationType.ts.html +0 -175
  128. package/coverage/src/index.html +0 -116
  129. package/coverage/src/models/assetContainer.ts.html +0 -106
  130. package/coverage/src/models/assetGalleries.ts.html +0 -103
  131. package/coverage/src/models/assetMediaGrouping.ts.html +0 -136
  132. package/coverage/src/models/assetMediaGroupingMetaData.ts.html +0 -97
  133. package/coverage/src/models/batch.ts.html +0 -178
  134. package/coverage/src/models/batchItem.ts.html +0 -127
  135. package/coverage/src/models/container.ts.html +0 -232
  136. package/coverage/src/models/contentDefinitionTypeID.ts.html +0 -142
  137. package/coverage/src/models/contentItem.ts.html +0 -202
  138. package/coverage/src/models/contentSectionDefaultModule.ts.html +0 -106
  139. package/coverage/src/models/contentSectionDefinition.ts.html +0 -196
  140. package/coverage/src/models/contentViewColumn.ts.html +0 -109
  141. package/coverage/src/models/exception.ts.html +0 -109
  142. package/coverage/src/models/index.html +0 -476
  143. package/coverage/src/models/instanceRole.ts.html +0 -106
  144. package/coverage/src/models/instanceUser.ts.html +0 -130
  145. package/coverage/src/models/locales.ts.html +0 -100
  146. package/coverage/src/models/media.ts.html +0 -178
  147. package/coverage/src/models/model.ts.html +0 -172
  148. package/coverage/src/models/notification.ts.html +0 -124
  149. package/coverage/src/models/options.ts.html +0 -109
  150. package/coverage/src/models/pageItem.ts.html +0 -268
  151. package/coverage/src/models/pageModel.ts.html +0 -130
  152. package/coverage/src/models/sharedModule.ts.html +0 -106
  153. package/coverage/src/models/sitemap.ts.html +0 -148
  154. package/coverage/src/models/websiteUser.ts.html +0 -157
  155. package/dist/.tsbuildinfo +0 -1
  156. package/dist/apiClient.d.ts.map +0 -1
  157. package/dist/apiClient.js.map +0 -1
  158. package/dist/apiMethods/assetMethods.d.ts.map +0 -1
  159. package/dist/apiMethods/assetMethods.js.map +0 -1
  160. package/dist/apiMethods/batchMethods.d.ts.map +0 -1
  161. package/dist/apiMethods/batchMethods.js.map +0 -1
  162. package/dist/apiMethods/clientInstance.d.ts.map +0 -1
  163. package/dist/apiMethods/clientInstance.js.map +0 -1
  164. package/dist/apiMethods/containerMethods.d.ts.map +0 -1
  165. package/dist/apiMethods/containerMethods.js.map +0 -1
  166. package/dist/apiMethods/contentMethods.d.ts.map +0 -1
  167. package/dist/apiMethods/contentMethods.js.map +0 -1
  168. package/dist/apiMethods/instanceMethods.d.ts.map +0 -1
  169. package/dist/apiMethods/instanceMethods.js.map +0 -1
  170. package/dist/apiMethods/instanceUserMethods.d.ts.map +0 -1
  171. package/dist/apiMethods/instanceUserMethods.js.map +0 -1
  172. package/dist/apiMethods/modelMethods.d.ts.map +0 -1
  173. package/dist/apiMethods/modelMethods.js.map +0 -1
  174. package/dist/apiMethods/pageMethods.d.ts.map +0 -1
  175. package/dist/apiMethods/pageMethods.js.map +0 -1
  176. package/dist/apiMethods/serverUserMethods.d.ts.map +0 -1
  177. package/dist/apiMethods/serverUserMethods.js.map +0 -1
  178. package/dist/apiMethods/webhookMethods.d.ts.map +0 -1
  179. package/dist/apiMethods/webhookMethods.js.map +0 -1
  180. package/dist/enums/assetGroupingType.d.ts.map +0 -1
  181. package/dist/enums/assetGroupingType.js.map +0 -1
  182. package/dist/enums/batchItemType.d.ts.map +0 -1
  183. package/dist/enums/batchItemType.js.map +0 -1
  184. package/dist/enums/batchOperationType.d.ts.map +0 -1
  185. package/dist/enums/batchOperationType.js.map +0 -1
  186. package/dist/enums/batchState..d.ts.map +0 -1
  187. package/dist/enums/batchState..js.map +0 -1
  188. package/dist/enums/pageItemTemplateType.d.ts.map +0 -1
  189. package/dist/enums/pageItemTemplateType.js.map +0 -1
  190. package/dist/enums/workflowOperationType.d.ts.map +0 -1
  191. package/dist/enums/workflowOperationType.js.map +0 -1
  192. package/dist/index.d.ts.map +0 -1
  193. package/dist/index.js.map +0 -1
  194. package/dist/models/assetContainer.d.ts.map +0 -1
  195. package/dist/models/assetContainer.js.map +0 -1
  196. package/dist/models/assetGalleries.d.ts.map +0 -1
  197. package/dist/models/assetGalleries.js.map +0 -1
  198. package/dist/models/assetMediaGrouping.d.ts.map +0 -1
  199. package/dist/models/assetMediaGrouping.js.map +0 -1
  200. package/dist/models/assetMediaGroupingMetaData.d.ts.map +0 -1
  201. package/dist/models/assetMediaGroupingMetaData.js.map +0 -1
  202. package/dist/models/batch.d.ts.map +0 -1
  203. package/dist/models/batch.js.map +0 -1
  204. package/dist/models/batchItem.d.ts.map +0 -1
  205. package/dist/models/batchItem.js.map +0 -1
  206. package/dist/models/batchTypes.d.ts.map +0 -1
  207. package/dist/models/batchTypes.js.map +0 -1
  208. package/dist/models/container.d.ts.map +0 -1
  209. package/dist/models/container.js.map +0 -1
  210. package/dist/models/contentDefinitionTypeID.d.ts.map +0 -1
  211. package/dist/models/contentDefinitionTypeID.js.map +0 -1
  212. package/dist/models/contentItem.d.ts.map +0 -1
  213. package/dist/models/contentItem.js.map +0 -1
  214. package/dist/models/contentItemHistory.d.ts.map +0 -1
  215. package/dist/models/contentItemHistory.js.map +0 -1
  216. package/dist/models/contentListFilterModel.d.ts.map +0 -1
  217. package/dist/models/contentListFilterModel.js.map +0 -1
  218. package/dist/models/contentSectionDefaultModule.d.ts.map +0 -1
  219. package/dist/models/contentSectionDefaultModule.js.map +0 -1
  220. package/dist/models/contentSectionDefinition.d.ts.map +0 -1
  221. package/dist/models/contentSectionDefinition.js.map +0 -1
  222. package/dist/models/contentViewColumn.d.ts.map +0 -1
  223. package/dist/models/contentViewColumn.js.map +0 -1
  224. package/dist/models/exception.d.ts.map +0 -1
  225. package/dist/models/exception.js.map +0 -1
  226. package/dist/models/instanceRole.d.ts.map +0 -1
  227. package/dist/models/instanceRole.js.map +0 -1
  228. package/dist/models/instanceUser.d.ts.map +0 -1
  229. package/dist/models/instanceUser.js.map +0 -1
  230. package/dist/models/itemComments.d.ts.map +0 -1
  231. package/dist/models/itemComments.js.map +0 -1
  232. package/dist/models/listParams.d.ts.map +0 -1
  233. package/dist/models/listParams.js.map +0 -1
  234. package/dist/models/locales.d.ts.map +0 -1
  235. package/dist/models/locales.js.map +0 -1
  236. package/dist/models/media.d.ts.map +0 -1
  237. package/dist/models/media.js.map +0 -1
  238. package/dist/models/model.d.ts.map +0 -1
  239. package/dist/models/model.js.map +0 -1
  240. package/dist/models/notification.d.ts.map +0 -1
  241. package/dist/models/notification.js.map +0 -1
  242. package/dist/models/options.d.ts.map +0 -1
  243. package/dist/models/options.js.map +0 -1
  244. package/dist/models/pageHistory.d.ts.map +0 -1
  245. package/dist/models/pageHistory.js.map +0 -1
  246. package/dist/models/pageItem.d.ts.map +0 -1
  247. package/dist/models/pageItem.js.map +0 -1
  248. package/dist/models/pageModel.d.ts.map +0 -1
  249. package/dist/models/pageModel.js.map +0 -1
  250. package/dist/models/serverUser.d.ts.map +0 -1
  251. package/dist/models/serverUser.js.map +0 -1
  252. package/dist/models/sharedModule.d.ts.map +0 -1
  253. package/dist/models/sharedModule.js.map +0 -1
  254. package/dist/models/sitemap.d.ts.map +0 -1
  255. package/dist/models/sitemap.js.map +0 -1
  256. package/dist/models/webhook.d.ts.map +0 -1
  257. package/dist/models/webhook.js.map +0 -1
  258. package/dist/models/websiteListing.d.ts.map +0 -1
  259. package/dist/models/websiteListing.js.map +0 -1
  260. package/dist/models/websiteUser.d.ts.map +0 -1
  261. package/dist/models/websiteUser.js.map +0 -1
package/docs/cicd.md CHANGED
@@ -1,607 +1,607 @@
1
- # CI/CD & Automated Environments
2
-
3
- This guide covers using the Agility CMS Management SDK in automated environments such as CI/CD pipelines, serverless functions, and other programmatic scenarios where the OAuth flow isn't practical.
4
-
5
- ## Table of Contents
6
-
7
- - [Overview](#overview)
8
- - [Token-Based Authentication](#token-based-authentication)
9
- - [Environment Configuration](#environment-configuration)
10
- - [CI/CD Pipeline Examples](#cicd-pipeline-examples)
11
- - [Serverless Functions](#serverless-functions)
12
- - [Token Management](#token-management)
13
- - [Security Best Practices](#security-best-practices)
14
-
15
- ---
16
-
17
- ## Overview
18
-
19
- In automated environments, the interactive OAuth flow isn't practical. Instead, you'll use **access tokens** directly. This approach is ideal for:
20
-
21
- - **CI/CD Pipelines** - Automated content deployment
22
- - **Serverless Functions** - Event-triggered content operations
23
- - **Scheduled Jobs** - Content synchronization, backups, etc.
24
- - **Build Processes** - Static site generation with fresh content
25
- - **Automated Testing** - Integration tests requiring content operations
26
-
27
- ---
28
-
29
- ## Token-Based Authentication
30
-
31
- ### Using Options Constructor
32
-
33
- ```typescript
34
- import * as mgmtApi from '@agility/management-sdk';
35
-
36
- // Set token via Options constructor
37
- const options = new mgmtApi.Options();
38
- options.token = process.env.AGILITY_API_TOKEN;
39
-
40
- const apiClient = new mgmtApi.ApiClient(options);
41
- // Token is automatically stored in keytar for consistency
42
-
43
- // Ready to use immediately
44
- const guid = process.env.AGILITY_GUID;
45
- const locale = 'en-us';
46
-
47
- const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
48
- console.log('Content retrieved:', contentItem.fields.title);
49
- ```
50
-
51
- ### Using setToken Method
52
-
53
- ```typescript
54
- import * as mgmtApi from '@agility/management-sdk';
55
-
56
- // Initialize without token
57
- const apiClient = new mgmtApi.ApiClient();
58
-
59
- // Set token programmatically
60
- await apiClient.setToken(process.env.AGILITY_API_TOKEN);
61
-
62
- // Ready to use
63
- const content = await apiClient.contentMethods.getContentList(guid, locale);
64
- ```
65
-
66
- ---
67
-
68
- ## Environment Configuration
69
-
70
- ### Environment Variables
71
-
72
- Set up your environment variables for secure token management:
73
-
74
- ```bash
75
- # .env file
76
- AGILITY_API_TOKEN=your_access_token_here
77
- AGILITY_GUID=your_website_guid
78
- AGILITY_LOCALE=en-us
79
- AGILITY_REGION=us # Optional: us, ca, eu, aus, dev
80
- ```
81
-
82
- ### Loading Configuration
83
-
84
- ```typescript
85
- import * as mgmtApi from '@agility/management-sdk';
86
- import dotenv from 'dotenv';
87
-
88
- // Load environment variables
89
- dotenv.config();
90
-
91
- // Validate required environment variables
92
- const requiredEnvVars = ['AGILITY_API_TOKEN', 'AGILITY_GUID'];
93
- for (const envVar of requiredEnvVars) {
94
- if (!process.env[envVar]) {
95
- throw new Error(`Missing required environment variable: ${envVar}`);
96
- }
97
- }
98
-
99
- // Initialize client with environment configuration
100
- const options = new mgmtApi.Options();
101
- options.token = process.env.AGILITY_API_TOKEN;
102
-
103
- const apiClient = new mgmtApi.ApiClient(options);
104
-
105
- // Global configuration
106
- const config = {
107
- guid: process.env.AGILITY_GUID!,
108
- locale: process.env.AGILITY_LOCALE || 'en-us',
109
- region: process.env.AGILITY_REGION || 'us'
110
- };
111
-
112
- export { apiClient, config };
113
- ```
114
-
115
- ---
116
-
117
- ## CI/CD Pipeline Examples
118
-
119
- ### GitHub Actions
120
-
121
- ```yaml
122
- # .github/workflows/content-deploy.yml
123
- name: Deploy Content
124
-
125
- on:
126
- push:
127
- branches: [main]
128
- workflow_dispatch:
129
-
130
- jobs:
131
- deploy:
132
- runs-on: ubuntu-latest
133
-
134
- steps:
135
- - uses: actions/checkout@v3
136
-
137
- - name: Setup Node.js
138
- uses: actions/setup-node@v3
139
- with:
140
- node-version: '18'
141
-
142
- - name: Install dependencies
143
- run: npm ci
144
-
145
- - name: Deploy Content
146
- env:
147
- AGILITY_API_TOKEN: ${{ secrets.AGILITY_API_TOKEN }}
148
- AGILITY_GUID: ${{ secrets.AGILITY_GUID }}
149
- AGILITY_LOCALE: 'en-us'
150
- run: node deploy-content.js
151
- ```
152
-
153
- ```javascript
154
- // deploy-content.js
155
- const mgmtApi = require('@agility/management-sdk');
156
-
157
- async function deployContent() {
158
- // Initialize with token from environment
159
- const options = new mgmtApi.Options();
160
- options.token = process.env.AGILITY_API_TOKEN;
161
-
162
- const apiClient = new mgmtApi.ApiClient(options);
163
-
164
- const guid = process.env.AGILITY_GUID;
165
- const locale = process.env.AGILITY_LOCALE;
166
-
167
- try {
168
- // Deploy content items
169
- const contentItems = [
170
- {
171
- properties: {
172
- referenceName: 'deployment-notice',
173
- definitionName: 'Announcement',
174
- state: 2
175
- },
176
- fields: {
177
- title: `Deployment ${new Date().toISOString()}`,
178
- content: 'Application deployed successfully',
179
- publishDate: new Date().toISOString()
180
- }
181
- }
182
- ];
183
-
184
- for (const item of contentItems) {
185
- const contentId = await apiClient.contentMethods.saveContentItem(
186
- item,
187
- guid,
188
- locale
189
- );
190
- console.log(`✅ Content created: ${contentId}`);
191
- }
192
-
193
- console.log('🚀 Content deployment completed successfully');
194
-
195
- } catch (error) {
196
- console.error('❌ Deployment failed:', error.message);
197
- process.exit(1);
198
- }
199
- }
200
-
201
- deployContent();
202
- ```
203
-
204
- ### GitLab CI
205
-
206
- ```yaml
207
- # .gitlab-ci.yml
208
- stages:
209
- - deploy
210
-
211
- deploy_content:
212
- stage: deploy
213
- image: node:18
214
- script:
215
- - npm ci
216
- - node deploy-content.js
217
- variables:
218
- AGILITY_GUID: $AGILITY_GUID
219
- AGILITY_LOCALE: "en-us"
220
- environment: production
221
- only:
222
- - main
223
- ```
224
-
225
- ### Jenkins Pipeline
226
-
227
- ```groovy
228
- pipeline {
229
- agent any
230
-
231
- environment {
232
- AGILITY_API_TOKEN = credentials('agility-api-token')
233
- AGILITY_GUID = credentials('agility-guid')
234
- AGILITY_LOCALE = 'en-us'
235
- }
236
-
237
- stages {
238
- stage('Deploy Content') {
239
- steps {
240
- sh 'npm ci'
241
- sh 'node deploy-content.js'
242
- }
243
- }
244
- }
245
- }
246
- ```
247
-
248
- ---
249
-
250
- ## Serverless Functions
251
-
252
- ### AWS Lambda
253
-
254
- ```typescript
255
- import * as mgmtApi from '@agility/management-sdk';
256
-
257
- // Initialize outside handler for connection reuse
258
- const options = new mgmtApi.Options();
259
- options.token = process.env.AGILITY_API_TOKEN;
260
- const apiClient = new mgmtApi.ApiClient(options);
261
-
262
- const config = {
263
- guid: process.env.AGILITY_GUID!,
264
- locale: process.env.AGILITY_LOCALE || 'en-us'
265
- };
266
-
267
- export const handler = async (event: any, context: any) => {
268
- try {
269
- // Process event data
270
- const { title, content, category } = JSON.parse(event.body);
271
-
272
- // Create content item
273
- const contentItem = {
274
- properties: {
275
- referenceName: 'api-content',
276
- definitionName: 'Article',
277
- state: 2
278
- },
279
- fields: {
280
- title: title,
281
- content: content,
282
- category: category,
283
- publishDate: new Date().toISOString()
284
- }
285
- };
286
-
287
- const contentId = await apiClient.contentMethods.saveContentItem(
288
- contentItem,
289
- config.guid,
290
- config.locale
291
- );
292
-
293
- return {
294
- statusCode: 200,
295
- body: JSON.stringify({
296
- success: true,
297
- contentId: contentId,
298
- message: 'Content created successfully'
299
- })
300
- };
301
-
302
- } catch (error) {
303
- console.error('Lambda error:', error);
304
-
305
- return {
306
- statusCode: 500,
307
- body: JSON.stringify({
308
- success: false,
309
- error: error.message
310
- })
311
- };
312
- }
313
- };
314
- ```
315
-
316
- ### Vercel Functions
317
-
318
- ```typescript
319
- // api/create-content.ts
320
- import type { VercelRequest, VercelResponse } from '@vercel/node';
321
- import * as mgmtApi from '@agility/management-sdk';
322
-
323
- export default async function handler(req: VercelRequest, res: VercelResponse) {
324
- if (req.method !== 'POST') {
325
- return res.status(405).json({ error: 'Method not allowed' });
326
- }
327
-
328
- try {
329
- // Initialize API client
330
- const options = new mgmtApi.Options();
331
- options.token = process.env.AGILITY_API_TOKEN;
332
- const apiClient = new mgmtApi.ApiClient(options);
333
-
334
- // Process request
335
- const { title, content } = req.body;
336
-
337
- const contentItem = {
338
- properties: {
339
- referenceName: 'vercel-content',
340
- definitionName: 'BlogPost',
341
- state: 2
342
- },
343
- fields: {
344
- title: title,
345
- content: content,
346
- publishDate: new Date().toISOString()
347
- }
348
- };
349
-
350
- const contentId = await apiClient.contentMethods.saveContentItem(
351
- contentItem,
352
- process.env.AGILITY_GUID!,
353
- 'en-us'
354
- );
355
-
356
- res.status(200).json({
357
- success: true,
358
- contentId: contentId
359
- });
360
-
361
- } catch (error) {
362
- console.error('Vercel function error:', error);
363
- res.status(500).json({
364
- success: false,
365
- error: error.message
366
- });
367
- }
368
- }
369
- ```
370
-
371
- ---
372
-
373
- ## Token Management
374
-
375
- ### Token Validation
376
-
377
- ```typescript
378
- import * as mgmtApi from '@agility/management-sdk';
379
-
380
- async function validateToken(token: string): Promise<boolean> {
381
- try {
382
- const options = new mgmtApi.Options();
383
- options.token = token;
384
- const apiClient = new mgmtApi.ApiClient(options);
385
-
386
- // Test token by making a simple API call
387
- const locales = await apiClient.instanceMethods.getLocales(
388
- process.env.AGILITY_GUID!
389
- );
390
-
391
- return locales.length > 0;
392
-
393
- } catch (error) {
394
- console.error('Token validation failed:', error.message);
395
- return false;
396
- }
397
- }
398
-
399
- // Usage in CI/CD
400
- if (!(await validateToken(process.env.AGILITY_API_TOKEN!))) {
401
- console.error('❌ Invalid API token');
402
- process.exit(1);
403
- }
404
- ```
405
-
406
- ### Token Rotation
407
-
408
- ```typescript
409
- // token-rotation.js
410
- const mgmtApi = require('@agility/management-sdk');
411
-
412
- class TokenRotationService {
413
- constructor() {
414
- this.currentToken = process.env.AGILITY_API_TOKEN;
415
- this.backupToken = process.env.AGILITY_API_TOKEN_BACKUP;
416
- }
417
-
418
- async getWorkingToken() {
419
- // Try current token first
420
- if (await this.validateToken(this.currentToken)) {
421
- return this.currentToken;
422
- }
423
-
424
- // Fallback to backup token
425
- if (await this.validateToken(this.backupToken)) {
426
- console.warn('⚠️ Using backup token - main token may be expired');
427
- return this.backupToken;
428
- }
429
-
430
- throw new Error('No valid tokens available');
431
- }
432
-
433
- async validateToken(token) {
434
- try {
435
- const options = new mgmtApi.Options();
436
- options.token = token;
437
- const apiClient = new mgmtApi.ApiClient(options);
438
-
439
- await apiClient.instanceMethods.getLocales(process.env.AGILITY_GUID);
440
- return true;
441
- } catch {
442
- return false;
443
- }
444
- }
445
- }
446
-
447
- module.exports = TokenRotationService;
448
- ```
449
-
450
- ---
451
-
452
- ## Security Best Practices
453
-
454
- ### Environment Variable Security
455
-
456
- ```typescript
457
- // security-config.ts
458
- export class SecurityConfig {
459
- private static validateToken(token: string): boolean {
460
- // Basic token format validation
461
- if (!token || typeof token !== 'string') {
462
- return false;
463
- }
464
-
465
- // Check minimum length
466
- if (token.length < 20) {
467
- return false;
468
- }
469
-
470
- // Check for placeholder values
471
- const placeholders = ['your_token', 'replace_me', 'token_here'];
472
- return !placeholders.some(placeholder =>
473
- token.toLowerCase().includes(placeholder)
474
- );
475
- }
476
-
477
- static getSecureToken(): string {
478
- const token = process.env.AGILITY_API_TOKEN;
479
-
480
- if (!token) {
481
- throw new Error('AGILITY_API_TOKEN environment variable is required');
482
- }
483
-
484
- if (!this.validateToken(token)) {
485
- throw new Error('Invalid token format detected');
486
- }
487
-
488
- return token;
489
- }
490
-
491
- static getSecureConfig() {
492
- return {
493
- token: this.getSecureToken(),
494
- guid: process.env.AGILITY_GUID || (() => {
495
- throw new Error('AGILITY_GUID environment variable is required');
496
- })(),
497
- locale: process.env.AGILITY_LOCALE || 'en-us'
498
- };
499
- }
500
- }
501
- ```
502
-
503
- ### Error Handling
504
-
505
- ```typescript
506
- // error-handling.ts
507
- import * as mgmtApi from '@agility/management-sdk';
508
-
509
- export class CICDErrorHandler {
510
- static async executeWithRetry<T>(
511
- operation: () => Promise<T>,
512
- maxRetries: number = 3,
513
- delay: number = 1000
514
- ): Promise<T> {
515
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
516
- try {
517
- return await operation();
518
- } catch (error) {
519
- console.error(`Attempt ${attempt} failed:`, error.message);
520
-
521
- if (attempt === maxRetries) {
522
- throw error;
523
- }
524
-
525
- // Exponential backoff
526
- const waitTime = delay * Math.pow(2, attempt - 1);
527
- console.log(`⏳ Retrying in ${waitTime}ms...`);
528
- await new Promise(resolve => setTimeout(resolve, waitTime));
529
- }
530
- }
531
-
532
- throw new Error('All retry attempts failed');
533
- }
534
-
535
- static handleCICDError(error: any, context: string): never {
536
- console.error(`❌ CICD Error in ${context}:`, error.message);
537
-
538
- // Log additional context for debugging
539
- if (error.response) {
540
- console.error('Response status:', error.response.status);
541
- console.error('Response data:', error.response.data);
542
- }
543
-
544
- // Exit with error code for CI/CD pipeline
545
- process.exit(1);
546
- }
547
- }
548
-
549
- // Usage example
550
- try {
551
- const result = await CICDErrorHandler.executeWithRetry(async () => {
552
- return await apiClient.contentMethods.saveContentItem(contentData, guid, locale);
553
- });
554
-
555
- console.log('✅ Content saved successfully:', result);
556
- } catch (error) {
557
- CICDErrorHandler.handleCICDError(error, 'content creation');
558
- }
559
- ```
560
-
561
- ### Logging and Monitoring
562
-
563
- ```typescript
564
- // cicd-logger.ts
565
- export class CICDLogger {
566
- private static logLevel = process.env.LOG_LEVEL || 'INFO';
567
-
568
- static info(message: string, data?: any) {
569
- const timestamp = new Date().toISOString();
570
- console.log(`[${timestamp}] INFO: ${message}`, data || '');
571
- }
572
-
573
- static error(message: string, error?: any) {
574
- const timestamp = new Date().toISOString();
575
- console.error(`[${timestamp}] ERROR: ${message}`, error || '');
576
- }
577
-
578
- static logOperation(operation: string, guid: string, locale: string) {
579
- this.info(`Starting operation: ${operation}`, { guid, locale });
580
- }
581
-
582
- static logSuccess(operation: string, result: any) {
583
- this.info(`Operation completed: ${operation}`, { result });
584
- }
585
-
586
- static logFailure(operation: string, error: any) {
587
- this.error(`Operation failed: ${operation}`, error);
588
- }
589
- }
590
- ```
591
-
592
- ---
593
-
594
- ## Navigation
595
- - [← Back to Main Documentation](../README.md)
596
- - [Authentication & Setup](./auth.md)
597
- - [AssetMethods](./asset-methods.md)
598
- - [BatchMethods](./batch-methods.md)
599
- - [ContainerMethods](./container-methods.md)
600
- - [ContentMethods](./content-methods.md)
601
- - [InstanceMethods](./instance-methods.md)
602
- - [InstanceUserMethods](./instance-user-methods.md)
603
- - [ModelMethods](./model-methods.md)
604
- - [PageMethods](./page-methods.md)
605
- - [ServerUserMethods](./server-user-methods.md)
606
- - [WebhookMethods](./webhook-methods.md)
1
+ # CI/CD & Automated Environments
2
+
3
+ This guide covers using the Agility CMS Management SDK in automated environments such as CI/CD pipelines, serverless functions, and other programmatic scenarios where the OAuth flow isn't practical.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Overview](#overview)
8
+ - [Token-Based Authentication](#token-based-authentication)
9
+ - [Environment Configuration](#environment-configuration)
10
+ - [CI/CD Pipeline Examples](#cicd-pipeline-examples)
11
+ - [Serverless Functions](#serverless-functions)
12
+ - [Token Management](#token-management)
13
+ - [Security Best Practices](#security-best-practices)
14
+
15
+ ---
16
+
17
+ ## Overview
18
+
19
+ In automated environments, the interactive OAuth flow isn't practical. Instead, you'll use **access tokens** directly. This approach is ideal for:
20
+
21
+ - **CI/CD Pipelines** - Automated content deployment
22
+ - **Serverless Functions** - Event-triggered content operations
23
+ - **Scheduled Jobs** - Content synchronization, backups, etc.
24
+ - **Build Processes** - Static site generation with fresh content
25
+ - **Automated Testing** - Integration tests requiring content operations
26
+
27
+ ---
28
+
29
+ ## Token-Based Authentication
30
+
31
+ ### Using Options Constructor
32
+
33
+ ```typescript
34
+ import * as mgmtApi from '@agility/management-sdk';
35
+
36
+ // Set token via Options constructor
37
+ const options = new mgmtApi.Options();
38
+ options.token = process.env.AGILITY_API_TOKEN;
39
+
40
+ const apiClient = new mgmtApi.ApiClient(options);
41
+ // Token is automatically stored in keytar for consistency
42
+
43
+ // Ready to use immediately
44
+ const guid = process.env.AGILITY_GUID;
45
+ const locale = 'en-us';
46
+
47
+ const contentItem = await apiClient.contentMethods.getContentItem(22, guid, locale);
48
+ console.log('Content retrieved:', contentItem.fields.title);
49
+ ```
50
+
51
+ ### Using setToken Method
52
+
53
+ ```typescript
54
+ import * as mgmtApi from '@agility/management-sdk';
55
+
56
+ // Initialize without token
57
+ const apiClient = new mgmtApi.ApiClient();
58
+
59
+ // Set token programmatically
60
+ await apiClient.setToken(process.env.AGILITY_API_TOKEN);
61
+
62
+ // Ready to use
63
+ const content = await apiClient.contentMethods.getContentList(guid, locale);
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Environment Configuration
69
+
70
+ ### Environment Variables
71
+
72
+ Set up your environment variables for secure token management:
73
+
74
+ ```bash
75
+ # .env file
76
+ AGILITY_API_TOKEN=your_access_token_here
77
+ AGILITY_GUID=your_website_guid
78
+ AGILITY_LOCALE=en-us
79
+ AGILITY_REGION=us # Optional: us, ca, eu, aus, dev
80
+ ```
81
+
82
+ ### Loading Configuration
83
+
84
+ ```typescript
85
+ import * as mgmtApi from '@agility/management-sdk';
86
+ import dotenv from 'dotenv';
87
+
88
+ // Load environment variables
89
+ dotenv.config();
90
+
91
+ // Validate required environment variables
92
+ const requiredEnvVars = ['AGILITY_API_TOKEN', 'AGILITY_GUID'];
93
+ for (const envVar of requiredEnvVars) {
94
+ if (!process.env[envVar]) {
95
+ throw new Error(`Missing required environment variable: ${envVar}`);
96
+ }
97
+ }
98
+
99
+ // Initialize client with environment configuration
100
+ const options = new mgmtApi.Options();
101
+ options.token = process.env.AGILITY_API_TOKEN;
102
+
103
+ const apiClient = new mgmtApi.ApiClient(options);
104
+
105
+ // Global configuration
106
+ const config = {
107
+ guid: process.env.AGILITY_GUID!,
108
+ locale: process.env.AGILITY_LOCALE || 'en-us',
109
+ region: process.env.AGILITY_REGION || 'us'
110
+ };
111
+
112
+ export { apiClient, config };
113
+ ```
114
+
115
+ ---
116
+
117
+ ## CI/CD Pipeline Examples
118
+
119
+ ### GitHub Actions
120
+
121
+ ```yaml
122
+ # .github/workflows/content-deploy.yml
123
+ name: Deploy Content
124
+
125
+ on:
126
+ push:
127
+ branches: [main]
128
+ workflow_dispatch:
129
+
130
+ jobs:
131
+ deploy:
132
+ runs-on: ubuntu-latest
133
+
134
+ steps:
135
+ - uses: actions/checkout@v3
136
+
137
+ - name: Setup Node.js
138
+ uses: actions/setup-node@v3
139
+ with:
140
+ node-version: '18'
141
+
142
+ - name: Install dependencies
143
+ run: npm ci
144
+
145
+ - name: Deploy Content
146
+ env:
147
+ AGILITY_API_TOKEN: ${{ secrets.AGILITY_API_TOKEN }}
148
+ AGILITY_GUID: ${{ secrets.AGILITY_GUID }}
149
+ AGILITY_LOCALE: 'en-us'
150
+ run: node deploy-content.js
151
+ ```
152
+
153
+ ```javascript
154
+ // deploy-content.js
155
+ const mgmtApi = require('@agility/management-sdk');
156
+
157
+ async function deployContent() {
158
+ // Initialize with token from environment
159
+ const options = new mgmtApi.Options();
160
+ options.token = process.env.AGILITY_API_TOKEN;
161
+
162
+ const apiClient = new mgmtApi.ApiClient(options);
163
+
164
+ const guid = process.env.AGILITY_GUID;
165
+ const locale = process.env.AGILITY_LOCALE;
166
+
167
+ try {
168
+ // Deploy content items
169
+ const contentItems = [
170
+ {
171
+ properties: {
172
+ referenceName: 'deployment-notice',
173
+ definitionName: 'Announcement',
174
+ state: 2
175
+ },
176
+ fields: {
177
+ title: `Deployment ${new Date().toISOString()}`,
178
+ content: 'Application deployed successfully',
179
+ publishDate: new Date().toISOString()
180
+ }
181
+ }
182
+ ];
183
+
184
+ for (const item of contentItems) {
185
+ const contentId = await apiClient.contentMethods.saveContentItem(
186
+ item,
187
+ guid,
188
+ locale
189
+ );
190
+ console.log(`✅ Content created: ${contentId}`);
191
+ }
192
+
193
+ console.log('🚀 Content deployment completed successfully');
194
+
195
+ } catch (error) {
196
+ console.error('❌ Deployment failed:', error.message);
197
+ process.exit(1);
198
+ }
199
+ }
200
+
201
+ deployContent();
202
+ ```
203
+
204
+ ### GitLab CI
205
+
206
+ ```yaml
207
+ # .gitlab-ci.yml
208
+ stages:
209
+ - deploy
210
+
211
+ deploy_content:
212
+ stage: deploy
213
+ image: node:18
214
+ script:
215
+ - npm ci
216
+ - node deploy-content.js
217
+ variables:
218
+ AGILITY_GUID: $AGILITY_GUID
219
+ AGILITY_LOCALE: "en-us"
220
+ environment: production
221
+ only:
222
+ - main
223
+ ```
224
+
225
+ ### Jenkins Pipeline
226
+
227
+ ```groovy
228
+ pipeline {
229
+ agent any
230
+
231
+ environment {
232
+ AGILITY_API_TOKEN = credentials('agility-api-token')
233
+ AGILITY_GUID = credentials('agility-guid')
234
+ AGILITY_LOCALE = 'en-us'
235
+ }
236
+
237
+ stages {
238
+ stage('Deploy Content') {
239
+ steps {
240
+ sh 'npm ci'
241
+ sh 'node deploy-content.js'
242
+ }
243
+ }
244
+ }
245
+ }
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Serverless Functions
251
+
252
+ ### AWS Lambda
253
+
254
+ ```typescript
255
+ import * as mgmtApi from '@agility/management-sdk';
256
+
257
+ // Initialize outside handler for connection reuse
258
+ const options = new mgmtApi.Options();
259
+ options.token = process.env.AGILITY_API_TOKEN;
260
+ const apiClient = new mgmtApi.ApiClient(options);
261
+
262
+ const config = {
263
+ guid: process.env.AGILITY_GUID!,
264
+ locale: process.env.AGILITY_LOCALE || 'en-us'
265
+ };
266
+
267
+ export const handler = async (event: any, context: any) => {
268
+ try {
269
+ // Process event data
270
+ const { title, content, category } = JSON.parse(event.body);
271
+
272
+ // Create content item
273
+ const contentItem = {
274
+ properties: {
275
+ referenceName: 'api-content',
276
+ definitionName: 'Article',
277
+ state: 2
278
+ },
279
+ fields: {
280
+ title: title,
281
+ content: content,
282
+ category: category,
283
+ publishDate: new Date().toISOString()
284
+ }
285
+ };
286
+
287
+ const contentId = await apiClient.contentMethods.saveContentItem(
288
+ contentItem,
289
+ config.guid,
290
+ config.locale
291
+ );
292
+
293
+ return {
294
+ statusCode: 200,
295
+ body: JSON.stringify({
296
+ success: true,
297
+ contentId: contentId,
298
+ message: 'Content created successfully'
299
+ })
300
+ };
301
+
302
+ } catch (error) {
303
+ console.error('Lambda error:', error);
304
+
305
+ return {
306
+ statusCode: 500,
307
+ body: JSON.stringify({
308
+ success: false,
309
+ error: error.message
310
+ })
311
+ };
312
+ }
313
+ };
314
+ ```
315
+
316
+ ### Vercel Functions
317
+
318
+ ```typescript
319
+ // api/create-content.ts
320
+ import type { VercelRequest, VercelResponse } from '@vercel/node';
321
+ import * as mgmtApi from '@agility/management-sdk';
322
+
323
+ export default async function handler(req: VercelRequest, res: VercelResponse) {
324
+ if (req.method !== 'POST') {
325
+ return res.status(405).json({ error: 'Method not allowed' });
326
+ }
327
+
328
+ try {
329
+ // Initialize API client
330
+ const options = new mgmtApi.Options();
331
+ options.token = process.env.AGILITY_API_TOKEN;
332
+ const apiClient = new mgmtApi.ApiClient(options);
333
+
334
+ // Process request
335
+ const { title, content } = req.body;
336
+
337
+ const contentItem = {
338
+ properties: {
339
+ referenceName: 'vercel-content',
340
+ definitionName: 'BlogPost',
341
+ state: 2
342
+ },
343
+ fields: {
344
+ title: title,
345
+ content: content,
346
+ publishDate: new Date().toISOString()
347
+ }
348
+ };
349
+
350
+ const contentId = await apiClient.contentMethods.saveContentItem(
351
+ contentItem,
352
+ process.env.AGILITY_GUID!,
353
+ 'en-us'
354
+ );
355
+
356
+ res.status(200).json({
357
+ success: true,
358
+ contentId: contentId
359
+ });
360
+
361
+ } catch (error) {
362
+ console.error('Vercel function error:', error);
363
+ res.status(500).json({
364
+ success: false,
365
+ error: error.message
366
+ });
367
+ }
368
+ }
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Token Management
374
+
375
+ ### Token Validation
376
+
377
+ ```typescript
378
+ import * as mgmtApi from '@agility/management-sdk';
379
+
380
+ async function validateToken(token: string): Promise<boolean> {
381
+ try {
382
+ const options = new mgmtApi.Options();
383
+ options.token = token;
384
+ const apiClient = new mgmtApi.ApiClient(options);
385
+
386
+ // Test token by making a simple API call
387
+ const locales = await apiClient.instanceMethods.getLocales(
388
+ process.env.AGILITY_GUID!
389
+ );
390
+
391
+ return locales.length > 0;
392
+
393
+ } catch (error) {
394
+ console.error('Token validation failed:', error.message);
395
+ return false;
396
+ }
397
+ }
398
+
399
+ // Usage in CI/CD
400
+ if (!(await validateToken(process.env.AGILITY_API_TOKEN!))) {
401
+ console.error('❌ Invalid API token');
402
+ process.exit(1);
403
+ }
404
+ ```
405
+
406
+ ### Token Rotation
407
+
408
+ ```typescript
409
+ // token-rotation.js
410
+ const mgmtApi = require('@agility/management-sdk');
411
+
412
+ class TokenRotationService {
413
+ constructor() {
414
+ this.currentToken = process.env.AGILITY_API_TOKEN;
415
+ this.backupToken = process.env.AGILITY_API_TOKEN_BACKUP;
416
+ }
417
+
418
+ async getWorkingToken() {
419
+ // Try current token first
420
+ if (await this.validateToken(this.currentToken)) {
421
+ return this.currentToken;
422
+ }
423
+
424
+ // Fallback to backup token
425
+ if (await this.validateToken(this.backupToken)) {
426
+ console.warn('⚠️ Using backup token - main token may be expired');
427
+ return this.backupToken;
428
+ }
429
+
430
+ throw new Error('No valid tokens available');
431
+ }
432
+
433
+ async validateToken(token) {
434
+ try {
435
+ const options = new mgmtApi.Options();
436
+ options.token = token;
437
+ const apiClient = new mgmtApi.ApiClient(options);
438
+
439
+ await apiClient.instanceMethods.getLocales(process.env.AGILITY_GUID);
440
+ return true;
441
+ } catch {
442
+ return false;
443
+ }
444
+ }
445
+ }
446
+
447
+ module.exports = TokenRotationService;
448
+ ```
449
+
450
+ ---
451
+
452
+ ## Security Best Practices
453
+
454
+ ### Environment Variable Security
455
+
456
+ ```typescript
457
+ // security-config.ts
458
+ export class SecurityConfig {
459
+ private static validateToken(token: string): boolean {
460
+ // Basic token format validation
461
+ if (!token || typeof token !== 'string') {
462
+ return false;
463
+ }
464
+
465
+ // Check minimum length
466
+ if (token.length < 20) {
467
+ return false;
468
+ }
469
+
470
+ // Check for placeholder values
471
+ const placeholders = ['your_token', 'replace_me', 'token_here'];
472
+ return !placeholders.some(placeholder =>
473
+ token.toLowerCase().includes(placeholder)
474
+ );
475
+ }
476
+
477
+ static getSecureToken(): string {
478
+ const token = process.env.AGILITY_API_TOKEN;
479
+
480
+ if (!token) {
481
+ throw new Error('AGILITY_API_TOKEN environment variable is required');
482
+ }
483
+
484
+ if (!this.validateToken(token)) {
485
+ throw new Error('Invalid token format detected');
486
+ }
487
+
488
+ return token;
489
+ }
490
+
491
+ static getSecureConfig() {
492
+ return {
493
+ token: this.getSecureToken(),
494
+ guid: process.env.AGILITY_GUID || (() => {
495
+ throw new Error('AGILITY_GUID environment variable is required');
496
+ })(),
497
+ locale: process.env.AGILITY_LOCALE || 'en-us'
498
+ };
499
+ }
500
+ }
501
+ ```
502
+
503
+ ### Error Handling
504
+
505
+ ```typescript
506
+ // error-handling.ts
507
+ import * as mgmtApi from '@agility/management-sdk';
508
+
509
+ export class CICDErrorHandler {
510
+ static async executeWithRetry<T>(
511
+ operation: () => Promise<T>,
512
+ maxRetries: number = 3,
513
+ delay: number = 1000
514
+ ): Promise<T> {
515
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
516
+ try {
517
+ return await operation();
518
+ } catch (error) {
519
+ console.error(`Attempt ${attempt} failed:`, error.message);
520
+
521
+ if (attempt === maxRetries) {
522
+ throw error;
523
+ }
524
+
525
+ // Exponential backoff
526
+ const waitTime = delay * Math.pow(2, attempt - 1);
527
+ console.log(`⏳ Retrying in ${waitTime}ms...`);
528
+ await new Promise(resolve => setTimeout(resolve, waitTime));
529
+ }
530
+ }
531
+
532
+ throw new Error('All retry attempts failed');
533
+ }
534
+
535
+ static handleCICDError(error: any, context: string): never {
536
+ console.error(`❌ CICD Error in ${context}:`, error.message);
537
+
538
+ // Log additional context for debugging
539
+ if (error.response) {
540
+ console.error('Response status:', error.response.status);
541
+ console.error('Response data:', error.response.data);
542
+ }
543
+
544
+ // Exit with error code for CI/CD pipeline
545
+ process.exit(1);
546
+ }
547
+ }
548
+
549
+ // Usage example
550
+ try {
551
+ const result = await CICDErrorHandler.executeWithRetry(async () => {
552
+ return await apiClient.contentMethods.saveContentItem(contentData, guid, locale);
553
+ });
554
+
555
+ console.log('✅ Content saved successfully:', result);
556
+ } catch (error) {
557
+ CICDErrorHandler.handleCICDError(error, 'content creation');
558
+ }
559
+ ```
560
+
561
+ ### Logging and Monitoring
562
+
563
+ ```typescript
564
+ // cicd-logger.ts
565
+ export class CICDLogger {
566
+ private static logLevel = process.env.LOG_LEVEL || 'INFO';
567
+
568
+ static info(message: string, data?: any) {
569
+ const timestamp = new Date().toISOString();
570
+ console.log(`[${timestamp}] INFO: ${message}`, data || '');
571
+ }
572
+
573
+ static error(message: string, error?: any) {
574
+ const timestamp = new Date().toISOString();
575
+ console.error(`[${timestamp}] ERROR: ${message}`, error || '');
576
+ }
577
+
578
+ static logOperation(operation: string, guid: string, locale: string) {
579
+ this.info(`Starting operation: ${operation}`, { guid, locale });
580
+ }
581
+
582
+ static logSuccess(operation: string, result: any) {
583
+ this.info(`Operation completed: ${operation}`, { result });
584
+ }
585
+
586
+ static logFailure(operation: string, error: any) {
587
+ this.error(`Operation failed: ${operation}`, error);
588
+ }
589
+ }
590
+ ```
591
+
592
+ ---
593
+
594
+ ## Navigation
595
+ - [← Back to Main Documentation](../README.md)
596
+ - [Authentication & Setup](./auth.md)
597
+ - [AssetMethods](./asset-methods.md)
598
+ - [BatchMethods](./batch-methods.md)
599
+ - [ContainerMethods](./container-methods.md)
600
+ - [ContentMethods](./content-methods.md)
601
+ - [InstanceMethods](./instance-methods.md)
602
+ - [InstanceUserMethods](./instance-user-methods.md)
603
+ - [ModelMethods](./model-methods.md)
604
+ - [PageMethods](./page-methods.md)
605
+ - [ServerUserMethods](./server-user-methods.md)
606
+ - [WebhookMethods](./webhook-methods.md)
607
607
  - [Multi-Instance Operations](./multi-instance-operations.md)