@keystrokehq/shopify 0.0.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 (46) hide show
  1. package/README.md +178 -0
  2. package/dist/_official/index.d.mts +3 -0
  3. package/dist/_official/index.mjs +3 -0
  4. package/dist/_runtime/index.d.mts +56 -0
  5. package/dist/_runtime/index.mjs +3 -0
  6. package/dist/articles.d.mts +174 -0
  7. package/dist/articles.mjs +252 -0
  8. package/dist/blogs.d.mts +113 -0
  9. package/dist/blogs.mjs +174 -0
  10. package/dist/client.d.mts +22 -0
  11. package/dist/client.mjs +90 -0
  12. package/dist/collections.d.mts +140 -0
  13. package/dist/collections.mjs +209 -0
  14. package/dist/connection.d.mts +2 -0
  15. package/dist/connection.mjs +3 -0
  16. package/dist/customers.d.mts +161 -0
  17. package/dist/customers.mjs +225 -0
  18. package/dist/events.d.mts +181 -0
  19. package/dist/events.mjs +67 -0
  20. package/dist/factory-DC-gY8L0.mjs +8 -0
  21. package/dist/fulfillments.d.mts +99 -0
  22. package/dist/fulfillments.mjs +167 -0
  23. package/dist/index.d.mts +1 -0
  24. package/dist/index.mjs +1 -0
  25. package/dist/integration-BN3pjCz4.mjs +204 -0
  26. package/dist/integration-BwDBsGX-.d.mts +71 -0
  27. package/dist/inventory.d.mts +103 -0
  28. package/dist/inventory.mjs +182 -0
  29. package/dist/locations.d.mts +47 -0
  30. package/dist/locations.mjs +81 -0
  31. package/dist/messaging.d.mts +1 -0
  32. package/dist/messaging.mjs +1 -0
  33. package/dist/operation-helpers-CKEDIx0o.mjs +21 -0
  34. package/dist/orders.d.mts +229 -0
  35. package/dist/orders.mjs +271 -0
  36. package/dist/products.d.mts +155 -0
  37. package/dist/products.mjs +171 -0
  38. package/dist/provider-app-DHxVZI6q.d.mts +37 -0
  39. package/dist/schemas.d.mts +233 -0
  40. package/dist/schemas.mjs +164 -0
  41. package/dist/shop.d.mts +20 -0
  42. package/dist/shop.mjs +31 -0
  43. package/dist/triggers.d.mts +23 -0
  44. package/dist/triggers.mjs +138 -0
  45. package/dist/webhook-management-BmIxO0vr.mjs +150 -0
  46. package/package.json +130 -0
