@jskit-ai/connectors-catalog 0.2.2 → 0.2.4

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 (192) hide show
  1. package/README.md +4 -4
  2. package/docs/ai.md +3 -3
  3. package/docs/airtable.md +1 -1
  4. package/docs/algolia.md +2 -2
  5. package/docs/amazon-redshift.md +2 -2
  6. package/docs/apollo-io.md +2 -2
  7. package/docs/asana.md +2 -2
  8. package/docs/ashby.md +1 -1
  9. package/docs/attention.md +2 -2
  10. package/docs/aws-athena.md +1 -1
  11. package/docs/aws-credentials.md +3 -3
  12. package/docs/aws-s3.md +1 -1
  13. package/docs/bigquery.md +2 -2
  14. package/docs/brevo.md +2 -2
  15. package/docs/calendly.md +3 -3
  16. package/docs/canva.md +2 -2
  17. package/docs/chargebee.md +2 -2
  18. package/docs/clay.md +2 -2
  19. package/docs/clickhouse.md +1 -1
  20. package/docs/confidence-flags.md +1 -1
  21. package/docs/contentful.md +1 -1
  22. package/docs/dbt-semantic-layer.md +2 -2
  23. package/docs/elevenlabs.md +2 -2
  24. package/docs/firebase-cloud-messaging.md +3 -3
  25. package/docs/firecrawl.md +4 -4
  26. package/docs/fireflies.md +1 -1
  27. package/docs/gatewayapi.md +1 -1
  28. package/docs/gemini-enterprise.md +1 -1
  29. package/docs/github-api.md +1 -1
  30. package/docs/gitlab-api.md +1 -1
  31. package/docs/gmail.md +1 -1
  32. package/docs/gong.md +1 -1
  33. package/docs/google-ads.md +3 -3
  34. package/docs/google-analytics.md +2 -2
  35. package/docs/google-docs.md +1 -1
  36. package/docs/google-drive.md +1 -1
  37. package/docs/google-maps-platform.md +2 -2
  38. package/docs/google-search-console.md +1 -1
  39. package/docs/google-sheets.md +1 -1
  40. package/docs/google-slides.md +2 -2
  41. package/docs/granola.md +2 -2
  42. package/docs/hex.md +2 -2
  43. package/docs/heygen.md +2 -2
  44. package/docs/inngest.md +1 -1
  45. package/docs/klipy.md +1 -1
  46. package/docs/lightspeed.md +2 -2
  47. package/docs/linear.md +1 -1
  48. package/docs/linkedin.md +2 -2
  49. package/docs/mailgun.md +1 -1
  50. package/docs/microsoft-excel.md +2 -2
  51. package/docs/microsoft-fabric.md +1 -1
  52. package/docs/microsoft-outlook.md +1 -1
  53. package/docs/microsoft-powerpoint.md +1 -1
  54. package/docs/microsoft-teams.md +1 -1
  55. package/docs/microsoft-word.md +1 -1
  56. package/docs/notion.md +1 -1
  57. package/docs/oura.md +3 -3
  58. package/docs/paddle.md +3 -3
  59. package/docs/pipedrive.md +2 -2
  60. package/docs/prestashop.md +1 -1
  61. package/docs/replicate.md +1 -1
  62. package/docs/resend.md +1 -1
  63. package/docs/salesforce.md +1 -1
  64. package/docs/sanity.md +3 -3
  65. package/docs/semrush.md +2 -2
  66. package/docs/sentry.md +1 -1
  67. package/docs/slack.md +1 -1
  68. package/docs/snowflake.md +5 -5
  69. package/docs/storyblok.md +1 -1
  70. package/docs/stripe.md +2 -2
  71. package/docs/tally.md +1 -1
  72. package/docs/telegram.md +2 -2
  73. package/docs/tiktok.md +3 -3
  74. package/docs/twilio.md +3 -3
  75. package/docs/twitch.md +2 -2
  76. package/docs/wave.md +3 -3
  77. package/docs/wix.md +13 -13
  78. package/docs/wordpress-com.md +1 -1
  79. package/docs/wordpress-self-hosted.md +1 -1
  80. package/docs/workday.md +2 -2
  81. package/docs/x-twitter.md +3 -3
  82. package/docs/xero.md +3 -3
  83. package/docs/zoho-books.md +2 -2
  84. package/docs/zoho-crm.md +2 -2
  85. package/package.json +4 -3
  86. package/patterns/ai-connections/PATTERN.md +16 -1
  87. package/patterns/ai-connections/example/ai-model.js +12 -3
  88. package/patterns/ai-connections/example/perplexity-answer.js +15 -4
  89. package/patterns/api-key-connection/PATTERN.md +9 -1
  90. package/patterns/api-key-connection/example/connections.js +5 -2
  91. package/patterns/aws-storage-queries/PATTERN.md +13 -3
  92. package/patterns/aws-storage-queries/example/s3-transfer.js +14 -3
  93. package/patterns/event-delivery/PATTERN.md +1 -1
  94. package/patterns/firebase-messaging/PATTERN.md +10 -0
  95. package/patterns/firebase-messaging/example/server/notifications.js +8 -0
  96. package/patterns/google-ads-search/PATTERN.md +18 -7
  97. package/patterns/google-ads-search/example/ads-setup.js +13 -5
  98. package/patterns/oauth-connection/PATTERN.md +1 -1
  99. package/patterns/paddle-catalogue/PATTERN.md +11 -2
  100. package/patterns/paddle-catalogue/example/create-products.js +5 -2
  101. package/patterns/public-image/PATTERN.md +10 -1
  102. package/patterns/public-image/example/logo-url.js +4 -1
  103. package/patterns/redshift-queries/PATTERN.md +1 -1
  104. package/patterns/source-scanning/PATTERN.md +13 -2
  105. package/patterns/source-scanning/example/source-scanner.js +9 -0
  106. package/src/server/ai.js +19 -5
  107. package/src/server/apify.js +2 -2
  108. package/src/server/asana.js +6 -6
  109. package/src/server/ashby.js +2 -1
  110. package/src/server/attention.js +12 -11
  111. package/src/server/awsTransport.js +6 -0
  112. package/src/server/bigquery.js +5 -4
  113. package/src/server/brevo.js +2 -1
  114. package/src/server/clay.js +2 -1
  115. package/src/server/clickhouse.js +2 -1
  116. package/src/server/confidence.js +6 -1
  117. package/src/server/connectorValues.js +33 -0
  118. package/src/server/databricks.js +7 -7
  119. package/src/server/dbt-semantic-layer.js +5 -5
  120. package/src/server/elevenlabs.js +2 -2
  121. package/src/server/firebase-cloud-messaging.js +2 -2
  122. package/src/server/gemini-enterprise.js +5 -5
  123. package/src/server/google-ads-search.js +68 -48
  124. package/src/server/google-ads.js +15 -17
  125. package/src/server/google-drive.js +7 -7
  126. package/src/server/google-maps-platform.js +4 -2
  127. package/src/server/google-search-console.js +4 -3
  128. package/src/server/google.js +8 -4
  129. package/src/server/googleAdsApi.js +14 -0
  130. package/src/server/granola.js +2 -2
  131. package/src/server/hubspot.js +2 -1
  132. package/src/server/incident-io.js +3 -2
  133. package/src/server/lexware.js +5 -4
  134. package/src/server/lightspeed.js +7 -5
  135. package/src/server/linkedin.js +2 -2
  136. package/src/server/mcpTransport.js +8 -4
  137. package/src/server/microsoft-fabric.js +3 -3
  138. package/src/server/microsoft-onedrive.js +2 -2
  139. package/src/server/microsoft-onenote.js +4 -3
  140. package/src/server/microsoft-outlook.js +6 -6
  141. package/src/server/microsoft-sharepoint.js +4 -2
  142. package/src/server/microsoft-teams.js +2 -1
  143. package/src/server/microsoft.js +20 -13
  144. package/src/server/notion.js +2 -1
  145. package/src/server/pipedrive.js +2 -1
  146. package/src/server/salesforce.js +12 -12
  147. package/src/server/semrush.js +9 -8
  148. package/src/server/snowflake.js +20 -20
  149. package/src/server/storyblok.js +2 -1
  150. package/src/server/tally.js +2 -1
  151. package/src/server/telegram.js +2 -6
  152. package/src/server/tiktok.js +3 -3
  153. package/src/server/twilio.js +3 -2
  154. package/src/server/twitch.js +5 -3
  155. package/src/server/types.js +13 -0
  156. package/src/server/wix.js +20 -878
  157. package/src/server/wixBookings.js +449 -0
  158. package/src/server/wixCms.js +132 -0
  159. package/src/server/wixStores.js +296 -0
  160. package/src/server/wixValues.js +35 -0
  161. package/src/server/wiz.js +18 -4
  162. package/src/server/woocommerce.js +1 -1
  163. package/src/server/wordpress-com.js +2 -1
  164. package/src/server/workday.js +9 -9
  165. package/src/server/x-twitter.js +2 -1
  166. package/src/server/xero.js +40 -40
  167. package/src/server/zoho-books.js +6 -6
  168. package/src/server/zoho-crm.js +5 -5
  169. package/src/shared/confidence.js +6 -1
  170. package/src/shared/dbt-semantic-layer.js +1 -1
  171. package/src/shared/figma.js +1 -1
  172. package/src/shared/google.js +8 -4
  173. package/src/shared/googleScope.js +4 -0
  174. package/src/shared/microsoft-fabric.js +4 -5
  175. package/src/shared/microsoft.js +8 -3
  176. package/src/shared/salesforce.js +1 -1
  177. package/src/shared/tokens.js +7 -3
  178. package/src/shared/uuid.js +13 -0
  179. package/src/shared/wix.js +4 -3
  180. package/src/shared/zoho-books.js +3 -4
  181. package/src/shared/zoho-crm.js +1 -1
  182. package/src/shared/{zoho-regions.js → zoho.js} +4 -1
  183. package/test/ai.test.js +1 -1
  184. package/test/brevo.test.js +1 -1
  185. package/test/chargebee.test.js +1 -1
  186. package/test/google-ads.test.js +8 -4
  187. package/test/linkedin.test.js +1 -1
  188. package/test/resend.test.js +2 -2
  189. package/test/salesforce.test.js +1 -1
  190. package/test/snowflake.test.js +7 -7
  191. package/test/tiktok.test.js +1 -1
  192. package/test/wiz.test.js +1 -1
