@shopify/cli-hydrogen 7.1.2 → 8.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.
- package/dist/commands/hydrogen/build-vite.js +19 -10
- package/dist/commands/hydrogen/build.js +10 -2
- package/dist/commands/hydrogen/check.js +1 -0
- package/dist/commands/hydrogen/codegen.js +1 -0
- package/dist/commands/hydrogen/customer-account/push.js +170 -0
- package/dist/commands/hydrogen/debug/cpu.js +10 -1
- package/dist/commands/hydrogen/deploy.js +110 -36
- package/dist/commands/hydrogen/dev-vite.js +128 -59
- package/dist/commands/hydrogen/dev.js +108 -51
- package/dist/commands/hydrogen/env/list.js +20 -28
- package/dist/commands/hydrogen/env/pull.js +29 -19
- package/dist/commands/hydrogen/env/{push__unstable.js → push.js} +34 -68
- package/dist/commands/hydrogen/generate/route.js +1 -0
- package/dist/commands/hydrogen/init.js +39 -21
- package/dist/commands/hydrogen/link.js +25 -6
- package/dist/commands/hydrogen/list.js +1 -0
- package/dist/commands/hydrogen/login.js +1 -0
- package/dist/commands/hydrogen/logout.js +1 -0
- package/dist/commands/hydrogen/preview.js +31 -16
- package/dist/commands/hydrogen/setup/css.js +8 -1
- package/dist/commands/hydrogen/setup/markets.js +1 -0
- package/dist/commands/hydrogen/setup/vite.js +244 -138
- package/dist/commands/hydrogen/setup.js +21 -23
- package/dist/commands/hydrogen/shortcut.js +10 -0
- package/dist/commands/hydrogen/unlink.js +1 -0
- package/dist/commands/hydrogen/upgrade.js +2 -1
- package/dist/generator-templates/assets/vite/package.json +3 -4
- package/dist/generator-templates/assets/vite/vite.config.js +15 -2
- package/dist/generator-templates/starter/CHANGELOG.md +129 -0
- package/dist/generator-templates/starter/README.md +3 -44
- package/dist/generator-templates/starter/app/components/Footer.tsx +1 -1
- package/dist/generator-templates/starter/app/components/Header.tsx +1 -1
- package/dist/generator-templates/starter/app/graphql/customer-account/CustomerDetailsQuery.ts +1 -0
- package/dist/generator-templates/starter/app/lib/fragments.ts +2 -0
- package/dist/generator-templates/starter/app/lib/root-data.ts +11 -0
- package/dist/generator-templates/starter/app/root.tsx +4 -20
- package/dist/generator-templates/starter/app/routes/account.orders._index.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/account.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/blogs.$blogHandle._index.tsx +3 -3
- package/dist/generator-templates/starter/app/routes/cart.tsx +1 -1
- package/dist/generator-templates/starter/app/routes/collections.all.tsx +160 -0
- package/dist/generator-templates/starter/app/routes/products.$handle.tsx +1 -2
- package/dist/generator-templates/starter/customer-accountapi.generated.d.ts +6 -3
- package/dist/generator-templates/starter/{remix.env.d.ts → env.d.ts} +8 -2
- package/dist/generator-templates/starter/package.json +14 -9
- package/dist/generator-templates/starter/server.ts +2 -1
- package/dist/generator-templates/starter/storefrontapi.generated.d.ts +59 -3
- package/dist/generator-templates/starter/vite.config.ts +26 -0
- package/dist/{commands/hydrogen/init.d.ts → init.d.ts} +11 -4
- package/dist/lib/check-lockfile.js +12 -18
- package/dist/lib/codegen.js +37 -13
- package/dist/lib/common.js +50 -0
- package/dist/lib/cpu-profiler.js +4 -1
- package/dist/lib/dev-shared.js +99 -0
- package/dist/lib/environment-variables.js +51 -30
- package/dist/lib/file.js +8 -1
- package/dist/lib/flags.js +37 -26
- package/dist/lib/get-oxygen-deployment-data.js +10 -17
- package/dist/lib/graphql/admin/customer-application-update.js +29 -0
- package/dist/lib/graphql/admin/get-oxygen-data.js +1 -0
- package/dist/lib/graphql/admin/list-environments.js +1 -0
- package/dist/lib/graphql/admin/pull-variables.js +4 -4
- package/dist/lib/graphql/admin/test-helper.js +37 -0
- package/dist/lib/log.js +86 -13
- package/dist/lib/mini-oxygen/common.js +19 -33
- package/dist/lib/mini-oxygen/index.js +6 -2
- package/dist/lib/mini-oxygen/node.js +43 -31
- package/dist/lib/mini-oxygen/workerd.js +72 -165
- package/dist/lib/missing-routes.js +1 -1
- package/dist/lib/onboarding/common.js +85 -70
- package/dist/lib/onboarding/local.js +19 -9
- package/dist/lib/onboarding/remote.js +35 -30
- package/dist/lib/package-managers.js +24 -0
- package/dist/lib/remix-config.js +17 -1
- package/dist/lib/render-errors.js +17 -10
- package/dist/lib/request-events.js +6 -1
- package/dist/lib/setups/i18n/replacers.js +9 -6
- package/dist/lib/setups/routes/generate.js +1 -0
- package/dist/lib/shell.js +2 -1
- package/dist/lib/shopify-config.js +19 -1
- package/dist/lib/template-diff.js +36 -15
- package/dist/lib/template-downloader.js +35 -5
- package/dist/lib/transpile/morph/functions.js +26 -8
- package/dist/lib/transpile/morph/typedefs.js +6 -4
- package/dist/lib/transpile/project.js +8 -4
- package/dist/lib/tunneling.js +44 -0
- package/dist/lib/verify-linked-storefront.js +24 -0
- package/dist/lib/virtual-routes.js +1 -1
- package/dist/lib/vite-config.js +39 -9
- package/oclif.manifest.json +704 -508
- package/package.json +32 -24
- package/dist/commands/hydrogen/deploy.test.js +0 -553
- package/dist/commands/hydrogen/env/list.test.js +0 -148
- package/dist/commands/hydrogen/env/pull.test.js +0 -207
- package/dist/commands/hydrogen/env/push__unstable.test.js +0 -383
- package/dist/commands/hydrogen/generate/route.test.js +0 -43
- package/dist/commands/hydrogen/init.test.js +0 -641
- package/dist/commands/hydrogen/link.test.js +0 -187
- package/dist/commands/hydrogen/list.test.js +0 -111
- package/dist/commands/hydrogen/setup.test.js +0 -61
- package/dist/commands/hydrogen/shortcut.test.js +0 -30
- package/dist/commands/hydrogen/unlink.test.js +0 -36
- package/dist/commands/hydrogen/upgrade.test.js +0 -786
- package/dist/generator-templates/starter/remix.config.js +0 -24
- package/dist/lib/auth.test.js +0 -157
- package/dist/lib/check-lockfile.test.js +0 -81
- package/dist/lib/check-version.test.js +0 -86
- package/dist/lib/environment-variables.test.js +0 -149
- package/dist/lib/file.test.js +0 -68
- package/dist/lib/flags.test.js +0 -43
- package/dist/lib/get-oxygen-deployment-data.test.js +0 -120
- package/dist/lib/gid.test.js +0 -15
- package/dist/lib/graphql/admin/client.test.js +0 -76
- package/dist/lib/graphql/admin/create-storefront.test.js +0 -64
- package/dist/lib/graphql/admin/link-storefront.test.js +0 -38
- package/dist/lib/graphql/admin/list-environments.test.js +0 -44
- package/dist/lib/graphql/admin/list-storefronts.test.js +0 -44
- package/dist/lib/graphql/admin/pull-variables.test.js +0 -43
- package/dist/lib/graphql/business-platform/user-account.test.js +0 -80
- package/dist/lib/log.test.js +0 -92
- package/dist/lib/mini-oxygen/assets.js +0 -134
- package/dist/lib/mini-oxygen/mini-oxygen.test.js +0 -214
- package/dist/lib/mini-oxygen/workerd-inspector-logs.js +0 -227
- package/dist/lib/mini-oxygen/workerd-inspector-proxy.js +0 -200
- package/dist/lib/mini-oxygen/workerd-inspector.js +0 -219
- package/dist/lib/missing-routes.test.js +0 -45
- package/dist/lib/remix-version-check.test.js +0 -39
- package/dist/lib/remix-version-interop.test.js +0 -13
- package/dist/lib/setups/i18n/domains.test.js +0 -39
- package/dist/lib/setups/i18n/replacers.test.js +0 -261
- package/dist/lib/setups/i18n/subdomains.test.js +0 -39
- package/dist/lib/setups/i18n/subfolders.test.js +0 -39
- package/dist/lib/setups/routes/generate.test.js +0 -296
- package/dist/lib/shell.test.js +0 -111
- package/dist/lib/shopify-config.test.js +0 -199
- package/dist/lib/string.test.js +0 -16
- package/dist/lib/virtual-routes.test.js +0 -49
- package/dist/lib/vite/hydrogen-middleware.js +0 -82
- package/dist/lib/vite/mini-oxygen.js +0 -152
- package/dist/lib/vite/plugins.d.ts +0 -27
- package/dist/lib/vite/plugins.js +0 -139
- package/dist/lib/vite/shared.js +0 -10
- package/dist/lib/vite/utils.js +0 -55
- package/dist/lib/vite/worker-entry.js +0 -1518
- /package/dist/generator-templates/starter/{.eslintrc.js → .eslintrc.cjs} +0 -0
|
@@ -31,7 +31,7 @@ export type CartLineFragment = Pick<
|
|
|
31
31
|
image?: StorefrontAPI.Maybe<
|
|
32
32
|
Pick<StorefrontAPI.Image, 'id' | 'url' | 'altText' | 'width' | 'height'>
|
|
33
33
|
>;
|
|
34
|
-
product: Pick<StorefrontAPI.Product, 'handle' | 'title' | 'id'>;
|
|
34
|
+
product: Pick<StorefrontAPI.Product, 'handle' | 'title' | 'id' | 'vendor'>;
|
|
35
35
|
selectedOptions: Array<
|
|
36
36
|
Pick<StorefrontAPI.SelectedOption, 'name' | 'value'>
|
|
37
37
|
>;
|
|
@@ -40,7 +40,7 @@ export type CartLineFragment = Pick<
|
|
|
40
40
|
|
|
41
41
|
export type CartApiQueryFragment = Pick<
|
|
42
42
|
StorefrontAPI.Cart,
|
|
43
|
-
'id' | 'checkoutUrl' | 'totalQuantity' | 'note'
|
|
43
|
+
'updatedAt' | 'id' | 'checkoutUrl' | 'totalQuantity' | 'note'
|
|
44
44
|
> & {
|
|
45
45
|
buyerIdentity: Pick<
|
|
46
46
|
StorefrontAPI.CartBuyerIdentity,
|
|
@@ -81,7 +81,10 @@ export type CartApiQueryFragment = Pick<
|
|
|
81
81
|
'id' | 'url' | 'altText' | 'width' | 'height'
|
|
82
82
|
>
|
|
83
83
|
>;
|
|
84
|
-
product: Pick<
|
|
84
|
+
product: Pick<
|
|
85
|
+
StorefrontAPI.Product,
|
|
86
|
+
'handle' | 'title' | 'id' | 'vendor'
|
|
87
|
+
>;
|
|
85
88
|
selectedOptions: Array<
|
|
86
89
|
Pick<StorefrontAPI.SelectedOption, 'name' | 'value'>
|
|
87
90
|
>;
|
|
@@ -673,6 +676,55 @@ export type StoreCollectionsQuery = {
|
|
|
673
676
|
};
|
|
674
677
|
};
|
|
675
678
|
|
|
679
|
+
export type CatalogQueryVariables = StorefrontAPI.Exact<{
|
|
680
|
+
country?: StorefrontAPI.InputMaybe<StorefrontAPI.CountryCode>;
|
|
681
|
+
language?: StorefrontAPI.InputMaybe<StorefrontAPI.LanguageCode>;
|
|
682
|
+
first?: StorefrontAPI.InputMaybe<StorefrontAPI.Scalars['Int']['input']>;
|
|
683
|
+
last?: StorefrontAPI.InputMaybe<StorefrontAPI.Scalars['Int']['input']>;
|
|
684
|
+
startCursor?: StorefrontAPI.InputMaybe<
|
|
685
|
+
StorefrontAPI.Scalars['String']['input']
|
|
686
|
+
>;
|
|
687
|
+
endCursor?: StorefrontAPI.InputMaybe<
|
|
688
|
+
StorefrontAPI.Scalars['String']['input']
|
|
689
|
+
>;
|
|
690
|
+
}>;
|
|
691
|
+
|
|
692
|
+
export type CatalogQuery = {
|
|
693
|
+
products: {
|
|
694
|
+
nodes: Array<
|
|
695
|
+
Pick<StorefrontAPI.Product, 'id' | 'handle' | 'title'> & {
|
|
696
|
+
featuredImage?: StorefrontAPI.Maybe<
|
|
697
|
+
Pick<
|
|
698
|
+
StorefrontAPI.Image,
|
|
699
|
+
'id' | 'altText' | 'url' | 'width' | 'height'
|
|
700
|
+
>
|
|
701
|
+
>;
|
|
702
|
+
priceRange: {
|
|
703
|
+
minVariantPrice: Pick<
|
|
704
|
+
StorefrontAPI.MoneyV2,
|
|
705
|
+
'amount' | 'currencyCode'
|
|
706
|
+
>;
|
|
707
|
+
maxVariantPrice: Pick<
|
|
708
|
+
StorefrontAPI.MoneyV2,
|
|
709
|
+
'amount' | 'currencyCode'
|
|
710
|
+
>;
|
|
711
|
+
};
|
|
712
|
+
variants: {
|
|
713
|
+
nodes: Array<{
|
|
714
|
+
selectedOptions: Array<
|
|
715
|
+
Pick<StorefrontAPI.SelectedOption, 'name' | 'value'>
|
|
716
|
+
>;
|
|
717
|
+
}>;
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
>;
|
|
721
|
+
pageInfo: Pick<
|
|
722
|
+
StorefrontAPI.PageInfo,
|
|
723
|
+
'hasPreviousPage' | 'hasNextPage' | 'startCursor' | 'endCursor'
|
|
724
|
+
>;
|
|
725
|
+
};
|
|
726
|
+
};
|
|
727
|
+
|
|
676
728
|
export type PageQueryVariables = StorefrontAPI.Exact<{
|
|
677
729
|
language?: StorefrontAPI.InputMaybe<StorefrontAPI.LanguageCode>;
|
|
678
730
|
country?: StorefrontAPI.InputMaybe<StorefrontAPI.CountryCode>;
|
|
@@ -1119,6 +1171,10 @@ interface GeneratedQueryTypes {
|
|
|
1119
1171
|
return: StoreCollectionsQuery;
|
|
1120
1172
|
variables: StoreCollectionsQueryVariables;
|
|
1121
1173
|
};
|
|
1174
|
+
'#graphql\n query Catalog(\n $country: CountryCode\n $language: LanguageCode\n $first: Int\n $last: Int\n $startCursor: String\n $endCursor: String\n ) @inContext(country: $country, language: $language) {\n products(first: $first, last: $last, before: $startCursor, after: $endCursor) {\n nodes {\n ...ProductItem\n }\n pageInfo {\n hasPreviousPage\n hasNextPage\n startCursor\n endCursor\n }\n }\n }\n #graphql\n fragment MoneyProductItem on MoneyV2 {\n amount\n currencyCode\n }\n fragment ProductItem on Product {\n id\n handle\n title\n featuredImage {\n id\n altText\n url\n width\n height\n }\n priceRange {\n minVariantPrice {\n ...MoneyProductItem\n }\n maxVariantPrice {\n ...MoneyProductItem\n }\n }\n variants(first: 1) {\n nodes {\n selectedOptions {\n name\n value\n }\n }\n }\n }\n\n': {
|
|
1175
|
+
return: CatalogQuery;
|
|
1176
|
+
variables: CatalogQueryVariables;
|
|
1177
|
+
};
|
|
1122
1178
|
'#graphql\n query Page(\n $language: LanguageCode,\n $country: CountryCode,\n $handle: String!\n )\n @inContext(language: $language, country: $country) {\n page(handle: $handle) {\n id\n title\n body\n seo {\n description\n title\n }\n }\n }\n': {
|
|
1123
1179
|
return: PageQuery;
|
|
1124
1180
|
variables: PageQueryVariables;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {defineConfig} from 'vite';
|
|
2
|
+
import {hydrogen} from '@shopify/hydrogen/vite';
|
|
3
|
+
import {oxygen} from '@shopify/mini-oxygen/vite';
|
|
4
|
+
import {vitePlugin as remix} from '@remix-run/dev';
|
|
5
|
+
import tsconfigPaths from 'vite-tsconfig-paths';
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
plugins: [
|
|
9
|
+
hydrogen(),
|
|
10
|
+
oxygen(),
|
|
11
|
+
remix({
|
|
12
|
+
presets: [hydrogen.preset()],
|
|
13
|
+
future: {
|
|
14
|
+
v3_fetcherPersist: true,
|
|
15
|
+
v3_relativeSplatPath: true,
|
|
16
|
+
v3_throwAbortReason: true,
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
tsconfigPaths(),
|
|
20
|
+
],
|
|
21
|
+
build: {
|
|
22
|
+
// Allow a strict Content-Security-Policy
|
|
23
|
+
// withtout inlining assets as base64:
|
|
24
|
+
assetsInlineLimit: 0,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _oclif_core_lib_interfaces_parser_js from '@oclif/core/lib/interfaces/parser.js';
|
|
2
2
|
import Command from '@shopify/cli-kit/node/base-command';
|
|
3
|
+
import { PackageManager } from '@shopify/cli-kit/node/node-package-manager';
|
|
3
4
|
|
|
4
5
|
declare const GENERATOR_SETUP_ASSETS_SUB_DIRS: readonly ["tailwind", "css-modules", "vanilla-extract", "postcss", "vite"];
|
|
5
6
|
type AssetDir = (typeof GENERATOR_SETUP_ASSETS_SUB_DIRS)[number];
|
|
@@ -25,6 +26,8 @@ type InitOptions = {
|
|
|
25
26
|
shortcut?: boolean;
|
|
26
27
|
installDeps?: boolean;
|
|
27
28
|
git?: boolean;
|
|
29
|
+
quickstart?: boolean;
|
|
30
|
+
packageManager?: PackageManager;
|
|
28
31
|
};
|
|
29
32
|
declare const LANGUAGES: {
|
|
30
33
|
readonly js: "JavaScript";
|
|
@@ -33,13 +36,15 @@ declare const LANGUAGES: {
|
|
|
33
36
|
type Language = keyof typeof LANGUAGES;
|
|
34
37
|
|
|
35
38
|
declare class Init extends Command {
|
|
39
|
+
static descriptionWithMarkdown: string;
|
|
36
40
|
static description: string;
|
|
37
41
|
static flags: {
|
|
38
42
|
routes: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
39
43
|
git: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
44
|
+
quickstart: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
45
|
+
'package-manager': _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
40
46
|
shortcut: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
41
47
|
markets: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
42
|
-
styling: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
43
48
|
'mock-shop': _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
44
49
|
'install-deps': _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
|
45
50
|
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
|
@@ -49,11 +54,13 @@ declare class Init extends Command {
|
|
|
49
54
|
};
|
|
50
55
|
run(): Promise<void>;
|
|
51
56
|
}
|
|
52
|
-
declare function runInit(options?: InitOptions
|
|
57
|
+
declare function runInit({ markets, ...options }?: InitOptions & {
|
|
58
|
+
markets?: InitOptions['i18n'];
|
|
59
|
+
}): Promise<{
|
|
53
60
|
language?: "js" | "ts" | undefined;
|
|
54
|
-
packageManager: "npm" | "
|
|
61
|
+
packageManager: "npm" | "yarn" | "pnpm" | "unknown" | "bun";
|
|
55
62
|
cssStrategy?: CssStrategy | undefined;
|
|
56
|
-
cliCommand: "h2" | "
|
|
63
|
+
cliCommand: "h2" | "yarn shopify hydrogen" | "pnpm shopify hydrogen" | "bun shopify hydrogen" | "npx shopify hydrogen";
|
|
57
64
|
depsInstalled: boolean;
|
|
58
65
|
depsError?: Error | undefined;
|
|
59
66
|
i18n?: "subfolders" | "domains" | "subdomains" | undefined;
|
|
@@ -3,7 +3,7 @@ import { resolvePath } from '@shopify/cli-kit/node/path';
|
|
|
3
3
|
import { checkIfIgnoredInGitRepository } from '@shopify/cli-kit/node/git';
|
|
4
4
|
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
5
5
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
6
|
-
import {
|
|
6
|
+
import { packageManagers } from './package-managers.js';
|
|
7
7
|
|
|
8
8
|
function missingLockfileWarning(shouldExit) {
|
|
9
9
|
const headline = "No lockfile found";
|
|
@@ -23,15 +23,9 @@ function missingLockfileWarning(shouldExit) {
|
|
|
23
23
|
renderWarning({ headline, body, nextSteps });
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
function multipleLockfilesWarning(
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
"yarn.lock": "yarn",
|
|
30
|
-
"package-lock.json": "npm",
|
|
31
|
-
"pnpm-lock.yaml": "pnpm"
|
|
32
|
-
};
|
|
33
|
-
const lockfileList = lockfiles2.map((lockfile) => {
|
|
34
|
-
return `${lockfile} (created by ${packageManagers[lockfile]})`;
|
|
26
|
+
function multipleLockfilesWarning(packageManagers2, shouldExit) {
|
|
27
|
+
const lockfileList = packageManagers2.map(({ name, lockfile }) => {
|
|
28
|
+
return `${lockfile} (created by ${name})`;
|
|
35
29
|
});
|
|
36
30
|
const headline = "Multiple lockfiles found";
|
|
37
31
|
const body = [
|
|
@@ -61,19 +55,19 @@ function lockfileIgnoredWarning(lockfile) {
|
|
|
61
55
|
async function checkLockfileStatus(directory, shouldExit = false) {
|
|
62
56
|
if (process.env.LOCAL_DEV)
|
|
63
57
|
return;
|
|
64
|
-
const
|
|
65
|
-
for (const
|
|
66
|
-
if (await fileExists(resolvePath(directory,
|
|
67
|
-
|
|
58
|
+
const foundPackageManagers = [];
|
|
59
|
+
for (const packageManager of packageManagers) {
|
|
60
|
+
if (await fileExists(resolvePath(directory, packageManager.lockfile))) {
|
|
61
|
+
foundPackageManagers.push(packageManager);
|
|
68
62
|
}
|
|
69
63
|
}
|
|
70
|
-
if (
|
|
64
|
+
if (foundPackageManagers.length === 0) {
|
|
71
65
|
return missingLockfileWarning(shouldExit);
|
|
72
66
|
}
|
|
73
|
-
if (
|
|
74
|
-
return multipleLockfilesWarning(
|
|
67
|
+
if (foundPackageManagers.length > 1) {
|
|
68
|
+
return multipleLockfilesWarning(foundPackageManagers, shouldExit);
|
|
75
69
|
}
|
|
76
|
-
const lockfile =
|
|
70
|
+
const lockfile = foundPackageManagers[0].lockfile;
|
|
77
71
|
const ignoredLockfile = await checkIfIgnoredInGitRepository(directory, [
|
|
78
72
|
lockfile
|
|
79
73
|
]).catch(() => {
|
package/dist/lib/codegen.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { getCodeFormatOptions, formatCode } from './format-code.js';
|
|
4
|
-
import { renderWarning
|
|
4
|
+
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
5
5
|
import { relativePath, joinPath, resolvePath, basename } from '@shopify/cli-kit/node/path';
|
|
6
6
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
7
7
|
|
|
@@ -17,6 +17,13 @@ if (isStandaloneProcess) {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
function normalizeCodegenError(errorMessage, rootDirectory) {
|
|
20
|
+
if (errorMessage.includes("AbortError: ")) {
|
|
21
|
+
const parsedError = errorMessage.split("AbortError: ")[1] ?? "";
|
|
22
|
+
const message2 = parsedError.split("\n")[0];
|
|
23
|
+
const details2 = parsedError.match(/tryMessage: '(.*)',$/m)?.[1];
|
|
24
|
+
if (message2)
|
|
25
|
+
return { message: message2, details: details2 };
|
|
26
|
+
}
|
|
20
27
|
const [first = "", ...rest] = errorMessage.replaceAll("[FAILED]", "").replace(/\s{2,}/g, "\n").replace(/\n,\n/, "\n").trim().split("\n");
|
|
21
28
|
const message = "[Codegen] " + first;
|
|
22
29
|
let details = rest.join("\n");
|
|
@@ -48,25 +55,27 @@ function spawnCodegenProcess({
|
|
|
48
55
|
const { message, details } = normalizeCodegenError(dataString, rootDirectory);
|
|
49
56
|
if (/`punycode`/.test(message))
|
|
50
57
|
return;
|
|
58
|
+
if (/\.body\[\d\]/.test(message))
|
|
59
|
+
return;
|
|
60
|
+
if (/console\.time(End)?\(\)/.test(message))
|
|
61
|
+
return;
|
|
51
62
|
console.log("");
|
|
52
63
|
renderWarning({ headline: message, body: details });
|
|
53
64
|
});
|
|
54
65
|
child.on("close", (code) => {
|
|
55
66
|
if (code && code > 0) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
message: `Codegen process exited with code ${code}`,
|
|
60
|
-
skipOclifErrorHandling: true,
|
|
61
|
-
tryMessage: "Try restarting the dev server."
|
|
67
|
+
renderWarning({
|
|
68
|
+
headline: "Codegen process exited with code " + code,
|
|
69
|
+
body: "There should be more logs above."
|
|
62
70
|
});
|
|
63
|
-
process.exit(code);
|
|
64
71
|
}
|
|
65
72
|
});
|
|
66
73
|
return child;
|
|
67
74
|
}
|
|
68
75
|
function codegen(options) {
|
|
69
76
|
return generateTypes(options).catch((error) => {
|
|
77
|
+
if (error instanceof AbortError)
|
|
78
|
+
throw error;
|
|
70
79
|
const { message, details } = normalizeCodegenError(
|
|
71
80
|
error.message,
|
|
72
81
|
options.rootDirectory
|
|
@@ -80,7 +89,12 @@ async function generateTypes({
|
|
|
80
89
|
forceSfapiVersion,
|
|
81
90
|
...dirs
|
|
82
91
|
}) {
|
|
83
|
-
const { generate, loadCodegenConfig, CodegenContext } = await import('@graphql-codegen/cli')
|
|
92
|
+
const { generate, loadCodegenConfig, CodegenContext } = await import('@graphql-codegen/cli').catch(() => {
|
|
93
|
+
throw new AbortError(
|
|
94
|
+
"Could not load GraphQL Codegen CLI.",
|
|
95
|
+
"Please make sure you have `@graphql-codegen/cli` installed as a dev dependency."
|
|
96
|
+
);
|
|
97
|
+
});
|
|
84
98
|
const { config: codegenConfig } = (
|
|
85
99
|
// Load <root>/codegen.ts if available
|
|
86
100
|
await loadCodegenConfig({
|
|
@@ -116,8 +130,18 @@ async function generateDefaultConfig({
|
|
|
116
130
|
rootDirectory,
|
|
117
131
|
appDirectory = resolvePath(rootDirectory, "app")
|
|
118
132
|
}, forceSfapiVersion) {
|
|
119
|
-
const { getSchema, preset, pluckConfig } = await import('@shopify/hydrogen-codegen')
|
|
120
|
-
|
|
133
|
+
const { getSchema, preset, pluckConfig } = await import('@shopify/hydrogen-codegen').catch(() => {
|
|
134
|
+
throw new AbortError(
|
|
135
|
+
"Could not load Hydrogen Codegen.",
|
|
136
|
+
"Please make sure you have `@shopify/hydrogen-codegen` installed as a dev dependency."
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
const { loadConfig } = await import('graphql-config').catch(() => {
|
|
140
|
+
throw new AbortError(
|
|
141
|
+
"Could not load GraphQL Config.",
|
|
142
|
+
"Please make sure you have `graphql-config` installed as a dev dependency."
|
|
143
|
+
);
|
|
144
|
+
});
|
|
121
145
|
const gqlConfig = await loadConfig({
|
|
122
146
|
rootDir: rootDirectory,
|
|
123
147
|
throwOnEmpty: false,
|
|
@@ -128,8 +152,8 @@ async function generateDefaultConfig({
|
|
|
128
152
|
const sfapiProject = findGqlProject(sfapiSchema, gqlConfig);
|
|
129
153
|
const defaultGlob = "*!(*.d).{ts,tsx,js,jsx}";
|
|
130
154
|
const appDirRelative = relativePath(rootDirectory, appDirectory);
|
|
131
|
-
const caapiSchema = getSchema("customer-account");
|
|
132
|
-
const caapiProject = findGqlProject(caapiSchema, gqlConfig);
|
|
155
|
+
const caapiSchema = getSchema("customer-account", { throwIfMissing: false });
|
|
156
|
+
const caapiProject = caapiSchema ? findGqlProject(caapiSchema, gqlConfig) : void 0;
|
|
133
157
|
const customerAccountAPIConfig = caapiProject?.documents ? {
|
|
134
158
|
["customer-accountapi.generated.d.ts"]: {
|
|
135
159
|
preset,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
3
|
+
|
|
4
|
+
function orderEnvironmentsBySafety(environments) {
|
|
5
|
+
return [
|
|
6
|
+
...environments.filter((environment) => environment.type === "PREVIEW"),
|
|
7
|
+
...environments.filter((environment) => environment.type === "CUSTOM"),
|
|
8
|
+
...environments.filter((environment) => environment.type === "PRODUCTION")
|
|
9
|
+
];
|
|
10
|
+
}
|
|
11
|
+
function createEnvironmentCliChoiceLabel(name, handle, branch) {
|
|
12
|
+
const metadataStringified = Object.entries({ handle, branch }).reduce((acc, [key, val]) => {
|
|
13
|
+
if (val) {
|
|
14
|
+
acc.push(`${key}: ${val}`);
|
|
15
|
+
}
|
|
16
|
+
return acc;
|
|
17
|
+
}, []).join(", ");
|
|
18
|
+
return `${name} ${colors.dim(`(${metadataStringified})`)}`;
|
|
19
|
+
}
|
|
20
|
+
function findEnvironmentOrThrow(environments, envHandle) {
|
|
21
|
+
const matchedEnvironment = environments.find(
|
|
22
|
+
({ handle }) => handle === envHandle
|
|
23
|
+
);
|
|
24
|
+
if (!matchedEnvironment) {
|
|
25
|
+
throw environmentNotFound("handle", envHandle);
|
|
26
|
+
}
|
|
27
|
+
return matchedEnvironment;
|
|
28
|
+
}
|
|
29
|
+
function findEnvironmentByBranchOrThrow(environments, branch) {
|
|
30
|
+
const matchedEnvironment = environments.find(({ branch: b }) => b === branch);
|
|
31
|
+
if (!matchedEnvironment) {
|
|
32
|
+
throw environmentNotFound("branch", branch);
|
|
33
|
+
}
|
|
34
|
+
return matchedEnvironment;
|
|
35
|
+
}
|
|
36
|
+
function environmentNotFound(criterion, value) {
|
|
37
|
+
return new AbortError(
|
|
38
|
+
"Environment not found",
|
|
39
|
+
`We could not find an environment matching the ${criterion} '${value}'.`,
|
|
40
|
+
[
|
|
41
|
+
[
|
|
42
|
+
"Run",
|
|
43
|
+
{ command: "env list" },
|
|
44
|
+
"to view a list of available environments."
|
|
45
|
+
]
|
|
46
|
+
]
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { createEnvironmentCliChoiceLabel, findEnvironmentByBranchOrThrow, findEnvironmentOrThrow, orderEnvironmentsBySafety };
|
package/dist/lib/cpu-profiler.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { readFile } from '@shopify/cli-kit/node/fs';
|
|
2
2
|
import { Session } from 'node:inspector';
|
|
3
|
+
import { handleMiniOxygenImportFail } from './mini-oxygen/common.js';
|
|
3
4
|
|
|
4
5
|
async function createCpuStartupProfiler() {
|
|
5
|
-
const { createMiniOxygen } = await import('@shopify/mini-oxygen')
|
|
6
|
+
const { createMiniOxygen } = await import('@shopify/mini-oxygen/node').catch(
|
|
7
|
+
handleMiniOxygenImportFail
|
|
8
|
+
);
|
|
6
9
|
const miniOxygen = createMiniOxygen({
|
|
7
10
|
script: "export default {}",
|
|
8
11
|
modules: true,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import colors from '@shopify/cli-kit/node/colors';
|
|
2
|
+
import { outputInfo, outputContent, outputToken } from '@shopify/cli-kit/node/output';
|
|
3
|
+
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
4
|
+
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
5
|
+
import { getStorefrontId, runCustomerAccountPush } from '../commands/hydrogen/customer-account/push.js';
|
|
6
|
+
import { getLocalVariables } from '../lib/environment-variables.js';
|
|
7
|
+
import { startTunnelPlugin, pollTunnelURL } from './tunneling.js';
|
|
8
|
+
import { getConfig } from './shopify-config.js';
|
|
9
|
+
import { getGraphiQLUrl } from './graphiql-url.js';
|
|
10
|
+
|
|
11
|
+
function isMockShop(envVariables) {
|
|
12
|
+
return envVariables.PUBLIC_STORE_DOMAIN === "mock.shop" || // We fallback to mock.shop if the env var is falsy.
|
|
13
|
+
// When it's undefined, it might be overwritten by remote variables.
|
|
14
|
+
envVariables.PUBLIC_STORE_DOMAIN === "";
|
|
15
|
+
}
|
|
16
|
+
function notifyIssueWithTunnelAndMockShop(cliCommand) {
|
|
17
|
+
renderInfo({
|
|
18
|
+
headline: "Using mock.shop with `--customer-account-push` flag is not supported",
|
|
19
|
+
body: "The functionalities of this flag are disabled.",
|
|
20
|
+
nextSteps: [
|
|
21
|
+
"You may continue knowing Customer Account API (/account) interactions will fail.",
|
|
22
|
+
[
|
|
23
|
+
"Or run",
|
|
24
|
+
{ command: `${cliCommand} env pull` },
|
|
25
|
+
"to link to your store credentials."
|
|
26
|
+
]
|
|
27
|
+
]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function getDevConfigInBackground(root, customerAccountPushFlag) {
|
|
31
|
+
return getLocalVariables(root).then(async ({ variables: localVariables }) => {
|
|
32
|
+
const customerAccountPush = customerAccountPushFlag && !isMockShop(localVariables);
|
|
33
|
+
if (customerAccountPush) {
|
|
34
|
+
await getStorefrontId(root);
|
|
35
|
+
}
|
|
36
|
+
const { shop, storefront } = await getConfig(root);
|
|
37
|
+
const storefrontId = storefront?.id;
|
|
38
|
+
return {
|
|
39
|
+
storefrontId,
|
|
40
|
+
customerAccountPush,
|
|
41
|
+
fetchRemote: !!shop && !!storefrontId,
|
|
42
|
+
localVariables,
|
|
43
|
+
storefrontTitle: storefront?.title
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const TUNNEL_DOMAIN = Object.freeze({
|
|
48
|
+
ORIGINAL: ".trycloudflare.com",
|
|
49
|
+
REBRANDED: ".tryhydrogen.dev"
|
|
50
|
+
});
|
|
51
|
+
async function startTunnelAndPushConfig(root, cliConfig, port, storefrontId) {
|
|
52
|
+
outputInfo("\nStarting tunnel...\n");
|
|
53
|
+
const tunnel = await startTunnelPlugin(cliConfig, port, "cloudflare");
|
|
54
|
+
const host = await pollTunnelURL(tunnel).then(
|
|
55
|
+
(host2) => (
|
|
56
|
+
// Replace branded tunnel domain:
|
|
57
|
+
host2.replace(TUNNEL_DOMAIN.ORIGINAL, TUNNEL_DOMAIN.REBRANDED)
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
const cleanup = await runCustomerAccountPush({
|
|
61
|
+
path: root,
|
|
62
|
+
devOrigin: host,
|
|
63
|
+
storefrontId
|
|
64
|
+
}).catch((error) => {
|
|
65
|
+
if (error instanceof AbortError) {
|
|
66
|
+
renderInfo({
|
|
67
|
+
headline: "Customer Account Application setup update fail.",
|
|
68
|
+
body: error.tryMessage || void 0,
|
|
69
|
+
nextSteps: error.nextSteps
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return { host, cleanup };
|
|
74
|
+
}
|
|
75
|
+
function getDebugBannerLine(publicInspectorPort) {
|
|
76
|
+
const isVSCode = process.env.TERM_PROGRAM === "vscode";
|
|
77
|
+
const debuggingDocsLink = "https://h2o.fyi/debugging/server-code" + (isVSCode ? "#visual-studio-code" : "#step-2-attach-a-debugger");
|
|
78
|
+
return outputContent`Debugging enabled on port ${String(
|
|
79
|
+
publicInspectorPort
|
|
80
|
+
)}.\nAttach a ${outputToken.link(
|
|
81
|
+
colors.yellow(isVSCode ? "VSCode debugger" : "debugger"),
|
|
82
|
+
debuggingDocsLink
|
|
83
|
+
)} or open DevTools in http://localhost:${String(publicInspectorPort)}.`.value;
|
|
84
|
+
}
|
|
85
|
+
function getUtilityBannerlines(host) {
|
|
86
|
+
host = host.endsWith("/") ? host.slice(0, -1) : host;
|
|
87
|
+
return [
|
|
88
|
+
`View GraphiQL API browser:
|
|
89
|
+
${getGraphiQLUrl({
|
|
90
|
+
host
|
|
91
|
+
})}`,
|
|
92
|
+
`View server network requests:
|
|
93
|
+
${host}/subrequest-profiler`
|
|
94
|
+
].map((value, index) => ({
|
|
95
|
+
subdued: `${index === 0 ? "" : "\n\n"}${value}`
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { TUNNEL_DOMAIN, getDebugBannerLine, getDevConfigInBackground, getUtilityBannerlines, isMockShop, notifyIssueWithTunnelAndMockShop, startTunnelAndPushConfig };
|
|
@@ -6,6 +6,8 @@ import { readAndParseDotEnv } from '@shopify/cli-kit/node/dot-env';
|
|
|
6
6
|
import { renderWarning } from '@shopify/cli-kit/node/ui';
|
|
7
7
|
import colors from '@shopify/cli-kit/node/colors';
|
|
8
8
|
import { getStorefrontEnvVariables } from './graphql/admin/pull-variables.js';
|
|
9
|
+
import { getStorefrontEnvironments } from './graphql/admin/list-environments.js';
|
|
10
|
+
import { findEnvironmentByBranchOrThrow } from './common.js';
|
|
9
11
|
import { login } from './auth.js';
|
|
10
12
|
|
|
11
13
|
const createEmptyRemoteVars = () => ({
|
|
@@ -14,50 +16,63 @@ const createEmptyRemoteVars = () => ({
|
|
|
14
16
|
});
|
|
15
17
|
async function getAllEnvironmentVariables({
|
|
16
18
|
root,
|
|
19
|
+
envHandle,
|
|
17
20
|
envBranch,
|
|
18
|
-
fetchRemote = true
|
|
21
|
+
fetchRemote = true,
|
|
22
|
+
localVariables: inlineLocalVariables
|
|
19
23
|
}) {
|
|
20
|
-
const dotEnvPath = resolvePath(root, ".env");
|
|
21
24
|
const [{ remoteVariables, remoteSecrets }, { variables: localVariables }] = await Promise.all([
|
|
22
25
|
// Get remote vars
|
|
23
|
-
fetchRemote ? getRemoteVariables(root, envBranch).catch(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
fetchRemote ? getRemoteVariables(root, envHandle, envBranch).catch(
|
|
27
|
+
(error) => {
|
|
28
|
+
renderWarning({
|
|
29
|
+
headline: "Failed to load environment variables from Shopify. The development server will still start, but the following error occurred:",
|
|
30
|
+
body: [error.message, error.tryMessage, error.nextSteps].filter(Boolean).join("\n\n")
|
|
31
|
+
});
|
|
32
|
+
return createEmptyRemoteVars();
|
|
33
|
+
}
|
|
34
|
+
) : createEmptyRemoteVars(),
|
|
30
35
|
// Get local vars
|
|
31
|
-
|
|
32
|
-
(exists) => exists ? readAndParseDotEnv(dotEnvPath) : { variables: {} }
|
|
33
|
-
)
|
|
36
|
+
inlineLocalVariables ? { variables: inlineLocalVariables } : getLocalVariables(root)
|
|
34
37
|
]);
|
|
35
38
|
const remoteSecretKeys = Object.keys(remoteSecrets);
|
|
36
39
|
const remotePublicKeys = Object.keys(remoteVariables);
|
|
37
40
|
const localKeys = Object.keys(localVariables);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
function logInjectedVariables() {
|
|
42
|
+
if (localKeys.length > 0 || remotePublicKeys.length + remoteSecretKeys.length > 0) {
|
|
43
|
+
outputInfo("\nEnvironment variables injected into MiniOxygen:\n");
|
|
44
|
+
outputInfo(
|
|
45
|
+
linesToColumns([
|
|
46
|
+
...remotePublicKeys.filter((key) => !localKeys.includes(key)).map((key) => [key, "from Oxygen"]),
|
|
47
|
+
...localKeys.map((key) => [key, "from local .env"]),
|
|
48
|
+
// Ensure secret variables always get added to the bottom of the list
|
|
49
|
+
...remoteSecretKeys.filter((key) => !localKeys.includes(key)).map((key) => [
|
|
50
|
+
colors.dim(key),
|
|
51
|
+
colors.dim("from Oxygen (Marked as secret)")
|
|
52
|
+
])
|
|
48
53
|
])
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
);
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
logInjectedVariables,
|
|
59
|
+
remoteVariables,
|
|
60
|
+
remoteSecrets,
|
|
61
|
+
localVariables,
|
|
62
|
+
allVariables: {
|
|
63
|
+
...remoteSecrets,
|
|
64
|
+
...remoteVariables,
|
|
65
|
+
...localVariables
|
|
66
|
+
}
|
|
56
67
|
};
|
|
57
68
|
}
|
|
58
|
-
async function getRemoteVariables(root, envBranch) {
|
|
69
|
+
async function getRemoteVariables(root, envHandle, envBranch) {
|
|
59
70
|
const { session, config } = await login(root);
|
|
60
|
-
|
|
71
|
+
if (envBranch) {
|
|
72
|
+
const environments = (await getStorefrontEnvironments(session, config.storefront.id))?.environments || [];
|
|
73
|
+
envHandle = findEnvironmentByBranchOrThrow(environments, envBranch).handle;
|
|
74
|
+
}
|
|
75
|
+
const envVariables = (await getStorefrontEnvVariables(session, config.storefront.id, envHandle))?.environmentVariables || [];
|
|
61
76
|
const remoteVariables = {};
|
|
62
77
|
const remoteSecrets = {};
|
|
63
78
|
for (const { key, value, isSecret } of envVariables) {
|
|
@@ -68,5 +83,11 @@ async function getRemoteVariables(root, envBranch) {
|
|
|
68
83
|
}
|
|
69
84
|
return { remoteVariables, remoteSecrets };
|
|
70
85
|
}
|
|
86
|
+
async function getLocalVariables(root) {
|
|
87
|
+
const dotEnvPath = resolvePath(root, ".env");
|
|
88
|
+
return await fileExists(dotEnvPath).then(
|
|
89
|
+
(exists) => exists ? readAndParseDotEnv(dotEnvPath) : { variables: {} }
|
|
90
|
+
);
|
|
91
|
+
}
|
|
71
92
|
|
|
72
|
-
export { getAllEnvironmentVariables };
|
|
93
|
+
export { getAllEnvironmentVariables, getLocalVariables };
|
package/dist/lib/file.js
CHANGED
|
@@ -13,7 +13,14 @@ async function replaceFileContent(filepath, formatConfig, replacer) {
|
|
|
13
13
|
}
|
|
14
14
|
return writeFile(filepath, content);
|
|
15
15
|
}
|
|
16
|
-
const DEFAULT_EXTENSIONS = [
|
|
16
|
+
const DEFAULT_EXTENSIONS = [
|
|
17
|
+
"tsx",
|
|
18
|
+
"ts",
|
|
19
|
+
"jsx",
|
|
20
|
+
"js",
|
|
21
|
+
"mjs",
|
|
22
|
+
"cjs"
|
|
23
|
+
];
|
|
17
24
|
async function findFileWithExtension(directory, fileBase, extensions = DEFAULT_EXTENSIONS) {
|
|
18
25
|
const dirFiles = await readdir(directory);
|
|
19
26
|
if (dirFiles.includes(fileBase)) {
|