@foxtware/mineral 0.1.27 → 0.1.29

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 (178) hide show
  1. package/.creds.yml.sample +29 -0
  2. package/AGENTS.md +24 -0
  3. package/_build_scripts/createNewFunction.js +26 -3
  4. package/api/dropbox/docs.md +7 -0
  5. package/api/dropbox/dropbox.constants.js +10 -0
  6. package/api/dropbox/dropbox.utils.js +67 -0
  7. package/api/dropbox/dropboxAccountGet.js +64 -0
  8. package/api/dropbox/dropboxFileCopy.js +67 -0
  9. package/api/dropbox/dropboxFileDelete.js +89 -0
  10. package/api/dropbox/dropboxFileDownload.js +139 -0
  11. package/api/dropbox/dropboxFileMetadataGet.js +100 -0
  12. package/api/dropbox/dropboxFileMove.js +67 -0
  13. package/api/dropbox/dropboxFileUpload.js +129 -0
  14. package/api/dropbox/dropboxFolderCreate.js +68 -0
  15. package/api/dropbox/dropboxFolderList.js +66 -0
  16. package/api/dropbox/dropboxGet.js +158 -0
  17. package/api/dropbox/dropboxSearch.js +161 -0
  18. package/api/dropbox/dropboxSharedLinkCreate.js +68 -0
  19. package/api/dropbox/dropboxSpaceUsageGet.js +55 -0
  20. package/api/dropbox/dropboxTemporaryLinkGet.js +75 -0
  21. package/api/fastsimon/.gitkeep +0 -0
  22. package/api/fastsimon/docs.md +14 -0
  23. package/api/fastsimon/fastsimon.constants.js +18 -0
  24. package/api/fastsimon/fastsimon.utils.js +246 -0
  25. package/api/fastsimon/fastsimonSearch.js +84 -0
  26. package/api/figma/docs.md +3 -3
  27. package/api/figma/figma.constants.js +1 -1
  28. package/api/figma/figma.utils.js +13 -2
  29. package/api/figma/figmaActivityLogsGet.js +44 -0
  30. package/api/figma/figmaAiUsageDailyGet.js +44 -0
  31. package/api/figma/figmaComponentGet.js +48 -0
  32. package/api/figma/figmaComponentSetGet.js +48 -0
  33. package/api/figma/figmaDevResourcesCreate.js +47 -0
  34. package/api/figma/figmaDevResourcesUpdate.js +47 -0
  35. package/api/figma/figmaDeveloperLogsCreate.js +47 -0
  36. package/api/figma/figmaDiscoveryGet.js +44 -0
  37. package/api/figma/figmaFileCommentCreate.js +50 -0
  38. package/api/figma/figmaFileCommentDelete.js +51 -0
  39. package/api/figma/figmaFileCommentReactionCreate.js +53 -0
  40. package/api/figma/figmaFileCommentReactionDelete.js +51 -0
  41. package/api/figma/figmaFileCommentReactionsGet.js +51 -0
  42. package/api/figma/figmaFileCommentsGet.js +48 -0
  43. package/api/figma/figmaFileComponentSetsGet.js +48 -0
  44. package/api/figma/figmaFileComponentsGet.js +48 -0
  45. package/api/figma/figmaFileDevResourceDelete.js +51 -0
  46. package/api/figma/figmaFileDevResourcesGet.js +48 -0
  47. package/api/figma/figmaFileGet.js +48 -0
  48. package/api/figma/figmaFileImageFillsGet.js +48 -0
  49. package/api/figma/figmaFileImagesGet.js +48 -0
  50. package/api/figma/figmaFileMetaGet.js +48 -0
  51. package/api/figma/figmaFileNodesGet.js +48 -0
  52. package/api/figma/figmaFileStylesGet.js +48 -0
  53. package/api/figma/figmaFileVersionsGet.js +48 -0
  54. package/api/figma/figmaFolderFilesGet.js +48 -0
  55. package/api/figma/figmaFolderFoldersGet.js +48 -0
  56. package/api/figma/figmaFolderMetaGet.js +48 -0
  57. package/api/figma/figmaGet.js +15 -63
  58. package/api/figma/figmaMeGet.js +53 -0
  59. package/api/figma/figmaOembedGet.js +44 -0
  60. package/api/figma/figmaPaymentsGet.js +44 -0
  61. package/api/figma/figmaProjectFilesGet.js +48 -0
  62. package/api/figma/figmaProjectMetaGet.js +48 -0
  63. package/api/figma/figmaStyleGet.js +48 -0
  64. package/api/figma/figmaTeamComponentSetsGet.js +48 -0
  65. package/api/figma/figmaTeamComponentsGet.js +48 -0
  66. package/api/figma/figmaTeamFoldersGet.js +48 -0
  67. package/api/figma/figmaTeamProjectsGet.js +48 -0
  68. package/api/figma/figmaTeamStylesGet.js +48 -0
  69. package/api/figma/figmaTeamWebhooksGet.js +47 -0
  70. package/api/figma/figmaVariablesLocalGet.js +48 -0
  71. package/api/figma/figmaVariablesPublishedGet.js +48 -0
  72. package/api/figma/figmaVariablesUpdate.js +50 -0
  73. package/api/figma/figmaWebhookCreate.js +47 -0
  74. package/api/figma/figmaWebhookDelete.js +48 -0
  75. package/api/figma/figmaWebhookGet.js +46 -0
  76. package/api/figma/figmaWebhookRequestsGet.js +47 -0
  77. package/api/figma/figmaWebhookUpdate.js +50 -0
  78. package/api/figma/figmaWebhooksGet.js +47 -0
  79. package/api/google/docs.md +1 -0
  80. package/api/google/google.constants.js +1 -0
  81. package/api/google/google.utils.js +21 -0
  82. package/api/google/googleanalyticsMetadataGet.js +62 -0
  83. package/api/google/googleanalyticsRealtimeReportRun.js +103 -0
  84. package/api/google/googleanalyticsReportRun.js +114 -0
  85. package/api/gorgias/gorgiasTicketCreate.js +1 -1
  86. package/api/gorgias/gorgiasTicketMessageCreate.js +1 -1
  87. package/api/gorgias/gorgiasTicketUpdate.js +1 -1
  88. package/api/linear/linearAttachmentCreate.js +1 -1
  89. package/api/linear/linearCommentCreate.js +1 -1
  90. package/api/linear/linearCommentUpdate.js +1 -1
  91. package/api/linear/linearIssueLabelCreate.js +1 -1
  92. package/api/linear/linearIssueUpdate.js +1 -1
  93. package/api/linear/linearProjectCreate.js +1 -1
  94. package/api/linear/linearProjectUpdate.js +1 -1
  95. package/api/linear/linearWebhookCreate.js +1 -1
  96. package/api/salesforce/salesforce.constants.js +13 -0
  97. package/api/salesforce/salesforce.utils.js +61 -0
  98. package/api/salesforce/salesforceAuthGet.js +115 -0
  99. package/api/salesforce/salesforceComposite.js +79 -0
  100. package/api/salesforce/salesforceCompositeBatch.js +73 -0
  101. package/api/salesforce/salesforceLimitsGet.js +55 -0
  102. package/api/salesforce/salesforceQuery.js +69 -0
  103. package/api/salesforce/salesforceQueryAll.js +62 -0
  104. package/api/salesforce/salesforceQueryMore.js +75 -0
  105. package/api/salesforce/salesforceRecentItemsGet.js +63 -0
  106. package/api/salesforce/salesforceResourcesGet.js +55 -0
  107. package/api/salesforce/salesforceSearch.js +62 -0
  108. package/api/salesforce/salesforceSobjectBasicInfoGet.js +81 -0
  109. package/api/salesforce/salesforceSobjectBlobGet.js +67 -0
  110. package/api/salesforce/salesforceSobjectCollectionCreate.js +78 -0
  111. package/api/salesforce/salesforceSobjectCollectionDelete.js +70 -0
  112. package/api/salesforce/salesforceSobjectCollectionGet.js +75 -0
  113. package/api/salesforce/salesforceSobjectCollectionUpdate.js +74 -0
  114. package/api/salesforce/salesforceSobjectCreate.js +66 -0
  115. package/api/salesforce/salesforceSobjectDelete.js +86 -0
  116. package/api/salesforce/salesforceSobjectDeleteByExternalId.js +91 -0
  117. package/api/salesforce/salesforceSobjectDeletedGet.js +71 -0
  118. package/api/salesforce/salesforceSobjectDescribe.js +81 -0
  119. package/api/salesforce/salesforceSobjectDescribeLayouts.js +64 -0
  120. package/api/salesforce/salesforceSobjectGet.js +93 -0
  121. package/api/salesforce/salesforceSobjectGetByExternalId.js +98 -0
  122. package/api/salesforce/salesforceSobjectTreeCreate.js +79 -0
  123. package/api/salesforce/salesforceSobjectUpdate.js +94 -0
  124. package/api/salesforce/salesforceSobjectUpdatedGet.js +71 -0
  125. package/api/salesforce/salesforceSobjectUpsert.js +74 -0
  126. package/api/salesforce/salesforceSobjectsDescribeGlobal.js +55 -0
  127. package/api/salesforce/salesforceVersionsGet.js +62 -0
  128. package/api/shopify/shopify.utils.js +53 -4
  129. package/api/shopify/shopifyMetaobjectCreate.js +79 -0
  130. package/api/shopify/shopifyMetaobjectDelete.js +90 -0
  131. package/api/shopify/shopifyMetaobjectGet.js +80 -0
  132. package/api/shopify/shopifyMetaobjectUpdate.js +108 -0
  133. package/api/shopify/shopifyStorefrontSearch.js +158 -0
  134. package/api/spotify/docs.md +8 -0
  135. package/api/spotify/spotify.constants.js +12 -0
  136. package/api/spotify/spotify.utils.js +106 -0
  137. package/api/spotify/spotifyAlbumGet.js +76 -0
  138. package/api/spotify/spotifyAlbumTracksGet.js +49 -0
  139. package/api/spotify/spotifyArtistAlbumsGet.js +55 -0
  140. package/api/spotify/spotifyArtistGet.js +71 -0
  141. package/api/spotify/spotifyArtistTopTracksGet.js +56 -0
  142. package/api/spotify/spotifyGet.js +171 -0
  143. package/api/spotify/spotifyMeGet.js +48 -0
  144. package/api/spotify/spotifyPlayerCurrentlyPlayingGet.js +62 -0
  145. package/api/spotify/spotifyPlayerDevicesGet.js +51 -0
  146. package/api/spotify/spotifyPlayerGet.js +63 -0
  147. package/api/spotify/spotifyPlayerNext.js +55 -0
  148. package/api/spotify/spotifyPlayerPause.js +55 -0
  149. package/api/spotify/spotifyPlayerPlay.js +70 -0
  150. package/api/spotify/spotifyPlayerPrevious.js +55 -0
  151. package/api/spotify/spotifyPlaylistCreate.js +63 -0
  152. package/api/spotify/spotifyPlaylistGet.js +91 -0
  153. package/api/spotify/spotifyPlaylistItemsAdd.js +61 -0
  154. package/api/spotify/spotifyPlaylistItemsGet.js +58 -0
  155. package/api/spotify/spotifyPlaylistItemsRemove.js +67 -0
  156. package/api/spotify/spotifyPlaylistUpdate.js +64 -0
  157. package/api/spotify/spotifyPlaylistsGet.js +47 -0
  158. package/api/spotify/spotifySavedTracksGet.js +46 -0
  159. package/api/spotify/spotifySavedTracksRemove.js +59 -0
  160. package/api/spotify/spotifySavedTracksSave.js +59 -0
  161. package/api/spotify/spotifySearch.js +174 -0
  162. package/api/spotify/spotifyTrackGet.js +76 -0
  163. package/api/tableau/tableau.constants.js +8 -0
  164. package/api/tableau/tableau.utils.js +93 -0
  165. package/api/tableau/tableauGet.js +174 -0
  166. package/api/tableau/tableauUserAdd.js +16 -94
  167. package/api/tableau/tableauUsersGet.js +46 -134
  168. package/api/tagalys/docs.md +2 -2
  169. package/api/tagalys/tagalys.constants.js +17 -0
  170. package/api/tagalys/tagalys.utils.js +125 -0
  171. package/api/tagalys/tagalysAnalyticsEventSend.js +125 -0
  172. package/api/tagalys/tagalysCollectionGet.js +100 -0
  173. package/api/tagalys/tagalysPopularSearchesGet.js +60 -0
  174. package/api/tagalys/tagalysRecommendationGet.js +109 -0
  175. package/api/tagalys/tagalysSearch.js +15 -89
  176. package/api/tagalys/tagalysSearchSuggestionsGet.js +76 -0
  177. package/package.json +2 -1
  178. package/server.js +3 -1