package/docs/wix.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Import `wixProvider` from `@jskit-ai/connectors-catalog/server/wix`. The
4
4
  runtime reads account sites and business locations, manages site contacts and
5
5
  booking-service settings, queries availability, creates/cancels bookings, reads orders
6
- and reads/edits products in both Wix catalogue versions. Vibe64 and CLI consumers
6
+ and reads/edits products in both Wix catalogue versions. Hosted-editor and CLI consumers
7
7
  edit the same JSON and use shared validation, authorization and encrypted file
8
8
  storage. Provider acceptance is still in progress; see Verification status below.
9
9
 
@@ -103,16 +103,16 @@ fields and input values fail explicitly. Cancellation preserves a verified grant
103
103
  ## Editors, hosting and automation
104
104
 
105
105
  For this account-key flow, the universal OAuth callback is **not applicable**.
106
- Customer VPS and custom-domain URLs do not enter the provider authentication
106
+ Customer server and custom-domain URLs do not enter the provider authentication
107
107
  request. Each connected customer account requires its own authorized account
108
- binding. A single Vibe64-owned account key cannot grant access to unrelated
108
+ binding. A single editor-owned account key cannot grant access to unrelated
109
109
  customers' Wix accounts.
110
110
 
111
111
  The application owner supplies the authorized key and its matching Wix account
112
112
  binding through private Env and configuration. The backend enforces access to
113
113
  that account and keeps the key off browsers. Separate keys do not establish
114
114
  independent quota pools; provider limits and permitted use still apply. CLI and
115
- Vibe64 users configure the same application-owned key flow.
115
+ hosted-editor users configure the same application-owned key flow.
116
116
 
117
117
  | Task | Automation assessment |
118
118
  |---|---|
