diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffd0ee7b..dd0a73d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: cache: "pnpm" - name: Install dependencies - run: pnpm install + run: pnpm install --no-frozen-lockfile - name: Check formatting run: pnpm run format:check diff --git a/package.json b/package.json index 5616cf0b..fb779b92 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "cmdk": "^1.1.1", "cookies-next": "^6.0.0", "date-fns": "^4.1.0", - "etsy-ts": "^4.2.0", + "etsy-ts": "4.2.0", "discord-api-types": "^0.38.17", "exa-js": "^1.8.8", "fast-deep-equal": "^3.1.3", @@ -140,6 +140,9 @@ "typescript": "^5.8.2", "typescript-eslint": "^8.27.0" }, + "patchedDependencies": { + "etsy-ts@4.2.0": "patches/etsy-ts@4.2.0.patch" + }, "ct3aMetadata": { "initVersion": "7.39.3" }, diff --git a/patches/etsy-ts@4.2.0.patch b/patches/etsy-ts@4.2.0.patch new file mode 100644 index 00000000..fdd4a1d2 --- /dev/null +++ b/patches/etsy-ts@4.2.0.patch @@ -0,0 +1,13 @@ +diff --git a/dist/api/data-contracts.d.ts b/dist/api/data-contracts.d.ts +index 5e8b06b081a84e93153e2e325ed76d53669fb033..675b39b3240104358379d1ef7ddc1d46bc1a3384 100644 +--- a/dist/api/data-contracts.d.ts ++++ b/dist/api/data-contracts.d.ts +@@ -2082,7 +2082,7 @@ export interface ICreateDraftListingPayload { + /** An enumerated string indicating who made the product. Helps buyers locate the listing under the Handmade heading. Requires 'is_supply' and 'when_made'. */ + who_made: "i_did" | "someone_else" | "collective"; + /** An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading. Requires 'is_supply' and 'who_made'. */ +- when_made: "made_to_order" | "2020_2023" | "2010_2019" | "2004_2009" | "before_2004" | "2000_2003" | "1990s" | "1980s" | "1970s" | "1960s" | "1950s" | "1940s" | "1930s" | "1920s" | "1910s" | "1900s" | "1800s" | "1700s" | "before_1700"; ++ when_made: "made_to_order" | "2020_2025" | "2010_2019" | "2006_2009" | "before_2006" | "2000_2005" | "1990s" | "1980s" | "1970s" | "1960s" | "1950s" | "1940s" | "1930s" | "1920s" | "1910s" | "1900s" | "1800s" | "1700s" | "before_1700"; + /** + * The numerical taxonomy ID of the listing. See [SellerTaxonomy](/documentation/reference#tag/SellerTaxonomy) and [BuyerTaxonomy](/documentation/reference#tag/BuyerTaxonomy) for more information. + * @min 1 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9cafcd36..4a403f4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + etsy-ts@4.2.0: + hash: 1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e + path: patches/etsy-ts@4.2.0.patch + importers: .: @@ -179,12 +184,12 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 - etsy-ts: - specifier: ^4.2.0 - version: 4.2.0 discord-api-types: specifier: ^0.38.17 version: 0.38.18 + etsy-ts: + specifier: 4.2.0 + version: 4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e) exa-js: specifier: ^1.8.8 version: 1.8.8(encoding@0.1.13)(ws@8.18.3)(zod@3.25.56) @@ -2091,14 +2096,14 @@ packages: '@types/node@18.19.111': resolution: {integrity: sha512-90sGdgA+QLJr1F9X79tQuEut0gEYIfkX9pydI4XGRgvFo9g2JWswefI+WUSUHPYVBHYSEfTEqBxA5hQvAZB3Mw==} - '@types/node@18.19.121': - resolution: {integrity: sha512-bHOrbyztmyYIi4f1R0s17QsPs1uyyYnGcXeZoGEd227oZjry0q6XQBQxd82X1I57zEfwO8h9Xo+Kl5gX1d9MwQ==} + '@types/node@18.19.124': + resolution: {integrity: sha512-hY4YWZFLs3ku6D2Gqo3RchTd9VRCcrjqp/I0mmohYeUVA5Y8eCXKJEasHxLAJVZRJuQogfd1GiJ9lgogBgKeuQ==} '@types/node@20.19.0': resolution: {integrity: sha512-hfrc+1tud1xcdVTABC2JiomZJEklMcXYNTVtZLAeqTVWD+qL5jkHKT+1lOtqDdGxt+mB53DTtiz673vfjU8D1Q==} - '@types/node@20.19.9': - resolution: {integrity: sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==} + '@types/node@20.19.13': + resolution: {integrity: sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==} '@types/pg@8.11.0': resolution: {integrity: sha512-sDAlRiBNthGjNFfvt0k6mtotoVYVQ63pA8R4EMWka7crawSR60waVYR0HAgmPRs/e2YaeJTD/43OoZ3PFw80pw==} @@ -2503,6 +2508,9 @@ packages: peerDependencies: axios: '>= 0.18 < 0.19.0 || >= 0.19.1' + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.7.7: resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} @@ -3301,6 +3309,15 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -3649,8 +3666,8 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + ip-address@10.0.1: + resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -3847,8 +3864,8 @@ packages: jose@6.0.11: resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==} - js-tiktoken@1.0.20: - resolution: {integrity: sha512-Xlaqhhs8VfCd6Sh7a1cFkZHQbYTLCwVJJWiHVxBYzLPxW0XsoxBy1hitmjkdIjD3Aon5BXLHFwU5O8WUx6HH+A==} + js-tiktoken@1.0.21: + resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3857,9 +3874,6 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - json-bigint@1.0.0: resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} @@ -3901,8 +3915,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - langsmith@0.3.50: - resolution: {integrity: sha512-yosW6sR0EFnMnYKKyBmcqTNknDVOs+dUfcswWk80JoRxox6WEyel7hmSkSzabP/GmTs0hXbrtc+lZwpJWSnI0w==} + langsmith@0.3.67: + resolution: {integrity: sha512-l4y3RmJ9yWF5a29fLg3eWZQxn6Q6dxTOgLGgQHzPGZHF3NUynn+A+airYIe/Yt4rwjGbuVrABAPsXBkVu/Hi7g==} peerDependencies: '@opentelemetry/api': '*' '@opentelemetry/exporter-trace-otlp-proto': '*' @@ -4413,8 +4427,8 @@ packages: sass: optional: true - node-abi@3.75.0: - resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} + node-abi@3.77.0: + resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==} engines: {node: '>=10'} node-addon-api@7.1.1: @@ -5183,8 +5197,8 @@ packages: resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} engines: {node: '>= 10'} - socks@2.8.6: - resolution: {integrity: sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==} + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} sonner@2.0.5: @@ -5204,9 +5218,6 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - sqlite3@5.1.7: resolution: {integrity: sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==} @@ -5803,7 +5814,7 @@ snapshots: '@anthropic-ai/sdk@0.40.1(encoding@0.1.13)': dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -6176,7 +6187,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -6203,8 +6214,8 @@ snapshots: ansi-styles: 5.2.0 camelcase: 6.3.0 decamelize: 1.2.0 - js-tiktoken: 1.0.20 - langsmith: 0.3.50(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)) + js-tiktoken: 1.0.21 + langsmith: 0.3.67(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)) mustache: 4.2.0 p-queue: 6.6.2 p-retry: 4.6.2 @@ -7382,14 +7393,14 @@ snapshots: '@types/node-fetch@2.6.13': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 form-data: 4.0.4 '@types/node@18.19.111': dependencies: undici-types: 5.26.5 - '@types/node@18.19.121': + '@types/node@18.19.124': dependencies: undici-types: 5.26.5 @@ -7397,13 +7408,13 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@20.19.9': + '@types/node@20.19.13': dependencies: undici-types: 6.21.0 '@types/pg@8.11.0': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 pg-protocol: 1.10.3 pg-types: 4.1.0 @@ -7421,7 +7432,7 @@ snapshots: '@types/sqlite3@3.1.11': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/stack-utils@2.0.3': {} @@ -7433,7 +7444,7 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 20.19.9 + '@types/node': 20.19.13 '@types/yargs-parser@21.0.3': {} @@ -7805,9 +7816,17 @@ snapshots: axe-core@4.10.3: {} - axios-auth-refresh@3.3.6(axios@1.7.7): + axios-auth-refresh@3.3.6(axios@1.11.0): dependencies: - axios: 1.7.7 + axios: 1.11.0 + + axios@1.11.0: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug axios@1.7.7: dependencies: @@ -7979,7 +7998,7 @@ snapshots: cloudflare@4.3.0(encoding@0.1.13): dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -8670,11 +8689,11 @@ snapshots: etag@1.8.1: {} - etsy-ts@4.2.0: + etsy-ts@4.2.0(patch_hash=1b38e33f32486e10e0a008fd3505d112c6ba6a828a3227ca85c9f2be552d2c1e): dependencies: - axios: 1.7.7 - axios-auth-refresh: 3.3.6(axios@1.7.7) - form-data: 4.0.3 + axios: 1.11.0 + axios-auth-refresh: 3.3.6(axios@1.11.0) + form-data: 4.0.4 tslib: 2.8.1 transitivePeerDependencies: - debug @@ -8819,6 +8838,8 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.11: {} + follow-redirects@1.15.9: {} for-each@0.3.5: @@ -9050,7 +9071,7 @@ snapshots: groq-sdk@0.3.0(encoding@0.1.13): dependencies: - '@types/node': 18.19.121 + '@types/node': 18.19.124 '@types/node-fetch': 2.6.13 abort-controller: 3.0.0 agentkeepalive: 4.6.0 @@ -9304,10 +9325,7 @@ snapshots: internmap@2.0.3: {} - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 + ip-address@10.0.1: optional: true ipaddr.js@1.9.1: {} @@ -9501,7 +9519,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.19.9 + '@types/node': 20.19.13 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -9513,7 +9531,7 @@ snapshots: jose@6.0.11: {} - js-tiktoken@1.0.20: + js-tiktoken@1.0.21: dependencies: base64-js: 1.5.1 @@ -9523,9 +9541,6 @@ snapshots: dependencies: argparse: 2.0.1 - jsbn@1.1.0: - optional: true - json-bigint@1.0.0: dependencies: bignumber.js: 9.3.0 @@ -9574,7 +9589,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - langsmith@0.3.50(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)): + langsmith@0.3.67(@opentelemetry/api@1.9.0)(openai@5.3.0(ws@8.18.3)(zod@3.25.56)): dependencies: '@types/uuid': 10.0.0 chalk: 4.1.2 @@ -10290,7 +10305,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - node-abi@3.75.0: + node-abi@3.77.0: dependencies: semver: 7.7.2 @@ -10643,7 +10658,7 @@ snapshots: minimist: 1.2.8 mkdirp-classic: 0.5.3 napi-build-utils: 2.0.0 - node-abi: 3.75.0 + node-abi: 3.77.0 pump: 3.0.3 rc: 1.2.8 simple-get: 4.0.1 @@ -11172,14 +11187,14 @@ snapshots: dependencies: agent-base: 6.0.2 debug: 4.4.1 - socks: 2.8.6 + socks: 2.8.7 transitivePeerDependencies: - supports-color optional: true - socks@2.8.6: + socks@2.8.7: dependencies: - ip-address: 9.0.5 + ip-address: 10.0.1 smart-buffer: 4.2.0 optional: true @@ -11194,9 +11209,6 @@ snapshots: split2@4.2.0: {} - sprintf-js@1.1.3: - optional: true - sqlite3@5.1.7: dependencies: bindings: 1.5.0 diff --git a/src/server/auth/custom-providers/etsy.ts b/src/server/auth/custom-providers/etsy.ts index 2358607b..20e3e3e2 100644 --- a/src/server/auth/custom-providers/etsy.ts +++ b/src/server/auth/custom-providers/etsy.ts @@ -10,7 +10,8 @@ export interface EtsyProfile { image_url_75x75?: string | null; } -export const etsyScopes = "email_r shops_r listings_r"; +export const etsyScopes = + "address_r address_w billing_r cart_r cart_w email_r favorites_r favorites_w feedback_r listings_d listings_r listings_w profile_r profile_w recommend_r recommend_w shops_r shops_w transactions_r transactions_w"; export default function EtsyProvider
( options: OAuthUserConfig
,
diff --git a/src/toolkits/toolkits/etsy/base.ts b/src/toolkits/toolkits/etsy/base.ts
index d585bf7d..31ee13ac 100644
--- a/src/toolkits/toolkits/etsy/base.ts
+++ b/src/toolkits/toolkits/etsy/base.ts
@@ -4,6 +4,8 @@ import { EtsyTools } from "./tools/tools";
import { getListings } from "@/toolkits/toolkits/etsy/tools/get-listings/base";
+import { createDraftListing } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/base";
+
import type { ToolkitConfig } from "@/toolkits/types";
export const etsyParameters = z.object({});
@@ -14,6 +16,7 @@ export const baseEtsyToolkitConfig: ToolkitConfig<
> = {
tools: {
[EtsyTools.getListings]: getListings,
+ [EtsyTools.createDraftListing]: createDraftListing,
},
parameters: etsyParameters,
};
diff --git a/src/toolkits/toolkits/etsy/client.tsx b/src/toolkits/toolkits/etsy/client.tsx
index dc79b09b..1274e57f 100644
--- a/src/toolkits/toolkits/etsy/client.tsx
+++ b/src/toolkits/toolkits/etsy/client.tsx
@@ -10,6 +10,8 @@ import { createClientToolkit } from "@/toolkits/create-toolkit";
import { getListingsClientConfig } from "@/toolkits/toolkits/etsy/tools/get-listings/client";
+import { createDraftListingClientConfig } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/client";
+
import { ToolkitGroups } from "@/toolkits/types";
import { EtsyTools } from "./tools/tools";
@@ -17,7 +19,8 @@ export const etsyClientToolkit = createClientToolkit(
baseEtsyToolkitConfig,
{
name: "Etsy Toolkit",
- description: "Etsy toolkit for fetching listing details.",
+ description:
+ "Etsy toolkit for Listing management, Payment management, Receipt management, Shipping management, Shop management and more!",
icon: SiEtsy,
form: null,
type: ToolkitGroups.DataSource,
@@ -37,5 +40,6 @@ export const etsyClientToolkit = createClientToolkit(
},
{
[EtsyTools.getListings]: getListingsClientConfig,
+ [EtsyTools.createDraftListing]: createDraftListingClientConfig,
},
);
diff --git a/src/toolkits/toolkits/etsy/server.ts b/src/toolkits/toolkits/etsy/server.ts
index a2cc94f5..9985fc3e 100644
--- a/src/toolkits/toolkits/etsy/server.ts
+++ b/src/toolkits/toolkits/etsy/server.ts
@@ -10,11 +10,13 @@ import { EtsyTools } from "./tools/tools";
import { EtsySecurityDataStorage } from "./security-data-storage";
import { getListingsServerConfig } from "@/toolkits/toolkits/etsy/tools/get-listings/server";
+import { createDraftListingServerConfig } from "@/toolkits/toolkits/etsy/tools/create-draft-listing/server";
export const etsyToolkitServer = createServerToolkit(
baseEtsyToolkitConfig,
"You have access to the Etsy toolkit for general account management. Currently, this toolkit provides:\n" +
- "- **Get Listings**: Retrieves all listings and their image URLs associated with the shop associated with the signed-in user.\n\n",
+ "- **Get Listings By Shop**: Retrieves listings associated with the shop owned by authenticated user. Has the ability to fetch associations relating to each listing as well.\n" +
+ "- **Create Draft Listing**: Creates a new draft listing in the shop owned by authenticated user. Accepts a variety of inputs to assign to listing.\n",
async () => {
const account = await api.accounts.getAccountByProvider("etsy");
@@ -32,7 +34,14 @@ export const etsyToolkitServer = createServerToolkit(
});
return {
- [EtsyTools.getListings]: getListingsServerConfig(etsy),
+ [EtsyTools.getListings]: getListingsServerConfig(
+ etsy,
+ account.providerAccountId,
+ ),
+ [EtsyTools.createDraftListing]: createDraftListingServerConfig(
+ etsy,
+ account.providerAccountId,
+ ),
};
},
);
diff --git a/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts
new file mode 100644
index 00000000..603e2866
--- /dev/null
+++ b/src/toolkits/toolkits/etsy/tools/create-draft-listing/base.ts
@@ -0,0 +1,299 @@
+import { z } from "zod";
+import { createBaseTool } from "@/toolkits/create-tool";
+import type { IShopListing } from "etsy-ts";
+
+export const createDraftListing = createBaseTool({
+ description:
+ "Creates a new draft listing in the Etsy shop associated with the authenticated user." +
+ "Requires input: quantity, title, description, price, who_made, when_made, is_supply, and taxonomy_id." +
+ "Optional inputs include: (if not specified, the default value is null" +
+ "shipping_profile_id — ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical." +
+ "return_policy_id - the numeric ID of the Return Policy." +
+ "materials - A list of material strings for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u)." +
+ "shop_section_id - The numeric ID of the shop section for this listing." +
+ "processing_min - The minimum number of days it takes to produce the item." +
+ "processing_max - The maximum number of days it takes to produce the item." +
+ "readiness_state_id - The numeric ID of the processing profile associated with the listing. Required when type is physical." +
+ "tags - A comma-separated list of tag strings for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}-'™©®]/u)." +
+ 'styles - An array of style strings for this listing, each of which is free-form text string such as "Formal", or "Steampunk". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters. (regex: /[^\\p{L}\\p{Nd}\\p{Zs}]/u).' +
+ "item_weight - The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0." +
+ "item_length - The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." +
+ "item_width - The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." +
+ "item_height - The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0." +
+ "item_weight_unit - The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided." +
+ "item_dimensions_unit - The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided." +
+ "is_personalizable - When ture, indicates that the listing is personalizable." +
+ "personalization_is_required - When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true" +
+ "personalization_char_count_max - The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true." +
+ "personalization_instructions - Instructions for personalization. Will only change if _is_personalizable is true." +
+ "production_partner_ids - An array of unique IDs of production partner ids." +
+ "image_ids - An array of numeric image IDs of the images in a listing, which can include up to 10 images." +
+ "is_customizable - When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders." +
+ "should_auto_renew - When true, renews a listing for four months upon expiration." +
+ "is_taxable - When true, applicable shop tax rates apply to this listing at checkout" +
+ "type - An enumerated type string that indicates whether the listing is physical or a digital download or both.",
+ inputSchema: z.object({
+ title: z
+ .string()
+ .min(1)
+ .max(140)
+ .describe(
+ "The title of the listing. Can only contain letters, numbers, punctuation marks, mathematical symbols, whitespace characters",
+ ),
+ description: z
+ .string()
+ .min(1)
+ .max(1000)
+ .describe("The description of the listing."),
+ price: z
+ .number()
+ .positive()
+ .describe(
+ "The price of the item. Must be a positive value with up to two decimal places.",
+ ),
+ quantity: z
+ .number()
+ .min(1)
+ .describe(
+ "The quantity of items available in this listing. Must be at least 1.",
+ ),
+ who_made: z
+ .enum(["i_did", "collective", "someone_else"])
+ .describe("Who made the item."),
+ when_made: z
+ .enum([
+ "made_to_order",
+ "2020_2025",
+ "2010_2019",
+ "2006_2009",
+ "before_2006",
+ "2000_2005",
+ "1990s",
+ "1980s",
+ "1970s",
+ "1960s",
+ "1950s",
+ "1940s",
+ "1930s",
+ "1920s",
+ "1910s",
+ "1900s",
+ "1800s",
+ "1700s",
+ "before_1700",
+ ])
+ .describe(
+ "An enumerated string for the era in which the maker made the product in this listing. Helps buyers locate the listing under the Vintage heading.",
+ ),
+ taxonomy_id: z
+ .number()
+ .int()
+ .positive()
+ .describe("The taxonomy ID for the category of the listing."),
+ is_supply: z
+ .boolean()
+ .describe(
+ "When true, tags the listing as a supply product, else indicates that it's a finished product.",
+ ),
+ shipping_profile_id: z
+ .number()
+ .int()
+ .positive()
+ .optional()
+ .describe(
+ "ID of the shipping profile to associate with the listing. REQUIRED if listing type is physical.",
+ ),
+ return_policy_id: z
+ .number()
+ .int()
+ .positive()
+ .optional()
+ .describe("The numeric ID of the Return Policy."),
+ materials: z
+ .array(
+ z
+ .string()
+ .regex(/[^\p{L}\p{Nd}\p{Zs}]/u, {
+ message:
+ "Valid materials strings contain only letters, numbers, and whitespace characters.",
+ })
+ .min(1)
+ .max(25)
+ .describe(
+ "A material string for materials used in the product. Valid materials strings contain only letters, numbers, and whitespace characters.",
+ ),
+ )
+ .max(25),
+ shop_section_id: z
+ .number()
+ .int()
+ .positive()
+ .optional()
+ .describe("The numeric ID of the shop section for this listing."),
+ processing_min: z
+ .number()
+ .int()
+ .min(0)
+ .optional()
+ .describe("The minimum number of days it takes to produce the item."),
+ processing_max: z
+ .number()
+ .int()
+ .min(0)
+ .optional()
+ .describe("The maximum number of days it takes to produce the item."),
+ readiness_state_id: z
+ .number()
+ .int()
+ .positive()
+ .optional()
+ .describe(
+ "The numeric ID of the processing profile associated with the listing. Required when type is physical.",
+ ),
+ tags: z
+ .array(
+ z
+ .string()
+ .regex(/^[\p{L}\p{Nd}\p{Zs}'™©®-]+$/u, {
+ message:
+ "Valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®.",
+ })
+ .min(1)
+ .max(25)
+ .describe(
+ "A tag string for the listing. When creating or updating a listing, valid tag strings contain only letters, numbers, whitespace characters, -, ', ™, ©, and ®.",
+ ),
+ )
+ .max(13)
+ .describe("A list of tag strings for the listing."),
+ styles: z
+ .array(
+ z
+ .string()
+ .regex(/[^\p{L}\p{Nd}\p{Zs}]/u, {
+ message:
+ "Valid style strings contain only letters, numbers, and whitespace characters.",
+ })
+ .min(1)
+ .max(25)
+ .describe(
+ 'A style string for this listing, such as "Formal", or "Steampunk". When creating or updating a listing, the listing may have up to two styles. Valid style strings contain only letters, numbers, and whitespace characters.',
+ ),
+ )
+ .max(2)
+ .describe("An array of style strings for this listing."),
+ item_weight: z
+ .number()
+ .positive()
+ .optional()
+ .describe(
+ "The numeric weight of the product measured in units set in 'item_weight_unit'. If set, the values must be greater than 0.",
+ ),
+ item_length: z
+ .number()
+ .positive()
+ .optional()
+ .describe(
+ "The numeric length of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.",
+ ),
+ item_width: z
+ .number()
+ .positive()
+ .optional()
+ .describe(
+ "The numeric width of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.",
+ ),
+ item_height: z
+ .number()
+ .positive()
+ .optional()
+ .describe(
+ "The numeric height of the product measured in units set in 'item_dimensions_unit'. If set, the values must be greater than 0.",
+ ),
+ item_weight_unit: z
+ .enum(["g", "kg", "oz", "lb"])
+ .optional()
+ .describe(
+ "The unit of measurement for the weight of the product. Valid values are 'g' (grams), 'kg' (kilograms), 'oz' (ounces), and 'lb' (pounds). Required if 'item_weight' is provided.",
+ ),
+ item_dimensions_unit: z
+ .enum(["mm", "cm", "m", "in", "ft"])
+ .optional()
+ .describe(
+ "The unit of measurement for the dimensions of the product. Valid values are 'mm' (millimeters), 'cm' (centimeters), 'm' (meters), 'in' (inches), and 'ft' (feet). Required if any of 'item_length', 'item_width', or 'item_height' is provided.",
+ ),
+ is_personalizable: z
+ .boolean()
+ .optional()
+ .describe("When true, indicates that the listing is personalizable."),
+ personalization_is_required: z
+ .boolean()
+ .optional()
+ .describe(
+ "When true, indicates that personalization is required for the listing. Will only change if _is_personalizable is true",
+ ),
+ personalization_char_count_max: z
+ .number()
+ .int()
+ .min(1)
+ .max(250)
+ .optional()
+ .describe(
+ "The maximum number of characters allowed for personalization. Will only change if _is_personalizable is true.",
+ ),
+ personalization_instructions: z
+ .string()
+ .max(500)
+ .optional()
+ .describe(
+ "Instructions for personalization. Will only change if _is_personalizable is true.",
+ ),
+ production_partner_ids: z
+ .array(
+ z
+ .number()
+ .int()
+ .positive()
+ .describe("A unique ID of a production partner."),
+ )
+ .optional()
+ .describe("An array of unique IDs of production partner ids."),
+ image_ids: z
+ .array(
+ z
+ .number()
+ .int()
+ .positive()
+ .describe("A numeric image ID of an image in a listing."),
+ )
+ .max(10)
+ .optional()
+ .describe(
+ "An array of numeric image IDs of the images in a listing, which can include up to 10 images.",
+ ),
+ is_customizable: z
+ .boolean()
+ .optional()
+ .describe(
+ "When true, a buyer may contact the seller for a customized order. The default value is true when a shop accepts custom orders. Does not apply to shops that do not accept custom orders.",
+ ),
+ should_auto_renew: z
+ .boolean()
+ .optional()
+ .describe("When true, renews a listing for four months upon expiration."),
+ is_taxable: z
+ .boolean()
+ .optional()
+ .describe(
+ "When true, applicable shop tax rates apply to this listing at checkout",
+ ),
+ type: z
+ .enum(["physical", "download", "both"])
+ .describe(
+ "An enumerated type string that indicates whether the listing is physical or a digital download or both.",
+ ),
+ }),
+ outputSchema: z.object({
+ result: z.customListing
+