A guide on how to participate in this project.
Before "Contribution":
- All Contributors and Maintainers are required to follow the Code of Conduct.
- See Pulsate Specification about the Pulsate's model and design.
Pulsate accepts the following issues:
These issues can be submitted by filling out the form.
If the issue type you wish to submit is not listed here, you can submit an empty issue here.
Please check the following points before submission.
- Similar issues have not already been submitted.
- Click here to check.
- (Bug report only) Is it not a security-related bug?
- If you are submitting such a bug report, you must submit it in an appropriate manner, not as an Issue. Please check our security policy for details.
Pulsate welcomes pull request submissions.
To submit a pull request to Pulsate, you need to clarify why this change is needed, summary of changes.
When you try to submit a pull request, a pre-prepared template will be displayed as a placeholder. Follow the template to describe the pull request you are submitting.
Before submitting a pull request, please check the following points:
- Check to see if the pull request you are submitting is the same as the one you are submitting.
- Click here to check.
- You are not trying to submit a PR that is still in progress.
- If you want to submit a PR in progress, please submit it as "Draft".
- Pull request title conforms to Conventional Commits
After finishing, please run pnpm format
to format the code. (If you are using VSCode, it will be formatted automatically.)
Once it has been reviewed and approved by the Pulsate maintainer, it can be merged.
During the review, keep the following in mind.
- Answer questions from the maintainer.
- Reply to any questions about changes from the maintainer during the review. This will be helpful during the review.
Pulsate commit messages must follow conventional commit.
- The commit message should be in the following form.
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
- The
type
must be the correct "type" for the change.- For example, Add new feature is
feat
, Fix bug isfix
.
- For example, Add new feature is
- If you make any backward-compatibility-breaking changes, you must set
scope
to!
and add a description of the destructive change tobody
.- Please contact the maintainer via Issue or Discussion once you make such a change. In most cases, such changes are not desired.
Pulsate assumes the following development environment.
- Node.js v20.x
- Pnpm (pnpm) v9.x
In order to develop with Pulsate, you need to fix the version of Node.js using the following tools.
- mise (recommended)
- This is a version control tool compatible with asdf. It is recommended to use mise unless there is some inconvenience.
- asdf
- With
.tool-versions
file, you can also fix the version of Node.js with asdf.
- With
Warning
If you are using a version of Node.js other than v20.x, which is the required environment for Pulsate, commands such as pnpm run
will not be available to maintain compatibility. Please fix your version before starting development.
To use mise, follow these steps:
- Install mise. See mise installation guide for details.
- Run
mise install
in the Pulsate root directory. - Run
node --version
and make sure your Node.js version is20.x
.
Pulsate uses pnpm to manage packages. Run the following command to install the package.
# If pnpm is not enabled:
corepack enable pnpm
pnpm install
To generate a Prisma Client from a defined Prisma schema, execute the following command. (Originally defined in the prepare
script, this is done automatically when updating dependencies.)
pnpm build:prisma
This command will create a Prisma Client in node_modules/.prisma/client
. You can import the client from here when you want to use it.
If you change the model, you can update the Prisma Client by running this command again.
A style guide for Pulsate development.
- These settings are bound by Prettier, ESLint, .editorconfig.
- Some editors and IDEs require special plug-ins to be installed.
- For more details, click here.
- All files must have spaces at the end of lines removed.
- In the case of Markdown, it is not necessary to remove it because it also means a line break.
- All files must have a single newline at the end.
- All files should be opened with
space
intent.- The size of the intent is about
2
characters.
- The size of the intent is about
- Use
lf
for line breaks. - Use
utf-8
character encoding.
The basic naming conventions follow the TypeScript Coding guidelines.
Acronyms and contractions of compound words are counted as one word. For example, for UUUID
, use Uuid
. For HTTPS
, use Https
.
In cases where the word is a single character, such as X_CONTENT
, the _
is omitted and XCONTENT
is used.
Also, in situations where camelCase
should be used, it is counted as a single word. For example, the name of a variable representing an account ID is accountId
.
-
The variable and function name is
camelCase
. -
The class name is
PascalCase
.- The class member and method name is
camelCase
.
- The class member and method name is
-
The interface name is
PascalCase
.- The interface member name is
camelCase
.
- The interface member name is
-
The enum name and member is
PascalCase
. -
The type name is
PascalCase
.- The type member name is
camelCase
.
- The type member name is
-
The namespace name is
PascalCase
. -
The file name should be in
camelCase
.- Use
lowercase
for a single word.
- Use
Pulsate uses a functional programming library called mini-fn
.
mini-fn
has a direct sum type Option<T>
, so you don't have to think whether the type should be T | undefined
or T | null
.
There is a dedicated function to handle the direct sum type, so you can use Option
or Result
instead if you want to handle null
or undefined
types.
/* Type Guard. Required for TypeScript to determine the type at code branches. */
// The `res` in this state is of type `Option<Account>` and it is not determined whether the value exists or not.
const res = await this.accountRepository.findByName(name);
// Check whether the value `res` exists or not by type guarding. If not, it is an error.
if (Option.isNone(res)) {
return Result.err(new Error('account not found'));
}
// Fix `res` as `account`.
const account = Option.unwrap(res);
If you need to define a property whose value may not exist. Do not use null
or undefined
, but use ?
.
// Good
interface Foo {
x?: string;
}
// Bad
interface Foo {
x: string | undefined;
y: string | null;
}
Do not use any
, use unknown
.
If you use an API with typing that returns any
, immediately make a type assertion to unknown
.
// Good
const foo = 'apple' as unknown
// Bad
const foo = 'apple' as any
Use single quotes for strings.
// Good
const a = 'hoge';
// Bad
const a = "hoge";
Use annotations when declaring arrays to ensure readability.
// Good
const a: string[]
// Bad
const a: Array<string>
Pulsate uses Prisma to manage the database schema migration.
For more information, see the Prisma documentation.