@@ -276,7 +276,7 @@ administrative write workflow). This is a backend site-wide credential, not each
276
276
  customer's authorization. The generated app must check booking ownership before
277
277
  returning private details or invoking actions. Frameworks other than JSKIT use the
278
278
  same configured site and Env credential with their native HTTP client. No editor
279
- or Vibe64 server is required by the deployed app.
279
+ or hosted server is required by the deployed app.
280
280
 
281
281
 
282
282
  ### Appointment availability
@@ -369,7 +369,7 @@ Check current bookability/capacity before submitting `bookings.create` with
369
369
  `kind: "CLASS"`. The generated app owns party-size selection and lost-capacity
370
370
  feedback. This does not reserve seats. A mismatched event/service/time-zone
371
371
  response is rejected. CLI/native framework users follow the same native flow and
372
- project-owned credentials; no Vibe64 service participates in the booking.
372
+ project-owned credentials; no hosted service participates in the booking.
373
373
 
374
374
 
375
375
  ### Select a resource and location
@@ -414,7 +414,7 @@ Detailed transaction/refund history requires the native transactions API.
414
414
  CLI-created JSKIT apps invoke these operations through the same connection
415
415
  service; other frameworks use the same site-scoped endpoints and Env key with
416
416
  their own HTTP client. The generated app owns commerce screens, authorization,
417
- fulfilment and payment reconciliation. No Vibe64 gateway or managed key is used.
417
+ fulfilment and payment reconciliation. No hosted gateway or managed key is used.
418
418
 
419
419
 
420
420
 
@@ -560,7 +560,7 @@ business object. Hide unauthorized sites in the app's picker as well.
560
560
 
561
561
  This is the same text configuration and operation interface for CLI projects.
562
562
  Other frameworks must enforce the configured allowed IDs and user authorization
563
- before choosing the site header. No new Vibe64 server or gateway is involved.
563
+ before choosing the site header. No new hosted server or gateway is involved.
564
564
 
565
565
 
566
566
  ### Filtered CMS content and references
@@ -935,7 +935,7 @@ fixtures. Package/rendered proof still requires the next refresh.
935
935
  for the selected service through the project-owned site connection. The response
936
936
  field is `serviceVariants`, not `serviceOptionsAndVariants`. Preserve its option
937
937
  IDs, choices, revision and decimal price strings. The generated application's
938
- own form displays the choices and collects participants per choice; Vibe64 does
938
+ own form displays the choices and collects participants per choice; the editor does
939
939
  not maintain a separate catalogue or expose the API key to that form.
940
940
 
941
941
  Use the selected service ID from `bookingServices.list` or `.get`. The API key
@@ -948,7 +948,7 @@ provider error and check service configuration before offering a booking.
948
948
 
949
949
  CLI callers use the same invocation and existing Env-backed connection as the
950
950
  other site operations. Other frameworks call Wix's native endpoint with their
951
- project-owned key and site header. No additional Vibe64 service is required.
951
+ project-owned key and site header. No additional hosted service is required.
952
952
 
953
953
  The lookup feeds the explicit availability and booking selections below.
954
954
  The generated app owns the form and authorization. Confirmation is an explicit operation described below; creation does not
@@ -1117,7 +1117,7 @@ Create Cart reference also lists **Manage eCommerce - Admin Permissions** as an
1117
1117
  alternative permission. Keep the selected site's ID in project configuration.
1118
1118
  Publish the Wix site and configure its checkout/payment methods before expecting
1119
1119
  a working payment page. SITE_NOT_PUBLISHED or CHECKOUT_PAGE_NOT_FOUND requires
1120
- fixing the Wix site, not adding an OAuth app or a Vibe64 gateway.
1120
+ fixing the Wix site, not adding an OAuth app or a hosted gateway.
1121
1121
 
1122
1122
  The app backend calls `carts.create` with a nonempty `catalogItems` array and an
1123
1123
  optional `note`. Each item has `quantity` and `catalogReference`:
@@ -1159,7 +1159,7 @@ JSKIT CLI/runtime consumers use the same calls with text/Env configuration. Othe
1159
1159
  frameworks POST `{ cart: { source: { channelType: "WEB" }, note? }, catalogItems }`
1160
1160
  to `/ecom/v2/carts`, then POST `{}` to `/ecom/v2/carts/{cartId}/get-checkout-url`
1161
1161
  with the project-owned key and `wix-site-id` header. They can use their framework's
1162
- normal redirect response. No card details, provider credentials or Vibe64 billing
1162
+ normal redirect response. No card details, provider credentials or hosted billing
1163
1163
  service are passed through the browser.
1164
1164
 
1165
1165
  References: [Create Cart](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/purchase-flow/cart-v2/create-cart),
@@ -1198,7 +1198,7 @@ This reader does not create shipments or send shipping notifications. Use the
1198
1198
  separate create/update operations documented below to record shipments or change
1199
1199
  tracking. Those writes can trigger Wix shipping notifications.
1200
1200
  CLI and other frameworks use the same project Env key, site header and native
1201
- endpoint; there is no Vibe64 service dependency.
1201
+ endpoint; there is no hosted service dependency.
1202
1202
 
1203
1203
  Reference: [Wix List Fulfillments For Single Order](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/orders/order-fulfillments/list-fulfillments-for-single-order).
1204
1204
 
@@ -113,7 +113,7 @@ provider consent remain owner steps; do not invent a client-creation endpoint.
113
113
 
114
114
  The application owner creates the provider registration and stores its secret
115
115
  in the application's private Env. Every editor and CLI uses this same
116
- [ownership model](../../connectors-core/docs/online-setup.md): the configuration
116
+ [ownership model](../../connectors-core/docs/application-setup.md): the configuration
117
117
  file holds the client ID and Env references; the editor does not own the
118
118
  application's grants.
119
119
 
@@ -149,7 +149,7 @@ inspect the site's content before deciding whether to repeat it.
149
149
  A non-Node framework uses its own HTTPS client, the same site URL/Env username
150
150
  and password binding, and these native `/wp-json/wp/v2/posts` or `/pages` routes.
151
151
  Use GET for reads, JSON POST for create/update, and DELETE with force=false for
