-
Notifications
You must be signed in to change notification settings - Fork 187
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(cli): CATALYST-246 create-catalyst login, create env, scaffold project #474
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
4 Ignored Deployments
|
149c9c3
to
4171e49
Compare
c069937
to
a78022a
Compare
a78022a
to
e9fe7a1
Compare
e9fe7a1
to
e01ddc9
Compare
e01ddc9
to
a4a80be
Compare
a4a80be
to
a6ad439
Compare
a6ad439
to
d41af61
Compare
d41af61
to
9264edf
Compare
9e10e5f
to
980f017
Compare
980f017
to
da38108
Compare
da38108
to
a061eb9
Compare
@bigcommerce/team-catalyst PR description updated + branch rebased. This one is ready for a final review 👍 |
⚡️🏠 Lighthouse reportWe ran Lighthouse against the changes and produced this report. Here's the summary:
Lighthouse ran against https://catalyst-latest-4qcnzug32-bigcommerce-platform.vercel.app/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot to unpack but looks good to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know you already merged this but left a few comments for cleanup whenever you get around to it!
module.exports = { | ||
extensionsToTreatAsEsm: ['.ts'], | ||
transform: { | ||
'^.+\\.(t|j)s?$': '@swc/jest', | ||
}, | ||
transformIgnorePatterns: [], | ||
// moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], | ||
moduleNameMapper: { | ||
'^(\\.{1,2}/.*)\\.js$': '$1', | ||
}, | ||
testEnvironment: 'node', | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All you need is this (see tsconfig.json
comments):
module.exports = { | |
extensionsToTreatAsEsm: ['.ts'], | |
transform: { | |
'^.+\\.(t|j)s?$': '@swc/jest', | |
}, | |
transformIgnorePatterns: [], | |
// moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], | |
moduleNameMapper: { | |
'^(\\.{1,2}/.*)\\.js$': '$1', | |
}, | |
testEnvironment: 'node', | |
}; | |
module.exports = { | |
transform: { | |
'^.+\\.(t|j)s?$': '@swc/jest', | |
}, | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this looks good! However, I do need to keep the moduleNameMapper
because this is a "type": "module"
package, and the .js
extensions on imports are not found if the mapper is not present
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops 🤦♂️ Had to restart ESLint, and now the changes are working. Removing moduleNameMapper! Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try changing the tsconfig to this along with the jest config changes.
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Node 18",
"compilerOptions": {
"strict": true,
"target": "es6",
"module": "ESNext",
"esModuleInterop": true,
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
}
}
Additionally, let's remove disable the dts
option and enable sourcemap
in tsup.config.ts
. We don't need types exported with the CLI and sourcemaps will be helpful for debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be okay to remove with the jest + tsconfig changes.
`BIGCOMMERCE_STORE_HASH=${storeHash}`, | ||
`BIGCOMMERCE_CHANNEL_ID=${channelId}`, | ||
`BIGCOMMERCE_ACCESS_TOKEN=${accessToken}`, | ||
`BIGCOMMERCE_CUSTOMER_IMPERSONATION_TOKEN=${customerImpersonationToken}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also add this?
CLIENT_LOGGER="false"
@@ -0,0 +1,29 @@ | |||
import { oraPromise } from 'ora'; | |||
|
|||
import { spinner } from './spinner.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the tsconfig changes, you can remove the .js
extension.
let projectName = kebabCase(opts.projectName); | ||
let projectDir = opts.projectDir && projectName ? join(opts.projectDir, projectName) : undefined; | ||
|
||
if (projectDir && projectName) { | ||
return { projectDir, projectName }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍹 Instead of using let
's, we can just do something like this just to clean these files up.
let projectName = kebabCase(opts.projectName); | |
let projectDir = opts.projectDir && projectName ? join(opts.projectDir, projectName) : undefined; | |
if (projectDir && projectName) { | |
return { projectDir, projectName }; | |
} | |
if (opts.projectName && opts.projectDir) { | |
return { | |
projectDir: join(opts.projectDir, projectName), | |
projectName: kebabCase(opts.projectName), | |
}; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is a little tricky, and the more I think about it, I think there's a lot of refactoring that I'm gonna need to do around each option. In this case:
projectDir
andprojectName
can be passed as CLI flagsprojectName
is optional, and if not passed as a flag it would be equal toundefined
in this function.- If
projectName
is undefined, we need to not return, because we need to prompt the user to enter a project name - If
projectName
is defined but invalid (such as entering weird characters like*
), I need to throw an error (just noticed this isn't currently accounted for) - It's possible for
projectName
to be a space character, in which case I need to throw an error (this isn't accounted for either) projectDir
always defaults toprocess.cwd()
, but if the user enters a path that does not exist, I need to throw
I think I can reuse the validate
method lower down in this file to help with a lot of this. I'll rework it in a separate PR 👍
constructor({ | ||
bigCommerceApiUrl, | ||
storeHash, | ||
accessToken, | ||
}: { | ||
bigCommerceApiUrl: string; | ||
storeHash: string; | ||
accessToken: string; | ||
}); | ||
constructor({ | ||
sampleDataApiUrl, | ||
storeHash, | ||
accessToken, | ||
}: { | ||
sampleDataApiUrl: string; | ||
storeHash: string; | ||
accessToken: string; | ||
}); | ||
constructor({ bigCommerceAuthUrl }: { bigCommerceAuthUrl: string }); | ||
constructor({ | ||
bigCommerceApiUrl, | ||
bigCommerceAuthUrl, | ||
sampleDataApiUrl, | ||
storeHash, | ||
accessToken, | ||
}: { | ||
bigCommerceApiUrl?: string; | ||
bigCommerceAuthUrl?: string; | ||
sampleDataApiUrl?: string; | ||
storeHash?: string; | ||
accessToken?: string; | ||
}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍹 Would love some descriptive interfaces for these overloaded args.
message: 'Which channel would you like to use?', | ||
choices: activeChannels | ||
.sort((a, b) => channelSortOrder.indexOf(a.platform) - channelSortOrder.indexOf(b.platform)) | ||
.map((ch) => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🍹 :nit:
.map((ch) => ({ | |
.map((channel) => ({ |
What/Why?
create-catalyst
CLI:create
andinit
.create
is the default command, and invoked by running[npm|pnpm|yarn] create @bigcommerce/catalyst@latest
. The command accepts a number of configurable options that can be passed as flags the CLI command (this is mostly useful for running the CLI in a CI environment). A number of the configurable options have some default values if they are left empty. If no options are passed as flags, the user is prompted to enter values for each option via terminal input. The end result is a Catalyst project, created in a local directory, with an (optionally) configured environment variable file, with dependencies installed, and if the environment variable file is configured, thecreate
command also runs GraphQL codegen for GraphQL types + lints the project to ensure the project can build without errors.init
is a utility command that can be used to swap the store that the Catalyst project is connected to. Running[npx|pnpx|yarn dlx] @bigcommerce/create-catalyst init
prompts the user for authentication credentials to a BigCommerce store, and when successfully authenticated, overwrites the current local.env.local
file with new environment variables that belong to the newly authenticated store.Testing
Includes Unit and Integration tests