Merge pull request #9 from saleor/add-linting
Add code formatting, git hooks and improved CI
This commit is contained in:
commit
6972dbd562
12 changed files with 1691 additions and 69 deletions
71
.eslintrc
Normal file
71
.eslintrc
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"tsconfigRootDir": "./",
|
||||
"project": ["./tsconfig.json"]
|
||||
},
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier" // prettier *has* to be the last one, to avoid conflicting rules
|
||||
],
|
||||
"ignorePatterns": ["pnpm-lock.yaml"],
|
||||
"plugins": ["simple-import-sort", "@typescript-eslint"],
|
||||
"rules": {
|
||||
"quotes": ["error", "double"],
|
||||
"react/react-in-jsx-scope": "off", // next does not require react imports
|
||||
"import/extensions": "off", // file extension not required when importing
|
||||
"react/jsx-filename-extension": "off",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "ForInStatement",
|
||||
"message": "for ... in disallowed, use for ... of instead"
|
||||
}
|
||||
],
|
||||
|
||||
"no-underscore-dangle": "off",
|
||||
"no-await-in-loop": "off",
|
||||
"react/jsx-props-no-spreading": "off",
|
||||
"react/require-default-props": "off",
|
||||
"simple-import-sort/imports": "warn",
|
||||
"simple-import-sort/exports": "warn",
|
||||
"import/first": "warn",
|
||||
"import/newline-after-import": "warn",
|
||||
"import/no-duplicates": "warn",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error"],
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
"allow": ["warn", "error", "debug"]
|
||||
}
|
||||
],
|
||||
"no-continue": "off",
|
||||
"operator-linebreak": "off",
|
||||
"max-len": "off",
|
||||
"array-callback-return": "off",
|
||||
"implicit-arrow-linebreak": "off",
|
||||
"@typescript-eslint/no-non-null-asserted-optional-chain": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"no-restricted-imports": "off",
|
||||
"no-restricted-exports": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
// TO FIX:
|
||||
"import/no-cycle": "off", // pathpidia issue
|
||||
"import/prefer-default-export": "off",
|
||||
"@typescript-eslint/no-misused-promises": ["error"],
|
||||
"@typescript-eslint/no-floating-promises": ["error"]
|
||||
},
|
||||
"settings": {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts", ".tsx"]
|
||||
},
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"alwaysTryTypes": true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
.github/workflows/main.yml
vendored
5
.github/workflows/main.yml
vendored
|
@ -16,10 +16,7 @@ jobs:
|
|||
run: pnpm install
|
||||
- name: Check linters
|
||||
run: pnpm lint
|
||||
- name: Validate paths
|
||||
run: |
|
||||
pnpm paths
|
||||
git diff --exit-code ./lib/\$path.ts
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
pnpx lint-staged
|
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
|||
.next
|
||||
saleor/api.tsx
|
||||
pnpm-lock.yaml
|
||||
graphql.schema.json
|
||||
lib/$path.ts
|
4
.prettierrc
Normal file
4
.prettierrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": false,
|
||||
"printWidth": 100
|
||||
}
|
16
README.md
16
README.md
|
@ -4,8 +4,8 @@ SDK for building great Saleor Apps.
|
|||
|
||||
<div>
|
||||
|
||||
[](https://www.npmjs.com/package/@saleor/app-sdk)
|
||||
[](https://www.npmjs.com/package/@saleor/app-sdk)
|
||||
[](https://www.npmjs.com/package/@saleor/app-sdk)
|
||||
[](https://www.npmjs.com/package/@saleor/app-sdk)
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -14,3 +14,15 @@ SDK for building great Saleor Apps.
|
|||
```bash
|
||||
npm i @saleor/app-sdk
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Code style
|
||||
|
||||
Before committing the code, Git pre-hooks will check staged changes for
|
||||
following the code styles. If you would like to format the code by yourself, run
|
||||
the command:
|
||||
|
||||
```bash
|
||||
pnpm lint
|
||||
```
|
||||
|
|
23
package.json
23
package.json
|
@ -9,7 +9,9 @@
|
|||
"watch": "tsc -w",
|
||||
"build": "tsup-node src/* --format esm,cjs --dts && clear-package-json package.json -o dist/package.json --fields publishConfig",
|
||||
"test": "uvu -r tsm spec",
|
||||
"test-watch": "watchlist src spec -- pnpm test"
|
||||
"test-watch": "watchlist src spec -- pnpm test",
|
||||
"prepare": "husky install",
|
||||
"lint": "prettier --loglevel warn --write . && eslint --fix ."
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
|
@ -21,14 +23,31 @@
|
|||
"retes": "^0.29.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"clean-publish": "^4.0.1",
|
||||
"@types/node": "^18.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.17.0",
|
||||
"@typescript-eslint/parser": "^5.30.7",
|
||||
"clean-publish": "^4.0.1",
|
||||
"eslint": "8.15.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.3.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.0",
|
||||
"eslint-plugin-react": "^7.30.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"husky": "^8.0.1",
|
||||
"prettier": "2.6.2",
|
||||
"tsm": "^2.2.1",
|
||||
"tsup": "^6.1.3",
|
||||
"typescript": "^4.7.4",
|
||||
"uvu": "^0.5.6",
|
||||
"watchlist": "^0.3.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,tsx}": "eslint --cache --fix",
|
||||
"*.{js,ts,tsx,css,md,json}": "prettier --write"
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
"./const": {
|
||||
|
|
1519
pnpm-lock.yaml
1519
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
33
src/index.ts
33
src/index.ts
|
@ -1,43 +1,38 @@
|
|||
import path from "path";
|
||||
import fg from "fast-glob";
|
||||
|
||||
import { print } from "graphql/language/printer.js";
|
||||
import path from "path";
|
||||
|
||||
const capitalize = (value: string) =>
|
||||
value.charAt(0).toUpperCase() + value.slice(1);
|
||||
const capitalize = (value: string) => value.charAt(0).toUpperCase() + value.slice(1);
|
||||
|
||||
const dropFileExtension = (filename: string) => path.parse(filename).name;
|
||||
|
||||
export const inferWebhooks = async (baseURL: string, webhooksPath: string, generatedGraphQL: any) => {
|
||||
export const inferWebhooks = async (
|
||||
baseURL: string,
|
||||
webhooksPath: string,
|
||||
generatedGraphQL: any
|
||||
) => {
|
||||
let entries;
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
entries = await fg(["*.js"], { cwd: webhooksPath });
|
||||
} else {
|
||||
entries = await fg(["*.ts"], { cwd: `pages/api/webhooks` });
|
||||
entries = await fg(["*.ts"], { cwd: "pages/api/webhooks" });
|
||||
}
|
||||
|
||||
return entries.map(dropFileExtension).map((name: string) => {
|
||||
const camelcaseName = name.split("-").map(capitalize).join("");
|
||||
const camelCaseName = name.split("-").map(capitalize).join("");
|
||||
|
||||
const eventName = name.toUpperCase().replace(new RegExp("-", "g"), "_");
|
||||
const eventName = name.toUpperCase().replace(/-/g, "_");
|
||||
let eventType: string;
|
||||
if (
|
||||
Object.values(generatedGraphQL.WebhookEventTypeAsyncEnum).includes(
|
||||
eventName
|
||||
)
|
||||
) {
|
||||
if (Object.values(generatedGraphQL.WebhookEventTypeAsyncEnum).includes(eventName)) {
|
||||
eventType = "asyncEvents";
|
||||
} else if (
|
||||
Object.values(generatedGraphQL.WebhookEventTypeSyncEnum).includes(
|
||||
eventName
|
||||
)
|
||||
) {
|
||||
} else if (Object.values(generatedGraphQL.WebhookEventTypeSyncEnum).includes(eventName)) {
|
||||
eventType = "syncEvents";
|
||||
} else {
|
||||
throw Error("Event type not found.");
|
||||
}
|
||||
|
||||
const statement = `${camelcaseName}SubscriptionDocument`;
|
||||
const statement = `${camelCaseName}SubscriptionDocument`;
|
||||
let query: string;
|
||||
if (statement in generatedGraphQL) {
|
||||
query = print((generatedGraphQL as any)[statement]);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import crypto from "crypto";
|
||||
|
||||
import * as jose from "jose";
|
||||
import type { Middleware } from "retes";
|
||||
import { Response } from "retes/response";
|
||||
|
@ -16,11 +15,10 @@ export const withBaseURL: Middleware = (handler) => async (request) => {
|
|||
return response;
|
||||
};
|
||||
|
||||
export const withSaleorDomainPresent: Middleware =
|
||||
(handler) => async (request) => {
|
||||
const saleor_domain = request.headers[SALEOR_DOMAIN_HEADER];
|
||||
export const withSaleorDomainPresent: Middleware = (handler) => async (request) => {
|
||||
const saleorDomain = request.headers[SALEOR_DOMAIN_HEADER];
|
||||
|
||||
if (!saleor_domain) {
|
||||
if (!saleorDomain) {
|
||||
return Response.BadRequest({
|
||||
success: false,
|
||||
message: "Missing Saleor domain header.",
|
||||
|
@ -28,7 +26,7 @@ export const withSaleorDomainPresent: Middleware =
|
|||
}
|
||||
|
||||
return handler(request);
|
||||
};
|
||||
};
|
||||
|
||||
export const withSaleorEventMatch =
|
||||
<E extends string>(expectedEvent: `${Lowercase<E>}`): Middleware =>
|
||||
|
@ -46,10 +44,9 @@ export const withSaleorEventMatch =
|
|||
return handler(request);
|
||||
};
|
||||
|
||||
export const withAuthTokenRequired: Middleware =
|
||||
(handler) => async (request) => {
|
||||
const auth_token = request.params.auth_token;
|
||||
if (!auth_token) {
|
||||
export const withAuthTokenRequired: Middleware = (handler) => async (request) => {
|
||||
const authToken = request.params.auth_token;
|
||||
if (!authToken) {
|
||||
return Response.BadRequest({
|
||||
success: false,
|
||||
message: "Missing auth token.",
|
||||
|
@ -57,12 +54,12 @@ export const withAuthTokenRequired: Middleware =
|
|||
}
|
||||
|
||||
return handler(request);
|
||||
};
|
||||
};
|
||||
|
||||
export const withWebhookSignatureVerified = (
|
||||
secretKey: string | undefined = undefined
|
||||
): Middleware => {
|
||||
return (handler) => async (request) => {
|
||||
export const withWebhookSignatureVerified =
|
||||
(secretKey: string | undefined = undefined): Middleware =>
|
||||
(handler) =>
|
||||
async (request) => {
|
||||
if (request.rawBody === undefined) {
|
||||
return Response.InternalServerError({
|
||||
success: false,
|
||||
|
@ -70,10 +67,8 @@ export const withWebhookSignatureVerified = (
|
|||
});
|
||||
}
|
||||
|
||||
const {
|
||||
[SALEOR_DOMAIN_HEADER]: saleorDomain,
|
||||
"saleor-signature": payloadSignature,
|
||||
} = request.headers;
|
||||
const { [SALEOR_DOMAIN_HEADER]: saleorDomain, "saleor-signature": payloadSignature } =
|
||||
request.headers;
|
||||
|
||||
if (secretKey !== undefined) {
|
||||
const calculatedSignature = crypto
|
||||
|
@ -88,7 +83,7 @@ export const withWebhookSignatureVerified = (
|
|||
});
|
||||
}
|
||||
} else {
|
||||
const [header, _, signature] = payloadSignature.split(".");
|
||||
const [header, , signature] = payloadSignature.split(".");
|
||||
const jws = {
|
||||
protected: header,
|
||||
payload: request.rawBody,
|
||||
|
@ -111,4 +106,3 @@ export const withWebhookSignatureVerified = (
|
|||
|
||||
return handler(request);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -11,8 +11,10 @@
|
|||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ES2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
"lib": ["ES2021"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
"target": "ES2021" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
"lib": [
|
||||
"ES2021"
|
||||
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
|
@ -25,7 +27,7 @@
|
|||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
"module": "commonjs" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
|
@ -71,12 +73,12 @@
|
|||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
|
|
Loading…
Reference in a new issue