@@ -0,0 +1,55 @@
1
+ // https://www.dropbox.com/developers/documentation/http/documentation#users-get_space_usage
2
+
3
+ const { ArgsWarden, logDeep } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { dropboxClient } = require('../dropbox/dropbox.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ]);
10
+
11
+ const dropboxSpaceUsageGet = async (
12
+ credsPayload,
13
+ {
14
+ fetchClient = dropboxClient,
15
+ } = {},
16
+ ) => {
17
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
18
+ credsPayload,
19
+ });
20
+ if (rejectResponse) {
21
+ return rejectResponse;
22
+ }
23
+
24
+ const response = await fetchClient.fetch({
25
+ context: { credsPayload },
26
+ requestPayload: {
27
+ method: 'post',
28
+ url: '/users/get_space_usage',
29
+ headers: {
30
+ 'Content-Type': 'application/json',
31
+ },
32
+ body: 'null',
33
+ },
34
+ });
35
+
36
+ const { ok, data, error } = response;
37
+ if (!ok) {
38
+ logDeep({ error });
39
+ return { ok: false, error };
40
+ }
41
+
42
+ return {
43
+ ok: true,
44
+ data,
45
+ };
46
+ };
47
+
48
+ const funcApiConfig = {
49
+ argsWarden,
50
+ };
51
+
52
+ module.exports = {
53
+ dropboxSpaceUsageGet,
54
+ funcApiConfig,
55
+ };
@@ -0,0 +1,75 @@
1
+ // https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link
2
+
3
+ const { ArgsWarden, actionSingleOrMultiple, logDeep } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { dropboxClient } = require('../dropbox/dropbox.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ['path'],
10
+ ]);
11
+
12
+ const dropboxTemporaryLinkGetSingle = async (
13
+ credsPayload,
14
+ path,
15
+ {
16
+ fetchClient = dropboxClient,
17
+ } = {},
18
+ ) => {
19
+ const response = await fetchClient.fetch({
20
+ context: { credsPayload },
21
+ requestPayload: {
22
+ method: 'post',
23
+ url: '/files/get_temporary_link',
24
+ body: { path },
25
+ },
26
+ });
27
+
28
+ const { ok, data, error } = response;
29
+ if (!ok) {
30
+ logDeep({ error });
31
+ return { ok: false, error };
32
+ }
33
+
34
+ return {
35
+ ok: true,
36
+ data,
37
+ };
38
+ };
39
+
40
+ const dropboxTemporaryLinkGet = async (
41
+ credsPayload,
42
+ path,
43
+ {
44
+ queueRunOptions,
45
+ fetchClient,
46
+ } = {},
47
+ ) => {
48
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
49
+ credsPayload,
50
+ path,
51
+ });
52
+ if (rejectResponse) {
53
+ return rejectResponse;
54
+ }
55
+
56
+ return actionSingleOrMultiple(
57
+ path,
58
+ dropboxTemporaryLinkGetSingle,
59
+ (pathItem) => ({
60
+ args: [credsPayload, pathItem, { fetchClient }],
61
+ }),
62
+ {
63
+ ...(queueRunOptions ? { queueRunOptions } : {}),
64
+ },
65
+ );
66
+ };
67
+
68
+ const funcApiConfig = {
69
+ argsWarden,
70
+ };
71
+
72
+ module.exports = {
73
+ dropboxTemporaryLinkGet,
74
+ funcApiConfig,
75
+ };
File without changes
@@ -0,0 +1,14 @@
1
+ # Fast Simon
2
+
3
+ - [API Documentation](https://docs.fastsimon.com/api/api-doc.html)
4
+ - [Serving API – full text search](https://docs.fastsimon.com/api/api-doc.html#tag/Serving-API/operation/fulltextProducts)
5
+ - [SDK docs](https://docs.fastsimon.com/sdk)
6
+
7
+ Public Serving API over HTTPS at `https://api.fastsimon.com`. Search and collection reads are unauthenticated beyond the store identifiers: every request carries `UUID` and `store_id` as query parameters (values from the Fast Simon dashboard after install). Admin / merchandising endpoints additionally require an API key and the `X-Site-UUID` / `X-Store-ID` headers.
8
+
9
+ Core serving flow:
10
+
11
+ 1. `GET /load` – returns site config including `cdn_cache_key` (required on subsequent product requests).
12
+ 2. `GET /full_text_search` – full-text product search with optional facets, sorting, narrowing filters, and pagination (`page_num`).
13
+
14
+ Product results land under `data.items`; facets under `data.facets`. When `facets_required=1` and `data.facets_completed` is false, repeat the request with `facets_required=2` to finish facet computation. JSONP is supported via a `callback` query param; this client uses plain JSON.
@@ -0,0 +1,18 @@
1
+ const BASE_URL = 'https://api.fastsimon.com';
2
+
3
+ // Common sort_by values documented on full_text_search
4
+ const SORT_BY_OPTIONS = [
5
+ 'relevency', // spelling as returned by the API docs
6
+ 'price_min_to_max',
7
+ 'price_max_to_min',
8
+ 'creation_date',
9
+ 'creation_date_oldest',
10
+ 'reviews',
11
+ 'a_to_z',
12
+ 'z_to_a',
13
+ ];
14
+
15
+ module.exports = {
16
+ BASE_URL,
17
+ SORT_BY_OPTIONS,
18
+ };
@@ -0,0 +1,246 @@
1
+ // https://docs.fastsimon.com/api/api-doc.html
2
+
3
+ const { BASE_URL } = require('../fastsimon/fastsimon.constants');
4
+ const { resolveCreds } = require('../pipelineSteps');
5
+ const {
6
+ FetchClient,
7
+ fetchClientCommonSteps,
8
+ appendUrlToBase,
9
+ } = require('../utils');
10
+
11
+ const sessionCacheKeyForCredsPayload = (credsPayload) => {
12
+ if (credsPayload?.credsPath) {
13
+ return credsPayload.credsPath;
14
+ }
15
+
16
+ return JSON.stringify(credsPayload);
17
+ };
18
+
19
+ // cdn_cache_key is required on product endpoints and is obtained from /load.
20
+ // Cache per creds identity so repeated searches in the same process reuse it.
21
+ const cdnCacheKeyByCredsKey = new Map();
22
+
23
+ const normaliseLoadData = (data) => {
24
+ if (data == null) {
25
+ return {};
26
+ }
27
+ if (typeof data === 'string') {
28
+ try {
29
+ return JSON.parse(data);
30
+ } catch {
31
+ return {};
32
+ }
33
+ }
34
+ return data;
35
+ };
36
+
37
+ const pickCdnCacheKey = (data) => {
38
+ const body = normaliseLoadData(data);
39
+ return (
40
+ body.cdn_cache_key ??
41
+ body.cdnCacheKey ??
42
+ body.cache_key ??
43
+ body.cacheKey ??
44
+ null
45
+ );
46
+ };
47
+
48
+ const useUrlAndAuthQuery = async (state) => {
49
+ const { requestPayload, context } = state;
50
+ const { creds } = context;
51
+ const {
52
+ UUID,
53
+ STORE_ID,
54
+ } = creds ?? {};
55
+
56
+ if (!UUID || !STORE_ID) {
57
+ return {
58
+ response: {
59
+ ok: false,
60
+ error: {
61
+ code: 'MISSING_FASTSIMON_CREDS',
62
+ message: 'fastsimon creds require UUID and STORE_ID',
63
+ },
64
+ },
65
+ breakChain: true,
66
+ };
67
+ }
68
+
69
+ const query = {
70
+ UUID,
71
+ store_id: STORE_ID,
72
+ ...(requestPayload.query || {}),
73
+ };
74
+
75
+ // Prefer an explicitly provided cdn_cache_key (e.g. from options),
76
+ // otherwise inject a previously cached one if present.
77
+ const cacheKey = sessionCacheKeyForCredsPayload(context.credsPayload || {});
78
+ if (!query.cdn_cache_key && cdnCacheKeyByCredsKey.has(cacheKey)) {
79
+ query.cdn_cache_key = cdnCacheKeyByCredsKey.get(cacheKey);
80
+ }
81
+
82
+ const searchParams = new URLSearchParams();
83
+ Object.entries(query).forEach(([key, value]) => {
84
+ if (value === undefined || value === null) {
85
+ return;
86
+ }
87
+ // narrow is documented as a JSON-encoded list of tuples; stringify objects/arrays
88
+ if (typeof value === 'object') {
89
+ searchParams.append(key, JSON.stringify(value));
90
+ } else {
91
+ searchParams.append(key, String(value));
92
+ }
93
+ });
94
+
95
+ const path = requestPayload.url || '';
96
+ const url = `${ appendUrlToBase(BASE_URL, path) }?${ searchParams.toString() }`;
97
+
98
+ return {
99
+ requestPayload: {
100
+ ...requestPayload,
101
+ url,
102
+ headers: {
103
+ Accept: 'application/json',
104
+ ...requestPayload.headers,
105
+ },
106
+ },
107
+ };
108
+ };
109
+
110
+ const rememberCdnCacheKey = async (state) => {
111
+ const { response, context } = state;
112
+ if (!response?.ok || !response?.data) {
113
+ return {};
114
+ }
115
+
116
+ const cdnCacheKey = pickCdnCacheKey(response.data);
117
+ if (cdnCacheKey == null) {
118
+ return {};
119
+ }
120
+
121
+ const cacheKey = sessionCacheKeyForCredsPayload(context.credsPayload || {});
122
+ cdnCacheKeyByCredsKey.set(cacheKey, cdnCacheKey);
123
+
124
+ return {};
125
+ };
126
+
127
+ /**
128
+ * Fast Simon often returns the body as a JSON string. Parse it, then for
129
+ * product payloads dig `items` into `data` and move everything else to `meta`
130
+ * (total_results, term, facets, page info, uuid, etc.).
131
+ */
132
+ const normaliseSearchResponse = async (state) => {
133
+ const { response } = state;
134
+ if (!response?.ok || response.data == null) {
135
+ return {};
136
+ }
137
+
138
+ let body = response.data;
139
+ if (typeof body === 'string') {
140
+ try {
141
+ body = JSON.parse(body);
142
+ } catch {
143
+ return {};
144
+ }
145
+ }
146
+
147
+ if (!body || typeof body !== 'object' || Array.isArray(body)) {
148
+ return {
149
+ response: {
150
+ data: body,
151
+ },
152
+ };
153
+ }
154
+
155
+ if (!Object.prototype.hasOwnProperty.call(body, 'items')) {
156
+ return {
157
+ response: {
158
+ data: body,
159
+ },
160
+ };
161
+ }
162
+
163
+ const { items, ...rest } = body;
164
+
165
+ return {
166
+ response: {
167
+ data: items,
168
+ meta: {
169
+ ...(response.meta || {}),
170
+ ...rest,
171
+ },
172
+ },
173
+ };
174
+ };
175
+
176
+ const fastsimonClient = new FetchClient({
177
+ pipeline: [
178
+ resolveCreds,
179
+ useUrlAndAuthQuery,
180
+ 'fetch',
181
+ fetchClientCommonSteps.exitEarlyOnNotOk,
182
+ rememberCdnCacheKey,
183
+ normaliseSearchResponse,
184
+ ],
185
+ });
186
+
187
+ /**
188
+ * Fetch (and cache) the current CDN cache key via GET /load.
189
+ * Safe to call repeatedly; subsequent calls hit the in-memory cache.
190
+ *
191
+ * Some stores' /load payloads omit `cdn_cache_key` even though the OpenAPI
192
+ * marks it required. In that case we fall back to the current Unix epoch
193
+ * (the documented type of the field), which is enough for the search CDN
194
+ * to accept the request.
195
+ */
196
+ const ensureCdnCacheKey = async (credsPayload, { fetchClient = fastsimonClient } = {}) => {
197
+ const cacheKey = sessionCacheKeyForCredsPayload(credsPayload);
198
+ if (cdnCacheKeyByCredsKey.has(cacheKey)) {
199
+ return {
200
+ ok: true,
201
+ data: { cdn_cache_key: cdnCacheKeyByCredsKey.get(cacheKey) },
202
+ };
203
+ }
204
+
205
+ const response = await fetchClient.fetch({
206
+ requestPayload: {
207
+ method: 'get',
208
+ url: '/load',
209
+ query: {},
210
+ },
211
+ context: {
212
+ credsPayload,
213
+ },
214
+ });
215
+
216
+ if (!response?.ok) {
217
+ return response;
218
+ }
219
+
220
+ let cdnCacheKey = pickCdnCacheKey(response.data);
221
+
222
+ if (cdnCacheKey == null) {
223
+ // Live /load responses for some stores return theme/config fields but no
224
+ // cdn_cache_key. The field is documented as a Unix epoch integer — using
225
+ // "now" is a safe cache-busting fallback that the Serving API accepts.
226
+ cdnCacheKey = Math.floor(Date.now() / 1000);
227
+ }
228
+
229
+ cdnCacheKeyByCredsKey.set(cacheKey, cdnCacheKey);
230
+
231
+ return {
232
+ ok: true,
233
+ data: {
234
+ cdn_cache_key: cdnCacheKey,
235
+ // surface whether we synthesised the key, in case callers care
236
+ synthesised: pickCdnCacheKey(response.data) == null,
237
+ },
238
+ };
239
+ };
240
+
241
+ module.exports = {
242
+ fastsimonClient,
243
+ ensureCdnCacheKey,
244
+ // exposed for tests / manual cache control
245
+ cdnCacheKeyByCredsKey,
246
+ };
@@ -0,0 +1,84 @@
1
+ // https://docs.fastsimon.com/api/api-doc.html#tag/Serving-API/operation/fulltextProducts
2
+
3
+ const { credsValidator } = require('../validators');
4
+ const { ArgsWarden } = require('../utils');
5
+ const { fastsimonClient, ensureCdnCacheKey } = require('../fastsimon/fastsimon.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ['query'],
10
+ ]);
11
+
12
+ const fastsimonSearch = async (
13
+ credsPayload,
14
+ query,
15
+ {
16
+ cdnCacheKey,
17
+ facetsRequired,
18
+ sortBy,
19
+ narrow,
20
+ pageNum,
21
+ fetchClient = fastsimonClient,
22
+ } = {},
23
+ ) => {
24
+
25
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
26
+ credsPayload,
27
+ query,
28
+ });
29
+ if (rejectResponse) {
30
+ return rejectResponse;
31
+ }
32
+
33
+ let resolvedCdnCacheKey = cdnCacheKey;
34
+ if (!resolvedCdnCacheKey) {
35
+ const loadRes = await ensureCdnCacheKey(credsPayload, { fetchClient });
36
+ if (!loadRes.ok) {
37
+ return loadRes;
38
+ }
39
+ resolvedCdnCacheKey = loadRes.data.cdn_cache_key;
40
+ }
41
+
42
+ const response = await fetchClient.fetch({
43
+ requestPayload: {
44
+ method: 'get',
45
+ url: '/full_text_search',
46
+ query: {
47
+ q: query,
48
+ cdn_cache_key: resolvedCdnCacheKey,
49
+ ...(facetsRequired !== undefined ? { facets_required: facetsRequired } : {}),
50
+ ...(sortBy ? { sort_by: sortBy } : {}),
51
+ ...(narrow !== undefined ? { narrow } : {}),
52
+ ...(pageNum !== undefined ? { page_num: pageNum } : {}),
53
+ },
54
+ },
55
+ context: {
56
+ credsPayload,
57
+ },
58
+ });
59
+
60
+ return response;
61
+ };
62
+
63
+ const funcApiConfig = {
64
+ argsWarden,
65
+ };
66
+
67
+ module.exports = {
68
+ fastsimonSearch,
69
+ funcApiConfig,
70
+ };
71
+
72
+ /*
73
+ curl -X POST "http://localhost:8000/fastsimonSearch" \
74
+ -H "Content-Type: application/json" \
75
+ -d '{
76
+ "credsPayload": { "credsPath": "fastsimon.au" },
77
+ "query": "dress",
78
+ "options": {
79
+ "facetsRequired": 1,
80
+ "pageNum": 1,
81
+ "sortBy": "relevency"
82
+ }
83
+ }'
84
+ */
package/api/figma/docs.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Figma
2
2
 
