diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1028e2e3d6..d045822cef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,19 +12,18 @@ Run the following commands to get started working on Hydrogen. | ----------------------------------------------- | --------------------------------------------- | | `git clone git@github.com:Shopify/hydrogen.git` | Clones the repo to your local computer | | `pnpm install` | Installs the dependencies with `pnpm` | -| `ppnpm run dev` | Runs the `dev` command in all packages | +| `ppnpm run dev` | Runs the `dev` command in all packages | | `pnpm run build` | `build`s packages for production distribution | ### Shopify Contributors If you have access to Shopify's `dev` CLI tool, you can use these commands instead: -| Command | Description | -| ------------ | ---------------------------------------------------------- | +| Command | Description | +| ------------ | ------------------------------------------------------------------------------- | | `dev up` | Sets up the development environment (installs dependencies and builds packages) | -| `dev server` | Starts the skeleton template dev server | -| `dev watch` | Starts a server to automatically rebuild changes in packages upon saving | - +| `dev server` | Starts the skeleton template dev server | +| `dev watch` | Starts a server to automatically rebuild changes in packages upon saving | > **Note:** When running `dev up`, if prompted about git hooks, select **"no"** to preserve the existing Husky hooks configuration. The project uses Husky for pre-commit hooks, and overriding this would disable important checks. @@ -40,8 +39,9 @@ Hydrogen is a monorepo built with [Turborepo](https://turbo.build/) and consists - `packages/hydrogen`: Opinionated [Remix](https://remix.run) components, hooks, and utilities provided by Hydrogen - `packages/hydrogen-react`: Platform-agnostic components, hooks, and utilities. This package is used by Hydrogen and published on its own for use by other React-based frameworks. -- `packages/create-hydrogen`: Package scripts to create new Hydrogen apps from the command line. +- `packages/hydrogen-core`: Framework-agnostic core utilities shared across Hydrogen packages. - `packages/hydrogen-codegen`: GraphQL <> TypeScript code generator for Storefront API queries. +- `packages/create-hydrogen`: Package scripts to create new Hydrogen apps from the command line. - `packages/remix-oxygen`: A [Remix](https://remix.run) runtime adapter for [Oxygen](https://shopify.dev/custom-storefronts/oxygen), Shopify’s serverless hosting platform. - `packages/cli`: A plugin for the [Shopify CLI](https://github.com/Shopify/cli) to provide specific commands for working on Hydrogen storefronts. - `templates`: Full working implementations of Hydrogen storefronts. Used for scaffolding new starter Hydrogen apps, testing, and feature development. @@ -54,8 +54,8 @@ The `Readme.md` files in the directories of individual packages and templates co The Hydrogen monorepo provides commands for linting and formatting, and uses [Husky](https://typicode.github.io/husky/) to run checks on staged commits automatically. -| Command | Description | -| ------------------- | ----------------------------------------- | +| Command | Description | +| -------------------- | ----------------------------------------- | | `pnpm run typecheck` | Checks source-code for invalid TypeScript | | `pnpm run lint` | Lints the code with ESLint | | `pnpm run format` | Formats the code with prettier | @@ -83,8 +83,8 @@ Hydrogen follows common React naming conventions for filenames, component names, If you are contributing a user-facing or noteworthy change to Hydrogen that should be added to the changelog, you should include a changeset with your PR by running the following command. -| Command | Description | -| ----------------------- | ----------------------- | +| Command | Description | +| ------------------------ | ----------------------- | | `pnpm run changeset add` | Add a changeset locally | Follow the prompts to select which package(s) are affected by your change, and whether the change is a major, minor or patch change. This will create a file in the `.changesets` directory of the repo. This change should be committed and included with your PR. @@ -101,8 +101,8 @@ When merging PRs, please select the **Squash and Merge** option, which consolida Hydrogen tests are run using [vitest](https://vitest.dev). You can run the tests with the following commands. -| Command | Description | -| -------------------- | ------------------------------------------------------- | +| Command | Description | +| --------------------- | ------------------------------------------------------- | | `pnpm run test` | Run the tests once | | `pnpm run test:watch` | Run the tests once and re-run them when files are saved | @@ -180,6 +180,7 @@ We use the ejson file `secrets.ejson` to store all our secrets. You can add new Secrets can only be decrypted if you have the private key. If you are new to the Shopify Hydrogen team, ask one of the other team members to send you a hush link with the private key. Once you have the hush link, paste this command in your terminal **WITHOUT running it yet**, then copy the private key value (from the hush link) to your clipboard and run the command: + ``` ./scripts/setup-ejson-private-key.sh ``` diff --git a/package.json b/package.json index 1058667912..9a99f2d758 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@shopify/cli": "3.91.1", "@total-typescript/ts-reset": "^0.6.1", "@types/eslint": "9.6.1", + "@types/node": "catalog:", "@types/semver": "^7.5.8", "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", diff --git a/packages/hydrogen-core/README.md b/packages/hydrogen-core/README.md new file mode 100644 index 0000000000..896c408f32 --- /dev/null +++ b/packages/hydrogen-core/README.md @@ -0,0 +1,9 @@ +# @shopify/hydrogen-core + +Framework-agnostic core utilities shared across Hydrogen packages. This package provides foundational helpers that are not tied to any specific rendering framework, making them reusable across the Hydrogen ecosystem. + +[Check out the docs](https://shopify.dev/custom-storefronts/hydrogen) + +## Contributing + +Interested in contributing? [Read our contributing guide](../../CONTRIBUTING.md) diff --git a/packages/hydrogen-core/package.json b/packages/hydrogen-core/package.json new file mode 100644 index 0000000000..6bb74c7127 --- /dev/null +++ b/packages/hydrogen-core/package.json @@ -0,0 +1,42 @@ +{ + "name": "@shopify/hydrogen-core", + "version": "0.0.0", + "description": "Framework-agnostic core utilities shared across Hydrogen packages", + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "publishConfig": { + "access": "public", + "@shopify:registry": "https://registry.npmjs.org" + }, + "type": "module", + "files": [ + "dist", + "skills" + ], + "sideEffects": false, + "repository": { + "type": "git", + "url": "https://github.com/Shopify/hydrogen", + "directory": "packages/hydrogen-core" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "tsup", + "test": "vitest run", + "test:watch": "vitest" + }, + "dependencies": {}, + "peerDependencies": {}, + "devDependencies": { + "tsup": "^8.4.0", + "@types/node": "catalog:", + "vitest": "^3.2.4" + } +} diff --git a/packages/hydrogen-core/skills/hydrogen-core-docs/SKILL.md b/packages/hydrogen-core/skills/hydrogen-core-docs/SKILL.md new file mode 100644 index 0000000000..6f00977e2d --- /dev/null +++ b/packages/hydrogen-core/skills/hydrogen-core-docs/SKILL.md @@ -0,0 +1,26 @@ +--- +name: hydrogen-core-docs +description: > + Guide for working with framework-agnostic core utilities + shared across Hydrogen. + Use when importing from `@shopify/hydrogen/core` or `@shopify/hydrogen-core`. +--- + +# @shopify/hydrogen-core + +`@shopify/hydrogen-core` provides framework-agnostic core utilities shared across the Hydrogen ecosystem. It can also be used from `@shopify/hydrogen` using the `core` entrypoint. + +## Public API + +### Mock Shop Utilities + +- `MOCK_SHOP_DOMAIN` — The domain string for Shopify's mock shop +- `isMockShop(domain: string): boolean` — Returns `true` if the given domain contains the mock shop domain + +## Architecture + +This package is the lowest layer in the Hydrogen package hierarchy. It contains utilities that: + +- Have **no framework dependencies** (no React, no Remix, no Node-specific APIs) +- Are shared by multiple Hydrogen packages (e.g., `@shopify/hydrogen`, `@shopify/cli-hydrogen`) +- Need to be independently testable and tree-shakeable diff --git a/packages/hydrogen-core/src/index.ts b/packages/hydrogen-core/src/index.ts new file mode 100644 index 0000000000..4dcbd57076 --- /dev/null +++ b/packages/hydrogen-core/src/index.ts @@ -0,0 +1 @@ +export * from './mock-shop'; diff --git a/packages/hydrogen-core/src/mock-shop.test.ts b/packages/hydrogen-core/src/mock-shop.test.ts new file mode 100644 index 0000000000..4057630a35 --- /dev/null +++ b/packages/hydrogen-core/src/mock-shop.test.ts @@ -0,0 +1,20 @@ +import {describe, it, expect} from 'vitest'; +import {isMockShop, MOCK_SHOP_DOMAIN} from './mock-shop'; + +describe('isMockShop', () => { + it('returns true for the exact mock.shop domain', () => { + expect(isMockShop(MOCK_SHOP_DOMAIN)).toBe(true); + }); + + it('returns true when mock.shop appears within a URL', () => { + expect(isMockShop('https://mock.shop/api/graphql')).toBe(true); + }); + + it('returns false for a real shop domain', () => { + expect(isMockShop('my-store.myshopify.com')).toBe(false); + }); + + it('returns false for an empty string', () => { + expect(isMockShop('')).toBe(false); + }); +}); diff --git a/packages/hydrogen-core/src/mock-shop.ts b/packages/hydrogen-core/src/mock-shop.ts new file mode 100644 index 0000000000..8f0f9464e0 --- /dev/null +++ b/packages/hydrogen-core/src/mock-shop.ts @@ -0,0 +1,3 @@ +export const MOCK_SHOP_DOMAIN = 'mock.shop'; +export const isMockShop = (domain: string): boolean => + domain.includes(MOCK_SHOP_DOMAIN); diff --git a/packages/hydrogen-core/tsconfig.json b/packages/hydrogen-core/tsconfig.json new file mode 100644 index 0000000000..de336bb879 --- /dev/null +++ b/packages/hydrogen-core/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*.ts", "globals.d.ts"], + "compilerOptions": { + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "dist", + "rootDir": ".", + "moduleResolution": "bundler", + "types": ["node"] + } +} diff --git a/packages/hydrogen-core/tsup.config.ts b/packages/hydrogen-core/tsup.config.ts new file mode 100644 index 0000000000..d2d2886024 --- /dev/null +++ b/packages/hydrogen-core/tsup.config.ts @@ -0,0 +1,17 @@ +import {defineConfig, Options} from 'tsup'; + +const sharedConfig: Options = { + splitting: false, + sourcemap: true, + clean: true, + format: ['esm'], +}; + +export default defineConfig([ + { + ...sharedConfig, + dts: true, + entry: ['src/index.ts'], + tsconfig: 'tsconfig.json', + }, +]); diff --git a/packages/hydrogen-core/vitest.config.ts b/packages/hydrogen-core/vitest.config.ts new file mode 100644 index 0000000000..b0602bf772 --- /dev/null +++ b/packages/hydrogen-core/vitest.config.ts @@ -0,0 +1,8 @@ +import {defineConfig} from 'vitest/config'; + +export default defineConfig({ + test: { + globals: false, + environment: 'happy-dom', + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74fcab1358..6861edde0e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -98,6 +98,9 @@ importers: '@types/eslint': specifier: 9.6.1 version: 9.6.1 + '@types/node': + specifier: 22.19.15 + version: 22.19.15 '@types/semver': specifier: ^7.5.8 version: 7.7.1 @@ -544,6 +547,18 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(happy-dom@20.8.9)(jiti@2.6.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.2))(yaml@2.8.3) + packages/hydrogen-core: + devDependencies: + '@types/node': + specifier: 22.19.15 + version: 22.19.15 + tsup: + specifier: ^8.4.0 + version: 8.5.1(@swc/core@1.15.11)(jiti@2.6.1)(postcss@8.5.8)(typescript@5.9.2)(yaml@2.8.3) + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.15)(happy-dom@20.8.9)(jiti@2.6.1)(lightningcss@1.30.2)(msw@2.12.10(@types/node@22.19.15)(typescript@5.9.2))(yaml@2.8.3) + packages/hydrogen-react: dependencies: '@google/model-viewer': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 88bb73b947..a5fed5b9d5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,6 +4,7 @@ packages: - packages/cli - packages/create-hydrogen - packages/hydrogen-codegen + - packages/hydrogen-core - packages/hydrogen-react - packages/hydrogen - packages/mini-oxygen