Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wake): headless checkout support #800

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b425eeb
feat: Add signup/login
lui-dias Jun 1, 2024
2bf150b
feat: Add address/checkout methods
lui-dias Jun 2, 2024
01c046e
refactor: Remove generic checkout
lui-dias Jun 8, 2024
bbc93cc
...
lui-dias Jun 12, 2024
b322401
...
lui-dias Jun 13, 2024
1533345
...
lui-dias Jun 14, 2024
4a0bff9
...
lui-dias Jun 14, 2024
2cf06b5
...
lui-dias Jun 18, 2024
568e6d4
...
lui-dias Jun 20, 2024
765121e
...
lui-dias Jun 21, 2024
363b6c3
...
lui-dias Jun 24, 2024
c1a5e00
...
lui-dias Jun 25, 2024
d141c73
...
lui-dias Jun 25, 2024
abba168
...
lui-dias Jun 26, 2024
1f9b7f1
...
lui-dias Jun 27, 2024
7fb488f
...
lui-dias Jul 4, 2024
f3d7083
...
lui-dias Jul 4, 2024
c19b950
...
lui-dias Jul 4, 2024
d2cc1b0
...
lui-dias Jul 29, 2024
6d192d3
...
lui-dias Jul 29, 2024
b28ad0e
...
lui-dias Jul 29, 2024
96e714c
...
lui-dias Aug 6, 2024
dc23258
recovery password
marcoshenriquemaia Aug 16, 2024
5c31acb
debug
viktormarinho Aug 16, 2024
f4db808
remove debug logs & return proper errors on actions
viktormarinho Aug 16, 2024
43467b3
add queries
marcoshenriquemaia Aug 16, 2024
e673151
removing viktor debug
marcoshenriquemaia Aug 16, 2024
deff442
regen manifest
viktormarinho Aug 22, 2024
77c7918
Merge remote-tracking branch 'deco-cx/main' into feat--checkout-wake
viktormarinho Sep 26, 2024
7609fb1
Merge remote-tracking branch 'deco-cx/main' into feat--checkout-wake
viktormarinho Sep 27, 2024
2ca3e6d
dont use deco/ in imports
viktormarinho Sep 27, 2024
a6f7d4c
merge latest changes from deco-cx/apps/main
viktormarinho Oct 3, 2024
8fb6366
update with main
viktormarinho Oct 8, 2024
b48f2ed
format & fix conflict
viktormarinho Oct 8, 2024
02e4036
add kitGroupId to removeKit action
viktormarinho Oct 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ jobs:

- name: Benchmark
continue-on-error: true
run: deno bench --lock=deno.lock --lock-write -A .
run: deno bench --lock=deno.lock --lock-write -A .
2 changes: 1 addition & 1 deletion .github/workflows/issues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.issue.number }}
LABELS: triage
LABELS: triage
16 changes: 8 additions & 8 deletions .github/workflows/releaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ on:
- main

permissions:
contents: write # Necessary for accessing and modifying repository content
pull-requests: write # Necessary for interacting with pull requests
actions: write # Necessary for triggering other workflows
contents: write # Necessary for accessing and modifying repository content
pull-requests: write # Necessary for interacting with pull requests
actions: write # Necessary for triggering other workflows

jobs:
tag-discussion:
Expand All @@ -21,9 +21,9 @@ jobs:
- name: Checkout Code
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.base.ref }} # Checkout the base branch (target repository)
repository: ${{ github.event.pull_request.base.repo.full_name }} # Checkout from the target repo
ref: ${{ github.event.pull_request.base.ref }} # Checkout the base branch (target repository)
repository: ${{ github.event.pull_request.base.repo.full_name }} # Checkout from the target repo

- name: Calculate new versions
id: calculate_versions
run: |
Expand Down Expand Up @@ -162,11 +162,11 @@ jobs:
run: |
git tag ${{ steps.determine_version.outputs.new_version }}
git push origin ${{ steps.determine_version.outputs.new_version }}

- name: Trigger Release Workflow
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.everest-preview+json" \
https://api.github.com/repos/${{ github.repository }}/actions/workflows/release.yaml/dispatches \
-d '{"ref":"main", "inputs":{"tag_name":"${{ steps.determine_version.outputs.new_version }}"}}'
-d '{"ref":"main", "inputs":{"tag_name":"${{ steps.determine_version.outputs.new_version }}"}}'
25 changes: 25 additions & 0 deletions a.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import "npm:@graphql-codegen/typescript";
import "npm:@graphql-codegen/typescript-operations";

import { type CodegenConfig, generate } from "npm:@graphql-codegen/cli";

const config: CodegenConfig = {
schema: "https://storefront-api.fbits.net/graphql",
documents: "./wake/utils/graphql/queries.ts",
generates: {
"./wake/utils/graphql/storefront.graphql.gen.ts": {
// This order matters
plugins: [
"typescript",
"typescript-operations",
],
config: {
skipTypename: true,
enumsAsTypes: true,
},
},
},
};

