@shopify/cli-hydrogen 5.2.0 → 5.2.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/dev.js +1 -2
- package/dist/commands/hydrogen/generate/route.test.js +0 -1
- package/dist/commands/hydrogen/init.js +3 -3
- package/dist/commands/hydrogen/preview.js +1 -2
- package/dist/generator-templates/starter/app/entry.server.tsx +9 -1
- package/dist/generator-templates/starter/app/root.tsx +9 -6
- package/dist/generator-templates/starter/app/routes/blogs._index.tsx +1 -1
- package/dist/generator-templates/starter/package.json +5 -5
- package/dist/generator-templates/starter/tsconfig.json +1 -0
- package/dist/lib/file.js +1 -1
- package/dist/lib/flags.js +3 -3
- package/dist/lib/format-code.js +4 -4
- package/dist/lib/graphql/admin/client.js +18 -0
- package/dist/lib/graphql/admin/client.test.js +28 -3
- package/dist/lib/setups/css/index.js +4 -2
- package/dist/lib/setups/routes/generate.js +11 -28
- package/dist/lib/setups/routes/generate.test.js +1 -3
- package/dist/lib/transpile-ts.js +4 -3
- package/dist/virtual-routes/components/HydrogenLogoBaseBW.jsx +22 -19
- package/dist/virtual-routes/components/HydrogenLogoBaseColor.jsx +37 -33
- package/dist/virtual-routes/components/IconBanner.jsx +282 -279
- package/dist/virtual-routes/components/IconDiscord.jsx +11 -10
- package/dist/virtual-routes/components/IconError.jsx +51 -48
- package/dist/virtual-routes/components/IconGithub.jsx +13 -12
- package/dist/virtual-routes/components/IconTwitter.jsx +11 -10
- package/dist/virtual-routes/components/Layout.jsx +2 -1
- package/dist/virtual-routes/routes/index.jsx +194 -105
- package/dist/virtual-routes/virtual-root.jsx +62 -8
- package/oclif.manifest.json +3 -3
- package/package.json +4 -4
|
@@ -16,7 +16,6 @@ import { addVirtualRoutes } from '../../lib/virtual-routes.js';
|
|
|
16
16
|
import { spawnCodegenProcess } from '../../lib/codegen.js';
|
|
17
17
|
import { getAllEnvironmentVariables } from '../../lib/environment-variables.js';
|
|
18
18
|
import { getConfig } from '../../lib/shopify-config.js';
|
|
19
|
-
import { findPort } from '../../lib/find-port.js';
|
|
20
19
|
import { setupLiveReload } from '../../lib/live-reload.js';
|
|
21
20
|
import { checkRemixVersions } from '../../lib/remix-version-check.js';
|
|
22
21
|
|
|
@@ -110,7 +109,7 @@ async function runDev({
|
|
|
110
109
|
return;
|
|
111
110
|
miniOxygen = await startMiniOxygen({
|
|
112
111
|
root,
|
|
113
|
-
port:
|
|
112
|
+
port: portFlag,
|
|
114
113
|
watch: !liveReload,
|
|
115
114
|
buildPathWorkerFile,
|
|
116
115
|
buildPathClient,
|
|
@@ -6,7 +6,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
|
6
6
|
import { AbortController } from '@shopify/cli-kit/node/abort';
|
|
7
7
|
import { commonFlags, flagsToCamelObject, parseProcessFlags } from '../../lib/flags.js';
|
|
8
8
|
import { checkHydrogenVersion } from '../../lib/check-version.js';
|
|
9
|
-
import {
|
|
9
|
+
import { STYLING_CHOICES } from './../../lib/setups/css/index.js';
|
|
10
10
|
import { I18N_CHOICES } from '../../lib/setups/i18n/index.js';
|
|
11
11
|
import { supressNodeExperimentalWarnings } from '../../lib/process.js';
|
|
12
12
|
import { setupRemoteTemplate, setupLocalStarterTemplate } from '../../lib/onboarding/index.js';
|
|
@@ -58,9 +58,9 @@ class Init extends Command {
|
|
|
58
58
|
`Invalid URL structure strategy: ${flags.markets}. Must be one of ${I18N_CHOICES.join(", ")}`
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
|
-
if (flags.styling && !
|
|
61
|
+
if (flags.styling && !STYLING_CHOICES.includes(flags.styling)) {
|
|
62
62
|
throw new AbortError(
|
|
63
|
-
`Invalid styling strategy: ${flags.styling}. Must be one of ${
|
|
63
|
+
`Invalid styling strategy: ${flags.styling}. Must be one of ${STYLING_CHOICES.join(", ")}`
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
await runInit(flagsToCamelObject(flags));
|
|
@@ -3,7 +3,6 @@ import { muteDevLogs } from '../../lib/log.js';
|
|
|
3
3
|
import { getProjectPaths } from '../../lib/remix-config.js';
|
|
4
4
|
import { commonFlags, DEFAULT_PORT } from '../../lib/flags.js';
|
|
5
5
|
import { startMiniOxygen } from '../../lib/mini-oxygen.js';
|
|
6
|
-
import { findPort } from '../../lib/find-port.js';
|
|
7
6
|
|
|
8
7
|
class Preview extends Command {
|
|
9
8
|
static description = "Runs a Hydrogen storefront in an Oxygen worker for production.";
|
|
@@ -26,7 +25,7 @@ async function runPreview({
|
|
|
26
25
|
const { root, buildPathWorkerFile, buildPathClient } = getProjectPaths(appPath);
|
|
27
26
|
const miniOxygen = await startMiniOxygen({
|
|
28
27
|
root,
|
|
29
|
-
port
|
|
28
|
+
port,
|
|
30
29
|
buildPathClient,
|
|
31
30
|
buildPathWorkerFile
|
|
32
31
|
});
|
|
@@ -2,6 +2,7 @@ import type {EntryContext} from '@shopify/remix-oxygen';
|
|
|
2
2
|
import {RemixServer} from '@remix-run/react';
|
|
3
3
|
import isbot from 'isbot';
|
|
4
4
|
import {renderToReadableStream} from 'react-dom/server';
|
|
5
|
+
import {createContentSecurityPolicy} from '@shopify/hydrogen';
|
|
5
6
|
|
|
6
7
|
export default async function handleRequest(
|
|
7
8
|
request: Request,
|
|
@@ -9,9 +10,14 @@ export default async function handleRequest(
|
|
|
9
10
|
responseHeaders: Headers,
|
|
10
11
|
remixContext: EntryContext,
|
|
11
12
|
) {
|
|
13
|
+
const {nonce, header, NonceProvider} = createContentSecurityPolicy();
|
|
14
|
+
|
|
12
15
|
const body = await renderToReadableStream(
|
|
13
|
-
<
|
|
16
|
+
<NonceProvider>
|
|
17
|
+
<RemixServer context={remixContext} url={request.url} />
|
|
18
|
+
</NonceProvider>,
|
|
14
19
|
{
|
|
20
|
+
nonce,
|
|
15
21
|
signal: request.signal,
|
|
16
22
|
onError(error) {
|
|
17
23
|
// eslint-disable-next-line no-console
|
|
@@ -26,6 +32,8 @@ export default async function handleRequest(
|
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
responseHeaders.set('Content-Type', 'text/html');
|
|
35
|
+
responseHeaders.set('Content-Security-Policy', header);
|
|
36
|
+
|
|
29
37
|
return new Response(body, {
|
|
30
38
|
headers: responseHeaders,
|
|
31
39
|
status: responseStatusCode,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {useNonce} from '@shopify/hydrogen';
|
|
1
2
|
import {defer, type LoaderArgs} from '@shopify/remix-oxygen';
|
|
2
3
|
import {
|
|
3
4
|
Links,
|
|
@@ -98,6 +99,7 @@ export async function loader({context}: LoaderArgs) {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
export default function App() {
|
|
102
|
+
const nonce = useNonce();
|
|
101
103
|
const data = useLoaderData<typeof loader>();
|
|
102
104
|
|
|
103
105
|
return (
|
|
@@ -112,9 +114,9 @@ export default function App() {
|
|
|
112
114
|
<Layout {...data}>
|
|
113
115
|
<Outlet />
|
|
114
116
|
</Layout>
|
|
115
|
-
<ScrollRestoration />
|
|
116
|
-
<Scripts />
|
|
117
|
-
<LiveReload />
|
|
117
|
+
<ScrollRestoration nonce={nonce} />
|
|
118
|
+
<Scripts nonce={nonce} />
|
|
119
|
+
<LiveReload nonce={nonce} />
|
|
118
120
|
</body>
|
|
119
121
|
</html>
|
|
120
122
|
);
|
|
@@ -123,6 +125,7 @@ export default function App() {
|
|
|
123
125
|
export function ErrorBoundary() {
|
|
124
126
|
const error = useRouteError();
|
|
125
127
|
const [root] = useMatches();
|
|
128
|
+
const nonce = useNonce();
|
|
126
129
|
let errorMessage = 'Unknown error';
|
|
127
130
|
let errorStatus = 500;
|
|
128
131
|
|
|
@@ -153,9 +156,9 @@ export function ErrorBoundary() {
|
|
|
153
156
|
)}
|
|
154
157
|
</div>
|
|
155
158
|
</Layout>
|
|
156
|
-
<ScrollRestoration />
|
|
157
|
-
<Scripts />
|
|
158
|
-
<LiveReload />
|
|
159
|
+
<ScrollRestoration nonce={nonce} />
|
|
160
|
+
<Scripts nonce={nonce} />
|
|
161
|
+
<LiveReload nonce={nonce} />
|
|
159
162
|
</body>
|
|
160
163
|
</html>
|
|
161
164
|
);
|
|
@@ -3,7 +3,7 @@ import {Link, useLoaderData, type V2_MetaFunction} from '@remix-run/react';
|
|
|
3
3
|
import {Pagination, getPaginationVariables} from '@shopify/hydrogen';
|
|
4
4
|
|
|
5
5
|
export const meta: V2_MetaFunction = () => {
|
|
6
|
-
return [{title: `Hydrogen |
|
|
6
|
+
return [{title: `Hydrogen | Blogs`}];
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export const loader = async ({request, context: {storefront}}: LoaderArgs) => {
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@remix-run/react": "1.19.1",
|
|
17
17
|
"@shopify/cli": "3.48.0",
|
|
18
|
-
"@shopify/cli-hydrogen": "^5.2.
|
|
19
|
-
"@shopify/hydrogen": "^2023.7.
|
|
18
|
+
"@shopify/cli-hydrogen": "^5.2.1",
|
|
19
|
+
"@shopify/hydrogen": "^2023.7.4",
|
|
20
20
|
"@shopify/remix-oxygen": "^1.1.3",
|
|
21
21
|
"graphql": "^16.6.0",
|
|
22
22
|
"graphql-tag": "^2.12.6",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"@shopify/prettier-config": "^1.1.2",
|
|
31
31
|
"@total-typescript/ts-reset": "^0.4.2",
|
|
32
32
|
"@types/eslint": "^8.4.10",
|
|
33
|
-
"@types/react": "^18.
|
|
34
|
-
"@types/react-dom": "^18.
|
|
33
|
+
"@types/react": "^18.2.20",
|
|
34
|
+
"@types/react-dom": "^18.2.7",
|
|
35
35
|
"eslint": "^8.20.0",
|
|
36
36
|
"eslint-plugin-hydrogen": "0.12.2",
|
|
37
37
|
"prettier": "^2.8.4",
|
|
38
|
-
"typescript": "^
|
|
38
|
+
"typescript": "^5.2.2"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=16.13"
|
package/dist/lib/file.js
CHANGED
|
@@ -8,7 +8,7 @@ async function replaceFileContent(filepath, formatConfig, replacer) {
|
|
|
8
8
|
if (typeof content !== "string")
|
|
9
9
|
return;
|
|
10
10
|
if (formatConfig) {
|
|
11
|
-
content = formatCode(content, formatConfig, filepath);
|
|
11
|
+
content = await formatCode(content, formatConfig, filepath);
|
|
12
12
|
}
|
|
13
13
|
return writeFile(filepath, content);
|
|
14
14
|
}
|
package/dist/lib/flags.js
CHANGED
|
@@ -3,7 +3,7 @@ import { camelize } from '@shopify/cli-kit/common/string';
|
|
|
3
3
|
import { renderInfo } from '@shopify/cli-kit/node/ui';
|
|
4
4
|
import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
|
|
5
5
|
import colors from '@shopify/cli-kit/node/colors';
|
|
6
|
-
import {
|
|
6
|
+
import { STYLING_CHOICES } from './setups/css/index.js';
|
|
7
7
|
import { I18N_CHOICES } from './setups/i18n/index.js';
|
|
8
8
|
|
|
9
9
|
const DEFAULT_PORT = 3e3;
|
|
@@ -50,10 +50,10 @@ const commonFlags = {
|
|
|
50
50
|
dependsOn: ["codegen-unstable"]
|
|
51
51
|
}),
|
|
52
52
|
styling: Flags.string({
|
|
53
|
-
description: `Sets the styling strategy to use. One of ${
|
|
53
|
+
description: `Sets the styling strategy to use. One of ${STYLING_CHOICES.map(
|
|
54
54
|
(item) => `\`${item}\``
|
|
55
55
|
).join(", ")}.`,
|
|
56
|
-
choices:
|
|
56
|
+
choices: STYLING_CHOICES,
|
|
57
57
|
env: "SHOPIFY_HYDROGEN_FLAG_STYLING"
|
|
58
58
|
}),
|
|
59
59
|
markets: Flags.string({
|
package/dist/lib/format-code.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import prettier from 'prettier';
|
|
2
1
|
import { extname } from '@shopify/cli-kit/node/path';
|
|
3
2
|
|
|
4
3
|
const DEFAULT_PRETTIER_CONFIG = {
|
|
@@ -9,21 +8,22 @@ const DEFAULT_PRETTIER_CONFIG = {
|
|
|
9
8
|
};
|
|
10
9
|
async function getCodeFormatOptions(filePath = process.cwd()) {
|
|
11
10
|
try {
|
|
11
|
+
const prettier = await import('prettier');
|
|
12
12
|
return await prettier.resolveConfig(filePath) || DEFAULT_PRETTIER_CONFIG;
|
|
13
13
|
} catch {
|
|
14
14
|
return DEFAULT_PRETTIER_CONFIG;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
function formatCode(content, config = DEFAULT_PRETTIER_CONFIG, filePath = "") {
|
|
17
|
+
async function formatCode(content, config = DEFAULT_PRETTIER_CONFIG, filePath = "") {
|
|
18
18
|
const ext = extname(filePath);
|
|
19
|
-
const
|
|
19
|
+
const prettier = await import('prettier');
|
|
20
|
+
return prettier.format(content, {
|
|
20
21
|
// Specify the TypeScript parser for ts/tsx files. Otherwise
|
|
21
22
|
// we need to use the babel parser because the default parser
|
|
22
23
|
// Otherwise prettier will print a warning.
|
|
23
24
|
parser: ext === ".tsx" || ext === ".ts" ? "typescript" : "babel",
|
|
24
25
|
...config
|
|
25
26
|
});
|
|
26
|
-
return formattedContent;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export { formatCode, getCodeFormatOptions };
|
|
@@ -20,6 +20,24 @@ async function adminRequest(query, session, variables) {
|
|
|
20
20
|
"Install the Hydrogen sales channel on your store to start creating and linking Hydrogen storefronts: https://apps.shopify.com/hydrogen"
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
|
+
if (errors?.some?.(
|
|
24
|
+
(error2) => error2.message.includes(
|
|
25
|
+
"Access denied for hydrogenStorefrontCreate field"
|
|
26
|
+
)
|
|
27
|
+
)) {
|
|
28
|
+
throw new AbortError("Couldn't connect storefront to Shopify", [
|
|
29
|
+
"Common reasons for this error include:",
|
|
30
|
+
{
|
|
31
|
+
list: {
|
|
32
|
+
items: [
|
|
33
|
+
"The Hydrogen sales channel isn't installed on the store.",
|
|
34
|
+
"You don't have the required account permission to manage apps or channels.",
|
|
35
|
+
"You're trying to connect to an ineligible store type (Trial, Development store)"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
23
41
|
throw error;
|
|
24
42
|
}
|
|
25
43
|
}
|
|
@@ -16,8 +16,8 @@ describe("adminRequest", () => {
|
|
|
16
16
|
});
|
|
17
17
|
expect(response).toContain(fakeResponse);
|
|
18
18
|
});
|
|
19
|
-
describe("error response", () => {
|
|
20
|
-
it("
|
|
19
|
+
describe("when there is an unknown error response", () => {
|
|
20
|
+
it("passes along the error message", async () => {
|
|
21
21
|
const fakeGraphqlError = {
|
|
22
22
|
errors: [
|
|
23
23
|
{
|
|
@@ -32,7 +32,9 @@ describe("adminRequest", () => {
|
|
|
32
32
|
});
|
|
33
33
|
await expect(response).rejects.toContain(fakeGraphqlError);
|
|
34
34
|
});
|
|
35
|
-
|
|
35
|
+
});
|
|
36
|
+
describe("when the app isn't installed", () => {
|
|
37
|
+
it("throws an AbortError", async () => {
|
|
36
38
|
const fakeGraphqlError = {
|
|
37
39
|
errors: [
|
|
38
40
|
{
|
|
@@ -46,6 +48,29 @@ describe("adminRequest", () => {
|
|
|
46
48
|
storeFqdn: ""
|
|
47
49
|
});
|
|
48
50
|
await expect(response).rejects.toThrowError(AbortError);
|
|
51
|
+
await expect(response).rejects.toMatch(
|
|
52
|
+
/Hydrogen sales channel isn\'t installed/
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe("when the user doesn't have access to hydrogenStorefrontCreate", () => {
|
|
57
|
+
it("throws an AbortError", async () => {
|
|
58
|
+
const fakeGraphqlError = {
|
|
59
|
+
errors: [
|
|
60
|
+
{
|
|
61
|
+
message: "Access denied for hydrogenStorefrontCreate field"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
};
|
|
65
|
+
vi.mocked(graphqlRequest).mockRejectedValue(fakeGraphqlError);
|
|
66
|
+
const response = adminRequest("", {
|
|
67
|
+
token: "",
|
|
68
|
+
storeFqdn: ""
|
|
69
|
+
});
|
|
70
|
+
await expect(response).rejects.toThrowError(AbortError);
|
|
71
|
+
await expect(response).rejects.toMatch(
|
|
72
|
+
/Couldn\'t connect storefront to Shopify/
|
|
73
|
+
);
|
|
49
74
|
});
|
|
50
75
|
});
|
|
51
76
|
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { renderSelectPrompt } from '@shopify/cli-kit/node/ui';
|
|
2
|
+
import { SETUP_CSS_STRATEGIES } from './assets.js';
|
|
3
|
+
export { SETUP_CSS_STRATEGIES } from './assets.js';
|
|
2
4
|
import { setupTailwind } from './tailwind.js';
|
|
3
5
|
import { setupPostCss } from './postcss.js';
|
|
4
6
|
import { setupCssModules } from './css-modules.js';
|
|
5
7
|
import { setupVanillaExtract } from './vanilla-extract.js';
|
|
6
|
-
export { SETUP_CSS_STRATEGIES } from './assets.js';
|
|
7
8
|
|
|
9
|
+
const STYLING_CHOICES = [...SETUP_CSS_STRATEGIES, "none"];
|
|
8
10
|
const CSS_STRATEGY_NAME_MAP = {
|
|
9
11
|
tailwind: "Tailwind",
|
|
10
12
|
"css-modules": "CSS Modules",
|
|
@@ -41,4 +43,4 @@ async function renderCssPrompt(options) {
|
|
|
41
43
|
});
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
export { CSS_STRATEGY_NAME_MAP, renderCssPrompt, setupCssStrategy };
|
|
46
|
+
export { CSS_STRATEGY_NAME_MAP, STYLING_CHOICES, renderCssPrompt, setupCssStrategy };
|
|
@@ -64,8 +64,7 @@ async function generateRoutes(options) {
|
|
|
64
64
|
options,
|
|
65
65
|
v2Flags.isV2RouteConvention
|
|
66
66
|
);
|
|
67
|
-
const typescript = options.typescript ??
|
|
68
|
-
const transpilerOptions = typescript ? void 0 : await getJsTranspilerOptions(rootDirectory);
|
|
67
|
+
const typescript = !!(options.typescript ?? tsconfigPath?.endsWith("tsconfig.json"));
|
|
69
68
|
const routes = [];
|
|
70
69
|
for (const route of routesArray) {
|
|
71
70
|
routes.push(
|
|
@@ -76,7 +75,6 @@ async function generateRoutes(options) {
|
|
|
76
75
|
rootDirectory,
|
|
77
76
|
appDirectory,
|
|
78
77
|
formatOptions,
|
|
79
|
-
transpilerOptions,
|
|
80
78
|
v2Flags
|
|
81
79
|
})
|
|
82
80
|
);
|
|
@@ -85,7 +83,6 @@ async function generateRoutes(options) {
|
|
|
85
83
|
routes,
|
|
86
84
|
routeGroups,
|
|
87
85
|
isTypescript: typescript,
|
|
88
|
-
transpilerOptions,
|
|
89
86
|
v2Flags,
|
|
90
87
|
formatOptions
|
|
91
88
|
};
|
|
@@ -98,12 +95,12 @@ async function getLocalePrefix(appDirectory, { localePrefix, routeName }, isV2Ro
|
|
|
98
95
|
const existingFiles = await readdir(joinPath(appDirectory, "routes")).catch(
|
|
99
96
|
() => []
|
|
100
97
|
);
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
(file) =>
|
|
98
|
+
const coreRouteWithLocaleRE = isV2RouteConvention ? /^\(\$(\w+)\)\.(_index|\$|cart).[jt]sx?$/ : /^\(\$(\w+)\)$/;
|
|
99
|
+
const coreRouteWithLocale = existingFiles.find(
|
|
100
|
+
(file) => coreRouteWithLocaleRE.test(file)
|
|
104
101
|
);
|
|
105
|
-
if (
|
|
106
|
-
return
|
|
102
|
+
if (coreRouteWithLocale) {
|
|
103
|
+
return coreRouteWithLocale.match(coreRouteWithLocaleRE)?.[1];
|
|
107
104
|
}
|
|
108
105
|
}
|
|
109
106
|
async function generateProjectFile(routeFrom, {
|
|
@@ -113,7 +110,6 @@ async function generateProjectFile(routeFrom, {
|
|
|
113
110
|
force,
|
|
114
111
|
adapter,
|
|
115
112
|
templatesRoot = getStarterDir(),
|
|
116
|
-
transpilerOptions,
|
|
117
113
|
formatOptions,
|
|
118
114
|
localePrefix,
|
|
119
115
|
v2Flags = {},
|
|
@@ -159,19 +155,17 @@ async function generateProjectFile(routeFrom, {
|
|
|
159
155
|
if (!await fileExists(dirname(destinationPath))) {
|
|
160
156
|
await mkdir(dirname(destinationPath));
|
|
161
157
|
}
|
|
158
|
+
const templateAppFilePath = getTemplateAppFile(filePath, templatesRoot);
|
|
162
159
|
if (!/\.[jt]sx?$/.test(filePath)) {
|
|
163
|
-
await copyFile(
|
|
164
|
-
getTemplateAppFile(filePath, templatesRoot),
|
|
165
|
-
destinationPath
|
|
166
|
-
);
|
|
160
|
+
await copyFile(templateAppFilePath, destinationPath);
|
|
167
161
|
continue;
|
|
168
162
|
}
|
|
169
163
|
let templateContent = convertTemplateToRemixVersion(
|
|
170
|
-
await readFile(
|
|
164
|
+
await readFile(templateAppFilePath),
|
|
171
165
|
v2Flags
|
|
172
166
|
);
|
|
173
167
|
if (!typescript) {
|
|
174
|
-
templateContent = transpileFile(templateContent
|
|
168
|
+
templateContent = await transpileFile(templateContent);
|
|
175
169
|
}
|
|
176
170
|
if (adapter) {
|
|
177
171
|
templateContent = templateContent.replace(
|
|
@@ -179,7 +173,7 @@ async function generateProjectFile(routeFrom, {
|
|
|
179
173
|
adapter
|
|
180
174
|
);
|
|
181
175
|
}
|
|
182
|
-
templateContent = formatCode(
|
|
176
|
+
templateContent = await formatCode(
|
|
183
177
|
templateContent,
|
|
184
178
|
formatOptions,
|
|
185
179
|
destinationPath
|
|
@@ -223,17 +217,6 @@ async function findRouteDependencies(routeFilePath, appDirectory) {
|
|
|
223
217
|
}
|
|
224
218
|
return [...fileDependencies];
|
|
225
219
|
}
|
|
226
|
-
async function getJsTranspilerOptions(rootDirectory) {
|
|
227
|
-
const jsConfigPath = joinPath(rootDirectory, "jsconfig.json");
|
|
228
|
-
if (!await fileExists(jsConfigPath))
|
|
229
|
-
return;
|
|
230
|
-
return JSON.parse(
|
|
231
|
-
(await readFile(jsConfigPath, { encoding: "utf8" })).replace(
|
|
232
|
-
/^\s*\/\/.*$/gm,
|
|
233
|
-
""
|
|
234
|
-
)
|
|
235
|
-
)?.compilerOptions;
|
|
236
|
-
}
|
|
237
220
|
async function renderRoutePrompt(options) {
|
|
238
221
|
const generateAll = await renderConfirmationPrompt({
|
|
239
222
|
message: "Scaffold all standard route files? " + Object.keys(ROUTE_MAP).join(", "),
|
|
@@ -39,7 +39,6 @@ describe("generate/route", () => {
|
|
|
39
39
|
expect(result).toMatchObject(
|
|
40
40
|
expect.objectContaining({
|
|
41
41
|
isTypescript: false,
|
|
42
|
-
transpilerOptions: { test: "js" },
|
|
43
42
|
formatOptions: { singleQuote: false },
|
|
44
43
|
routes: expect.any(Array)
|
|
45
44
|
})
|
|
@@ -61,7 +60,7 @@ describe("generate/route", () => {
|
|
|
61
60
|
});
|
|
62
61
|
vi.mocked(getRemixConfig).mockResolvedValue({
|
|
63
62
|
...directories,
|
|
64
|
-
tsconfigPath: "somewhere",
|
|
63
|
+
tsconfigPath: "somewhere/tsconfig.json",
|
|
65
64
|
future: {
|
|
66
65
|
v2_routeConvention: true
|
|
67
66
|
}
|
|
@@ -74,7 +73,6 @@ describe("generate/route", () => {
|
|
|
74
73
|
expect(result).toMatchObject(
|
|
75
74
|
expect.objectContaining({
|
|
76
75
|
isTypescript: true,
|
|
77
|
-
transpilerOptions: void 0,
|
|
78
76
|
routes: expect.any(Array),
|
|
79
77
|
formatOptions: expect.any(Object)
|
|
80
78
|
})
|
package/dist/lib/transpile-ts.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
|
-
import ts from 'typescript';
|
|
4
3
|
import glob from 'fast-glob';
|
|
5
4
|
import { outputDebug } from '@shopify/cli-kit/node/output';
|
|
6
5
|
import { getCodeFormatOptions, formatCode } from './format-code.js';
|
|
@@ -18,7 +17,9 @@ const DEFAULT_TS_CONFIG = {
|
|
|
18
17
|
forceConsistentCasingInFileNames: true,
|
|
19
18
|
skipLibCheck: true
|
|
20
19
|
};
|
|
21
|
-
function transpileFile(code, config = DEFAULT_TS_CONFIG) {
|
|
20
|
+
async function transpileFile(code, config = DEFAULT_TS_CONFIG) {
|
|
21
|
+
const tsImport = await import('typescript');
|
|
22
|
+
const ts = tsImport.default ?? tsImport;
|
|
22
23
|
const withArtificialNewLines = escapeNewLines(code);
|
|
23
24
|
const compiled = ts.transpileModule(withArtificialNewLines, {
|
|
24
25
|
reportDiagnostics: false,
|
|
@@ -82,7 +83,7 @@ async function transpileProject(projectDir) {
|
|
|
82
83
|
continue;
|
|
83
84
|
}
|
|
84
85
|
const tsx = await fs.readFile(entry, "utf8");
|
|
85
|
-
const mjs = formatCode(transpileFile(tsx), formatConfig);
|
|
86
|
+
const mjs = await formatCode(await transpileFile(tsx), formatConfig);
|
|
86
87
|
await fs.rm(entry);
|
|
87
88
|
await fs.writeFile(entry.replace(/\.ts(x?)$/, ".js$1"), mjs, "utf8");
|
|
88
89
|
}
|
|
@@ -1,28 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
const HydrogenLogoBaseBW = (props) => /* @__PURE__ */ jsxs(
|
|
2
3
|
"svg",
|
|
3
4
|
{
|
|
4
5
|
width: 81,
|
|
5
6
|
height: 82,
|
|
6
7
|
fill: "none",
|
|
7
8
|
xmlns: "http://www.w3.org/2000/svg",
|
|
8
|
-
...props
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
...props,
|
|
10
|
+
children: [
|
|
11
|
+
/* @__PURE__ */ jsx(
|
|
12
|
+
"path",
|
|
13
|
+
{
|
|
14
|
+
d: "M39.955 81.28 2.138 61.19l12.933-6.818 14.562 7.733 12.218-6.441L27.29 47.93l12.933-6.833L78.04 61.189l-12.934 6.817L51.35 60.7l-12.236 6.457 13.774 7.308-12.933 6.817Z",
|
|
15
|
+
fill: "#000"
|
|
16
|
+
}
|
|
17
|
+
),
|
|
18
|
+
/* @__PURE__ */ jsx(
|
|
19
|
+
"path",
|
|
20
|
+
{
|
|
21
|
+
fillRule: "evenodd",
|
|
22
|
+
clipRule: "evenodd",
|
|
23
|
+
d: "m40.225 0 39.953 21.227-15.073 7.945-13.756-7.308-10.096 5.328 13.775 7.309-15.075 7.945L0 21.22l15.073-7.945 14.562 7.732 10.078-5.313-14.56-7.731L40.225 0ZM29.426 7.967l14.564 7.734L29.63 23.27 15.07 15.537l-10.794 5.69 35.68 18.956 10.793-5.688-13.773-7.307L51.352 19.6l13.757 7.308 10.794-5.69-35.68-18.956-10.797 5.704Z",
|
|
24
|
+
fill: "#000"
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
]
|
|
28
|
+
}
|
|
26
29
|
);
|
|
27
30
|
export {
|
|
28
31
|
HydrogenLogoBaseBW
|
|
@@ -1,42 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
const HydrogenLogoBaseColor = (props) => /* @__PURE__ */
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
const HydrogenLogoBaseColor = (props) => /* @__PURE__ */ jsxs(
|
|
3
3
|
"svg",
|
|
4
4
|
{
|
|
5
5
|
width: 76,
|
|
6
6
|
height: 81,
|
|
7
7
|
fill: "none",
|
|
8
8
|
xmlns: "http://www.w3.org/2000/svg",
|
|
9
|
-
...props
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
9
|
+
...props,
|
|
10
|
+
children: [
|
|
11
|
+
/* @__PURE__ */ jsx(
|
|
12
|
+
"path",
|
|
13
|
+
{
|
|
14
|
+
d: "M37.817 80.149 0 60.057l12.934-6.817 14.561 7.733 12.218-6.441-14.561-7.733 12.933-6.833 37.818 20.091-12.934 6.817-13.757-7.307-12.236 6.457 13.775 7.308-12.934 6.817Z",
|
|
15
|
+
fill: "#000"
|
|
16
|
+
}
|
|
17
|
+
),
|
|
18
|
+
/* @__PURE__ */ jsx(
|
|
19
|
+
"path",
|
|
20
|
+
{
|
|
21
|
+
d: "M37.818 40.183 0 20.092l12.934-6.818 14.562 7.733 12.218-6.441-14.562-7.733L38.086 0l37.817 20.091-12.934 6.817-13.756-7.307-12.236 6.457 13.774 7.308-12.933 6.817Z",
|
|
22
|
+
fill: "url(#a)"
|
|
23
|
+
}
|
|
24
|
+
),
|
|
25
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
26
|
+
"linearGradient",
|
|
27
|
+
{
|
|
28
|
+
id: "a",
|
|
29
|
+
x1: 74.48,
|
|
30
|
+
y1: 21.654,
|
|
31
|
+
x2: 18.735,
|
|
32
|
+
y2: 51.694,
|
|
33
|
+
gradientUnits: "userSpaceOnUse",
|
|
34
|
+
children: [
|
|
35
|
+
/* @__PURE__ */ jsx("stop", { offset: 2e-3, stopColor: "#430470" }),
|
|
36
|
+
/* @__PURE__ */ jsx("stop", { offset: 0.385, stopColor: "#8E01F0" }),
|
|
37
|
+
/* @__PURE__ */ jsx("stop", { offset: 0.635, stopColor: "#354CF6" }),
|
|
38
|
+
/* @__PURE__ */ jsx("stop", { offset: 1, stopColor: "#01FFFF" })
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
) })
|
|
42
|
+
]
|
|
43
|
+
}
|
|
40
44
|
);
|
|
41
45
|
export {
|
|
42
46
|
HydrogenLogoBaseColor
|