3
- - [Developer documentation](https://www.figma.com/developers/api)
4
- - [Authentication](https://www.figma.com/developers/api#authentication)
3
+ - [Developer documentation](https://developers.figma.com/docs/rest-api/)
4
+ - [Authentication](https://developers.figma.com/docs/rest-api/authentication/)
5
5
 
6
- REST JSON at `https://api.figma.com/v1` for files, comments, and variables, authenticated with a personal access token in the `X-Figma-Token` header.
6
+ REST JSON at `https://api.figma.com` for files, comments, variables, components, styles, folders, dev resources, webhooks, and organization APIs. Personal and plan access tokens use the `X-Figma-Token` header; OAuth 2 access tokens use `Authorization: Bearer`.
@@ -1,4 +1,4 @@
1
- const FIGMA_API_BASE_URL = 'https://api.figma.com/v1';
1
+ const FIGMA_API_BASE_URL = 'https://api.figma.com';
2
2
  const MAX_PER_PAGE = 100;
3
3
 
4
4
  module.exports = {
@@ -8,13 +8,24 @@ const {
8
8
  const useAuthHeaders = async (state) => {
9
9
  const { requestPayload, context } = state;
10
10
  const { creds } = context;
11
- const { API_KEY } = creds;
11
+ const {
12
+ API_KEY,
13
+ ACCESS_TOKEN,
14
+ } = creds ?? {};
15
+
16
+ const authHeaders = ACCESS_TOKEN
17
+ ? {
18
+ Authorization: `Bearer ${ ACCESS_TOKEN }`,
19
+ }
20
+ : {
21
+ 'X-Figma-Token': API_KEY,
22
+ };
12
23
 
13
24
  return {
14
25
  requestPayload: {
15
26
  ...requestPayload,
16
27
  headers: {
17
- 'X-Figma-Token': API_KEY,
28
+ ...authHeaders,
18
29
  ...requestPayload.headers,
19
30
  },
20
31
  },
@@ -0,0 +1,44 @@
1
+ // https://developers.figma.com/docs/rest-api/activity-logs-endpoints/
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { figmaClient } = require('../figma/figma.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ]);
10
+
11
+ const figmaActivityLogsGet = async (
12
+ credsPayload,
13
+ {
14
+ params,
15
+ fetchClient = figmaClient,
16
+ } = {},
17
+ ) => {
18
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
19
+ credsPayload
20
+ });
21
+ if (rejectResponse) {
22
+ return rejectResponse;
23
+ }
24
+
25
+ return fetchClient.fetch({
26
+ requestPayload: {
27
+ method: 'get',
28
+ url: `/v1/activity_logs`,
29
+ params,
30
+ },
31
+ context: {
32
+ credsPayload,
33
+ },
34
+ });
35
+ };
36
+
37
+ const funcApiConfig = {
38
+ argsWarden,
39
+ };
40
+
41
+ module.exports = {
42
+ figmaActivityLogsGet,
43
+ funcApiConfig,
44
+ };
@@ -0,0 +1,44 @@
1
+ // https://developers.figma.com/docs/rest-api/ai-usage-endpoints/
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { figmaClient } = require('../figma/figma.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ]);
10
+
11
+ const figmaAiUsageDailyGet = async (
12
+ credsPayload,
13
+ {
14
+ params,
15
+ fetchClient = figmaClient,
16
+ } = {},
17
+ ) => {
18
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
19
+ credsPayload
20
+ });
21
+ if (rejectResponse) {
22
+ return rejectResponse;
23
+ }
24
+
25
+ return fetchClient.fetch({
26
+ requestPayload: {
27
+ method: 'get',
28
+ url: `/v1/ai_usage/daily`,
29
+ params,
30
+ },
31
+ context: {
32
+ credsPayload,
33
+ },
34
+ });
35
+ };
36
+
37
+ const funcApiConfig = {
38
+ argsWarden,
39
+ };
40
+
41
+ module.exports = {
42
+ figmaAiUsageDailyGet,
43
+ funcApiConfig,
44
+ };
@@ -0,0 +1,48 @@
1
+ // https://developers.figma.com/docs/rest-api/component-endpoints/
2
+
3
+ const { ArgsWarden } = require('../utils');
4
+ const { credsValidator } = require('../validators');
5
+ const { figmaClient } = require('../figma/figma.utils');
6
+
7
+ const argsWarden = new ArgsWarden([
8
+ ['credsPayload', credsValidator],
9
+ ['key'],
10
+ ]);
11
+
12
+ const figmaComponentGet = async (
13
+ credsPayload,
14
+ key,
15
+ {
16
+ params,
17
+ fetchClient = figmaClient,
18
+ } = {},
19
+ ) => {
20
+ const rejectResponse = await argsWarden.responseIfRejectingArgs({
21
+ credsPayload,
22
+ key,
23
+ });
24
+ if (rejectResponse) {
25
+ return rejectResponse;
26
+ }
27
+
28
+ return fetchClient.fetch({
29
+ requestPayload: {
30
+ method: 'get',
31
+ url: `/v1/components/${ key }`,
32
+
33
+
34
+ },
35
+ context: {
36
+ credsPayload,
37
+ },
38
+ });
39
+ };
40
+
41
+ const funcApiConfig = {
42
+ argsWarden,
43
+ };
44
+
45
+ module.exports = {
46
+ figmaComponentGet,
47
+ funcApiConfig,
48
+ };