await import("deco/scripts/apps/bundle.ts");
await generate({ ...config }, true);
12 changes: 12 additions & 0 deletions checkout/manifest.gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// DO NOT EDIT. This file is generated by deco.
// This file SHOULD be checked into source version control.
// This file is automatically updated during development when running `dev.ts`.

const manifest = {
"name": "checkout",
"baseUrl": import.meta.url,
};

export type Manifest = typeof manifest;

export default manifest;
1 change: 1 addition & 0 deletions deco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const config = {
app("decopilot-app"),
app("smarthint"),
app("ra-trustvox"),
app("checkout"),
app("anthropic"),
app("resend"),
app("emailjs"),
Expand Down
17 changes: 17 additions & 0 deletions shopify/utils/storefront/storefront.graphql.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7704,6 +7704,8 @@ export type FilterFragment = { id: string, label: string, type: FilterType, valu

export type CartFragment = { id: string, checkoutUrl: any, totalQuantity: number, lines: { nodes: Array<{ id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } } | { id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } }> }, cost: { subtotalAmount: { amount: any, currencyCode: CurrencyCode }, totalAmount: { amount: any, currencyCode: CurrencyCode }, checkoutChargeAmount: { amount: any, currencyCode: CurrencyCode } }, discountCodes: Array<{ code: string, applicable: boolean }>, discountAllocations: Array<{ discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } }> };

export type CustomerFragment = { id: string, email?: string | null, firstName?: string | null, lastName?: string | null };

