diff --git a/packages/react/src/ShopifyCookies.tsx b/packages/react/src/ShopifyCookies.tsx
index 3fd9c3f1..0a5764ab 100644
--- a/packages/react/src/ShopifyCookies.tsx
+++ b/packages/react/src/ShopifyCookies.tsx
@@ -16,6 +16,17 @@ interface ShopifyCookiesProps {
hasUserConsent?: boolean;
}
+/**
+ * Set user and session cookies and refresh the expiry time
+ * @param domain - The domain scope of the cookie
+ * @param hasUserConsent - Defaults to false. If hasUserConsent is true, we can set Shopify unique user token cookie
+ * @example
+ * ```tsx
+ * import {ShopifyCookies} from '@shopify/hydrogen-react';
+ *
+ *
+ * ```
+ */
export function ShopifyCookies(props: ShopifyCookiesProps) {
const {domain = '', hasUserConsent = false} = props;
diff --git a/packages/react/src/analytics-utils.ts b/packages/react/src/analytics-utils.ts
index 7abb3899..f9b48cff 100644
--- a/packages/react/src/analytics-utils.ts
+++ b/packages/react/src/analytics-utils.ts
@@ -26,25 +26,40 @@ export function schemaWrapper(schemaId: string, payload: object) {
* Parses global id (gid) and returns the resource type and id.
* @see https://shopify.dev/api/usage/gids
* @param gid - A shopify GID (string)
- * @returns \{ id: number, resource: string \}
+ * @returns \{ id: string | number | null, resource: string| null \}
*
* @example
* ```ts
* const {id, resource} = parseGid('gid://shopify/Order/123')
* // => id = 123, resource = 'Order'
+ *
+ * * const {id, resource} = parseGid('gid://shopify/Cart/abc123')
+ * // => id = "abc123", resource = 'Cart'
* ```
**/
export function parseGid(gid: string | undefined): {
- id: number | null;
+ id: string | number | null;
resource: string | null;
} {
- if (typeof gid !== 'string') return {id: null, resource: null};
- const matches = gid.match(/^gid:\/\/.hopify\/(\w+)\/(\d+)/);
+ const defaultReturn = {id: null, resource: null};
+
+ if (typeof gid !== 'string') {
+ return defaultReturn;
+ }
+
+ // TODO: add support for parsing query parameters on complex gids
+ const matches = gid.match(/^gid:\/\/.hopify\/(\w+)\/([a-z0-9]+)/);
+
if (!matches || matches.length === 1) {
- return {id: null, resource: null};
+ return defaultReturn;
+ }
+ const id = matches[2] ?? null;
+ const resource = matches[1] ?? null;
+
+ // if id is of only numbers, return as an integer
+ if (id && /^\d+$/.test(id)) {
+ return {id: parseInt(id, 10), resource};
}
- const id = matches[2] ? parseInt(matches[2], 10) : null;
- const resource = matches[1] ? matches[1] : null;
return {id, resource};
}
diff --git a/packages/react/src/cookie-utils.test.ts b/packages/react/src/cookie-utils.test.ts
new file mode 100644
index 00000000..e3a8b345
--- /dev/null
+++ b/packages/react/src/cookie-utils.test.ts
@@ -0,0 +1,31 @@
+import {
+ buildUUID,
+ hexTime,
+ getShopifyCookies,
+ ShopifyCookies,
+} from './cookies-utils.js';
+
+describe('cookies-utils', () => {
+ describe('buildUUID', () => {
+ it('returns a string', () => {
+ expect(typeof buildUUID()).toBe('string');
+ });
+ });
+
+ describe('hexTime', () => {
+ it('returns a string', () => {
+ expect(typeof hexTime()).toBe('string');
+ });
+ });
+
+ describe('getShopifyCookies', () => {
+ it('returns object with SHOPIFY_Y and SHOPIFY_X', () => {
+ const cookie =
+ '_shopify_m=persistent; _y=44c60bb0-577c-4901-874c-92cb323fccf1; _shopify_y=44c60bb0-577c-4901-874c-92cb323fccf1; _shopify_y=44c60bb0-577c-4901-874c-92cb323fccf1; _tracking_consent={"lim":["GDPR"],"v":"2.0","con":{"GDPR":""},"reg":"CCPA"}; _shopify_s=a797b9ef-C0E7-4536-18BA-2828BA504882';
+ expect(getShopifyCookies(cookie)).toMatchObject({
+ _shopify_y: '44c60bb0-577c-4901-874c-92cb323fccf1',
+ _shopify_s: 'a797b9ef-C0E7-4536-18BA-2828BA504882',
+ });
+ });
+ });
+});