@useairfoil/producer-shopify 0.0.1 → 0.2.0
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.
- package/README.md +255 -0
- package/dist/chunk-Bp6m_JJh.js +13 -0
- package/dist/index.d.ts +965 -0
- package/dist/index.js +4 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +49 -0
- package/dist/main.js.map +1 -0
- package/dist/manifest-BFfx2LkS.js +91 -0
- package/dist/manifest-BFfx2LkS.js.map +1 -0
- package/dist/manifest-CPOEExQU.d.ts +34 -0
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +3 -0
- package/dist/src-DqmiLrYS.js +984 -0
- package/dist/src-DqmiLrYS.js.map +1 -0
- package/package.json +45 -7
- package/src/api.ts +636 -0
- package/src/auth.ts +116 -0
- package/src/connector.ts +268 -0
- package/src/index.ts +36 -0
- package/src/main.ts +20 -0
- package/src/manifest.ts +86 -0
- package/src/sandbox.ts +38 -0
- package/src/schemas.ts +319 -0
- package/src/start.ts +52 -0
- package/src/throttle.ts +89 -0
- package/src/transient-retry.ts +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-DqmiLrYS.js","names":["make","layer","Schema","backoff","make","ShopifyAuth.ShopifyAuth","TransientRetry.withTransientRetry","Throttle.retryableErrorCode","Throttle.retryDelay","layer","layerConfig","ShopifyApiClient.ShopifyApiClient","ShopifyAuth.layer","ShopifyApiClient.layer"],"sources":["../src/auth.ts","../src/schemas.ts","../src/throttle.ts","../src/transient-retry.ts","../src/api.ts","../src/connector.ts"],"sourcesContent":["import { Auth } from \"@useairfoil/connector-kit\";\nimport { Config, Context, Data, Duration, Effect, Layer, Redacted, Schema } from \"effect\";\nimport { HttpClient, HttpClientRequest, HttpClientResponse } from \"effect/unstable/http\";\n\nimport type { ShopifyConfig } from \"./manifest\";\n\ntype ShopifyAuthConfig = Pick<ShopifyConfig, \"shopDomain\" | \"clientId\" | \"clientSecret\">;\n\nexport type ShopifyAuthErrorReason = \"shop_not_permitted\" | \"invalid_client\" | \"exchange_failed\";\n\nexport class ShopifyAuthError extends Data.TaggedError(\"ShopifyAuthError\")<{\n readonly reason: ShopifyAuthErrorReason;\n readonly message: string;\n}> {}\n\nexport type ShopifyAuthService = Auth.TokenCache<ShopifyAuthError>;\n\nexport class ShopifyAuth extends Context.Service<ShopifyAuth, ShopifyAuthService>()(\n \"@useairfoil/producer-shopify/ShopifyAuth\",\n) {}\n\nconst TokenResponseSchema = Schema.Struct({\n access_token: Schema.String,\n expires_in: Schema.Number,\n});\n\nconst ErrorResponseSchema = Schema.Struct({\n error: Schema.optional(Schema.String),\n});\n\nconst normalizedShopDomain = (shopDomain: string): string =>\n shopDomain.replace(/^https?:\\/\\//i, \"\").replace(/\\/+$/g, \"\");\n\nconst errorFor = (reason: ShopifyAuthErrorReason): ShopifyAuthError => {\n switch (reason) {\n case \"shop_not_permitted\":\n return new ShopifyAuthError({\n reason,\n message: \"The Shopify app and store must belong to the same Shopify organization\",\n });\n case \"invalid_client\":\n return new ShopifyAuthError({\n reason,\n message: \"The Shopify client ID or client secret is invalid\",\n });\n case \"exchange_failed\":\n return new ShopifyAuthError({\n reason,\n message: \"Shopify authentication failed\",\n });\n }\n};\n\nconst decodeRejectedResponse = (\n response: HttpClientResponse.HttpClientResponse,\n): Effect.Effect<ShopifyAuthErrorReason> =>\n HttpClientResponse.schemaBodyJson(ErrorResponseSchema)(response).pipe(\n Effect.map((body) => {\n switch (body.error) {\n case \"shop_not_permitted\":\n return \"shop_not_permitted\";\n case \"invalid_client\":\n return \"invalid_client\";\n default:\n return \"exchange_failed\";\n }\n }),\n Effect.catch(() => Effect.succeed<ShopifyAuthErrorReason>(\"exchange_failed\")),\n );\n\nexport const make = Effect.fnUntraced(function* (config: ShopifyAuthConfig) {\n const client = yield* HttpClient.HttpClient;\n const endpoint = `https://${normalizedShopDomain(config.shopDomain)}/admin/oauth/access_token`;\n\n return yield* Auth.makeTokenCache({\n acquire: Effect.scoped(\n Effect.gen(function* () {\n const request = HttpClientRequest.post(endpoint).pipe(\n HttpClientRequest.bodyUrlParams({\n grant_type: \"client_credentials\",\n client_id: config.clientId,\n client_secret: Redacted.value(config.clientSecret),\n }),\n );\n const response = yield* client\n .execute(request)\n .pipe(Effect.mapError(() => errorFor(\"exchange_failed\")));\n const successfulResponse = yield* HttpClientResponse.filterStatusOk(response).pipe(\n Effect.catchTag(\"HttpClientError\", () =>\n decodeRejectedResponse(response).pipe(\n Effect.flatMap((reason) => Effect.fail(errorFor(reason))),\n ),\n ),\n );\n const body = yield* HttpClientResponse.schemaBodyJson(TokenResponseSchema)(\n successfulResponse,\n ).pipe(Effect.mapError(() => errorFor(\"exchange_failed\")));\n\n return {\n value: Redacted.make(body.access_token),\n expiresIn: Duration.seconds(body.expires_in),\n };\n }),\n ),\n });\n});\n\nexport const layer = (\n config: ShopifyAuthConfig,\n): Layer.Layer<ShopifyAuth, never, HttpClient.HttpClient> =>\n Layer.effect(ShopifyAuth)(make(config));\n\nexport const layerConfig = (\n config: Config.Wrap<ShopifyAuthConfig>,\n): Layer.Layer<ShopifyAuth, Config.ConfigError, HttpClient.HttpClient> =>\n Layer.unwrap(Config.unwrap(config).pipe(Effect.map(layer)));\n","import * as Schema from \"effect/Schema\";\n\nexport const PageInfoSchema = Schema.Struct({\n hasNextPage: Schema.Boolean,\n endCursor: Schema.NullOr(Schema.String),\n});\n\nexport const ProductStatusSchema = Schema.Literals([\"ACTIVE\", \"ARCHIVED\", \"DRAFT\", \"UNLISTED\"]);\n\nexport const RestProductStatusSchema = Schema.Literals([\"active\", \"archived\", \"draft\"]);\n\nexport const ProductVariantInventoryPolicySchema = Schema.Literals([\"CONTINUE\", \"DENY\"]);\n\nexport const RestProductVariantInventoryPolicySchema = Schema.Literals([\"continue\", \"deny\"]);\n\nexport const ProductFeaturedMediaSchema = Schema.Any;\n\nexport const ProductOptionSchema = Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n position: Schema.Number,\n values: Schema.Array(Schema.String),\n});\n\nexport const ProductVariantSchema = Schema.Struct({\n id: Schema.String,\n legacyResourceId: Schema.String,\n title: Schema.String,\n sku: Schema.NullOr(Schema.String),\n barcode: Schema.NullOr(Schema.String),\n price: Schema.String,\n compareAtPrice: Schema.NullOr(Schema.String),\n inventoryPolicy: ProductVariantInventoryPolicySchema,\n taxable: Schema.Boolean,\n createdAt: Schema.String,\n updatedAt: Schema.String,\n});\n\nexport const ProductWebhookImageSchema = Schema.Struct({\n src: Schema.String,\n alt: Schema.NullOr(Schema.String),\n});\n\nexport const ProductWebhookOptionSchema = Schema.Struct({\n id: Schema.Number,\n name: Schema.String,\n position: Schema.Number,\n values: Schema.Array(Schema.String),\n});\n\nexport const ProductWebhookVariantSchema = Schema.Struct({\n admin_graphql_api_id: Schema.String,\n id: Schema.Number,\n title: Schema.String,\n price: Schema.Union([Schema.String, Schema.Number]),\n inventory_policy: RestProductVariantInventoryPolicySchema,\n compare_at_price: Schema.NullOr(Schema.Union([Schema.String, Schema.Number])),\n created_at: Schema.String,\n updated_at: Schema.String,\n taxable: Schema.Boolean,\n barcode: Schema.NullOr(Schema.String),\n sku: Schema.NullOr(Schema.String),\n});\n\nexport const ProductWebhookVariantGidSchema = Schema.Struct({\n admin_graphql_api_id: Schema.String,\n updated_at: Schema.String,\n});\n\nexport const ProductSchema = Schema.Struct({\n id: Schema.String,\n legacyResourceId: Schema.String,\n title: Schema.String,\n handle: Schema.String,\n descriptionHtml: Schema.String,\n productType: Schema.String,\n vendor: Schema.String,\n status: ProductStatusSchema,\n tags: Schema.Array(Schema.String),\n createdAt: Schema.String,\n updatedAt: Schema.String,\n publishedAt: Schema.NullOr(Schema.String),\n templateSuffix: Schema.NullOr(Schema.String),\n featuredMedia: Schema.NullOr(ProductFeaturedMediaSchema),\n options: Schema.Array(ProductOptionSchema),\n variants: Schema.Array(ProductVariantSchema),\n});\n\nexport const ProductWebhookPayloadSchema = Schema.Struct({\n id: Schema.Number,\n admin_graphql_api_id: Schema.String,\n body_html: Schema.NullOr(Schema.String),\n created_at: Schema.NullOr(Schema.String),\n handle: Schema.String,\n image: Schema.optional(Schema.NullOr(ProductWebhookImageSchema)),\n images: Schema.optional(Schema.Array(Schema.Any)),\n options: Schema.Array(ProductWebhookOptionSchema),\n product_type: Schema.String,\n published_at: Schema.NullOr(Schema.String),\n published_scope: Schema.optional(Schema.String),\n status: RestProductStatusSchema,\n tags: Schema.String,\n template_suffix: Schema.NullOr(Schema.String),\n title: Schema.String,\n updated_at: Schema.String,\n variants: Schema.Array(ProductWebhookVariantSchema),\n variant_gids: Schema.Array(ProductWebhookVariantGidSchema),\n vendor: Schema.String,\n});\n\nexport const ProductDeleteWebhookPayloadSchema = Schema.Struct({\n id: Schema.Number,\n});\n\nexport const ProductEventSchema = Schema.Union([\n Schema.Struct({\n _tag: Schema.Literal(\"upsert\"),\n payload: ProductWebhookPayloadSchema,\n }),\n Schema.Struct({\n _tag: Schema.Literal(\"delete\"),\n id: Schema.String,\n version: Schema.String,\n }),\n]);\n\nexport const MoneySchema = Schema.Struct({\n amount: Schema.String,\n currency_code: Schema.String,\n});\n\nexport const MoneyBagSchema = Schema.Struct({\n shop_money: MoneySchema,\n presentment_money: MoneySchema,\n});\n\nexport const CartLineItemSchema = Schema.Struct({\n id: Schema.Union([Schema.String, Schema.Number]),\n properties: Schema.NullOr(Schema.Unknown),\n quantity: Schema.Number,\n variant_id: Schema.Union([Schema.String, Schema.Number]),\n key: Schema.String,\n discounted_price: Schema.String,\n discounts: Schema.Array(Schema.Unknown),\n gift_card: Schema.Boolean,\n grams: Schema.Number,\n line_price: Schema.String,\n original_line_price: Schema.String,\n original_price: Schema.String,\n price: Schema.String,\n product_id: Schema.Union([Schema.String, Schema.Number]),\n sku: Schema.NullOr(Schema.String),\n taxable: Schema.Boolean,\n title: Schema.String,\n total_discount: Schema.String,\n vendor: Schema.String,\n discounted_price_set: MoneyBagSchema,\n line_price_set: MoneyBagSchema,\n original_line_price_set: MoneyBagSchema,\n price_set: MoneyBagSchema,\n total_discount_set: MoneyBagSchema,\n parent_relationship: Schema.NullOr(Schema.Unknown),\n});\n\nexport const CartWebhookPayloadSchema = Schema.Struct({\n id: Schema.String,\n token: Schema.String,\n line_items: Schema.Array(CartLineItemSchema),\n note: Schema.NullOr(Schema.String),\n updated_at: Schema.String,\n created_at: Schema.String,\n});\n\nexport const CartEventSchema = Schema.Struct({\n id: Schema.String,\n token: Schema.String,\n topic: Schema.Literals([\"carts/create\", \"carts/update\"]),\n lineItems: Schema.Array(CartLineItemSchema),\n note: Schema.NullOr(Schema.String),\n updatedAt: Schema.String,\n createdAt: Schema.String,\n});\n\nexport const WebhookPayloadSchema = Schema.Unknown;\n\nconst splitTags = (value: string): ReadonlyArray<string> => {\n if (value.trim() === \"\") {\n return [];\n }\n return value\n .split(\",\")\n .map((tag) => tag.trim())\n .filter((tag) => tag.length > 0);\n};\n\nconst normalizeProductStatus = (status: RestProductStatus): ProductStatus => {\n switch (status) {\n case \"active\":\n return \"ACTIVE\";\n case \"archived\":\n return \"ARCHIVED\";\n case \"draft\":\n return \"DRAFT\";\n }\n};\n\nconst normalizeInventoryPolicy = (\n policy: RestProductVariantInventoryPolicy,\n): ProductVariantInventoryPolicy => {\n switch (policy) {\n case \"continue\":\n return \"CONTINUE\";\n case \"deny\":\n return \"DENY\";\n }\n};\n\nconst normalizeProductOption = (restOption: ProductWebhookOption): ProductOption => {\n return {\n id: `gid://shopify/ProductOption/${restOption.id}`,\n name: restOption.name,\n position: restOption.position,\n values: restOption.values,\n };\n};\n\nconst normalizeProductVariant = (restVariant: ProductWebhookVariant): ProductVariant => {\n return {\n id: restVariant.admin_graphql_api_id,\n legacyResourceId: String(restVariant.id),\n title: restVariant.title,\n sku: restVariant.sku,\n barcode: restVariant.barcode,\n price: String(restVariant.price),\n compareAtPrice:\n restVariant.compare_at_price === null ? null : String(restVariant.compare_at_price),\n inventoryPolicy: normalizeInventoryPolicy(restVariant.inventory_policy),\n taxable: restVariant.taxable,\n createdAt: restVariant.created_at,\n updatedAt: restVariant.updated_at,\n };\n};\n\nconst normalizeProductFeaturedMedia = (\n image: ProductWebhookImage | null | undefined,\n): ProductFeaturedMedia | null => {\n if (image === null || image === undefined) {\n return null;\n }\n\n return {\n image: {\n url: image.src,\n altText: image.alt,\n },\n };\n};\n\nexport const ShopifyNormalize = {\n productWebhook: (payload: ProductWebhookPayload & { readonly created_at: string }): Product => ({\n id: payload.admin_graphql_api_id,\n legacyResourceId: String(payload.id),\n title: payload.title,\n handle: payload.handle,\n descriptionHtml: payload.body_html ?? \"\",\n productType: payload.product_type,\n vendor: payload.vendor,\n status: normalizeProductStatus(payload.status),\n tags: splitTags(payload.tags),\n createdAt: payload.created_at,\n updatedAt: payload.updated_at,\n publishedAt: payload.published_at,\n templateSuffix: payload.template_suffix,\n featuredMedia: normalizeProductFeaturedMedia(payload.image),\n options: payload.options.map(normalizeProductOption),\n variants: payload.variants.map(normalizeProductVariant),\n }),\n\n cartWebhook: (\n payload: CartWebhookPayload,\n topic: \"carts/create\" | \"carts/update\",\n ): CartEvent => ({\n id: payload.id,\n token: payload.token,\n topic,\n lineItems: payload.line_items,\n note: payload.note,\n updatedAt: payload.updated_at,\n createdAt: payload.created_at,\n }),\n} as const;\n\nexport type PageInfo = Schema.Schema.Type<typeof PageInfoSchema>;\nexport type ProductStatus = Schema.Schema.Type<typeof ProductStatusSchema>;\nexport type RestProductStatus = Schema.Schema.Type<typeof RestProductStatusSchema>;\nexport type ProductVariantInventoryPolicy = Schema.Schema.Type<\n typeof ProductVariantInventoryPolicySchema\n>;\nexport type RestProductVariantInventoryPolicy = Schema.Schema.Type<\n typeof RestProductVariantInventoryPolicySchema\n>;\nexport type ProductFeaturedMedia = Schema.Schema.Type<typeof ProductFeaturedMediaSchema>;\nexport type ProductOption = Schema.Schema.Type<typeof ProductOptionSchema>;\nexport type ProductVariant = Schema.Schema.Type<typeof ProductVariantSchema>;\nexport type ProductWebhookImage = Schema.Schema.Type<typeof ProductWebhookImageSchema>;\nexport type ProductWebhookOption = Schema.Schema.Type<typeof ProductWebhookOptionSchema>;\nexport type ProductWebhookVariant = Schema.Schema.Type<typeof ProductWebhookVariantSchema>;\nexport type ProductWebhookVariantGid = Schema.Schema.Type<typeof ProductWebhookVariantGidSchema>;\nexport type Product = Schema.Schema.Type<typeof ProductSchema>;\nexport type ProductWebhookPayload = Schema.Schema.Type<typeof ProductWebhookPayloadSchema>;\nexport type ProductDeleteWebhookPayload = Schema.Schema.Type<\n typeof ProductDeleteWebhookPayloadSchema\n>;\nexport type Money = Schema.Schema.Type<typeof MoneySchema>;\nexport type MoneyBag = Schema.Schema.Type<typeof MoneyBagSchema>;\nexport type CartLineItem = Schema.Schema.Type<typeof CartLineItemSchema>;\nexport type CartWebhookPayload = Schema.Schema.Type<typeof CartWebhookPayloadSchema>;\nexport type CartEvent = Schema.Schema.Type<typeof CartEventSchema>;\nexport type WebhookPayload = Schema.Schema.Type<typeof WebhookPayloadSchema>;\n","// Shopify reports GraphQL throttling in HTTP 200 responses.\n// https://shopify.dev/docs/api/usage/limits\nimport { Duration, Effect, Option, Random, Schema } from \"effect\";\n\nconst ThrottleStatusSchema = Schema.Struct({\n maximumAvailable: Schema.Number,\n currentlyAvailable: Schema.Number,\n restoreRate: Schema.Number,\n});\n\nexport type ThrottleStatus = Schema.Schema.Type<typeof ThrottleStatusSchema>;\n\nconst GraphQLErrorSchema = Schema.Struct({\n extensions: Schema.optional(Schema.Struct({ code: Schema.optional(Schema.String) })),\n});\n\nconst GraphQLEnvelopeSchema = Schema.Struct({\n errors: Schema.optional(Schema.Array(GraphQLErrorSchema)),\n extensions: Schema.optional(\n Schema.Struct({\n cost: Schema.optional(\n Schema.Struct({\n requestedQueryCost: Schema.optional(Schema.Number),\n throttleStatus: Schema.optional(ThrottleStatusSchema),\n }),\n ),\n }),\n ),\n});\n\nconst decodeEnvelope = Schema.decodeUnknownOption(GraphQLEnvelopeSchema);\n\nconst readThrottleCost = (\n body: unknown,\n): { readonly requestedQueryCost: number; readonly status: ThrottleStatus } | undefined =>\n decodeEnvelope(body).pipe(\n Option.flatMap((envelope) => {\n const cost = envelope.extensions?.cost;\n const status = cost?.throttleStatus;\n const requestedQueryCost = cost?.requestedQueryCost;\n return status === undefined || requestedQueryCost === undefined\n ? Option.none()\n : Option.some({ requestedQueryCost, status });\n }),\n Option.getOrUndefined,\n );\n\nconst retryableCodes = new Set([\"THROTTLED\", \"INTERNAL_SERVER_ERROR\"]);\n\nexport type RetryableErrorCode = \"THROTTLED\" | \"INTERNAL_SERVER_ERROR\";\n\n/** Retries only when every GraphQL error is transient. */\nexport const retryableErrorCode = (body: unknown): RetryableErrorCode | undefined =>\n decodeEnvelope(body).pipe(\n Option.flatMap((envelope) => {\n const codes = envelope.errors?.map((error) => error.extensions?.code) ?? [];\n const allRetryable =\n codes.length > 0 && codes.every((code) => code !== undefined && retryableCodes.has(code));\n if (!allRetryable) return Option.none<RetryableErrorCode>();\n return Option.some<RetryableErrorCode>(\n codes.includes(\"THROTTLED\") ? \"THROTTLED\" : \"INTERNAL_SERVER_ERROR\",\n );\n }),\n Option.getOrUndefined,\n );\n\nconst backoff = (baseDelay: Duration.Duration, attempt: number): Effect.Effect<Duration.Duration> =>\n Random.nextBetween(0.8, 1.2).pipe(\n Effect.map((jitter) => Duration.times(baseDelay, 2 ** attempt * jitter)),\n );\n\n/** Uses Shopify's cost deficit for throttling and backoff for internal errors. */\nexport const retryDelay = (\n code: RetryableErrorCode,\n body: unknown,\n attempt: number,\n options: { readonly baseDelay: Duration.Duration },\n): Effect.Effect<Duration.Duration> => {\n if (code === \"INTERNAL_SERVER_ERROR\") return backoff(options.baseDelay, attempt);\n const cost = readThrottleCost(body);\n if (cost === undefined || cost.status.restoreRate <= 0) {\n return backoff(options.baseDelay, attempt);\n }\n const deficitMillis =\n (Math.max(0, cost.requestedQueryCost - cost.status.currentlyAvailable) /\n cost.status.restoreRate) *\n 1000;\n return Effect.succeed(Duration.max(Duration.millis(Math.ceil(deficitMillis)), options.baseDelay));\n};\n","import { Metrics } from \"@useairfoil/connector-kit\";\nimport { Clock, Duration, Effect, Random } from \"effect\";\nimport { HttpClient, HttpClientResponse } from \"effect/unstable/http\";\n\nimport { manifest } from \"./manifest\";\n\nconst parseRetryAfter = (\n header: string | undefined,\n atMillis: number,\n): Duration.Duration | undefined => {\n if (header === undefined || header.trim() === \"\") return undefined;\n const seconds = Number(header);\n if (Number.isFinite(seconds)) return Duration.seconds(Math.max(seconds, 0));\n const parsedDate = Date.parse(header);\n return Number.isNaN(parsedDate) ? undefined : Duration.millis(Math.max(parsedDate - atMillis, 0));\n};\n\nconst otherTransientStatuses = new Set([408, 500, 502, 503, 504]);\n\nconst backoff = (baseDelay: Duration.Duration, attempt: number): Effect.Effect<Duration.Duration> =>\n Random.nextBetween(0.8, 1.2).pipe(\n Effect.map((jitter) => Duration.times(baseDelay, 2 ** attempt * jitter)),\n );\n\nconst delayFor = (\n response: HttpClientResponse.HttpClientResponse,\n attempt: number,\n options: {\n readonly baseDelay: Duration.Duration;\n readonly retryAfterFallback: Duration.Duration;\n },\n): Effect.Effect<Duration.Duration> => {\n if (response.status !== 429) return backoff(options.baseDelay, attempt);\n return Clock.currentTimeMillis.pipe(\n Effect.map(\n (now) => parseRetryAfter(response.headers[\"retry-after\"], now) ?? options.retryAfterFallback,\n ),\n );\n};\n\nconst retryReason = (status: number): Metrics.ApiRetryReason =>\n status === 429 ? \"rate_limit\" : status === 408 ? \"timeout\" : \"server_error\";\n\n/** Retries transient responses and honors Shopify's `Retry-After` header on 429. */\nexport const withTransientRetry = <E, R>(\n client: HttpClient.HttpClient.With<E, R>,\n options: {\n readonly maxRetries: number;\n readonly baseDelay: Duration.Duration;\n readonly retryAfterFallback: Duration.Duration;\n },\n): HttpClient.HttpClient.With<E, R> => {\n const loop = (\n effect: Effect.Effect<HttpClientResponse.HttpClientResponse, E, R>,\n remaining: number,\n attempt: number,\n ): Effect.Effect<HttpClientResponse.HttpClientResponse, E, R> =>\n Effect.flatMap(effect, (response) => {\n const isRetryable = response.status === 429 || otherTransientStatuses.has(response.status);\n if (!isRetryable || remaining <= 0) return Effect.succeed(response);\n return delayFor(response, attempt, options).pipe(\n Effect.tap(() =>\n Metrics.recordApiRetry({\n connector: manifest.name,\n reason: retryReason(response.status),\n }),\n ),\n Effect.flatMap(Effect.sleep),\n Effect.flatMap(() => loop(effect, remaining - 1, attempt + 1)),\n );\n });\n\n return HttpClient.transform(client, (effect) => loop(effect, options.maxRetries, 0));\n};\n","import { ConnectorError, Metrics, Telemetry } from \"@useairfoil/connector-kit\";\nimport {\n Config,\n Context,\n Duration,\n Effect,\n Layer,\n Option,\n Redacted,\n Schedule,\n Schema,\n Stream,\n} from \"effect\";\nimport { HttpClient, HttpClientRequest } from \"effect/unstable/http\";\n\nimport type { PageInfo, Product } from \"./schemas\";\n\nimport * as ShopifyAuth from \"./auth\";\nimport { manifest, type ShopifyConfig } from \"./manifest\";\nimport {\n PageInfoSchema,\n ProductOptionSchema,\n ProductStatusSchema,\n ProductVariantInventoryPolicySchema,\n} from \"./schemas\";\nimport * as Throttle from \"./throttle\";\nimport * as TransientRetry from \"./transient-retry\";\n\nexport type ShopifyProductPage = {\n readonly items: ReadonlyArray<Product>;\n readonly endCursor: string | null;\n readonly hasMore: boolean;\n};\n\nexport type ShopifyApiClientService = {\n readonly checkConnection: Effect.Effect<void, ConnectorError>;\n readonly checkProductsAccess: Effect.Effect<void, ConnectorError>;\n readonly fetchGraphQL: <A>(options: {\n readonly operationName: string;\n readonly query: string;\n readonly variables?: Record<string, unknown>;\n readonly schema: Schema.Decoder<A>;\n }) => Effect.Effect<A, ConnectorError>;\n readonly fetchProducts: (options: {\n readonly first: number;\n readonly after?: string;\n }) => Effect.Effect<ShopifyProductPage, ConnectorError>;\n /**\n * Fetches the complete product with every variant page.\n * Webhook payloads include only the first 100 variants.\n */\n readonly fetchProductById: (id: string) => Effect.Effect<Product, ConnectorError>;\n};\n\nexport class ShopifyApiClient extends Context.Service<ShopifyApiClient, ShopifyApiClientService>()(\n \"@useairfoil/producer-shopify/ShopifyApiClient\",\n) {}\n\nconst ProductsQuery = `#graphql\nquery AirfoilProducts($first: Int!, $after: String) {\n products(first: $first, after: $after, sortKey: UPDATED_AT, reverse: true) {\n nodes {\n id\n legacyResourceId\n title\n handle\n descriptionHtml\n productType\n vendor\n status\n tags\n createdAt\n updatedAt\n publishedAt\n templateSuffix\n featuredMedia {\n ... on MediaImage {\n image {\n url\n altText\n }\n }\n }\n options(first: 100) {\n id\n name\n position\n values\n }\n variants(first: 25) {\n nodes {\n id\n legacyResourceId\n title\n sku\n barcode\n price\n compareAtPrice\n inventoryPolicy\n taxable\n createdAt\n updatedAt\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n}\n`;\n\nconst ProductByIdQuery = `#graphql\nquery AirfoilProductById($id: ID!) {\n product(id: $id) {\n id\n legacyResourceId\n title\n handle\n descriptionHtml\n productType\n vendor\n status\n tags\n createdAt\n updatedAt\n publishedAt\n templateSuffix\n featuredMedia {\n ... on MediaImage {\n image {\n url\n altText\n }\n }\n }\n options(first: 100) {\n id\n name\n position\n values\n }\n variants(first: 25) {\n nodes {\n id\n legacyResourceId\n title\n sku\n barcode\n price\n compareAtPrice\n inventoryPolicy\n taxable\n createdAt\n updatedAt\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n}\n`;\n\nconst ProductVariantsQuery = `#graphql\nquery AirfoilProductVariants($id: ID!, $first: Int!, $after: String) {\n product(id: $id) {\n variants(first: $first, after: $after) {\n nodes {\n id\n legacyResourceId\n title\n sku\n barcode\n price\n compareAtPrice\n inventoryPolicy\n taxable\n createdAt\n updatedAt\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n}\n`;\n\nconst ProductsAccessQuery = `#graphql\nquery AirfoilProductsAccess {\n products(first: 1) {\n nodes {\n id\n }\n }\n}\n`;\n\nconst ShopIdentityQuery = `#graphql\nquery AirfoilShopIdentity {\n shop {\n id\n }\n}\n`;\n\nconst ShopIdentitySchema = Schema.Struct({\n shop: Schema.Struct({ id: Schema.String }),\n});\n\nconst ProductsAccessSchema = Schema.Struct({\n products: Schema.Struct({\n nodes: Schema.Array(Schema.Struct({ id: Schema.String })),\n }),\n});\n\nconst LegacyResourceIdSchema = Schema.Union([Schema.String, Schema.Number]);\n\nconst GraphQLProductVariantNodeSchema = Schema.Struct({\n id: Schema.String,\n legacyResourceId: LegacyResourceIdSchema,\n title: Schema.String,\n sku: Schema.NullOr(Schema.String),\n barcode: Schema.NullOr(Schema.String),\n price: Schema.String,\n compareAtPrice: Schema.NullOr(Schema.String),\n inventoryPolicy: ProductVariantInventoryPolicySchema,\n taxable: Schema.Boolean,\n createdAt: Schema.String,\n updatedAt: Schema.String,\n});\n\nconst GraphQLProductNodeSchema = Schema.Struct({\n id: Schema.String,\n legacyResourceId: LegacyResourceIdSchema,\n title: Schema.String,\n handle: Schema.String,\n descriptionHtml: Schema.String,\n productType: Schema.String,\n vendor: Schema.String,\n status: ProductStatusSchema,\n tags: Schema.Array(Schema.String),\n createdAt: Schema.String,\n updatedAt: Schema.String,\n publishedAt: Schema.NullOr(Schema.String),\n templateSuffix: Schema.NullOr(Schema.String),\n featuredMedia: Schema.NullOr(Schema.Any),\n options: Schema.Array(ProductOptionSchema),\n variants: Schema.Struct({\n nodes: Schema.Array(GraphQLProductVariantNodeSchema),\n pageInfo: PageInfoSchema,\n }),\n});\n\nconst GraphQLProductsDataSchema = Schema.Struct({\n products: Schema.Struct({\n nodes: Schema.Array(GraphQLProductNodeSchema),\n pageInfo: PageInfoSchema,\n }),\n});\n\nconst GraphQLProductByIdDataSchema = Schema.Struct({\n product: Schema.NullOr(GraphQLProductNodeSchema),\n});\n\nconst GraphQLProductVariantsDataSchema = Schema.Struct({\n product: Schema.NullOr(\n Schema.Struct({\n variants: Schema.Struct({\n nodes: Schema.Array(GraphQLProductVariantNodeSchema),\n pageInfo: PageInfoSchema,\n }),\n }),\n ),\n});\n\ntype GraphQLProductsData = Schema.Schema.Type<typeof GraphQLProductsDataSchema>;\ntype GraphQLProductNode = Schema.Schema.Type<typeof GraphQLProductNodeSchema>;\ntype GraphQLProductVariantNode = Schema.Schema.Type<typeof GraphQLProductVariantNodeSchema>;\n\nconst normalizeProductNode = (\n node: GraphQLProductNode,\n variants: ReadonlyArray<GraphQLProductVariantNode>,\n): Product => ({\n id: node.id,\n legacyResourceId: String(node.legacyResourceId),\n title: node.title,\n handle: node.handle,\n descriptionHtml: node.descriptionHtml,\n productType: node.productType,\n vendor: node.vendor,\n status: node.status,\n tags: node.tags,\n createdAt: node.createdAt,\n updatedAt: node.updatedAt,\n publishedAt: node.publishedAt,\n templateSuffix: node.templateSuffix,\n featuredMedia: node.featuredMedia,\n options: node.options,\n variants: variants.map((variant) => ({\n ...variant,\n legacyResourceId: String(variant.legacyResourceId),\n })),\n});\n\nconst graphqlEndpoint = (config: ShopifyConfig): string => {\n const shopDomain = config.shopDomain.replace(/^https?:\\/\\//i, \"\").replace(/\\/+$/g, \"\");\n return `https://${shopDomain}/admin/api/${config.apiVersion}/graphql.json`;\n};\n\nconst hasGraphqlErrors = (body: unknown): boolean => {\n if (typeof body !== \"object\" || body === null) {\n return false;\n }\n const errors = (body as { readonly errors?: unknown }).errors;\n return Array.isArray(errors) && errors.length > 0;\n};\n\nconst summarizeBody = (body: unknown): string => {\n try {\n return JSON.stringify(body);\n } catch {\n return String(body);\n }\n};\n\nexport const make = Effect.fnUntraced(function* (config: ShopifyConfig) {\n const auth = yield* ShopifyAuth.ShopifyAuth;\n const retryBaseDelay = Duration.millis(config.retryBaseDelayMs);\n const graphqlRetryBaseDelay = Duration.millis(config.graphqlRetryBaseDelayMs);\n const requestTimeout = Duration.seconds(config.requestTimeoutSeconds);\n const transportRetrySchedule = Schedule.exponential(retryBaseDelay).pipe(\n Schedule.jittered,\n Schedule.upTo({ times: config.transportMaxRetries }),\n Schedule.tap(() => Metrics.recordApiRetry({ connector: manifest.name, reason: \"transport\" })),\n );\n const client = (yield* HttpClient.HttpClient).pipe(\n HttpClient.mapRequestEffect((request) =>\n auth.get.pipe(\n Effect.map((token) =>\n HttpClientRequest.setHeader(request, \"X-Shopify-Access-Token\", Redacted.value(token)),\n ),\n ),\n ),\n HttpClient.mapRequest(HttpClientRequest.acceptJson),\n (c) =>\n TransientRetry.withTransientRetry(c, {\n maxRetries: config.responseMaxRetries,\n baseDelay: retryBaseDelay,\n retryAfterFallback: Duration.seconds(config.retryAfterFallbackSeconds),\n }),\n // HTTP responses are handled above, so this retries transport errors only.\n HttpClient.retryTransient({\n retryOn: \"errors-only\",\n schedule: transportRetrySchedule,\n }),\n );\n const endpoint = graphqlEndpoint(config);\n\n const fetchGraphQL = <A>(options: {\n readonly operationName: string;\n readonly query: string;\n readonly variables?: Record<string, unknown>;\n readonly schema: Schema.Decoder<A>;\n }): Effect.Effect<A, ConnectorError> => {\n const attempt = (remainingRetries: number): Effect.Effect<A, ConnectorError> =>\n Effect.gen(function* () {\n const request = yield* HttpClientRequest.post(endpoint).pipe(\n HttpClientRequest.bodyJson({\n query: options.query,\n variables: options.variables ?? {},\n }),\n Effect.mapError(\n (cause) =>\n new ConnectorError({ message: \"Failed to encode Shopify GraphQL request\", cause }),\n ),\n );\n\n const { body, status } = yield* Effect.scoped(\n client.execute(request).pipe(\n Effect.tapError((error) => Telemetry.annotateError(\"api_http\", error)),\n Effect.mapError((error) => {\n if (error._tag === \"ShopifyAuthError\") {\n return new ConnectorError({ message: error.message, cause: error });\n }\n return new ConnectorError({\n message: \"Shopify GraphQL request failed\",\n cause: error,\n });\n }),\n Effect.flatMap((response) =>\n response.json.pipe(\n Effect.tapError((error) => Telemetry.annotateError(\"api_json\", error)),\n Effect.mapError(\n (error) =>\n new ConnectorError({\n message: \"Shopify GraphQL returned invalid JSON\",\n cause: error,\n }),\n ),\n Effect.map((body) => ({\n body,\n status: response.status,\n })),\n ),\n ),\n ),\n );\n\n if (status < 200 || status >= 300) {\n const error = { status, body, operationName: options.operationName };\n yield* Effect.logWarning(\"Shopify GraphQL returned non-2xx status\").pipe(\n Effect.annotateLogs({\n operationName: options.operationName,\n status,\n body: summarizeBody(body),\n }),\n );\n yield* Telemetry.annotateError(\"api_status\", error);\n return yield* Effect.fail(\n new ConnectorError({\n message: \"Shopify GraphQL returned non-2xx status\",\n cause: error,\n }),\n );\n }\n\n if (hasGraphqlErrors(body)) {\n const retryableCode = Throttle.retryableErrorCode(body);\n if (retryableCode !== undefined && remainingRetries > 0) {\n const attemptIndex = config.graphqlMaxRetries - remainingRetries;\n const wait = yield* Throttle.retryDelay(retryableCode, body, attemptIndex, {\n baseDelay: graphqlRetryBaseDelay,\n });\n yield* Effect.logWarning(\n \"Shopify GraphQL request returned a retryable error, retrying\",\n ).pipe(\n Effect.annotateLogs({\n operationName: options.operationName,\n code: retryableCode,\n remainingRetries,\n waitMillis: Duration.toMillis(wait),\n }),\n );\n yield* Metrics.recordApiRetry({\n connector: manifest.name,\n reason: retryableCode === \"THROTTLED\" ? \"rate_limit\" : \"server_error\",\n });\n yield* Effect.sleep(wait);\n return yield* attempt(remainingRetries - 1);\n }\n\n yield* Effect.logWarning(\"Shopify GraphQL returned errors\").pipe(\n Effect.annotateLogs({\n operationName: options.operationName,\n body: summarizeBody(body),\n }),\n );\n yield* Telemetry.annotateError(\"api_graphql\", body);\n return yield* Effect.fail(\n new ConnectorError({ message: \"Shopify GraphQL returned errors\", cause: body }),\n );\n }\n\n const data =\n typeof body === \"object\" && body !== null ? (body as { data?: unknown }).data : undefined;\n return yield* Schema.decodeUnknownEffect(options.schema)(data).pipe(\n Effect.tapError((error) => Telemetry.annotateError(\"api_decode\", error)),\n Effect.mapError(\n (error) =>\n new ConnectorError({\n message: \"Shopify GraphQL response schema decode failed\",\n cause: error,\n }),\n ),\n );\n }).pipe(\n Effect.withSpan(Telemetry.SpanName.apiFetch, {\n kind: \"client\",\n attributes: { [Telemetry.Attr.apiPath]: `graphql:${options.operationName}` },\n }),\n );\n\n return attempt(config.graphqlMaxRetries).pipe(\n Effect.timeout(requestTimeout),\n Effect.mapError((error) =>\n error instanceof ConnectorError\n ? error\n : new ConnectorError({ message: \"Shopify GraphQL request timed out\", cause: error }),\n ),\n );\n };\n\n const nextPageCursor = (\n pageInfo: PageInfo,\n ): Effect.Effect<Option.Option<string>, ConnectorError> => {\n if (!pageInfo.hasNextPage) {\n return Effect.succeed(Option.none());\n }\n if (pageInfo.endCursor === null) {\n return Effect.fail(\n new ConnectorError({\n message: \"Shopify GraphQL pageInfo.endCursor is required when hasNextPage is true\",\n }),\n );\n }\n return Effect.succeed(Option.some(pageInfo.endCursor));\n };\n\n const fetchRemainingProductVariants = (\n productId: string,\n initialCursor: string,\n ): Effect.Effect<ReadonlyArray<GraphQLProductVariantNode>, ConnectorError> =>\n Stream.paginate(initialCursor, (after) =>\n fetchGraphQL({\n operationName: \"AirfoilProductVariants\",\n query: ProductVariantsQuery,\n variables: { id: productId, first: 100, after },\n schema: GraphQLProductVariantsDataSchema,\n }).pipe(\n Effect.flatMap((data) => {\n if (data.product === null) {\n return Effect.fail(\n new ConnectorError({\n message: \"Shopify product disappeared while fetching variants\",\n }),\n );\n }\n const variants = data.product.variants;\n return nextPageCursor(variants.pageInfo).pipe(\n Effect.map((cursor) => [variants.nodes, cursor] as const),\n );\n }),\n ),\n ).pipe(Stream.runCollect);\n\n const loadProductVariants = (\n node: GraphQLProductNode,\n ): Effect.Effect<ReadonlyArray<GraphQLProductVariantNode>, ConnectorError> =>\n nextPageCursor(node.variants.pageInfo).pipe(\n Effect.flatMap(\n Option.match({\n onNone: () => Effect.succeed(node.variants.nodes),\n onSome: (cursor) =>\n fetchRemainingProductVariants(node.id, cursor).pipe(\n Effect.map((remaining) => [...node.variants.nodes, ...remaining]),\n ),\n }),\n ),\n );\n\n const fetchProducts = (options: {\n readonly first: number;\n readonly after?: string;\n }): Effect.Effect<ShopifyProductPage, ConnectorError> =>\n fetchGraphQL({\n operationName: \"AirfoilProducts\",\n query: ProductsQuery,\n variables: { first: options.first, after: options.after ?? null },\n schema: GraphQLProductsDataSchema,\n }).pipe(\n Effect.flatMap((data: GraphQLProductsData) =>\n nextPageCursor(data.products.pageInfo).pipe(\n Effect.andThen(\n Effect.forEach(data.products.nodes, (node) =>\n loadProductVariants(node).pipe(\n Effect.map((variants) => normalizeProductNode(node, variants)),\n ),\n ),\n ),\n Effect.map((items) => ({\n items,\n endCursor: data.products.pageInfo.endCursor,\n hasMore: data.products.pageInfo.hasNextPage,\n })),\n ),\n ),\n );\n\n const fetchProductById = (id: string): Effect.Effect<Product, ConnectorError> =>\n fetchGraphQL({\n operationName: \"AirfoilProductById\",\n query: ProductByIdQuery,\n variables: { id },\n schema: GraphQLProductByIdDataSchema,\n }).pipe(\n Effect.flatMap((data) => {\n const node = data.product;\n if (node === null) {\n return Effect.fail(\n new ConnectorError({\n message: \"Shopify product not found while refreshing from webhook\",\n }),\n );\n }\n return loadProductVariants(node).pipe(\n Effect.map((variants) => normalizeProductNode(node, variants)),\n );\n }),\n );\n\n const checkConnection = fetchGraphQL({\n operationName: \"AirfoilShopIdentity\",\n query: ShopIdentityQuery,\n schema: ShopIdentitySchema,\n }).pipe(Effect.asVoid);\n\n const checkProductsAccess = fetchGraphQL({\n operationName: \"AirfoilProductsAccess\",\n query: ProductsAccessQuery,\n schema: ProductsAccessSchema,\n }).pipe(Effect.asVoid);\n\n return { checkConnection, checkProductsAccess, fetchGraphQL, fetchProducts, fetchProductById };\n});\n\nexport const layer = (\n config: ShopifyConfig,\n): Layer.Layer<ShopifyApiClient, ConnectorError, HttpClient.HttpClient | ShopifyAuth.ShopifyAuth> =>\n Layer.effect(ShopifyApiClient)(make(config));\n\nexport const layerConfig = (\n config: Config.Wrap<ShopifyConfig>,\n): Layer.Layer<\n ShopifyApiClient,\n ConnectorError | Config.ConfigError,\n HttpClient.HttpClient | ShopifyAuth.ShopifyAuth\n> => Layer.effect(ShopifyApiClient)(Config.unwrap(config).pipe(Effect.flatMap(make)));\n","import {\n Connector,\n ConnectorError,\n Cursor,\n Fetch,\n Resource,\n Webhook,\n} from \"@useairfoil/connector-kit\";\nimport { Config, Context, Effect, Layer, Redacted, Schema } from \"effect\";\nimport { HttpServerResponse } from \"effect/unstable/http\";\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\n\nimport type { ShopifyConfig } from \"./manifest\";\n\nimport * as ShopifyApiClient from \"./api\";\nimport * as ShopifyAuth from \"./auth\";\nimport {\n CartEventSchema,\n CartWebhookPayloadSchema,\n ProductDeleteWebhookPayloadSchema,\n ProductEventSchema,\n ProductSchema,\n ProductWebhookPayloadSchema,\n ShopifyNormalize,\n} from \"./schemas\";\nexport { manifest, ShopifyConfigDef } from \"./manifest\";\nexport type { ShopifyConfig } from \"./manifest\";\n\nconst verifyWebhookSignature = (options: {\n readonly rawBody: Uint8Array;\n readonly signature: string | null;\n readonly secret: string;\n}): Effect.Effect<void, ConnectorError> =>\n Effect.try({\n try: () => {\n if (!options.signature) {\n throw new Error(\"Missing x-shopify-hmac-sha256 header\");\n }\n const digest = createHmac(\"sha256\", options.secret)\n .update(Buffer.from(options.rawBody))\n .digest();\n const provided = Buffer.from(options.signature, \"base64\");\n if (provided.length !== digest.length || !timingSafeEqual(digest, provided)) {\n throw new Error(\"Invalid Shopify webhook signature\");\n }\n },\n catch: (cause) =>\n new ConnectorError({\n message: \"Shopify webhook verification failed\",\n cause,\n }),\n });\n\nconst decodeWebhookPayload = <A>(schema: Schema.Decoder<A>) => Schema.decodeUnknownEffect(schema);\n\nexport const make = Effect.fnUntraced(function* (config: ShopifyConfig) {\n const api = yield* ShopifyApiClient.ShopifyApiClient;\n\n const Products = Resource.entity({\n name: \"products\",\n schema: ProductSchema,\n key: \"id\",\n version: \"updatedAt\",\n check: api.checkProductsAccess,\n backfill: Fetch.page({\n pageCursor: Cursor.string(),\n cutoff: Cursor.isoDateTime(),\n fetch: ({ pageCursor, cutoff }) =>\n api\n .fetchProducts({\n first: 50,\n after: typeof pageCursor === \"string\" ? pageCursor : undefined,\n })\n .pipe(\n Effect.map((page) => ({\n mutations: page.items\n .filter((row) => Date.parse(row.updatedAt) <= Date.parse(String(cutoff)))\n .map(Resource.upsert),\n nextPageCursor: page.endCursor ?? undefined,\n hasMore: page.hasMore,\n })),\n ),\n }),\n webhook: Resource.webhook({\n schema: ProductEventSchema,\n handler: ({ payload }) => {\n if (payload._tag === \"delete\") {\n return Effect.succeed([\n Resource.delete({\n key: `gid://shopify/Product/${payload.id}`,\n version: payload.version,\n }),\n ]);\n }\n const product = payload.payload;\n if (\n product.created_at !== null &&\n product.variants.length === product.variant_gids.length\n ) {\n return Effect.succeed([\n Resource.upsert(\n ShopifyNormalize.productWebhook({ ...product, created_at: product.created_at }),\n ),\n ]);\n }\n // Refetch when Shopify truncates variants or omits the creation time.\n return api\n .fetchProductById(product.admin_graphql_api_id)\n .pipe(Effect.map((row) => [Resource.upsert(row)]));\n },\n }),\n });\n\n const CartEvents = Resource.entity({\n name: \"cart_events\",\n schema: CartEventSchema,\n key: \"id\",\n version: \"updatedAt\",\n check: api.checkConnection,\n webhook: Resource.webhook({\n schema: Schema.Struct({\n ...CartWebhookPayloadSchema.fields,\n topic: Schema.Literals([\"carts/create\", \"carts/update\"]),\n }),\n handler: ({ payload }) =>\n Effect.succeed([Resource.upsert(ShopifyNormalize.cartWebhook(payload, payload.topic))]),\n }),\n });\n\n const webhookRoute = Webhook.route({\n path: \"/webhooks/shopify\",\n ackMode: \"after-publish\",\n schema: Schema.Unknown,\n handler: ({ request, rawBody, payload: json, to }) =>\n Effect.gen(function* () {\n const verificationError = yield* verifyWebhookSignature({\n rawBody,\n signature: request.headers[\"x-shopify-hmac-sha256\"] ?? null,\n secret: Redacted.value(config.webhookSecret),\n }).pipe(Effect.match({ onFailure: (error) => error, onSuccess: () => undefined }));\n if (verificationError) {\n return HttpServerResponse.jsonUnsafe(\n { ok: false, error: verificationError.message },\n { status: 401 },\n );\n }\n\n const topic = request.headers[\"x-shopify-topic\"] ?? \"\";\n switch (topic) {\n case \"products/create\":\n case \"products/update\": {\n const payload = yield* decodeWebhookPayload(ProductWebhookPayloadSchema)(json).pipe(\n Effect.mapError(\n (cause) =>\n new ConnectorError({\n message: `Invalid Shopify webhook payload for ${topic}`,\n cause,\n }),\n ),\n Effect.match({\n onFailure: (error) => ({ _tag: \"Error\" as const, error }),\n onSuccess: (value) => ({ _tag: \"Success\" as const, value }),\n }),\n );\n if (payload._tag === \"Error\") {\n return HttpServerResponse.jsonUnsafe(\n { ok: false, error: payload.error.message },\n { status: 400 },\n );\n }\n yield* to(Products, { _tag: \"upsert\", payload: payload.value });\n break;\n }\n case \"products/delete\": {\n const triggeredAt = request.headers[\"x-shopify-triggered-at\"];\n if (!triggeredAt) {\n return HttpServerResponse.jsonUnsafe(\n { ok: false, error: \"Missing x-shopify-triggered-at header\" },\n { status: 400 },\n );\n }\n const payload = yield* decodeWebhookPayload(ProductDeleteWebhookPayloadSchema)(\n json,\n ).pipe(\n Effect.mapError(\n (cause) =>\n new ConnectorError({\n message: \"Invalid Shopify webhook payload for products/delete\",\n cause,\n }),\n ),\n Effect.match({\n onFailure: (error) => ({ _tag: \"Error\" as const, error }),\n onSuccess: (value) => ({ _tag: \"Success\" as const, value }),\n }),\n );\n if (payload._tag === \"Error\") {\n return HttpServerResponse.jsonUnsafe(\n { ok: false, error: payload.error.message },\n { status: 400 },\n );\n }\n yield* to(Products, {\n _tag: \"delete\",\n id: String(payload.value.id),\n version: triggeredAt,\n });\n break;\n }\n case \"carts/create\":\n case \"carts/update\": {\n const payload = yield* decodeWebhookPayload(CartWebhookPayloadSchema)(json).pipe(\n Effect.mapError(\n (cause) =>\n new ConnectorError({\n message: `Invalid Shopify webhook payload for ${topic}`,\n cause,\n }),\n ),\n Effect.match({\n onFailure: (error) => ({ _tag: \"Error\" as const, error }),\n onSuccess: (value) => ({ _tag: \"Success\" as const, value }),\n }),\n );\n if (payload._tag === \"Error\") {\n return HttpServerResponse.jsonUnsafe(\n { ok: false, error: payload.error.message },\n { status: 400 },\n );\n }\n yield* to(CartEvents, { ...payload.value, topic });\n break;\n }\n default:\n yield* Effect.logWarning(\"Ignoring unknown Shopify webhook topic\").pipe(\n Effect.annotateLogs({ topic }),\n );\n }\n\n return HttpServerResponse.jsonUnsafe({ ok: true });\n }),\n });\n\n return Connector.define({\n name: \"producer-shopify\",\n title: \"Shopify\",\n resources: [Products, CartEvents],\n webhooks: [webhookRoute],\n });\n});\n\nexport type ShopifyConnectorRuntime = Effect.Success<ReturnType<typeof make>>;\n\nexport class ShopifyConnector extends Context.Service<ShopifyConnector, ShopifyConnectorRuntime>()(\n \"@useairfoil/producer-shopify/ShopifyConnector\",\n) {}\n\nexport const layer = (config: ShopifyConfig) => {\n const authLayer = ShopifyAuth.layer(config);\n const apiLayer = ShopifyApiClient.layer(config).pipe(Layer.provide(authLayer));\n\n return Layer.effect(ShopifyConnector)(\n make(config).pipe(Effect.annotateLogs({ component: \"producer-shopify\" })),\n ).pipe(Layer.provide(apiLayer));\n};\n\nexport const layerConfig = (config: Config.Wrap<ShopifyConfig>) =>\n Layer.unwrap(Config.unwrap(config).pipe(Effect.map(layer)));\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useairfoil/producer-shopify",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"repository": "useairfoil/typescript-sdk",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"src",
|
|
8
|
+
"README.md"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./manifest": {
|
|
20
|
+
"types": "./dist/manifest.d.ts",
|
|
21
|
+
"import": "./dist/manifest.js",
|
|
22
|
+
"default": "./dist/manifest.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
9
25
|
"scripts": {
|
|
10
|
-
"
|
|
26
|
+
"build": "tsdown",
|
|
27
|
+
"docker:build": "docker build --load --file Dockerfile --tag airfoil/producer-shopify:local ../..",
|
|
28
|
+
"start": "tsx --env-file=.env src/main.ts start",
|
|
29
|
+
"sandbox": "tsx --env-file=.env src/main.ts sandbox",
|
|
30
|
+
"test": "dotenvx run --ignore=MISSING_ENV_FILE --quiet -- vitest",
|
|
31
|
+
"test:ci": "dotenvx run --ignore=MISSING_ENV_FILE --quiet -- vitest run",
|
|
32
|
+
"typecheck": "tsc --noEmit"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@effect/platform-node": "^4.0.0-rc.108",
|
|
36
|
+
"@effect/sql-pg": "^4.0.0-rc.108",
|
|
37
|
+
"@useairfoil/connector-kit": "0.6.0",
|
|
38
|
+
"@useairfoil/wings": "0.4.5",
|
|
39
|
+
"effect": "^4.0.0-rc.108"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@dotenvx/dotenvx": "^1.62.0",
|
|
43
|
+
"@effect/vitest": "^4.0.0-rc.108",
|
|
44
|
+
"@types/node": "^24.2.0",
|
|
45
|
+
"@useairfoil/effect-vcr": "0.4.6",
|
|
46
|
+
"tsdown": "^0.15.6",
|
|
47
|
+
"tsx": "^4.21.0",
|
|
48
|
+
"vitest": "^4.1.0"
|
|
11
49
|
}
|
|
12
50
|
}
|