export type CreateCartMutationVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -7767,6 +7769,13 @@ export type ProductRecommendationsQueryVariables = Exact<{

export type ProductRecommendationsQuery = { productRecommendations?: Array<{ availableForSale: boolean, createdAt: any, description: string, descriptionHtml: any, handle: string, id: string, isGiftCard: boolean, onlineStoreUrl?: any | null, productType: string, publishedAt: any, requiresSellingPlan: boolean, tags: Array<string>, title: string, totalInventory?: number | null, updatedAt: any, vendor: string, featuredImage?: { altText?: string | null, url: any } | null, images: { nodes: Array<{ altText?: string | null, url: any }> }, media: { nodes: Array<{ alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null } | { alt?: string | null, mediaContentType: MediaContentType, previewImage?: { altText?: string | null, url: any } | null }> }, options: Array<{ name: string, values: Array<string> }>, priceRange: { minVariantPrice: { amount: any, currencyCode: CurrencyCode }, maxVariantPrice: { amount: any, currencyCode: CurrencyCode } }, seo: { title?: string | null, description?: string | null }, variants: { nodes: Array<{ availableForSale: boolean, barcode?: string | null, currentlyNotInStock: boolean, id: string, quantityAvailable?: number | null, requiresShipping: boolean, sku?: string | null, title: string, weight?: number | null, weightUnit: WeightUnit, compareAtPrice?: { amount: any, currencyCode: CurrencyCode } | null, image?: { altText?: string | null, url: any } | null, price: { amount: any, currencyCode: CurrencyCode }, selectedOptions: Array<{ name: string, value: string }>, unitPrice?: { amount: any, currencyCode: CurrencyCode } | null, unitPriceMeasurement?: { measuredType?: UnitPriceMeasurementMeasuredType | null, quantityValue: number, referenceUnit?: UnitPriceMeasurementMeasuredUnit | null, quantityUnit?: UnitPriceMeasurementMeasuredUnit | null } | null }> }, collections: { nodes: Array<{ description: string, descriptionHtml: any, handle: string, id: string, title: string, updatedAt: any, image?: { altText?: string | null, url: any } | null }> } }> | null };

export type FetchCustomerInfoQueryVariables = Exact<{
customerAccessToken: Scalars['String']['input'];
}>;


export type FetchCustomerInfoQuery = { customer?: { id: string, email?: string | null, firstName?: string | null, lastName?: string | null } | null };

export type AddItemToCartMutationVariables = Exact<{
cartId: Scalars['ID']['input'];
lines: Array<CartLineInput> | CartLineInput;
Expand All @@ -7790,3 +7799,11 @@ export type UpdateItemsMutationVariables = Exact<{


export type UpdateItemsMutation = { payload?: { cart?: { id: string, checkoutUrl: any, totalQuantity: number, lines: { nodes: Array<{ id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } } | { id: string, quantity: number, merchandise: { id: string, title: string, image?: { url: any, altText?: string | null } | null, product: { title: string }, price: { amount: any, currencyCode: CurrencyCode } }, cost: { totalAmount: { amount: any, currencyCode: CurrencyCode }, subtotalAmount: { amount: any, currencyCode: CurrencyCode }, amountPerQuantity: { amount: any, currencyCode: CurrencyCode }, compareAtAmountPerQuantity?: { amount: any, currencyCode: CurrencyCode } | null } }> }, cost: { subtotalAmount: { amount: any, currencyCode: CurrencyCode }, totalAmount: { amount: any, currencyCode: CurrencyCode }, checkoutChargeAmount: { amount: any, currencyCode: CurrencyCode } }, discountCodes: Array<{ code: string, applicable: boolean }>, discountAllocations: Array<{ discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } } | { discountedAmount: { amount: any, currencyCode: CurrencyCode } }> } | null } | null };

export type SignInWithEmailAndPasswordMutationVariables = Exact<{
email: Scalars['String']['input'];
password: Scalars['String']['input'];
}>;


export type SignInWithEmailAndPasswordMutation = { customerAccessTokenCreate?: { customerAccessToken?: { accessToken: string, expiresAt: any } | null, customerUserErrors: Array<{ code?: CustomerErrorCode | null, message: string }> } | null };
149 changes: 133 additions & 16 deletions utils/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ interface GraphQLResponse<D> {
errors: unknown[];
}

type GraphQLAPI<D = unknown> = Record<string, {
response: GraphQLResponse<D>;
body: {
query: string;
variables?: Record<string, unknown>;
operationName?: string;
};
}>;
type GraphQLAPI<D = unknown> = Record<
string,
{
response: GraphQLResponse<D>;
body: {
query: string;
variables?: Record<string, unknown>;
operationName?: string;
};
}
>;

export const gql = (query: TemplateStringsArray, ...fragments: string[]) =>
query.reduce((a, c, i) => `${a}${fragments[i - 1]}${c}`);
Expand All @@ -40,22 +43,30 @@ export const createGraphqlClient = (

return {
query: async <D, V>(
{ query = "", fragments = [], variables, operationName }: {
{
query = "",
fragments = [],
variables,
operationName,
}: {
query: string;
fragments?: string[];
variables?: V;
operationName?: string;
},
init?: RequestInit,
): Promise<D> => {
const { data, errors } = await http[key as any]({}, {
...init,
body: {
query: [query, ...fragments].join("\n"),
variables: variables as any,
operationName,
const { data, errors } = await http[key as any](
{},
{
...init,
body: {
query: [query, ...fragments].join("\n"),
variables: variables as any,
operationName,
},
},
}).then((res) => res.json());
).then((res) => res.json());

if (Array.isArray(errors) && errors.length > 0) {
throw errors;
Expand All @@ -65,3 +76,109 @@ export const createGraphqlClient = (
},
};
};

/*
How update storefront.graphql.json data?
Search for this query on graphql playground


query IntrospectionQuery {
__schema {
queryType {
name
}
mutationType {
name
}
subscriptionType {
name
}
types {
...FullType
}
directives {
name
description
locations
args {
...InputValue
}
}
}
}

fragment FullType on __Type {
kind
name
description
fields(includeDeprecated: true) {
name
description
args {
...InputValue
}
type {
...TypeRef
}
isDeprecated
deprecationReason
}
inputFields {
...InputValue
}
interfaces {
...TypeRef
}
enumValues(includeDeprecated: true) {
name
description
isDeprecated
deprecationReason
}
possibleTypes {
...TypeRef
}
}

fragment InputValue on __InputValue {
name
description
type {
...TypeRef
}
defaultValue
}

fragment TypeRef on __Type {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
ofType {
kind
name
}
}
}
}
}
}
}
}
*/
40 changes: 40 additions & 0 deletions wake/actions/associateCheckout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { badRequest } from "@deco/deco";
import type { AppContext } from "../mod.ts";
import authenticate from "../utils/authenticate.ts";
import { getCartCookie } from "../utils/cart.ts";
import ensureCheckout from "../utils/ensureCheckout.ts";
import ensureCustomerToken from "../utils/ensureCustomerToken.ts";
import { CheckoutCustomerAssociate } from "../utils/graphql/queries.ts";
import type {
CheckoutCustomerAssociateMutation,
CheckoutCustomerAssociateMutationVariables,
} from "../utils/graphql/storefront.graphql.gen.ts";
import { parseHeaders } from "../utils/parseHeaders.ts";

// https://wakecommerce.readme.io/docs/storefront-api-checkoutcustomerassociate
export default async function (_props: object, req: Request, ctx: AppContext) {
try {
const headers = parseHeaders(req.headers);
const checkoutId = ensureCheckout(getCartCookie(req.headers));
const customerAccessToken = ensureCustomerToken(
await authenticate(req, ctx),
);

// associate account to checkout
await ctx.storefront.query<
CheckoutCustomerAssociateMutation,
CheckoutCustomerAssociateMutationVariables
>(
{
variables: {
customerAccessToken,
checkoutId,
},
...CheckoutCustomerAssociate,
},
{ headers },
);
} catch (err) {
throw badRequest(err);
}
}
Loading
Loading