152
- trash. There is no Vibe64 runtime or JSKIT service requirement for that framework.
152
+ trash. There is no hosted runtime or JSKIT service requirement for that framework.
153
153
 
154
154
  ## Media and user operations
155
155
 
package/docs/workday.md CHANGED
@@ -63,7 +63,7 @@ registration. Task availability depends on the administrator's permissions.
63
63
  Tenant Setup – Security**, enable **OAuth 2.0 Clients Enabled**, and apply the
64
64
  organization's normal security-change process.
65
65
  3. Search for **Register API Client**. Enter a recognizable client name such as
66
- `DogAndGroom — production` or `DogAndGroom — sandbox`.
66
+ `Bookings — production` or `Bookings — sandbox`.
67
67
  Choose **Authorization Code Grant** and **Bearer** access tokens.
68
68
  4. Leave **Support Proof Key for Code Exchange (PKCE)** disabled for this
69
69
  confidential setup. The captured Workday connector expects the client secret
@@ -138,7 +138,7 @@ updates, employment changes, bulk sync or automatic pagination.
138
138
 
139
139
  The application owner creates the provider registration and stores its secret
140
140
  in the application's private Env. Every editor and CLI uses this same
141
- [ownership model](../../connectors-core/docs/online-setup.md): the configuration
141
+ [ownership model](../../connectors-core/docs/application-setup.md): the configuration
142
142
  file holds the client ID and Env references; the editor does not own the
143
143
  application's grants.
144
144
 
package/docs/x-twitter.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Import `xTwitterProvider` from `@jskit-ai/connectors-catalog/server/x-twitter`.
4
4
  This adapter reads public profiles, post timelines and recent search using an app-only
5
5
  bearer token. The shared connection service and file store work from a CLI or
6
- application server. Vibe64 edits the same JSON; saving does not contact X.
6
+ application server. A hosted editor edits the same JSON; saving does not contact X.
7
7
 
8
8
  ## Create the provider application
9
9
 