@@ -0,0 +1,204 @@
1
+ import { defineOfficialIntegration } from "@keystrokehq/integration-authoring/official";
2
+ import { z } from "zod";
3
+ import { CredentialSet } from "@keystrokehq/core";
4
+ import { createHmac, timingSafeEqual } from "node:crypto";
5
+ import { TokenExchangeError, normalizeOAuthTokens, parseOAuthTokenResponse } from "@keystrokehq/credential-connection";
6
+
7
+ //#region src/_official/provider-app.ts
8
+ const shopifyAppCredentialSet = new CredentialSet({
9
+ id: "shopify-app",
10
+ exposure: "platform-only",
11
+ name: "Shopify App",
12
+ auth: z.object({
13
+ clientId: z.string(),
14
+ clientSecret: z.string(),
15
+ webhookSecret: z.string()
16
+ })
17
+ });
18
+ const shopifyPlatformProviderSeed = {
19
+ provider: "shopify",
20
+ appRef: "shopify-platform",
21
+ displayName: "Shopify Platform",
22
+ credentialSetName: "Keystroke Shopify Platform App",
23
+ envShape: {
24
+ KEYSTROKE_PLATFORM_SHOPIFY_APP_ID: z.string().optional(),
25
+ KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_ID: z.string().optional(),
26
+ KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_SECRET: z.string().optional(),
27
+ KEYSTROKE_PLATFORM_SHOPIFY_WEBHOOK_SECRET: z.string().optional()
28
+ },
29
+ requiredEnvKeys: [
30
+ "KEYSTROKE_PLATFORM_SHOPIFY_APP_ID",
31
+ "KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_ID",
32
+ "KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_SECRET",
33
+ "KEYSTROKE_PLATFORM_SHOPIFY_WEBHOOK_SECRET"
34
+ ],
35
+ externalAppIdEnvKey: "KEYSTROKE_PLATFORM_SHOPIFY_APP_ID",
36
+ buildCredentials: (env) => ({
37
+ clientId: env.KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_ID,
38
+ clientSecret: env.KEYSTROKE_PLATFORM_SHOPIFY_CLIENT_SECRET,
39
+ webhookSecret: env.KEYSTROKE_PLATFORM_SHOPIFY_WEBHOOK_SECRET
40
+ })
41
+ };
42
+
43
+ //#endregion
44
+ //#region src/oauth-connection.ts
45
+ /**
46
+ * Shopify OAuth connection configuration.
47
+ *
48
+ * Shopify's OAuth flow is per-shop: every handshake is scoped to a specific
49
+ * `{shop}.myshopify.com` domain that the user supplies up front. That shop
50
+ * domain shows up in three places that make Shopify different from a plain
51
+ * OAuth 2.0 integration:
52
+ *
53
+ * - `buildAuthUrl` must point at the shop-specific authorize endpoint at
54
+ * `https://{shop}.myshopify.com/admin/oauth/authorize`. The shop domain is
55
+ * threaded in from the initiate-connection request via `initiateInput`.
56
+ * - `exchangeCode` verifies the Shopify HMAC signature on the callback query
57
+ * string before trusting any of it, and POSTs to the same shop-specific
58
+ * token endpoint. HMAC verification uses `timingSafeEqual` to avoid leaking
59
+ * bytes through timing side channels.
60
+ * - `refreshToken` reads the shop domain out of `oauthClient.metadata` (set
61
+ * during the initial exchange) so proactive refreshes still target the
62
+ * right store, and the `vault` mapping promotes the shop domain into
63
+ * `SHOPIFY_STORE_DOMAIN` so the vault has both the access token and the
64
+ * store it belongs to.
65
+ *
66
+ * Shopify responds with JSON, so we reuse `parseOAuthTokenResponse` +
67
+ * `normalizeOAuthTokens` from `@keystrokehq/credential-connection` to avoid reimplementing
68
+ * the token-response plumbing.
69
+ */
70
+ function normalizeShopifyShopDomain(raw) {
71
+ const trimmed = raw?.trim().toLowerCase();
72
+ if (!trimmed) throw new Error("Shopify requires a store domain.");
73
+ const normalized = trimmed.endsWith(".myshopify.com") ? trimmed : `${trimmed}.myshopify.com`;
74
+ if (!/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/i.test(normalized)) throw new Error("Invalid Shopify store domain.");
75
+ return normalized;
76
+ }
77
+ function verifyShopifyCallbackHmac(queryParams, clientSecret) {
78
+ const receivedHmac = queryParams.hmac;
79
+ if (!receivedHmac) return false;
80
+ const canonical = Object.entries(queryParams).filter(([key]) => key !== "hmac" && key !== "signature").sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `${key}=${value}`).join("&");
81
+ const expected = createHmac("sha256", clientSecret).update(canonical).digest("hex");
82
+ const received = Buffer.from(receivedHmac, "utf8");
83
+ const expectedBuffer = Buffer.from(expected, "utf8");
84
+ if (received.length !== expectedBuffer.length) return false;
85
+ return timingSafeEqual(received, expectedBuffer);
86
+ }
87
+ function resolveShopifyTokenUrl(shopDomain) {
88
+ return `https://${shopDomain}/admin/oauth/access_token`;
89
+ }
90
+ async function shopifyTokenPost(shopDomain, body, missingTokenError) {
91
+ const response = await fetch(resolveShopifyTokenUrl(shopDomain), {
92
+ method: "POST",
93
+ headers: {
94
+ Accept: "application/json",
95
+ "Content-Type": "application/json"
96
+ },
97
+ body: JSON.stringify(body)
98
+ });
99
+ if (!response.ok) throw new TokenExchangeError(response.status);
100
+ const raw = await parseOAuthTokenResponse(response);
101
+ raw._shopifyShopDomain = shopDomain;
102
+ const { accessToken, refreshToken, expiresIn } = normalizeOAuthTokens(raw);
103
+ if (!accessToken) throw new Error(missingTokenError);
104
+ return {
105
+ accessToken,
106
+ refreshToken,
107
+ expiresIn,
108
+ raw
109
+ };
110
+ }
111
+ const shopifyOAuthConnection = {
112
+ kind: "oauth",
113
+ tokenType: "refreshable",
114
+ authUrl: "https://{shop}.myshopify.com/admin/oauth/authorize",
115
+ tokenUrl: "https://{shop}.myshopify.com/admin/oauth/access_token",
116
+ revokeUrl: null,
117
+ scopes: [
118
+ "read_products",
119
+ "write_products",
120
+ "read_orders",
121
+ "write_orders",
122
+ "read_customers",
123
+ "write_customers",
124
+ "read_inventory",
125
+ "write_inventory",
126
+ "read_locations",
127
+ "read_fulfillments",
128
+ "write_fulfillments",
129
+ "read_content",
130
+ "write_content",
131
+ "read_webhooks",
132
+ "write_webhooks"
133
+ ],
134
+ vault: {
135
+ accessToken: "SHOPIFY_ACCESS_TOKEN",
136
+ raw: { SHOPIFY_STORE_DOMAIN: "_shopifyShopDomain" }
137
+ },
138
+ buildAuthUrl({ oauthClient, redirectUri, state, connection, initiateInput, requestedScopes }) {
139
+ const rawShopDomain = initiateInput?.shopDomain;
140
+ if (typeof rawShopDomain !== "string") throw new Error("Shopify requires a store domain.");
141
+ const scopes = requestedScopes ?? connection.scopes;
142
+ const shopDomain = normalizeShopifyShopDomain(rawShopDomain);
143
+ const url = new URL(`https://${shopDomain}/admin/oauth/authorize`);
144
+ url.searchParams.set("client_id", oauthClient.clientId);
145
+ url.searchParams.set("scope", scopes.join(","));
146
+ url.searchParams.set("redirect_uri", redirectUri);
147
+ url.searchParams.set("state", state);
148
+ return url.toString();
149
+ },
150
+ async exchangeCode({ oauthClient, code, queryParams }) {
151
+ if (!code) throw new Error("Missing authorization code");
152
+ const shopDomain = normalizeShopifyShopDomain(queryParams.shop);
153
+ if (!verifyShopifyCallbackHmac(queryParams, oauthClient.clientSecret)) throw new Error("Invalid Shopify OAuth callback signature");
154
+ return shopifyTokenPost(shopDomain, {
155
+ client_id: oauthClient.clientId,
156
+ client_secret: oauthClient.clientSecret,
157
+ code
158
+ }, "No access token in Shopify response");
159
+ },
160
+ async refreshToken({ oauthClient, refreshToken }) {
161
+ const rawShopDomain = oauthClient.metadata?.shopDomain;
162
+ if (typeof rawShopDomain !== "string") throw new Error("Missing Shopify store domain for token refresh.");
163
+ return shopifyTokenPost(normalizeShopifyShopDomain(rawShopDomain), {
164
+ grant_type: "refresh_token",
165
+ refresh_token: refreshToken,
166
+ client_id: oauthClient.clientId,
167
+ client_secret: oauthClient.clientSecret
168
+ }, "No access token in Shopify refresh response");
169
+ },
170
+ extractInstallationInfo({ tokenResult }) {
171
+ const shopDomain = typeof tokenResult.raw._shopifyShopDomain === "string" ? tokenResult.raw._shopifyShopDomain : void 0;
172
+ return {
173
+ externalInstallationId: shopDomain,
174
+ externalWorkspaceId: shopDomain,
175
+ metadata: shopDomain ? { shopDomain } : void 0
176
+ };
177
+ }
178
+ };
179
+
180
+ //#endregion
181
+ //#region src/integration.ts
182
+ const shopifyStoreDomainSchema = z.string().min(1).regex(/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/i, "Shopify store domain must look like \"example.myshopify.com\".");
183
+ const shopifyAuthSchema = z.object({
184
+ SHOPIFY_STORE_DOMAIN: shopifyStoreDomainSchema,
185
+ SHOPIFY_ACCESS_TOKEN: z.string().min(1)
186
+ });
187
+ const shopifyOfficialIntegration = {
188
+ id: "shopify",
189
+ name: "Shopify",
190
+ description: "Shopify Admin API — stores, products, orders, customers, and webhooks",
191
+ auth: shopifyAuthSchema,
192
+ connections: [{
193
+ id: "oauth",
194
+ ...shopifyOAuthConnection
195
+ }]
196
+ };
197
+ const shopifyBundle = defineOfficialIntegration({
198
+ ...shopifyOfficialIntegration,
199
+ internal: { providerApp: shopifyAppCredentialSet }
200
+ });
201
+ const shopify = shopifyBundle.credentialSet;
202
+
203
+ //#endregion
204
+ export { shopifyAppCredentialSet as a, shopifyStoreDomainSchema as i, shopifyBundle as n, shopifyPlatformProviderSeed as o, shopifyOfficialIntegration as r, shopify as t };
@@ -0,0 +1,71 @@
1
+ import * as _keystrokehq_integration_authoring_official0 from "@keystrokehq/integration-authoring/official";
2
+ import { z } from "zod";
3
+ import * as _keystrokehq_core0 from "@keystrokehq/core";
4
+ import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
5
+ import { InferCredentialSetAuth } from "@keystrokehq/core/credential-set";
6
+
7
+ //#region src/integration.d.ts
8
+ declare const shopifyOfficialIntegration: {
9
+ id: "shopify";
10
+ name: string;
11
+ description: string;
12
+ auth: z.ZodObject<{
13
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
14
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
15
+ }, z.core.$strip>;
16
+ connections: {
17
+ kind: "oauth";
18
+ tokenType: "refreshable";
19
+ authUrl: "https://{shop}.myshopify.com/admin/oauth/authorize";
20
+ tokenUrl: "https://{shop}.myshopify.com/admin/oauth/access_token";
21
+ revokeUrl: null;
22
+ scopes: readonly ["read_products", "write_products", "read_orders", "write_orders", "read_customers", "write_customers", "read_inventory", "write_inventory", "read_locations", "read_fulfillments", "write_fulfillments", "read_content", "write_content", "read_webhooks", "write_webhooks"];
23
+ vault: {
24
+ readonly accessToken: "SHOPIFY_ACCESS_TOKEN";
25
+ readonly raw: {
26
+ readonly SHOPIFY_STORE_DOMAIN: "_shopifyShopDomain";
27
+ };
28
+ };
29
+ buildAuthUrl: ({
30
+ oauthClient,
31
+ redirectUri,
32
+ state,
33
+ connection,
34
+ initiateInput,
35
+ requestedScopes
36
+ }: _keystrokehq_core_credential_set0.BuildAuthUrlContext) => string;
37
+ exchangeCode: ({
38
+ oauthClient,
39
+ code,
40
+ queryParams
41
+ }: _keystrokehq_core_credential_set0.ExchangeCodeContext) => Promise<_keystrokehq_core_credential_set0.TokenResult>;
42
+ refreshToken: ({
43
+ oauthClient,
44
+ refreshToken
45
+ }: _keystrokehq_core_credential_set0.RefreshTokenContext) => Promise<_keystrokehq_core_credential_set0.TokenResult>;
46
+ extractInstallationInfo: ({
47
+ tokenResult
48
+ }: _keystrokehq_core_credential_set0.ExtractInstallationContext) => {
49
+ externalInstallationId: string | undefined;
50
+ externalWorkspaceId: string | undefined;
51
+ metadata: {
52
+ shopDomain: string;
53
+ } | undefined;
54
+ };
55
+ id: string;
56
+ }[];
57
+ };
58
+ declare const shopifyBundle: _keystrokehq_integration_authoring_official0.OfficialIntegrationBundle<"shopify", z.ZodObject<{
59
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
60
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
61
+ }, z.core.$strip>>;
62
+ declare const shopify: _keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
63
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
64
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
65
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
66
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
67
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
68
+ }, z.core.$strip>>[] | undefined>;
69
+ type ShopifyCredentials = InferCredentialSetAuth<typeof shopify>;
70
+ //#endregion
71
+ export { shopifyOfficialIntegration as i, shopify as n, shopifyBundle as r, ShopifyCredentials as t };
@@ -0,0 +1,103 @@
1
+ import { z } from "zod";
2
+ import * as _keystrokehq_core0 from "@keystrokehq/core";
3
+ import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
4
+
5
+ //#region src/inventory.d.ts
6
+ declare const listInventoryItems: _keystrokehq_core0.Operation<z.ZodObject<{
7
+ first: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
8
+ after: z.ZodOptional<z.ZodString>;
9
+ query: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strip>, z.ZodObject<{
11
+ nodes: z.ZodArray<z.ZodObject<{
12
+ id: z.ZodString;
13
+ sku: z.ZodOptional<z.ZodNullable<z.ZodString>>;
14
+ tracked: z.ZodOptional<z.ZodBoolean>;
15
+ }, z.core.$strip>>;
16
+ pageInfo: z.ZodObject<{
17
+ hasNextPage: z.ZodBoolean;
18
+ hasPreviousPage: z.ZodOptional<z.ZodBoolean>;
19
+ startCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
20
+ endCursor: z.ZodNullable<z.ZodString>;
21
+ }, z.core.$strip>;
22
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
23
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
24
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
25
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
26
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
27
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
28
+ }, z.core.$strip>>[] | undefined>], undefined>;
29
+ declare const getInventoryItem: _keystrokehq_core0.Operation<z.ZodObject<{
30
+ id: z.ZodString;
31
+ }, z.core.$strip>, z.ZodObject<{
32
+ id: z.ZodString;
33
+ sku: z.ZodOptional<z.ZodNullable<z.ZodString>>;
34
+ tracked: z.ZodOptional<z.ZodBoolean>;
35
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
36
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
37
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
38
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
39
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
40
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
41
+ }, z.core.$strip>>[] | undefined>], undefined>;
42
+ declare const getInventoryLevelsForItem: _keystrokehq_core0.Operation<z.ZodObject<{
43
+ inventoryItemId: z.ZodString;
44
+ first: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
45
+ after: z.ZodOptional<z.ZodString>;
46
+ }, z.core.$strip>, z.ZodObject<{
47
+ nodes: z.ZodArray<z.ZodObject<{
48
+ id: z.ZodString;
49
+ quantities: z.ZodArray<z.ZodObject<{
50
+ name: z.ZodString;
51
+ quantity: z.ZodNumber;
52
+ }, z.core.$strip>>;
53
+ item: z.ZodOptional<z.ZodObject<{
54
+ id: z.ZodString;
55
+ sku: z.ZodOptional<z.ZodNullable<z.ZodString>>;
56
+ tracked: z.ZodOptional<z.ZodBoolean>;
57
+ }, z.core.$strip>>;
58
+ location: z.ZodOptional<z.ZodObject<{
59
+ id: z.ZodString;
60
+ name: z.ZodString;
61
+ isActive: z.ZodOptional<z.ZodBoolean>;
62
+ fulfillsOnlineOrders: z.ZodOptional<z.ZodBoolean>;
63
+ }, z.core.$strip>>;
64
+ }, z.core.$strip>>;
65
+ pageInfo: z.ZodObject<{
66
+ hasNextPage: z.ZodBoolean;
67
+ hasPreviousPage: z.ZodOptional<z.ZodBoolean>;
68
+ startCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
69
+ endCursor: z.ZodNullable<z.ZodString>;
70
+ }, z.core.$strip>;
71
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
72
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
73
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
74
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
75
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
76
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
77
+ }, z.core.$strip>>[] | undefined>], undefined>;
78
+ declare const adjustInventoryQuantities: _keystrokehq_core0.Operation<z.ZodObject<{
79
+ name: z.ZodDefault<z.ZodString>;
80
+ reason: z.ZodString;
81
+ referenceDocumentUri: z.ZodOptional<z.ZodString>;
82
+ changes: z.ZodArray<z.ZodObject<{
83
+ inventoryItemId: z.ZodString;
84
+ locationId: z.ZodString;
85
+ delta: z.ZodNumber;
86
+ }, z.core.$strip>>;
87
+ }, z.core.$strip>, z.ZodObject<{
88
+ createdAt: z.ZodOptional<z.ZodISODateTime>;
89
+ reason: z.ZodString;
90
+ referenceDocumentUri: z.ZodOptional<z.ZodNullable<z.ZodString>>;
91
+ changes: z.ZodArray<z.ZodObject<{
92
+ name: z.ZodString;
93
+ delta: z.ZodNumber;
94
+ }, z.core.$strip>>;
95
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
96
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
97
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
98
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
99
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
100
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
101
+ }, z.core.$strip>>[] | undefined>], undefined>;
102
+ //#endregion
103
+ export { adjustInventoryQuantities, getInventoryItem, getInventoryLevelsForItem, listInventoryItems };
@@ -0,0 +1,182 @@
1
+ import { shopifyConnectionNodesSchema, shopifyGlobalIdSchema, shopifyInventoryItemSchema, shopifyInventoryLevelSchema, shopifyUserErrorSchema } from "./schemas.mjs";
2
+ import { createShopifyClient } from "./client.mjs";
3
+ import { t as shopifyOperation } from "./factory-DC-gY8L0.mjs";
4
+ import { r as shopifyPageInputSchema, t as assertNoUserErrors } from "./operation-helpers-CKEDIx0o.mjs";
5
+ import { z } from "zod";
6
+
7
+ //#region src/inventory.ts
8
+ const inventoryItemSelection = `
9
+ id
10
+ sku
11
+ tracked
12
+ `;
13
+ const inventoryLevelSelection = `
14
+ id
15
+ quantities(names: ["available", "committed", "incoming", "on_hand", "reserved"]) {
16
+ name
17
+ quantity
18
+ }
19
+ item {
20
+ ${inventoryItemSelection}
21
+ }
22
+ location {
23
+ id
24
+ name
25
+ isActive
26
+ fulfillsOnlineOrders
27
+ }
28
+ `;
29
+ const listInventoryItemsResponseSchema = z.object({ inventoryItems: shopifyConnectionNodesSchema(shopifyInventoryItemSchema) });
30
+ const getInventoryItemResponseSchema = z.object({ inventoryItem: shopifyInventoryItemSchema.nullable() });
31
+ const inventoryLevelsResponseSchema = z.object({ inventoryItem: z.object({ inventoryLevels: shopifyConnectionNodesSchema(shopifyInventoryLevelSchema) }).nullable() });
32
+ const inventoryAdjustmentResponseSchema = z.object({
33
+ inventoryAdjustmentGroup: z.object({
34
+ createdAt: z.iso.datetime().optional(),
35
+ reason: z.string(),
36
+ referenceDocumentUri: z.string().nullable().optional(),
37
+ changes: z.array(z.object({
38
+ name: z.string(),
39
+ delta: z.number()
40
+ }))
41
+ }).nullable(),
42
+ userErrors: z.array(shopifyUserErrorSchema)
43
+ });
44
+ const listInventoryItems = shopifyOperation({
45
+ id: "list_shopify_inventory_items",
46
+ name: "List Shopify Inventory Items",
47
+ description: "List inventory items from the connected Shopify store.",
48
+ input: shopifyPageInputSchema,
49
+ output: shopifyConnectionNodesSchema(shopifyInventoryItemSchema),
50
+ run: async (input, credentials) => {
51
+ return (await createShopifyClient(credentials).graphql(`
52
+ query ListInventoryItems($first: Int!, $after: String, $query: String) {
53
+ inventoryItems(first: $first, after: $after, query: $query) {
54
+ nodes {
55
+ ${inventoryItemSelection}
56
+ }
57
+ pageInfo {
58
+ hasNextPage
59
+ hasPreviousPage
60
+ startCursor
61
+ endCursor
62
+ }
63
+ }
64
+ }
65
+ `, listInventoryItemsResponseSchema, { variables: {
66
+ first: input.first,
67
+ ...input.after ? { after: input.after } : {},
68
+ ...input.query ? { query: input.query } : {}
69
+ } })).inventoryItems;
70
+ }
71
+ });
72
+ const getInventoryItem = shopifyOperation({
73
+ id: "get_shopify_inventory_item",
74
+ name: "Get Shopify Inventory Item",
75
+ description: "Retrieve a single Shopify inventory item by its global ID.",
76
+ input: z.object({ id: shopifyGlobalIdSchema }),
77
+ output: shopifyInventoryItemSchema,
78
+ run: async (input, credentials) => {
79
+ const response = await createShopifyClient(credentials).graphql(`
80
+ query GetInventoryItem($id: ID!) {
81
+ inventoryItem(id: $id) {
82
+ ${inventoryItemSelection}
83
+ }
84
+ }
85
+ `, getInventoryItemResponseSchema, { variables: { id: input.id } });
86
+ if (!response.inventoryItem) throw new Error(`Shopify inventory item not found: ${input.id}`);
87
+ return response.inventoryItem;
88
+ }
89
+ });
90
+ const getInventoryLevelsForItem = shopifyOperation({
91
+ id: "get_shopify_inventory_levels_for_item",
92
+ name: "Get Shopify Inventory Levels For Item",
93
+ description: "Retrieve inventory levels for a specific Shopify inventory item.",
94
+ input: z.object({
95
+ inventoryItemId: shopifyGlobalIdSchema,
96
+ first: z.number().int().min(1).max(100).optional().default(25),
97
+ after: z.string().optional()
98
+ }),
99
+ output: shopifyConnectionNodesSchema(shopifyInventoryLevelSchema),
100
+ run: async (input, credentials) => {
101
+ const response = await createShopifyClient(credentials).graphql(`
102
+ query GetInventoryLevelsForItem($id: ID!, $first: Int!, $after: String) {
103
+ inventoryItem(id: $id) {
104
+ inventoryLevels(first: $first, after: $after) {
105
+ nodes {
106
+ ${inventoryLevelSelection}
107
+ }
108
+ pageInfo {
109
+ hasNextPage
110
+ hasPreviousPage
111
+ startCursor
112
+ endCursor
113
+ }
114
+ }
115
+ }
116
+ }
117
+ `, inventoryLevelsResponseSchema, { variables: {
118
+ id: input.inventoryItemId,
119
+ first: input.first,
120
+ ...input.after ? { after: input.after } : {}
121
+ } });
122
+ if (!response.inventoryItem) throw new Error(`Shopify inventory item not found for inventory levels lookup: ${input.inventoryItemId}`);
123
+ return response.inventoryItem.inventoryLevels;
124
+ }
125
+ });
126
+ const adjustInventoryQuantities = shopifyOperation({
127
+ id: "adjust_shopify_inventory_quantities",
128
+ name: "Adjust Shopify Inventory Quantities",
129
+ description: "Adjust inventory quantities at specific Shopify locations.",
130
+ needsApproval: true,
131
+ input: z.object({
132
+ name: z.string().min(1).default("available"),
133
+ reason: z.string().min(1),
134
+ referenceDocumentUri: z.string().optional(),
135
+ changes: z.array(z.object({
136
+ inventoryItemId: shopifyGlobalIdSchema,
137
+ locationId: shopifyGlobalIdSchema,
138
+ delta: z.number().int()
139
+ })).min(1)
140
+ }),
141
+ output: z.object({
142
+ createdAt: z.iso.datetime().optional(),
143
+ reason: z.string(),
144
+ referenceDocumentUri: z.string().nullable().optional(),
145
+ changes: z.array(z.object({
146
+ name: z.string(),
147
+ delta: z.number()
148
+ }))
149
+ }),
150
+ run: async (input, credentials) => {
151
+ const response = await createShopifyClient(credentials).graphql(`
152
+ mutation AdjustInventoryQuantities($input: InventoryAdjustQuantitiesInput!) {
153
+ inventoryAdjustQuantities(input: $input) {
154
+ inventoryAdjustmentGroup {
155
+ createdAt
156
+ reason
157
+ referenceDocumentUri
158
+ changes {
159
+ name
160
+ delta
161
+ }
162
+ }
163
+ userErrors {
164
+ field
165
+ message
166
+ }
167
+ }
168
+ }
169
+ `, z.object({ inventoryAdjustQuantities: inventoryAdjustmentResponseSchema }), { variables: { input: {
170
+ name: input.name,
171
+ reason: input.reason,
172
+ referenceDocumentUri: input.referenceDocumentUri,
173
+ changes: input.changes
174
+ } } });
175
+ assertNoUserErrors(response.inventoryAdjustQuantities.userErrors);
176
+ if (!response.inventoryAdjustQuantities.inventoryAdjustmentGroup) throw new Error("Shopify did not return the inventory adjustment group.");
177
+ return response.inventoryAdjustQuantities.inventoryAdjustmentGroup;
178
+ }
179
+ });
180
+
181
+ //#endregion
182
+ export { adjustInventoryQuantities, getInventoryItem, getInventoryLevelsForItem, listInventoryItems };
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ import * as _keystrokehq_core0 from "@keystrokehq/core";
3
+ import * as _keystrokehq_core_credential_set0 from "@keystrokehq/core/credential-set";
4
+
5
+ //#region src/locations.d.ts
6
+ declare const listLocations: _keystrokehq_core0.Operation<z.ZodObject<{
7
+ first: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
8
+ after: z.ZodOptional<z.ZodString>;
9
+ query: z.ZodOptional<z.ZodString>;
10
+ includeInactive: z.ZodOptional<z.ZodBoolean>;
11
+ includeLegacy: z.ZodOptional<z.ZodBoolean>;
12
+ }, z.core.$strip>, z.ZodObject<{
13
+ nodes: z.ZodArray<z.ZodObject<{
14
+ id: z.ZodString;
15
+ name: z.ZodString;
16
+ isActive: z.ZodOptional<z.ZodBoolean>;
17
+ fulfillsOnlineOrders: z.ZodOptional<z.ZodBoolean>;
18
+ }, z.core.$strip>>;
19
+ pageInfo: z.ZodObject<{
20
+ hasNextPage: z.ZodBoolean;
21
+ hasPreviousPage: z.ZodOptional<z.ZodBoolean>;
22
+ startCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
23
+ endCursor: z.ZodNullable<z.ZodString>;
24
+ }, z.core.$strip>;
25
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
26
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
27
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
28
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
29
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
30
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
31
+ }, z.core.$strip>>[] | undefined>], undefined>;
32
+ declare const getLocation: _keystrokehq_core0.Operation<z.ZodObject<{
33
+ id: z.ZodString;
34
+ }, z.core.$strip>, z.ZodObject<{
35
+ id: z.ZodString;
36
+ name: z.ZodString;
37
+ isActive: z.ZodOptional<z.ZodBoolean>;
38
+ fulfillsOnlineOrders: z.ZodOptional<z.ZodBoolean>;
39
+ }, z.core.$strip>, readonly [_keystrokehq_core0.CredentialSet<"shopify", z.ZodObject<{
40
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
41
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
42
+ }, z.core.$strip>, readonly _keystrokehq_core_credential_set0.CredentialConnection<z.ZodObject<{
43
+ SHOPIFY_STORE_DOMAIN: z.ZodString;
44
+ SHOPIFY_ACCESS_TOKEN: z.ZodString;
45
+ }, z.core.$strip>>[] | undefined>], undefined>;
46
+ //#endregion
47
+ export { getLocation, listLocations };
@@ -0,0 +1,81 @@
1
+ import { shopifyConnectionNodesSchema, shopifyGlobalIdSchema, shopifyLocationSchema } from "./schemas.mjs";
2
+ import { createShopifyClient } from "./client.mjs";
3
+ import { t as shopifyOperation } from "./factory-DC-gY8L0.mjs";
4
+ import { r as shopifyPageInputSchema } from "./operation-helpers-CKEDIx0o.mjs";
5
+ import { z } from "zod";
6
+
7
+ //#region src/locations.ts
8
+ const locationSelection = `
9
+ id
10
+ name
11
+ isActive
12
+ fulfillsOnlineOrders
13
+ `;
14
+ const listLocationsResponseSchema = z.object({ locations: shopifyConnectionNodesSchema(shopifyLocationSchema) });
15
+ const getLocationResponseSchema = z.object({ location: shopifyLocationSchema.nullable() });
16
+ const listLocations = shopifyOperation({
17
+ id: "list_shopify_locations",
18
+ name: "List Shopify Locations",
19
+ description: "List locations from the connected Shopify store.",
20
+ input: shopifyPageInputSchema.extend({
21
+ includeInactive: z.boolean().optional(),
22
+ includeLegacy: z.boolean().optional()
23
+ }),
24
+ output: shopifyConnectionNodesSchema(shopifyLocationSchema),
25
+ run: async (input, credentials) => {
26
+ return (await createShopifyClient(credentials).graphql(`
27
+ query ListLocations(
28
+ $first: Int!
29
+ $after: String
30
+ $query: String
31
+ $includeInactive: Boolean
32
+ $includeLegacy: Boolean
33
+ ) {
34
+ locations(
35
+ first: $first
36
+ after: $after
37
+ query: $query
38
+ includeInactive: $includeInactive
39
+ includeLegacy: $includeLegacy
40
+ ) {
41
+ nodes {
42
+ ${locationSelection}
43
+ }
44
+ pageInfo {
45
+ hasNextPage
46
+ hasPreviousPage
47
+ startCursor
48
+ endCursor
49
+ }
50
+ }
51
+ }
52
+ `, listLocationsResponseSchema, { variables: {
53
+ first: input.first,
54
+ ...input.after ? { after: input.after } : {},
55
+ ...input.query ? { query: input.query } : {},
56
+ ...input.includeInactive !== void 0 ? { includeInactive: input.includeInactive } : {},
57
+ ...input.includeLegacy !== void 0 ? { includeLegacy: input.includeLegacy } : {}
58
+ } })).locations;
59
+ }
60
+ });
61
+ const getLocation = shopifyOperation({
62
+ id: "get_shopify_location",
63
+ name: "Get Shopify Location",
64
+ description: "Retrieve a single Shopify location by its global ID.",
65
+ input: z.object({ id: shopifyGlobalIdSchema }),
66
+ output: shopifyLocationSchema,
67
+ run: async (input, credentials) => {
68
+ const response = await createShopifyClient(credentials).graphql(`
69
+ query GetLocation($id: ID!) {
70
+ location(id: $id) {
71
+ ${locationSelection}
72
+ }
73
+ }
74
+ `, getLocationResponseSchema, { variables: { id: input.id } });
75
+ if (!response.location) throw new Error(`Shopify location not found: ${input.id}`);
76
+ return response.location;
77
+ }
78
+ });
79
+
80
+ //#endregion
81
+ export { getLocation, listLocations };