@jskit-ai/connectors-catalog 0.1.1

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 (399) hide show
  1. package/README.md +192 -0
  2. package/docs/ai-upstream-notices.md +51 -0
  3. package/docs/ai.md +191 -0
  4. package/docs/airtable.md +130 -0
  5. package/docs/algolia.md +190 -0
  6. package/docs/amazon-redshift.md +229 -0
  7. package/docs/amplitude.md +210 -0
  8. package/docs/apify.md +162 -0
  9. package/docs/apollo-io.md +200 -0
  10. package/docs/asana.md +126 -0
  11. package/docs/ashby.md +188 -0
  12. package/docs/atlassian.md +224 -0
  13. package/docs/attention.md +162 -0
  14. package/docs/aws-athena.md +150 -0
  15. package/docs/aws-credentials.md +75 -0
  16. package/docs/aws-s3.md +193 -0
  17. package/docs/bigquery.md +146 -0
  18. package/docs/brevo.md +122 -0
  19. package/docs/calendly.md +158 -0
  20. package/docs/canva.md +191 -0
  21. package/docs/chargebee.md +192 -0
  22. package/docs/clay.md +194 -0
  23. package/docs/clickhouse.md +242 -0
  24. package/docs/confidence-exp.md +74 -0
  25. package/docs/confidence-flags.md +75 -0
  26. package/docs/confidence-oauth.md +137 -0
  27. package/docs/contentful.md +123 -0
  28. package/docs/databricks.md +180 -0
  29. package/docs/dbt-semantic-layer.md +175 -0
  30. package/docs/elevenlabs.md +102 -0
  31. package/docs/figma.md +132 -0
  32. package/docs/firebase-cloud-messaging.md +262 -0
  33. package/docs/firecrawl.md +137 -0
  34. package/docs/fireflies.md +95 -0
  35. package/docs/fireworks-ai.md +53 -0
  36. package/docs/gatewayapi.md +113 -0
  37. package/docs/gemini-enterprise.md +224 -0
  38. package/docs/github-api.md +133 -0
  39. package/docs/gitlab-api.md +138 -0
  40. package/docs/gmail.md +133 -0
  41. package/docs/gong.md +205 -0
  42. package/docs/google-ads.md +156 -0
  43. package/docs/google-analytics.md +202 -0
  44. package/docs/google-docs.md +105 -0
  45. package/docs/google-drive.md +108 -0
  46. package/docs/google-maps-platform.md +208 -0
  47. package/docs/google-oauth.md +123 -0
  48. package/docs/google-search-console.md +124 -0
  49. package/docs/google-sheets.md +94 -0
  50. package/docs/google-slides.md +95 -0
  51. package/docs/granola.md +178 -0
  52. package/docs/hex.md +161 -0
  53. package/docs/heygen.md +124 -0
  54. package/docs/hubspot.md +142 -0
  55. package/docs/incident-io.md +118 -0
  56. package/docs/inngest.md +178 -0
  57. package/docs/klipy.md +149 -0
  58. package/docs/lexware.md +144 -0
  59. package/docs/lightspeed.md +193 -0
  60. package/docs/linear.md +137 -0
  61. package/docs/linkedin.md +196 -0
  62. package/docs/logo-dev.md +152 -0
  63. package/docs/mailgun.md +153 -0
  64. package/docs/mapbox.md +174 -0
  65. package/docs/microsoft-excel.md +97 -0
  66. package/docs/microsoft-fabric.md +249 -0
  67. package/docs/microsoft-oauth.md +143 -0
  68. package/docs/microsoft-onedrive.md +76 -0
  69. package/docs/microsoft-onenote.md +75 -0
  70. package/docs/microsoft-outlook.md +90 -0
  71. package/docs/microsoft-powerpoint.md +119 -0
  72. package/docs/microsoft-sharepoint.md +75 -0
  73. package/docs/microsoft-teams.md +72 -0
  74. package/docs/microsoft-word.md +119 -0
  75. package/docs/miro.md +117 -0
  76. package/docs/n8n.md +169 -0
  77. package/docs/notion.md +137 -0
  78. package/docs/oura.md +161 -0
  79. package/docs/paddle.md +168 -0
  80. package/docs/perplexity.md +85 -0
  81. package/docs/pipedrive.md +120 -0
  82. package/docs/polar.md +63 -0
  83. package/docs/posthog.md +227 -0
  84. package/docs/prestashop.md +151 -0
  85. package/docs/replicate.md +60 -0
  86. package/docs/resend.md +153 -0
  87. package/docs/salesforce.md +234 -0
  88. package/docs/sanity.md +122 -0
  89. package/docs/semrush.md +276 -0
  90. package/docs/sentry.md +112 -0
  91. package/docs/sevdesk.md +107 -0
  92. package/docs/shopify.md +206 -0
  93. package/docs/slack.md +257 -0
  94. package/docs/snowflake.md +271 -0
  95. package/docs/storyblok.md +130 -0
  96. package/docs/stripe.md +77 -0
  97. package/docs/supabase.md +51 -0
  98. package/docs/tally.md +105 -0
  99. package/docs/telegram.md +165 -0
  100. package/docs/tiktok.md +201 -0
  101. package/docs/twilio.md +284 -0
  102. package/docs/twitch.md +428 -0
  103. package/docs/wave.md +440 -0
  104. package/docs/wix.md +1249 -0
  105. package/docs/wiz.md +177 -0
  106. package/docs/woocommerce.md +400 -0
  107. package/docs/wordpress-com.md +358 -0
  108. package/docs/wordpress-self-hosted.md +252 -0
  109. package/docs/workday.md +292 -0
  110. package/docs/x-twitter.md +188 -0
  111. package/docs/xero.md +429 -0
  112. package/docs/zoho-books.md +214 -0
  113. package/docs/zoho-crm.md +192 -0
  114. package/package.json +153 -0
  115. package/patterns/ai-connections/PATTERN.md +84 -0
  116. package/patterns/ai-connections/example/ai-model.js +11 -0
  117. package/patterns/ai-connections/example/perplexity-answer.js +29 -0
  118. package/patterns/api-key-connection/PATTERN.md +368 -0
  119. package/patterns/api-key-connection/example/connections.js +18 -0
  120. package/patterns/api-key-connection/example/integrations.json +19 -0
  121. package/patterns/assistant-mcp/PATTERN.md +110 -0
  122. package/patterns/assistant-mcp/example/integrations.json +13 -0
  123. package/patterns/assistant-mcp-oauth/PATTERN.md +235 -0
  124. package/patterns/assistant-mcp-oauth/example/integrations.json +102 -0
  125. package/patterns/aws-storage-queries/PATTERN.md +169 -0
  126. package/patterns/aws-storage-queries/example/formats/data-formats.js +35 -0
  127. package/patterns/aws-storage-queries/example/formats/package-lock.json +49 -0
  128. package/patterns/aws-storage-queries/example/formats/package.json +12 -0
  129. package/patterns/aws-storage-queries/example/formats/verify-formats.mjs +37 -0
  130. package/patterns/aws-storage-queries/example/integrations.json +38 -0
  131. package/patterns/aws-storage-queries/example/s3-transfer.js +34 -0
  132. package/patterns/event-delivery/PATTERN.md +151 -0
  133. package/patterns/event-delivery/example/integrations.json +17 -0
  134. package/patterns/firebase-messaging/PATTERN.md +156 -0
  135. package/patterns/firebase-messaging/example/server/notifications.js +23 -0
  136. package/patterns/google-ads-search/PATTERN.md +92 -0
  137. package/patterns/google-ads-search/example/ads-setup.js +25 -0
  138. package/patterns/oauth-connection/PATTERN.md +724 -0
  139. package/patterns/oauth-connection/example/integrations.json +20 -0
  140. package/patterns/paddle-catalogue/PATTERN.md +78 -0
  141. package/patterns/paddle-catalogue/example/create-products.js +38 -0
  142. package/patterns/public-image/PATTERN.md +84 -0
  143. package/patterns/public-image/example/integrations.json +13 -0
  144. package/patterns/public-image/example/logo-url.js +16 -0
  145. package/patterns/redshift-queries/PATTERN.md +150 -0
  146. package/patterns/redshift-queries/example/integrations.json +33 -0
  147. package/patterns/source-scanning/PATTERN.md +83 -0
  148. package/patterns/source-scanning/example/source-scanner.js +13 -0
  149. package/src/client/firebase-cloud-messaging.js +10 -0
  150. package/src/client/google-analytics.js +72 -0
  151. package/src/client/google-maps-platform.js +39 -0
  152. package/src/client/logo-dev.js +36 -0
  153. package/src/server/ai.js +46 -0
  154. package/src/server/airtable.js +67 -0
  155. package/src/server/algolia.js +63 -0
  156. package/src/server/amazon-redshift.js +96 -0
  157. package/src/server/amplitude.js +31 -0
  158. package/src/server/apify.js +68 -0
  159. package/src/server/apollo-io.js +85 -0
  160. package/src/server/asana.js +64 -0
  161. package/src/server/ashby.js +61 -0
  162. package/src/server/atlassian.js +32 -0
  163. package/src/server/attention.js +93 -0
  164. package/src/server/aws-athena.js +82 -0
  165. package/src/server/aws-s3.js +49 -0
  166. package/src/server/awsTransport.js +75 -0
  167. package/src/server/bigquery.js +97 -0
  168. package/src/server/brevo.js +97 -0
  169. package/src/server/calendly.js +77 -0
  170. package/src/server/canva.js +13 -0
  171. package/src/server/chargebee.js +88 -0
  172. package/src/server/clay.js +78 -0
  173. package/src/server/clickhouse.js +66 -0
  174. package/src/server/confidence.js +29 -0
  175. package/src/server/contentful.js +40 -0
  176. package/src/server/databricks.js +55 -0
  177. package/src/server/dbt-semantic-layer.js +95 -0
  178. package/src/server/elevenlabs.js +81 -0
  179. package/src/server/figma.js +24 -0
  180. package/src/server/firebase-cloud-messaging.js +111 -0
  181. package/src/server/firecrawl.js +70 -0
  182. package/src/server/fireflies.js +31 -0
  183. package/src/server/fireworks-ai.js +16 -0
  184. package/src/server/gatewayapi.js +48 -0
  185. package/src/server/gemini-enterprise.js +47 -0
  186. package/src/server/github-api.js +90 -0
  187. package/src/server/gitlab-api.js +67 -0
  188. package/src/server/gmail.js +60 -0
  189. package/src/server/gong.js +52 -0
  190. package/src/server/google-ads-search.js +134 -0
  191. package/src/server/google-ads.js +80 -0
  192. package/src/server/google-docs.js +36 -0
  193. package/src/server/google-drive.js +71 -0
  194. package/src/server/google-maps-platform.js +90 -0
  195. package/src/server/google-search-console.js +31 -0
  196. package/src/server/google-sheets.js +60 -0
  197. package/src/server/google-slides.js +36 -0
  198. package/src/server/google.js +61 -0
  199. package/src/server/granola.js +115 -0
  200. package/src/server/graphqlOperation.js +15 -0
  201. package/src/server/hex.js +29 -0
  202. package/src/server/heygen.js +54 -0
  203. package/src/server/hubspot.js +85 -0
  204. package/src/server/incident-io.js +68 -0
  205. package/src/server/inngest.js +86 -0
  206. package/src/server/jsonOperation.js +34 -0
  207. package/src/server/klipy.js +34 -0
  208. package/src/server/lexware.js +59 -0
  209. package/src/server/lightspeed.js +82 -0
  210. package/src/server/linear.js +52 -0
  211. package/src/server/linkedin.js +74 -0
  212. package/src/server/mailgun.js +76 -0
  213. package/src/server/mapbox.js +46 -0
  214. package/src/server/mcpRegistration.js +41 -0
  215. package/src/server/mcpTransport.js +60 -0
  216. package/src/server/microsoft-excel.js +67 -0
  217. package/src/server/microsoft-fabric.js +81 -0
  218. package/src/server/microsoft-onedrive.js +58 -0
  219. package/src/server/microsoft-onenote.js +52 -0
  220. package/src/server/microsoft-outlook.js +58 -0
  221. package/src/server/microsoft-powerpoint.js +5 -0
  222. package/src/server/microsoft-sharepoint.js +46 -0
  223. package/src/server/microsoft-teams.js +29 -0
  224. package/src/server/microsoft-word.js +5 -0
  225. package/src/server/microsoft.js +88 -0
  226. package/src/server/miro.js +29 -0
  227. package/src/server/n8n.js +78 -0
  228. package/src/server/notion.js +76 -0
  229. package/src/server/oura.js +48 -0
  230. package/src/server/paddle.js +83 -0
  231. package/src/server/perplexity.js +15 -0
  232. package/src/server/pipedrive.js +95 -0
  233. package/src/server/polar.js +20 -0
  234. package/src/server/posthog.js +44 -0
  235. package/src/server/prestashop.js +42 -0
  236. package/src/server/replicate.js +42 -0
  237. package/src/server/resend.js +93 -0
  238. package/src/server/salesforce.js +84 -0
  239. package/src/server/sanity.js +31 -0
  240. package/src/server/semrush.js +359 -0
  241. package/src/server/sentry.js +30 -0
  242. package/src/server/sevdesk.js +20 -0
  243. package/src/server/shopify.js +99 -0
  244. package/src/server/slack.js +143 -0
  245. package/src/server/snowflake.js +139 -0
  246. package/src/server/storyblok.js +49 -0
  247. package/src/server/stripe.js +13 -0
  248. package/src/server/supabase.js +13 -0
  249. package/src/server/tally.js +78 -0
  250. package/src/server/telegram.js +55 -0
  251. package/src/server/tiktok.js +86 -0
  252. package/src/server/twilio.js +90 -0
  253. package/src/server/twitch.js +409 -0
  254. package/src/server/wave.js +520 -0
  255. package/src/server/wix.js +1048 -0
  256. package/src/server/wiz.js +117 -0
  257. package/src/server/woocommerce.js +412 -0
  258. package/src/server/wordpress-com.js +236 -0
  259. package/src/server/wordpress-self-hosted.js +134 -0
  260. package/src/server/workday.js +136 -0
  261. package/src/server/x-twitter.js +110 -0
  262. package/src/server/xero.js +397 -0
  263. package/src/server/zoho-books.js +90 -0
  264. package/src/server/zoho-crm.js +89 -0
  265. package/src/server/zohoOAuth.js +21 -0
  266. package/src/shared/ai-models.json +8049 -0
  267. package/src/shared/ai.js +63 -0
  268. package/src/shared/algolia.js +29 -0
  269. package/src/shared/amazon-redshift.js +51 -0
  270. package/src/shared/amplitude.js +28 -0
  271. package/src/shared/atlassian.js +43 -0
  272. package/src/shared/aws.js +72 -0
  273. package/src/shared/canva.js +66 -0
  274. package/src/shared/chargebee.js +26 -0
  275. package/src/shared/clickhouse.js +38 -0
  276. package/src/shared/confidence.js +28 -0
  277. package/src/shared/databricks.js +33 -0
  278. package/src/shared/dbt-semantic-layer.js +32 -0
  279. package/src/shared/definitions.js +140 -0
  280. package/src/shared/figma.js +21 -0
  281. package/src/shared/firebase-cloud-messaging.js +45 -0
  282. package/src/shared/gemini-enterprise.js +33 -0
  283. package/src/shared/gong.js +33 -0
  284. package/src/shared/google-ads-search.js +31 -0
  285. package/src/shared/google-ads.js +28 -0
  286. package/src/shared/google-maps-platform.js +28 -0
  287. package/src/shared/google.js +133 -0
  288. package/src/shared/granola.js +25 -0
  289. package/src/shared/hex.js +28 -0
  290. package/src/shared/inngest.js +35 -0
  291. package/src/shared/lightspeed.js +75 -0
  292. package/src/shared/linkedin.js +27 -0
  293. package/src/shared/logo-dev.js +21 -0
  294. package/src/shared/mapbox.js +38 -0
  295. package/src/shared/mcp.js +92 -0
  296. package/src/shared/microsoft-fabric.js +47 -0
  297. package/src/shared/microsoft.js +231 -0
  298. package/src/shared/miro.js +27 -0
  299. package/src/shared/oura.js +23 -0
  300. package/src/shared/posthog.js +33 -0
  301. package/src/shared/prestashop.js +23 -0
  302. package/src/shared/salesforce.js +36 -0
  303. package/src/shared/semrush.js +24 -0
  304. package/src/shared/shopify.js +51 -0
  305. package/src/shared/siteUrl.js +12 -0
  306. package/src/shared/slack.js +88 -0
  307. package/src/shared/snowflake.js +55 -0
  308. package/src/shared/tiktok.js +22 -0
  309. package/src/shared/tokens.js +747 -0
  310. package/src/shared/twilio.js +41 -0
  311. package/src/shared/twitch.js +49 -0
  312. package/src/shared/wave.js +52 -0
  313. package/src/shared/wix.js +40 -0
  314. package/src/shared/wiz.js +41 -0
  315. package/src/shared/wordpress-com.js +30 -0
  316. package/src/shared/wordpress.js +69 -0
  317. package/src/shared/workday.js +50 -0
  318. package/src/shared/x-twitter.js +19 -0
  319. package/src/shared/xero.js +46 -0
  320. package/src/shared/zoho-books.js +39 -0
  321. package/src/shared/zoho-crm.js +43 -0
  322. package/src/shared/zoho-regions.js +12 -0
  323. package/test/ai.test.js +136 -0
  324. package/test/airtable.test.js +125 -0
  325. package/test/algolia.test.js +207 -0
  326. package/test/amazon-redshift.test.js +272 -0
  327. package/test/amplitude.test.js +239 -0
  328. package/test/apify.test.js +93 -0
  329. package/test/apollo-io.test.js +125 -0
  330. package/test/asana.test.js +99 -0
  331. package/test/ashby.test.js +97 -0
  332. package/test/atlassian.test.js +249 -0
  333. package/test/attention.test.js +79 -0
  334. package/test/aws.test.js +405 -0
  335. package/test/brevo.test.js +71 -0
  336. package/test/calendly.test.js +136 -0
  337. package/test/canva.test.js +258 -0
  338. package/test/chargebee.test.js +195 -0
  339. package/test/clickhouse.test.js +278 -0
  340. package/test/confidence.test.js +205 -0
  341. package/test/databricks.test.js +253 -0
  342. package/test/dbt-semantic-layer.test.js +221 -0
  343. package/test/designMcp.test.js +336 -0
  344. package/test/elevenlabs.test.js +52 -0
  345. package/test/firebase-cloud-messaging.test.js +242 -0
  346. package/test/firecrawl.test.js +66 -0
  347. package/test/gemini-enterprise.test.js +218 -0
  348. package/test/github-api.test.js +167 -0
  349. package/test/gitlab-api.test.js +160 -0
  350. package/test/gong.test.js +192 -0
  351. package/test/google-ads.test.js +350 -0
  352. package/test/google-maps-platform.test.js +191 -0
  353. package/test/google.test.js +710 -0
  354. package/test/granola.test.js +240 -0
  355. package/test/hex.test.js +253 -0
  356. package/test/heygen.test.js +121 -0
  357. package/test/hubspot.test.js +103 -0
  358. package/test/inngest.test.js +219 -0
  359. package/test/lightspeed.test.js +250 -0
  360. package/test/linear.test.js +146 -0
  361. package/test/linkedin.test.js +243 -0
  362. package/test/logo-dev.test.js +79 -0
  363. package/test/mailgun.test.js +107 -0
  364. package/test/mapbox.test.js +181 -0
  365. package/test/mcp.test.js +227 -0
  366. package/test/microsoft-fabric.test.js +258 -0
  367. package/test/microsoft.test.js +554 -0
  368. package/test/n8nOAuth.test.js +188 -0
  369. package/test/notionOAuth.test.js +183 -0
  370. package/test/oura.test.js +211 -0
  371. package/test/paddleCatalogue.test.js +51 -0
  372. package/test/paddlePermissions.test.js +101 -0
  373. package/test/perplexityComposition.test.js +39 -0
  374. package/test/pipedriveOAuth.test.js +140 -0
  375. package/test/posthog.test.js +200 -0
  376. package/test/prestashop.test.js +207 -0
  377. package/test/resend.test.js +163 -0
  378. package/test/salesforce.test.js +276 -0
  379. package/test/semrush.test.js +479 -0
  380. package/test/sentry.test.js +35 -0
  381. package/test/shopify.test.js +247 -0
  382. package/test/slack.test.js +320 -0
  383. package/test/snowflake.test.js +391 -0
  384. package/test/tally.test.js +75 -0
  385. package/test/telegram.test.js +58 -0
  386. package/test/tiktok.test.js +243 -0
  387. package/test/tokens.test.js +1079 -0
  388. package/test/twilio.test.js +221 -0
  389. package/test/twitch.test.js +573 -0
  390. package/test/wave.test.js +678 -0
  391. package/test/wix.test.js +1099 -0
  392. package/test/wiz.test.js +185 -0
  393. package/test/wordpress-com.test.js +469 -0
  394. package/test/wordpress.test.js +660 -0
  395. package/test/workday.test.js +314 -0
  396. package/test/x-twitter.test.js +256 -0
  397. package/test/xero.test.js +700 -0
  398. package/test/zoho-books.test.js +253 -0
  399. package/test/zoho-crm.test.js +223 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "registrations": {
4
+ "wordpress": {
5
+ "source": "own",
6
+ "clientId": "YOUR_ASSIGNED_CLIENT_ID",
7
+ "clientSecretRef": "env:WORDPRESS_COM_CLIENT_SECRET",
8
+ "callbackUrlRef": "env:WORDPRESS_COM_CALLBACK_URL"
9
+ }
10
+ },
11
+ "integrations": {
12
+ "publishing": {
13
+ "provider": "wordpress-com",
14
+ "displayName": "Publishing account",
15
+ "accountMode": "per-user",
16
+ "scopes": ["users", "sites", "posts"],
17
+ "authentication": { "method": "oauth2", "registrationRef": "wordpress" }
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,78 @@
1
+ ---
2
+ id: connectors/paddle-catalogue
3
+ title: Create Paddle products with prices
4
+ summary: Compose a sequential catalogue batch and preserve partial success for application-owned recovery.
5
+ keywords: paddle, products, prices, batch, payments
6
+ requires: @jskit-ai/connectors-core, @jskit-ai/connectors-catalog
7
+ ---
8
+
9
+ # Create Paddle products with prices
10
+
11
+ ## Use when
12
+
13
+ Use the [Paddle setup guide](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/paddle.md) to configure and verify the
14
+ application's merchant key. This recipe creates catalogue entries only.
15
+ Checkout, subscriptions and charging customers are separate application work.
16
+
17
+ ## Do not use when
18
+
19
+ Use the payments-core reviewed catalogue workflow when the application requires
20
+ durable publication recovery. This bounded recipe is not that workflow.
21
+
22
+ ## Framework APIs
23
+
24
+ Adapt [create-products.js](example/create-products.js) into the application's
25
+ backend. Replace its repository-relative provider import with
26
+ `@jskit-ai/connectors-catalog/server/paddle`. Pass the application's connection
27
+ runtime, authenticated context, integration ID and an array of `{ product,
28
+ price }` inputs described in the guide. The newly created product supplies the
29
+ price's product_id. One item implements product-with-price; several implement
30
+ batch creation. The limit of 100 items is this recipe's bounded workload choice,
31
+ not a Paddle API limit. It executes serially and does not invent a remote batch
32
+ API or transaction.
33
+
34
+ ## Invariants
35
+
36
+ The recipe validates the entire cloned batch before the first write. It calls
37
+ the ordinary runtime for each request, preserving authorization and the
38
+ connection's configured sandbox/live environment. The sandbox setting used for
39
+ local schema validation sends no request and does not override runtime routing.
40
+
41
+ ## Product decisions
42
+
43
+ For assistant use, authorize the complete cloned request with
44
+ `authorizeAssistantAction`, action `products.create` for one item or
45
+ `products.batchCreate` for several, before calling the recipe. The host must
46
+ bind approval to that exact snapshot and caller. Individual runtime invocations
47
+ still enforce their policies; do not turn off runtime authorization to bypass
48
+ an additional required approval. Application use instead enforces its normal
49
+ administrator permissions. This file does not supply a public HTTP endpoint.
50
+
51
+ ## Avoid
52
+
53
+ Retain `completed` and `failed` in app-owned operation state. A failed price
54
+ step includes the newly created product ID. No later items run after failure,
55
+ and no failed call is retried. An interrupted request may have succeeded at
56
+ Paddle; inspect the merchant catalogue before repeating any write. Process
57
+ termination can prevent the returned report from being saved, so an application
58
+ needing crash recovery must record each completed step durably. This small
59
+ recipe does not promise crash recovery, rollback or exactly-once execution.
60
+
61
+ ## Variation points
62
+
63
+ CLI users can call this same JavaScript recipe with their own runtime. Vibe64
64
+ configures the project; it does not execute catalogue writes on configuration
65
+ save. Laravel applications implement this composition with their own framework
66
+ and Paddle client, without importing JavaScript or depending on Vibe64.
67
+
68
+ ## Example files
69
+
70
+ - [create-products.js](example/create-products.js): sequential product/price
71
+ composition with input validation and a partial-success report.
72
+
73
+ ## Verification
74
+
75
+ Exercise the recipe with controlled provider responses. Verify whole-batch
76
+ validation before writes, authorization for each operation, product-to-price
77
+ identity, stop-on-failure behavior and preservation of completed IDs. A returned
78
+ report does not prove durable recovery or live merchant acceptance.
@@ -0,0 +1,38 @@
1
+ import { paddleProvider } from "../../../src/server/paddle.js";
2
+
3
+ // Application-owned composition: pass an application-mode connection runtime.
4
+ // An assistant host must approve the complete batch before calling this recipe.
5
+ async function createProductsWithPrices({ runtime, context, integrationId, items, signal }) {
6
+ if (!Array.isArray(items) || !items.length || items.length > 100) {
7
+ throw new TypeError("Supply between 1 and 100 products with prices.");
8
+ }
9
+ const batch = structuredClone(items);
10
+ // Validate every item before the first write, using the adapter's own schema.
11
+ for (const item of batch) {
12
+ if (!item || typeof item !== "object" || Object.keys(item).some((key) => !["product", "price"].includes(key)) ||
13
+ !item.product || !item.price || Object.hasOwn(item.price, "product_id")) {
14
+ throw new TypeError("Each item needs product and price inputs; the new product supplies product_id.");
15
+ }
16
+ paddleProvider.operations["products.create"].request(item.product, { environment: "sandbox" });
17
+ paddleProvider.operations["prices.create"].request({ ...item.price, product_id: `pro_${"a".repeat(26)}` }, { environment: "sandbox" });
18
+ }
19
+ const completed = [];
20
+ for (const [index, item] of batch.entries()) {
21
+ let productId;
22
+ let stage = "product";
23
+ try {
24
+ const product = await runtime.invoke({ context, integrationId, signal, operation: "products.create", input: item.product });
25
+ productId = product.data.id;
26
+ stage = "price";
27
+ const price = await runtime.invoke({ context, integrationId, signal, operation: "prices.create", input: { ...item.price, product_id: productId } });
28
+ completed.push({ index, productId, priceId: price.data.id });
29
+ } catch {
30
+ // Do not replay the batch: a failed request may have reached Paddle.
31
+ // Do not include raw provider errors or credential-bearing diagnostics.
32
+ return { completed, failed: { index, stage, ...(productId ? { productId } : {}), outcome: "requires-review" } };
33
+ }
34
+ }
35
+ return { completed, failed: null };
36
+ }
37
+
38
+ export { createProductsWithPrices };
@@ -0,0 +1,84 @@
1
+ ---
2
+ id: connectors/public-image
3
+ title: Public logo images from portable integration configuration
4
+ summary: Resolve a publishable image key deliberately and use the shared URL library in a browser, backend or CLI.
5
+ keywords: connectors, integrations, logo-dev, images, public-key, cli, files
6
+ requires: @jskit-ai/connectors-core, @jskit-ai/connectors-catalog
7
+ ---
8
+
9
+ # Public logo images from portable integration configuration
10
+
11
+ ## Use when
12
+
13
+ Use for Logo.dev's public image service. `createLogoDevImageUrl` is implemented
14
+ in the library; the example owns only application configuration and wiring.
15
+ This path does not need a server connection grant or a database.
16
+
17
+ ## Do not use when
18
+
19
+ Private JSON API keys, user OAuth tokens and managed service credentials must
20
+ not be placed in public image URLs. Logo.dev search/describe use different
21
+ credentials and are outside this pattern.
22
+
23
+ ## Product decisions
24
+
25
+ Choose the domains that may load images, attribution placement and missing-image
26
+ behavior. Choose whether a build step publishes the permitted key in public
27
+ configuration or an authorized backend returns image URLs. The application's
28
+ existing access policy applies before exposing its configured resources.
29
+
30
+ ## Invariants
31
+
32
+ - CLI and Vibe64 edit the same reference-only `integrations.json`.
33
+ - Only a `pk_` key enters an image URL; a private key fails validation.
34
+ - URL creation is local and does not establish a verified account connection.
35
+ - Browser load/error events report delivery. A monogram is not proof of a brand logo.
36
+ - Domain restrictions concern the app that loads the image, including previews
37
+ and custom domains. The editor VM may have a different origin.
38
+
39
+ ## Framework APIs
40
+
41
+ Use `parseIntegrationConfiguration` from connectors-core/shared/configuration,
42
+ `logoDevDefinition` from connectors-catalog/shared, and
43
+ `createLogoDevImageUrl` from connectors-catalog/client/logo-dev. The latter is
44
+ portable to Node and browsers and exposes `logoDevImageSchema` for input fields.
45
+ Use the application's reference resolver; no environment object goes to the
46
+ browser. See [provider setup](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/logo-dev.md) for inputs and limitations.
47
+
48
+ ## Example files
49
+
50
+ `integrations.json` is ordinary application source. `logo-url.js` demonstrates
51
+ resolving its chosen integration and producing a public URL from the library.
52
+ Supply authorized configuration, a resolver and the desired image input:
53
+
54
+ ```js
55
+ const url = await logoUrlFromConfiguration({
56
+ configurationText, integrationId: "logos", resolveReference,
57
+ image: { domain: "example.com", fallback: "404" }
58
+ });
59
+ ```
60
+
61
+ In Vue, compute the URL from approved public configuration and bind `:src` on
62
+ an `<img>` with `alt`, `referrerpolicy="origin"` and an `@error` fallback. A CLI
63
+ can print or embed the same URL without generating an application. Treat the
64
+ returned URL as containing a public key; do not substitute a private credential.
65
+
66
+ ## Variation points
67
+
68
+ Application code owns public configuration delivery, allowed domains, display
69
+ size, theme and fallback. Use explicit permanent-hosting arrangements if the
70
+ product needs to retain or redistribute provider assets.
71
+
72
+ ## Verification
73
+
74
+ Library tests cover key and domain validation, option bounds and fixed-origin
75
+ URL construction. Browser fixtures exercise simulated image success and error.
76
+ Source-pattern tests use a supplied resolver and reject a different provider
77
+ slot. Editor tests verify reference-only source, field errors and reload.
78
+ These checks need neither live credentials nor generated sample applications.
79
+
80
+ ## Avoid
81
+
82
+ Do not call server `connectApiKey` to manufacture a Connected receipt for this
83
+ image flow. Do not send a secret key, an environment dump or a caller-selected
84
+ service origin to the browser. Do not treat key naming as provider quota isolation.
@@ -0,0 +1,13 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "registrations": {},
4
+ "integrations": {
5
+ "logos": {
6
+ "provider": "logo-dev",
7
+ "displayName": "Company logos",
8
+ "accountMode": "shared",
9
+ "scopes": [],
10
+ "authentication": { "method": "api-key", "secretRef": "env:LOGO_DEV_PUBLISHABLE_KEY" }
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,16 @@
1
+ import { parseIntegrationConfiguration } from "@jskit-ai/connectors-core/shared/configuration";
2
+ import { logoDevDefinition } from "@jskit-ai/connectors-catalog/shared";
3
+ import { createLogoDevImageUrl } from "@jskit-ai/connectors-catalog/client/logo-dev";
4
+
5
+ // The application authorizes access before passing its configuration and resolver.
6
+ async function logoUrlFromConfiguration({ configurationText, integrationId, resolveReference, image }) {
7
+ const configuration = parseIntegrationConfiguration(configurationText, { providers: [logoDevDefinition], allowUnknownProviders: true });
8
+ const integration = configuration.integrations[integrationId];
9
+ if (!Object.hasOwn(configuration.integrations, integrationId) || integration.provider !== "logo-dev") {
10
+ throw new Error("Select a configured Logo.dev integration.");
11
+ }
12
+ const publishableKey = await resolveReference(integration.authentication.secretRef);
13
+ return createLogoDevImageUrl({ ...image, publishableKey });
14
+ }
15
+
16
+ export { logoUrlFromConfiguration };
@@ -0,0 +1,150 @@
1
+ ---
2
+ id: connectors/redshift-queries
3
+ title: Redshift queries with shared AWS credentials
4
+ summary: Compose file configuration, Redshift Data API operations and application query ownership.
5
+ keywords: redshift, aws, sql, warehouse, serverless, provisioned, iam, connectors, cli, files
6
+ requires: @jskit-ai/connectors-core, @jskit-ai/connectors-catalog
7
+ ---
8
+
9
+ # Redshift queries with shared AWS credentials
10
+
11
+ ## Use when
12
+
13
+ A CLI operator or application backend needs database/schema/table metadata or authorized SQL in
14
+ one configured Redshift warehouse. JSKIT owns configuration validation, AWS SDK
15
+ signing, operation input validation, target checks and response parsing. The
16
+ application owns which user may submit a query or access its result.
17
+
18
+ ## Do not use when
19
+
20
+ This fragment does not provide application login, per-user IAM Identity Center
21
+ federation, warehouse provisioning or a managed paid/public allocation. Never
22
+ turn a shared AWS key into an unrestricted SQL endpoint for application users.
23
+ SQL can modify data; read-only behavior requires appropriate database grants.
24
+
25
+ ## Product decisions
26
+
27
+ Select serverless or provisioned in the same JSON edited by Vibe64. Serverless
28
+ requires a workgroup name; provisioned requires a cluster identifier and may use
29
+ an explicit database user. Both require a database and region. Store AWS secrets
30
+ outside the file. Temporary credentials additionally need `sessionTokenRef` and
31
+ host renewal. See the [Redshift guide](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/amazon-redshift.md) for setup,
32
+ field names, automation feasibility and remaining federation work.
33
+
34
+ ## Invariants
35
+
36
+ Use the application's existing authentication and authorization policy to build
37
+ the trusted context. Bind logical query tokens and returned statement IDs to
38
+ the actual application/user in application-owned state; a text file can hold
39
+ that state. Authorize exact SQL, parameter values and statement ownership before
40
+ invoking the service. Matching the configured warehouse is only a target check.
41
+
42
+ The library does not resolve ambient AWS profiles or switch to a more privileged
43
+ account after a denial. The application resolves its own credential bindings; editable references do
44
+ not grant AWS permissions. This shared credential mode has no provider callback
45
+ URL and does not depend on an Online registration or allocation.
46
+
47
+ ## Framework APIs
48
+
49
+ Follow the [API-key connection pattern](../api-key-connection/PATTERN.md) to read
50
+ configuration, create protected file connection storage, resolve explicit
51
+ bindings and implement `authorize`. Register this runtime export:
52
+
53
+ ```js
54
+ import { amazonRedshiftProvider } from "@jskit-ai/connectors-catalog/server/amazon-redshift";
55
+ const providers = [amazonRedshiftProvider];
56
+ // Pass providers with configuration, store, resolveReference and authorize
57
+ // to createConnectionService or the ordinary connector Feature.
58
+ ```
59
+
60
+ The library's `connectApiKey({context, integrationId})` reads a table metadata
61
+ page. It does not submit SQL or grant future query permission. Use
62
+ `databases.list` for visible database names, `schemas.list` for schemas in the
63
+ configured database, `tables.list` for tables and `table.describe` for columns.
64
+ Each listing accepts `maxResults` (1–1000) and an opaque `nextToken`; schema
65
+ listing also accepts `schemaPattern`. An absent or empty NextToken ends paging.
66
+ Database names returned by discovery do not change this connection's configured
67
+ target or authorize another database. Use another project-owned configuration
68
+ slot for another database and authorize metadata visibility before invocation.
69
+
70
+ ## Example files
71
+
72
+ [example/integrations.json](example/integrations.json) has two independent
73
+ configuration slots demonstrating both deployment types. Actual resource names
74
+ and environment bindings must come from the owner. Do not generate a new app to
75
+ use these libraries; compose them in the existing backend or CLI entry point.
76
+
77
+ After the application has authorized the statement and stored its logical
78
+ request token, call:
79
+
80
+ ```js
81
+ const submitted = await service.invoke({
82
+ context, integrationId: "serverless-reports", operation: "query.start",
83
+ input: {
84
+ sql: "select order_id::varchar, total from reporting.orders where customer_id = :customer limit 100",
85
+ parameters: [{ name: "customer", value: authorizedCustomerId }],
86
+ clientToken: storedLogicalRequestToken
87
+ }
88
+ });
89
+ // Persist submitted.Id with the authorized application's query owner.
90
+ const status = await service.invoke({
91
+ context, integrationId: "serverless-reports", operation: "query.status",
92
+ input: { statementId: submitted.Id }
93
+ });
94
+ ```
95
+
96
+ Use parameters for values; do not concatenate user input into the SQL. Tokens
97
+ are required, case-sensitive and 1–64 characters. Reuse the same token only for
98
+ the same logical request and identical input within AWS's deduplication window.
99
+ An ambiguous response must not trigger an automatic submission with a new token.
100
+
101
+ A returned ID is submission, not completion. `query.status` reports SUBMITTED,
102
+ PICKED, STARTED, FINISHED, ABORTED or FAILED. The application controls bounded
103
+ polling and cancellation. When status is FINISHED with a result set:
104
+
105
+ ```js
106
+ const page = await service.invoke({
107
+ context, integrationId: "serverless-reports", operation: "query.results",
108
+ input: { statementId: authorizedStatementId }
109
+ });
110
+ // ColumnMetadata describes each position in Records. Preserve typed cells.
111
+ // If another page is needed, pass page.NextToken unchanged as nextToken.
112
+ ```
113
+
114
+ Result cells retain AWS's tags: `stringValue`, `longValue`, `doubleValue`,
115
+ `booleanValue`, `isNull` and `blobValue`. Do not collapse empty strings, zero or
116
+ false into null. Binary values are Uint8Array; explicitly encode them in an
117
+ application JSON response. Large integers outside JavaScript's safe range are
118
+ rejected: select them as VARCHAR for exact text. Results are one AWS page;
119
+ there is no `maxResults` parameter for `query.results`.
120
+
121
+ For explicit remote cancellation, authorize the statement owner then invoke
122
+ `query.cancel` with its ID. The returned boolean receipt does not establish
123
+ rollback or a final job state. Read status if the final outcome is needed.
124
+ Closing a UI, aborting local HTTP or disconnecting does not cancel remote SQL.
125
+
126
+ ## Variation points
127
+
128
+ Change only the configured resource slot when targeting a provisioned cluster.
129
+ The operation interface stays the same. An explicit `databaseUser` uses that
130
+ database identity; omit it for the IAM-derived identity. Table listing and
131
+ description accept a bounded page size and opaque cursors. Metadata filters
132
+ support AWS's SQL-style patterns.
133
+
134
+ ## Avoid
135
+
136
+ Do not expose arbitrary database/workgroup overrides, use query IDs as bearer
137
+ authorization, log SQL/result metadata indiscriminately, assume that a table
138
+ listing proves every SELECT permission, or reimplement AWS signing in scaffolding.
139
+ The runtime does not enforce SELECT-only SQL by parsing or matching prefixes.
140
+
141
+ ## Verification
142
+
143
+ Run the single focused `test/amazon-redshift.test.js` file in the catalogue
144
+ package. It uses real SDK signing with controlled responses and file storage.
145
+ It covers both targets, input validation, SQL parameters, statement checks,
146
+ typed result pages, credentials, errors and local cancellation. Shared-form
147
+ browser checks pass at phone, tablet and desktop sizes; Public editor checks
148
+ pass at phone/desktop sizes for both deployment types, region selection,
149
+ validation, inactive-field removal and save/reload.
150
+ No live AWS account, executed SQL or generated application is claimed.
@@ -0,0 +1,33 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "registrations": {},
4
+ "integrations": {
5
+ "serverless-reports": {
6
+ "provider": "amazon-redshift",
7
+ "accountMode": "shared",
8
+ "scopes": [],
9
+ "authentication": { "method": "api-key", "secretRef": "env:REPORTING_AWS_SECRET_ACCESS_KEY" },
10
+ "settings": {
11
+ "deploymentType": "serverless",
12
+ "region": "us-east-1",
13
+ "accessKeyIdRef": "env:REPORTING_AWS_ACCESS_KEY_ID",
14
+ "workgroup": "analytics",
15
+ "database": "dev"
16
+ }
17
+ },
18
+ "cluster-reports": {
19
+ "provider": "amazon-redshift",
20
+ "accountMode": "shared",
21
+ "scopes": [],
22
+ "authentication": { "method": "api-key", "secretRef": "env:CLUSTER_AWS_SECRET_ACCESS_KEY" },
23
+ "settings": {
24
+ "deploymentType": "provisioned",
25
+ "region": "us-east-1",
26
+ "accessKeyIdRef": "env:CLUSTER_AWS_ACCESS_KEY_ID",
27
+ "clusterIdentifier": "analytics-cluster",
28
+ "database": "dev",
29
+ "databaseUser": "report_reader"
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: connectors/source-scanning
3
+ title: Authorised project source scans with Wiz
4
+ summary: Use the shared scanner runtime from a CLI or a host worker with portable configuration and explicit source ownership.
5
+ keywords: connectors, integrations, wiz, security, source, scanning, cli, worker, cancellation
6
+ requires: @jskit-ai/connectors-core, @jskit-ai/connectors-catalog
7
+ ---
8
+
9
+ # Authorised project source scans with Wiz
10
+
11
+ ## Use when
12
+
13
+ A CLI or host needs to scan an authorised source snapshot with its own Wiz account.
14
+ `createWizScanner` implements configuration checks, command construction,
15
+ credential isolation, bounded process execution, report validation and cleanup.
16
+ The example wires that library to application-owned authority and snapshot lookup.
17
+
18
+ ## Do not use when
19
+
20
+ This is not an HTTP application-data connector, user login, a managed gateway,
21
+ or an implementation of Vibe64's coding agents. It does not generate an app.
22
+ Auth0 and native Windows execution are not implemented in the current runner.
23
+
24
+ ## Product decisions
25
+
26
+ The host chooses which principals may scan which projects, the stable application
27
+ and shared subject identities, snapshot lifetime, worker resource/network limits,
28
+ Wiz policies and authorised report readers. It decides how to display findings
29
+ and whether a blocking verdict prevents a later operation.
30
+
31
+ ## Invariants
32
+
33
+ - CLI and UI edit the same reference-only `integrations.json`.
34
+ - Browser input never supplies a source path, executable, environment or identity.
35
+ - The host checks access before resolving source and credentials.
36
+ - The snapshot must remain immutable while the scan runs; keep its revision with
37
+ the findings and mark the result stale when current source differs.
38
+ - A passed policy verdict is not a proof that there are no vulnerabilities.
39
+ - Missing/invalid reports, cancellation and failed scans never become clean scans.
40
+ - Provider credentials are isolated from coding-agent sessions and credentials.
41
+ - The host supplies its own authorized provider credentials; editor edition does
42
+ not select a shared Vibe64 provider account.
43
+
44
+ ## Framework APIs
45
+
46
+ Use `parseIntegrationConfiguration` from connectors-core/shared/configuration,
47
+ `wizDefinition` from connectors-catalog/shared, and `createWizScanner` from
48
+ connectors-catalog/server/wiz. Supply the host's `authorize`, `resolveReference`,
49
+ `resolveScanTarget` and installed CLI absolute path. The runtime's `scan` operation
50
+ accepts only context, integration ID and an optional AbortSignal.
51
+ See [Wiz setup and limits](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/wiz.md).
52
+
53
+ ## Example files
54
+
55
+ `source-scanner.js` reads a normal text configuration file and returns the scanner.
56
+ Both an authenticated HTTP handler and an ordinary CLI command can call it.
57
+ Its callbacks belong to the application; do not replace them with unconditional
58
+ approval in a multi-user service. Do not run this example merely to validate source.
59
+
60
+ ## Variation points
61
+
62
+ CLI commands can use local user authority; a server uses its workspace/project
63
+ policy. Hosts may set the deadline, report-size limit, proxy and CA environment
64
+ for an isolated worker. Snapshot creation and findings storage stay host-owned.
65
+
66
+ A Laravel application can use a PHP worker to invoke the same installed Wiz CLI
67
+ or call an explicitly configured scan worker over HTTP. It reads ordinary JSON
68
+ and needs no Node/JSKIT runtime. That PHP or HTTP implementation owns its process
69
+ and identity boundary; this package supplies a working JavaScript implementation
70
+ and documents the protocol, not an already implemented PHP library or gateway.
71
+
72
+ ## Verification
73
+
74
+ Use a controlled executable and temporary source to verify command arguments,
75
+ isolated credentials, policy results, malformed reports, cancellation and cleanup.
76
+ Editor checks cover all configuration fields and persistence. Actual authentication
77
+ and findings require separately authorised provider acceptance.
78
+
79
+ ## Avoid
80
+
81
+ Do not infer workspace grants from a shared slot, return raw provider stderr,
82
+ replay scans automatically, pass arbitrary CLI flags, use a mutable working tree
83
+ as if it were a fixed revision, or substitute a generic API reader for source scans.
@@ -0,0 +1,13 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { parseIntegrationConfiguration } from "@jskit-ai/connectors-core/shared/configuration";
3
+ import { wizDefinition } from "@jskit-ai/connectors-catalog/shared";
4
+ import { createWizScanner } from "@jskit-ai/connectors-catalog/server/wiz";
5
+
6
+ export async function projectSourceScanner({ configFile = "integrations.json", installedWizCliPath,
7
+ authorize, resolveReference, resolveScanTarget, environment }) {
8
+ const configuration = parseIntegrationConfiguration(await readFile(configFile, "utf8"), {
9
+ providers: [wizDefinition], allowUnknownProviders: true
10
+ });
11
+ return createWizScanner({ configuration, executable: installedWizCliPath,
12
+ authorize, resolveReference, resolveScanTarget, environment });
13
+ }
@@ -0,0 +1,10 @@
1
+ import { validateSchemaPayload } from "@jskit-ai/kernel/shared/validators";
2
+ import { firebaseCloudMessagingDefinition } from "../shared/firebase-cloud-messaging.js";
3
+
4
+ function firebaseCloudMessagingWebConfiguration(settings) {
5
+ if (settings?.clientMode !== "web") throw new TypeError("Select Include web push before configuring browser registration.");
6
+ const values = validateSchemaPayload({ schema: firebaseCloudMessagingDefinition.settingsSchema(settings), mode: "replace" }, settings);
7
+ return { firebaseConfig: { projectId: values.projectId, apiKey: values.apiKey, appId: values.appId, messagingSenderId: values.appId.split(":")[1] }, vapidKey: values.vapidKey };
8
+ }
9
+
10
+ export { firebaseCloudMessagingWebConfiguration };
@@ -0,0 +1,72 @@
1
+ // Optional browser implementation. The application owns consent and route hooks.
2
+ const installations = new WeakMap();
3
+
4
+ function createGoogleAnalytics({ measurementId, window: browser = globalThis.window } = {}) {
5
+ if (typeof measurementId !== "string" || !/^G-[A-Z0-9]+$/.test(measurementId) || measurementId.length > 64) throw new TypeError("Supply a valid GA4 Measurement ID.");
6
+ if (!browser?.document) throw new TypeError("Initialize Google Analytics in the browser after hydration.");
7
+ const existing = installations.get(browser);
8
+ if (existing) {
9
+ if (existing.measurementId !== measurementId) throw new Error("This page already has an Analytics owner. Reload to change the Measurement ID.");
10
+ return existing.controller;
11
+ }
12
+ if (browser.gtag || browser.document.querySelector('script[src*="googletagmanager.com/"]')) throw new Error("Use the application's existing Google tag or Tag Manager instead of installing a second tracker.");
13
+ if (browser.dataLayer !== undefined && !Array.isArray(browser.dataLayer)) throw new TypeError("The existing dataLayer must be an array.");
14
+ let enabled = false, initialized = false, disposed = false, script, lastPage;
15
+ const disabledKey = `ga-disable-${measurementId}`;
16
+ browser[disabledKey] = true;
17
+ function active() { if (disposed) throw new Error("Analytics has been disposed. Reload before configuring tracking again."); }
18
+ function queue(...args) { browser.gtag(...args); }
19
+ const controller = Object.freeze({
20
+ setConsent(granted) {
21
+ active();
22
+ if (typeof granted !== "boolean") throw new TypeError("Pass an explicit consent boolean.");
23
+ enabled = granted;
24
+ browser[disabledKey] = !granted;
25
+ if (!granted) { lastPage = undefined; return; }
26
+ if (initialized) return;
27
+ // Check again: another integration may have installed a tag since creation.
28
+ if (browser.gtag || browser.document.querySelector('script[src*="googletagmanager.com/"]')) {
29
+ enabled = false; browser[disabledKey] = true;
30
+ throw new Error("Use the application's existing Google tracking installation.");
31
+ }
32
+ browser.dataLayer ||= [];
33
+ browser.gtag = function () { browser.dataLayer.push(arguments); };
34
+ queue("js", new Date());
35
+ queue("config", measurementId, { send_page_view: false });
36
+ script = browser.document.createElement("script");
37
+ script.async = true;
38
+ script.src = `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(measurementId)}`;
39
+ browser.document.head.appendChild(script);
40
+ initialized = true;
41
+ },
42
+ pageView({ location = browser.location.href, title = browser.document.title } = {}) {
43
+ active();
44
+ if (!enabled) return false;
45
+ const url = new URL(location);
46
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password) throw new TypeError("Supply a public HTTP(S) page URL without credentials.");
47
+ if (typeof title !== "string") throw new TypeError("Supply a page title.");
48
+ if (lastPage === url.href) return false;
49
+ const previous = lastPage;
50
+ lastPage = url.href;
51
+ queue("event", "page_view", { send_to: measurementId, page_location: url.href, page_title: title, ...(previous ? { page_referrer: previous } : {}) });
52
+ return true;
53
+ },
54
+ event(name, parameters = {}) {
55
+ active();
56
+ if (!enabled) return false;
57
+ if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_]{0,39}$/.test(name) || /^(?:google_|ga_|firebase_)/.test(name) || name === "page_view") throw new TypeError("Use a valid event name; page views use pageView.");
58
+ if (!parameters || typeof parameters !== "object" || Array.isArray(parameters)) throw new TypeError("Supply an event parameter object.");
59
+ queue("event", name, { ...parameters, send_to: measurementId });
60
+ return true;
61
+ },
62
+ dispose() {
63
+ enabled = false; disposed = true; browser[disabledKey] = true;
64
+ script?.remove();
65
+ // Loaded Google code cannot be unloaded. Keep ownership until page reload.
66
+ }
67
+ });
68
+ installations.set(browser, { measurementId, controller });
69
+ return controller;
70
+ }
71
+
72
+ export { createGoogleAnalytics };