@@ -117,7 +117,7 @@ advertised as individual users connecting their X accounts.
117
117
  [Authentication boundary](https://docs.x.com/fundamentals/authentication/oauth-2-0/application-only).
118
118
 
119
119
  An OAuth callback is **not applicable to this bearer-token flow**. Neither a
120
- customer's VPS hostname nor a custom application domain changes authentication.
120
+ customer's server hostname nor a custom application domain changes authentication.
121
121
  The application owner supplies its authorized token through private Env and
122
122
  retains that credential ownership when moving hosts.
123
123
 
@@ -171,7 +171,7 @@ rendering a purported complete result.
171
171
 
172
172
  A native framework uses the same Env token in its server-side HTTP client,
173
173
  `Authorization: Bearer <value>`, and these fixed API paths/query parameters.
174
- It does not require JSKIT or Vibe64 at runtime. The application owns query
174
+ It does not require JSKIT or a hosted editor at runtime. The application owns query
175
175
  permissions, pagination controls, spend limits, escaping post text, joining
176
176
  expansions, attribution and links back to the original post. Do not turn returned
177
177
  media URLs into arbitrary backend downloads or render post text as trusted HTML.
package/docs/xero.md CHANGED
@@ -4,7 +4,7 @@ The `xeroProvider` export from `@jskit-ai/connectors-catalog/server/xero`
4
4
  connects an own web registration through the shared OAuth runtime. It discovers
5
5
  authorised tenants and provides organisation settings, contacts, invoices,
6
6
  payments, reports, budgets, manual journals, bank transactions and attachments. Configuration, consent, refresh and encrypted file storage work from
7
- an ordinary backend or CLI; no database or Vibe64 service is required.
7
+ an ordinary backend or CLI; no database or hosted service is required.
8
8
 
9
9
  ## Create the provider registration
10
10
 
@@ -120,7 +120,7 @@ describe the underlying read parameters and lightweight responses.
120
120
 
121
121
  Each application owns its provider registration, callback route, credentials
122
122
  and grants. Hosted and installed editors configure the same app-owned setup;
123
- neither supplies a shared Vibe64 registration or token gateway. Use the app's
123
+ neither supplies a shared registration or token gateway. Use the app's
124
124
  assigned public URL as the initial callback origin, append the route the backend
125
125
  actually implements, and register the exact URL with the provider. Keep the
126
126
  client secret and callback binding in the application's Env.
@@ -337,7 +337,7 @@ Dates use `YYYY-MM-DD`. Choose the contact from `contacts.list`; aged reports ar
337
337
 
338
338
  Select **Read budgets** (`accounting.budgets.read`) and reconnect. Call `budgets.list` with `tenantId`; call `budgets.get` with that tenant and the returned budget UUID as `id`. Both accept optional `DateFrom` and `DateTo` in `YYYY-MM-DD` format (capitalization matches Xero). The adapter preserves account budget lines, balances, periods, notes and tracking data, and rejects a detail response for a different budget. It does not create or edit budgets.
339
339
 
340
- For a summary, separately select **Read budget summary reports** (`accounting.reports.budgetsummary.read`) and reconnect. `reports.budgetSummary` takes `tenantId`, required `date`, optional `periods` (1–12) and optional integer `timeframe`: 1=month, 3=quarter, 12=year. This differs from the string timeframe used by profit/loss reports. The application owns rendering; no Vibe64 runtime is required.
340
+ For a summary, separately select **Read budget summary reports** (`accounting.reports.budgetsummary.read`) and reconnect. `reports.budgetSummary` takes `tenantId`, required `date`, optional `periods` (1–12) and optional integer `timeframe`: 1=month, 3=quarter, 12=year. This differs from the string timeframe used by profit/loss reports. The application owns rendering; no hosted runtime is required.
341
341
 
342
342
  ### Bank transaction and manual journal reads
343
343
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Import `zohoBooksProvider` from `@jskit-ai/connectors-catalog/server/zoho-books`.
4
4
  This initial adapter discovers organisations and reads contact and invoice pages.
5
- CLI and Vibe64 use the same configuration, OAuth service and encrypted file store.
5
+ The CLI and a hosted editor use the same configuration, OAuth service and encrypted file store.
6
6
  Saving configuration does not connect an account.
7
7
 
8
8
  ## Register and configure
@@ -156,7 +156,7 @@ refresh tokens. [Token lifecycle and revocation](https://www.zoho.com/books/api/
156
156
 
157
157
  The application owner creates the provider registration and stores its secret
158
158
  in the application's private Env. Every editor and CLI uses this same
159
- [ownership model](../../connectors-core/docs/online-setup.md): the configuration
159
+ [ownership model](../../connectors-core/docs/application-setup.md): the configuration
160
160
  file holds the client ID and Env references; the editor does not own the
161
161
  application's grants.
162
162
 
package/docs/zoho-crm.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Import `zohoCrmProvider` from `@jskit-ai/connectors-catalog/server/zoho-crm`.
4
4
  The initial adapter reads the current CRM user and pages of leads, contacts,
5
5
  accounts and deals. It uses the existing OAuth connection service and encrypted
6
- file store. Vibe64 and CLI users edit the same `integrations.json`; saving that
6
+ file store. Hosted-editor and CLI users edit the same `integrations.json`; saving that
7
7
  file does not perform consent or verify credentials.
8
8
 
9
9
  ## Register a client
@@ -134,7 +134,7 @@ Revocation is separate from deleting this integration's configuration.
134
134
 
135
135
  The application owner creates the provider registration and stores its secret
136
136
  in the application's private Env. Every editor and CLI uses this same
137
- [ownership model](../../connectors-core/docs/online-setup.md): the configuration
137
+ [ownership model](../../connectors-core/docs/application-setup.md): the configuration
138
138
  file holds the client ID and Env references; the editor does not own the
139
139
  application's grants.
140
140
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/connectors-catalog",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Provider definitions and focused API operations for JSKIT connectors.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -117,6 +117,7 @@
117
117
  "./server/workday": "./src/server/workday.js",
118
118
  "./server/shopify": "./src/server/shopify.js",
119
119
  "./server/wiz": "./src/server/wiz.js",
120
+ "./server/types": "./src/server/types.js",
120
121
  "./locales/en.json": "./locales/en.json"
121
122
  },
122
123
  "dependencies": {
@@ -124,14 +125,14 @@
124
125
  "@aws-sdk/client-redshift-data": "3.1128.0",
125
126
  "@aws-sdk/client-s3": "3.1128.0",
126
127
  "@aws-sdk/s3-request-presigner": "3.1128.0",
127
- "@jskit-ai/connectors-core": "0.2.2",
128
+ "@jskit-ai/connectors-core": "0.2.4",
128
129
  "@modelcontextprotocol/sdk": "1.32.1",
129
130
  "@smithy/fetch-http-handler": "5.8.0",
130
131
  "jose": "^6.1.3",
131
132
  "json-rest-schema": "^1.0.17"
132
133
  },
133
134
  "peerDependencies": {
134
- "@jskit-ai/kernel": "0.2.2"
135
+ "@jskit-ai/kernel": "0.2.4"
135
136
  },
136
137
  "jskit": {
137
138
  "kind": "runtime",
@@ -38,6 +38,18 @@ to authorized application, user, provider and integration. The application owns
38
38
  key-entry and disconnect screens. Never return connection parameters to a
39
39
  browser or share coding-agent subscription credentials.
40
40
 
41
+ Each collaborator the composition receives (`authorize`, `createModel`,
42
+ `createClient` and `resolveReference`) is a required parameter typed in a JSDoc
43
+ `@param` and called directly, without a `typeof` probe at the call or a no-op
44
+ default. `createPerplexityAnswers()` checks `authorize` and `createClient` once,
45
+ as input validation when it is composed, so a missing one fails there instead of
46
+ on the first answer. `authorize` and `resolveReference` are typed with
47
+ `ConnectorAuthorize` and `ResolveReference` from
48
+ `@jskit-ai/connectors-core/server/types`. Only the production
49
+ `resolveReference = createEnvironmentReferenceResolver(process.env)` stays as a default, in
50
+ both compositions. A server feature that uses it follows
51
+ [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
52
+
41
53
  ## Do not use when
42
54
 
43
55
  Frameworks outside Node follow their own configuration and AI client patterns.
@@ -65,6 +77,9 @@ Do not add a runtime catalogue fetch, token billing, an inference proxy, a
65
77
  cross-language runtime or a silent paid fallback. Never infer that a model
66
78
  marked free can be used without the authentication its provider requires.
67
79
 
80
+ Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
81
+ with a setter after construction, or keep a module-level registry.
82
+
68
83
  ## Existing Perplexity connector slots
69
84
 
70
85
  Use `example/perplexity-answer.js` when configuration already has provider
@@ -80,6 +95,6 @@ search_results. For stream=true consume the async iterator, rendering deltas
80
95
  and retaining final citations/search_results; cancel with AbortSignal.
81
96
  Allow only safe HTTP(S) links in rendered citations. Never send the API key/client
82
97
  to a browser. A public route must sanitize SDK failures and enforce app budgets.
83
- This is direct app-to-provider traffic, with no Vibe64 token sales or proxy.
98
+ This is direct app-to-provider traffic, with no hosted token sales or proxy.
84
99
  A trusted CLI operator can use the same JSON/Env and factory. Other frameworks
85
100
  use their own native Perplexity/OpenAI-compatible clients and the same slot.
@@ -1,8 +1,17 @@
1
+ import { createEnvironmentReferenceResolver } from "@jskit-ai/connectors-core/server";
1
2
  import { createAiConnectionResolver } from "@jskit-ai/connectors-catalog/server/ai";
2
3
 
3
- // App-owned composition. Supply the authenticated authorization policy and the
4
- // SDK model factory used by this application. Omit resolveReference for Env.
5
- export function createConfiguredAiModel({ configuration, authorize, resolveReference, createModel }) {
4
+ /**
5
+ * App-owned composition. Supply the authenticated authorization policy and the
6
+ * SDK model factory used by this application. Omit resolveReference for Env.
7
+ * @param {object} dependencies
8
+ * @param {object} dependencies.configuration The integration configuration.
9
+ * @param {import("@jskit-ai/connectors-core/server/types").ConnectorAuthorize} dependencies.authorize The application's access policy: the owner, or null.
10
+ * @param {import("@jskit-ai/connectors-core/server/types").ResolveReference} [dependencies.resolveReference]
11
+ * @param {(parameters: object) => unknown} dependencies.createModel The application's SDK model factory.
12
+ */
13
+ export function createConfiguredAiModel({ configuration, authorize,
14
+ resolveReference = createEnvironmentReferenceResolver(process.env), createModel }) {
6
15
  const connections = createAiConnectionResolver({ configuration, authorize, resolveReference });
7
16
  return async ({ context, integrationId }) => {
8
17
  const parameters = await connections.resolve({ context, integrationId });
@@ -2,11 +2,22 @@ import { ConnectorError, createEnvironmentReferenceResolver } from "@jskit-ai/co
2
2
  import { validateIntegrationConfiguration } from "@jskit-ai/connectors-core/shared/configuration";
3
3
  import { perplexityProvider } from "@jskit-ai/connectors-catalog/server/perplexity";
4
4
 
5
- // App-owned composition, not an inference service. Supply the application's native
6
- // OpenAI-compatible client factory. Credentials and the returned client stay server-side.
5
+ /**
6
+ * App-owned composition, not an inference service. Supply the application's native
7
+ * OpenAI-compatible client factory. Credentials and the returned client stay server-side.
8
+ * @param {object} dependencies
9
+ * @param {object} dependencies.configuration The integration configuration.
10
+ * @param {import("@jskit-ai/connectors-core/server/types").ConnectorAuthorize} dependencies.authorize The application's access policy: the owner, or null.
11
+ * @param {(options: object) => { chat: { completions: { create: (body: object, request: object) => Promise<any> } } }} dependencies.createClient
12
+ * The application's native SDK client factory, such as `options => new OpenAI(options)`.
13
+ * @param {import("@jskit-ai/connectors-core/server/types").ResolveReference} [dependencies.resolveReference]
14
+ */
7
15
  export function createPerplexityAnswers({ configuration, authorize, createClient,
8
- resolveReference = createEnvironmentReferenceResolver() }) {
9
- if (typeof authorize !== "function" || typeof createClient !== "function") throw new TypeError("Supply application authorization and its native client factory.");
16
+ resolveReference = createEnvironmentReferenceResolver(process.env) }) {
17
+ // readable-check: allow method-probe - input validation: the application passes its access policy and its SDK client factory
18
+ if (typeof authorize !== "function" || typeof createClient !== "function") {
19
+ throw new TypeError("Supply application authorization and its native client factory.");
20
+ }
10
21
  const config = validateIntegrationConfiguration(configuration, { providers: [perplexityProvider], allowUnknownProviders: true });
11
22
  return async ({ context, integrationId, question, model, stream = false, signal }) => {
12
23
  const slot = Object.hasOwn(config.integrations, integrationId) ? config.integrations[integrationId] : null;
@@ -112,6 +112,12 @@ not require putting credentials into source.
112
112
  - An optional frontend key reference is distinct from the primary backend key.
113
113
  Only the application may deliberately expose a suitable search-only key;
114
114
  successful backend verification does not verify that frontend key's restrictions.
115
+ - Each collaborator the composition receives (`authorize`) is a required
116
+ parameter typed in a JSDoc `@param` and called directly, without a `typeof`
117
+ probe, a "requires x" guard or a no-op default. `authorize` is typed with
118
+ `ConnectorAuthorize` from `@jskit-ai/connectors-core/server/types`. Only the
119
+ production `env = process.env` stays as a default. A server feature that uses
120
+ it follows [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
115
121
 
116
122
  ## Framework APIs
117
123
 
@@ -168,7 +174,7 @@ const protection = createCredentialProtection({
168
174
  const store = createFileConnectionStore({ directory: process.env.CONNECTOR_STATE_DIRECTORY, protection });
169
175
  const connections = createConnectionService({
170
176
  configuration, providers, store,
171
- resolveReference: createEnvironmentReferenceResolver(),
177
+ resolveReference: createEnvironmentReferenceResolver(process.env),
172
178
  authorize: applicationConnectionPolicy
173
179
  });
174
180
 
@@ -243,6 +249,8 @@ Do not turn provider metadata into arbitrary authenticated URL forwarding.
243
249
  Do not retry a paid or mutating request automatically. Do not mark an untested
244
250
  managed mode or an unimplemented provider operation available.
245
251
 
252
+ Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
253
+ with a setter after construction, or keep a module-level registry.
246
254
 
247
255
  ## Granola meeting data
248
256
 
@@ -5,8 +5,11 @@ import { createFileConnectionStore, createCredentialProtection } from "@jskit-ai
5
5
  import { resendProvider } from "@jskit-ai/connectors-catalog/server/resend";
6
6
  import { firecrawlProvider } from "@jskit-ai/connectors-catalog/server/firecrawl";
7
7
 
8
- // Both a manually written CLI and a server can compose this application-owned module.
9
- // The application supplies its existing identity and permission policy.
8
+ /**
9
+ * Both a manually written CLI and a server can compose this application-owned module.
10
+ * The application supplies its existing identity and permission policy.
11
+ * @param {{ authorize: import("@jskit-ai/connectors-core/server/types").ConnectorAuthorize, env?: Record<string, string | undefined>, configFile?: string }} dependencies
12
+ */
10
13
  export async function applicationConnections({ authorize, env = process.env, configFile = "integrations.json" }) {
11
14
  const providers = [resendProvider, firecrawlProvider];
12
15
  const configuration = parseIntegrationConfiguration(await readFile(configFile, "utf8"), { providers });
@@ -19,7 +19,7 @@ composes those libraries with the application's identity and resource policy.
19
19
  ## Do not use when
20
20
 
21
21
  Do not use this as an application login, an AWS account creator, a general SDK
22
- proxy, or proof that a managed Vibe64 allocation exists. Do not use a machine's
22
+ proxy, or proof that a managed host's allocation exists. Do not use a machine's
23
23
  default AWS credentials for arbitrary application users. Per-user federation,
24
24
  AWS IAM Identity Center, noncommercial AWS partitions and arbitrary endpoints
25
25
  are outside the fragment. Athena statements can write data and incur costs;
@@ -28,8 +28,8 @@ connecting does not approve arbitrary future SQL.
28
28
  ## Product decisions
29
29
 
30
30
  Use the exact [S3](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/aws-s3.md) or
31
- [Athena](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/aws-athena.md) JSON. The same file is usable by CLI and the
32
- Vibe64 form. Store the actual secret access key, access key ID and optional
31
+ [Athena](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/aws-athena.md) JSON. The same file is usable by CLI and a
32
+ hosted editor's form. Store the actual secret access key, access key ID and optional
33
33
  session token outside source. The access key ID uses `settings.accessKeyIdRef`,
34
34
  the secret uses `authentication.secretRef`, and temporary credentials add
35
35
  `settings.sessionTokenRef`. A missing explicit binding is an error.
@@ -43,6 +43,13 @@ account assignments, quotas and credential renewal are separate operations.
43
43
  There is no OAuth callback for these modes. See
44
44
  [AWS ownership](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/connectors-catalog/docs/aws-credentials.md).
45
45
 
46
+ Each collaborator the composition receives (the connection `service`) is a
47
+ required parameter typed in a JSDoc `@param` and called directly, without a
48
+ `typeof` probe, a "requires x" guard or a no-op default. Only the production
49
+ `fetchImpl = globalThis.fetch` stays as a default. A server feature that uses it
50
+ follows
51
+ [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
52
+
46
53
  ## Framework APIs
47
54
 
48
55
  Follow the [API-key connection pattern](../api-key-connection/PATTERN.md) to
@@ -154,6 +161,9 @@ Do not expose presigned URLs in logs, infer table permission from a workgroup
154
161
  read, treat workgroup membership as user isolation, or poll queries without an
155
162
  application-controlled limit.
156
163
 
164
+ Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
165
+ with a setter after construction, or keep a module-level registry.
166
+
157
167
  ## Verification
158
168
 
159
169
  Missing credential references fail before HTTP. Expired/rejected AWS credentials
@@ -1,6 +1,17 @@
1
- // Application-owned composition: service.authorize must approve this exact key
2
- // for context. The same function works in a Node CLI or application backend.
3
- // Pass a bounded signal for both signing and the complete response-body read.
1
+ /**
2
+ * Application-owned composition: service.authorize must approve this exact key
3
+ * for context. The same function works in a Node CLI or application backend.
4
+ * Pass a bounded signal for both signing and the complete response-body read.
5
+ * @param {object} request
6
+ * @param {import("@jskit-ai/connectors-core/server/types").ConnectorsCore} request.service
7
+ * @param {object} request.context
8
+ * @param {string} request.integrationId
9
+ * @param {string} request.key
10
+ * @param {"download" | "upload"} request.direction
11
+ * @param {Blob | ArrayBuffer | ArrayBufferView} [request.body]
12
+ * @param {AbortSignal} request.signal
13
+ * @param {typeof globalThis.fetch} [request.fetchImpl]
14
+ */
4
15
  export async function transferS3Object({ service, context, integrationId, key,
5
16
  direction, body, signal, fetchImpl = globalThis.fetch }) {
6
17
  if (!["download", "upload"].includes(direction)) throw new TypeError("Choose download or upload.");
@@ -145,7 +145,7 @@ schedules with awareness of daylight-saving behavior.
145
145
  Expose the SDK route through the app's normal server composition, then deploy
146
146
  and sync its HTTPS `/api/inngest` URL in the selected Inngest environment.
147
147
  Keep the Signing Key private and let the native adapter verify signatures.
148
- JSKIT CLI users follow the same steps without Vibe64. Other stacks use native
148
+ JSKIT CLI users follow the same steps. Other stacks use native
149
149
  SDKs where available and the same event name/payload/Env contract; this example
150
150
  does not promise an SDK in every language. No function execution, cloud sync
151
151
  or generated application is performed by this reference pattern.
@@ -39,6 +39,13 @@ reference, stable project identity and public settings. Verify before reporting
39
39
  Connected; authorize every audience before sending. Preserve the existing file
40
40
  store and token lock instead of copying the grant implementation.
41
41
 
42
+ Each collaborator the composition receives (`authorizeConnectionOperation`) is a
43
+ required parameter typed in a JSDoc `@param` and called directly, without a
44
+ `typeof` probe, a "requires x" guard or a no-op default. It is typed with
45
+ `ConnectorAuthorize` from `@jskit-ai/connectors-core/server/types`. A server
46
+ feature that uses it follows
47
+ [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
48
+
42
49
  ## Framework APIs
43
50
 
44
51
  Use `parseIntegrationConfiguration`, `createConnectionService`,
@@ -154,3 +161,6 @@ Do not expose service-account JSON to the browser, confuse Firebase API keys
154
161
  with private service credentials, or choose the paid project from caller input.
155
162
  Do not treat an accepted message receipt as device delivery or automatically
156
163
  retry a send whose outcome is unknown.
164
+
165
+ Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
166
+ with a setter after construction, or keep a module-level registry.
@@ -4,6 +4,14 @@ import { createConnectionService, createEnvironmentReferenceResolver } from "@js
4
4
  import { createFileConnectionStore, createCredentialProtection } from "@jskit-ai/connectors-core/server/file-storage";
5
5
  import { firebaseCloudMessagingProvider } from "@jskit-ai/connectors-catalog/server/firebase-cloud-messaging";
6
6
 
7
+ /**
8
+ * @param {object} options
9
+ * @param {string} options.configurationPath
10
+ * @param {string} options.runtimeDirectory
11
+ * @param {Buffer} options.credentialKey
12
+ * @param {Record<string, string | undefined>} options.environment
13
+ * @param {import("@jskit-ai/connectors-core/server/types").ConnectorAuthorize} options.authorizeConnectionOperation The application's access policy.
14
+ */
7
15
  export async function openNotificationConnections({
8
16
  configurationPath, runtimeDirectory, credentialKey, environment,
9
17
  authorizeConnectionOperation
@@ -27,18 +27,20 @@ const created = await ads.create(review.reviewId); // starts PAUSED
27
27
  `configuration.extensions.googleAdsSearch[integrationId]` holds the saved plan.
28
28
  Validate it with `validateGoogleAdsSearchPlan` from the package's shared
29
29
  `google-ads-search` export. Keep OAuth settings separate so campaign edits do not
30
- invalidate consent. The runtime has no Vibe64 protocol, frontend, Env injection or
30
+ invalidate consent. The runtime has no command protocol, frontend, Env injection or
31
31
  storage owner. CLI apps can call it directly. Normal `connections.authorize` must
32
32
  authorize the trusted application's advertising administrator for each operation;
33
33
  never accept a subject identity from a request body.
34
34
 
35
- For Vibe64, compose `example/ads-setup.js` into the app's existing Integration setup
36
- command and return exactly one JSON result on stdout. Derive `context` and the
35
+ When a host runs the app's integration setup command, compose `example/ads-setup.js`
36
+ into that command and return exactly one JSON result on stdout. Pass the host's
37
+ request protocol as the fragment's third argument: `protocol`, the id its requests
38
+ carry and its response echoes, and `maxResponseBytes`, the largest response it
39
+ accepts; the host's own command contract names both. Derive `context` and the
37
40
  allowed integration ID from trusted command composition before calling the
38
41
  fragment. Keep connection status/connect/reconnect/disconnect operations intact.
39
- Read the public Vibe64 `application-google-ads.md` command contract when targeting
40
- that editor. Other frameworks implement its JSON/Env and operation contract with
41
- their native libraries; they do not execute this JavaScript fragment.
42
+ Other frameworks implement its JSON/Env and operation contract with their native
43
+ libraries; they do not execute this JavaScript fragment.
42
44
 
43
45
  The Search recipe supports only non-political manual-CPC campaigns with one ad
44
46
  group, phrase keywords and a website conversion goal. Account creation, PMax,
@@ -66,9 +68,15 @@ persistent OAuth grants. Reviews include live account values and the saved plan.
66
68
  Creation is paused and atomic; launch rechecks the live review. Do not replay a
67
69
  write after an uncertain response. Disconnecting does not pause campaigns.
68
70
 
71
+ Each collaborator the composition receives (the `createGoogleAdsSearchService()`
72
+ service) is a required parameter typed in a JSDoc `@param` and called directly,
73
+ without a `typeof` probe, a "requires x" guard or a no-op default. A server
74
+ feature that uses it follows
75
+ [typed features](https://github.com/mobily-enterprises/jskit-ai/blob/main/packages/agent-docs/site/guide/framework/typed-features.md).
76
+
69
77
  ## Example files
70
78
 
71
- `example/ads-setup.js` maps the optional editor command to the shared service. It
79
+ `example/ads-setup.js` maps a host's optional setup command to the shared service. It
72
80
  contains no HTTP endpoint, credential resolution or trusted-identity inference.
73
81
 
74
82
  ## Variation points
@@ -90,3 +98,6 @@ approval and conversion/billing readiness require operator verification.
90
98
  Do not put secrets in JSON, stdout or chat. Do not execute conversion snippets in
91
99
  the editor, confuse OAuth consent with advertiser approval, or claim live account
92
100
  acceptance from fixture tests. Keep larger campaign types outside this recipe.
101
+
102
+ Do not probe a collaborator, default one to `null`, `{}` or a no-op, fill a slot
103
+ with a setter after construction, or keep a module-level registry.
@@ -1,7 +1,15 @@
1
- // Compose the service in the application's existing authenticated command owner.
2
- // No stdin value establishes the trusted application/administrator identity.
3
- export async function dispatchAdsSetup(request, service) {
4
- if (request?.protocol !== "vibe64.integration-setup.command.v1" || typeof request.requestId !== "string" ||
1
+ /**
2
+ * Runs one advertising setup request against the Google Ads Search service. Compose
3
+ * the service in the application's existing authenticated command owner: no request
4
+ * value establishes the trusted application or administrator identity.
5
+ * @param {{ protocol: string, requestId: string, operation: string, ads: Record<string, any> }} request The parsed setup command.
6
+ * @param {import("@jskit-ai/connectors-catalog/server/types").GoogleAdsSearchService} service
7
+ * @param {object} host The command host's request protocol.
8
+ * @param {string} host.protocol The protocol id that requests carry and the response echoes.
9
+ * @param {number} host.maxResponseBytes The largest response the host accepts.
10
+ */
11
+ export async function dispatchAdsSetup(request, service, { protocol, maxResponseBytes }) {
12
+ if (request?.protocol !== protocol || typeof request.requestId !== "string" ||
5
13
  !/^[A-Za-z0-9_-]{1,200}$/.test(request.requestId) || !request.ads || Array.isArray(request.ads) || typeof request.ads !== "object") {
6
14
  throw new Error("Invalid advertising setup request.");
7
15
  }
@@ -20,6 +28,6 @@ export async function dispatchAdsSetup(request, service) {
20
28
  default: throw new Error("Unsupported advertising setup operation.");
21
29
  }
22
30
  const response = { protocol: request.protocol, requestId: request.requestId, status: "ads", operation: request.operation, data };
23
- if (Buffer.byteLength(JSON.stringify(response)) > 32768) throw new Error("Advertising result exceeds the editor's display limit. Inspect Google Ads before repeating any write.");
31
+ if (Buffer.byteLength(JSON.stringify(response)) > maxResponseBytes) throw new Error("Advertising result exceeds the host's response limit. Inspect Google Ads before repeating any write.");
24
32
  return response;
25
33
  }
@@ -69,7 +69,7 @@ const protection = createCredentialProtection({
69
69
  const connections = createConnectionService({
70
70
  configuration, providers,
71
71
  store: createFileConnectionStore({ directory: process.env.CONNECTOR_STATE_DIRECTORY, protection }),
72
- resolveReference: createEnvironmentReferenceResolver(), authorize: applicationConnectionPolicy
72
+ resolveReference: createEnvironmentReferenceResolver(process.env), authorize: applicationConnectionPolicy
73
73
  });
74
74
  ```
75
75