Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Add auto-generated REST resources #316

Merged
merged 2 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 5 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ module.exports = {
es2021: true,
},
extends: ['plugin:@shopify/typescript', 'plugin:@shopify/prettier'],
ignorePatterns: ['dist/'],
ignorePatterns: ['dist/', 'src/rest-resources'],
rules: {
'import/no-named-as-default': 0,
'no-mixed-operators': 0,
'no-console': 0,
'lines-around-comment': 0,
},
overrides: [
{
files: [
'src/rest_resources/__tests__/*.ts',
'src/rest_resources/base.ts',
'src/rest_resources/admin*/*.ts',
'src/__tests__/*.ts',
'src/base-rest-resource.ts',
'src/rest-resources/*',
],
rules: {
'@typescript-eslint/naming-convention': [
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ jobs:
run: yarn lint
- name: Test
run: yarn test
- name: Test REST resources
run: yarn test_rest_resources
7 changes: 6 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
module.exports = {
preset: 'ts-jest',
preset: 'ts-jest/presets/default-esm', // or other ESM presets
globals: {
'ts-jest': {
useESM: true,
},
},
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'js', 'json'],
watchPathIgnorePatterns: ['<rootDir>/node_modules/'],
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"types": "dist/index.d.ts",
"prettier": "@shopify/prettier-config",
"scripts": {
"test": "jest",
"test": "jest --testPathIgnorePatterns=src/rest-resources/__tests__",
"test_rest_resources": "ls src/rest-resources/__tests__ | xargs -I \"{}\" sh -c 'yarn jest --no-coverage --testPathPattern=\\\"{}\\\" || exit 255'",
"build": "tsc",
"lint": "eslint '**/*.{ts,tsx}' --max-warnings 0",
"clean": "rimraf ./dist tsconfig.tsbuildinfo",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {Session} from '../../auth/session';
import {RestResourceRequestError} from '../../error';
import {Session} from '../auth/session';
import {ApiVersion} from '../base-types';
import {Context} from '../context';
import {RestResourceRequestError, RestResourceError} from '../error';

import FakeResource from './fake_resource';
import FakeResourceWithCustomPrefix from './fake_resource_with_custom_prefix';
import FakeResource from './fake-resource';
import FakeResourceWithCustomPrefix from './fake-resource-with-custom-prefix';

describe('Base REST resource', () => {
const domain = 'test-shop.myshopify.io';
Expand Down Expand Up @@ -393,4 +395,14 @@ describe('Base REST resource', () => {
headers,
}).toMatchMadeHttpRequest();
});

it('throws an error if the API versions mismatch', async () => {
Context.API_VERSION = ApiVersion.January22;

await expect(FakeResource.all({session})).rejects.toThrowError(
new RestResourceError(
`Current Context.API_VERSION '${ApiVersion.January22}' does not match resource version ${ApiVersion.Unstable}`,
),
);
});
});
2 changes: 1 addition & 1 deletion src/__tests__/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Cookies from 'cookies';

import * as ShopifyErrors from '../error';
import {Context} from '../context';
import {ApiVersion, ContextParams} from '../base_types';
import {ApiVersion, ContextParams} from '../base-types';

jest.mock('cookies');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Base, {ResourcePath} from '../base';
import {SessionInterface} from '../../auth/session/types';
import Base, {ResourcePath} from '../base-rest-resource';
import {SessionInterface} from '../auth/session/types';
import {ApiVersion} from '../base-types';

interface FakeResourceWithCustomPrefixFindArgs {
session: SessionInterface;
id: string | number;
}

export default class FakeResourceWithCustomPrefix extends Base {
public static API_VERSION = ApiVersion.Unstable;
protected static NAME = 'fake_resource_with_custom_prefix';
protected static PLURAL_NAME = 'fake_resource_with_custom_prefixes';
protected static CUSTOM_PREFIX = '/admin/custom_prefix';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Base, {ParamSet, ResourcePath} from '../base';
import {SessionInterface} from '../../auth/session/types';
import Base, {ParamSet, ResourcePath} from '../base-rest-resource';
import {SessionInterface} from '../auth/session/types';
import {ApiVersion} from '../base-types';

interface FakeResourceFindArgs {
params?: ParamSet;
Expand All @@ -20,6 +21,7 @@ interface FakeResourceCustomArgs {
}

export default class FakeResource extends Base {
public static API_VERSION = ApiVersion.Unstable;
protected static NAME = 'fake_resource';
protected static PLURAL_NAME = 'fake_resources';

Expand Down
19 changes: 14 additions & 5 deletions src/rest_resources/base.ts → src/base-rest-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import {
HttpResponseError,
RestResourceError,
RestResourceRequestError,
} from '../error';
import {SessionInterface} from '../auth/session/types';
import {RestClient} from '../clients/rest';
import {RestRequestReturn} from '../clients/rest/types';
import {DataType, GetRequestParams} from '../clients/http_client/types';
} from './error';
import {SessionInterface} from './auth/session/types';
import {RestClient} from './clients/rest';
import {RestRequestReturn} from './clients/rest/types';
import {DataType, GetRequestParams} from './clients/http_client/types';
import {ApiVersion} from './base-types';
import {Context} from './context';

export interface IdSet {
[id: string]: string | number | null;
Expand Down Expand Up @@ -56,6 +58,7 @@ class Base {
// For instance attributes
[key: string]: any;

public static API_VERSION: ApiVersion;
public static NEXT_PAGE_INFO: GetRequestParams | undefined;
public static PREV_PAGE_INFO: GetRequestParams | undefined;

Expand Down Expand Up @@ -97,6 +100,12 @@ class Base {
body,
entity,
}: RequestArgs): Promise<RestRequestReturn> {
if (Context.API_VERSION !== this.API_VERSION) {
throw new RestResourceError(
`Current Context.API_VERSION '${Context.API_VERSION}' does not match resource version ${this.API_VERSION}`,
);
}

const client = new RestClient(session.shop, session.accessToken);

const path = this.getPath({http_method, operation, urlIds, entity});
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/clients/graphql/__tests__/graphql_client.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ShopifyHeader} from '../../../base_types';
import {ShopifyHeader} from '../../../base-types';
import {GraphqlClient} from '../graphql_client';
import {Context} from '../../../context';
import * as ShopifyErrors from '../../../error';
Expand Down
2 changes: 1 addition & 1 deletion src/clients/graphql/__tests__/storefront_client.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ShopifyHeader} from '../../../base_types';
import {ShopifyHeader} from '../../../base-types';
import {StorefrontClient} from '../storefront_client';
import {Context} from '../../../context';

Expand Down
2 changes: 1 addition & 1 deletion src/clients/graphql/graphql_client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {MissingRequiredArgument} from '../../error';
import {Context} from '../../context';
import {ShopifyHeader} from '../../base_types';
import {ShopifyHeader} from '../../base-types';
import {HttpClient} from '../http_client/http_client';
import {DataType, RequestReturn} from '../http_client/types';
import * as ShopifyErrors from '../../error';
Expand Down
2 changes: 1 addition & 1 deletion src/clients/graphql/storefront_client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Context} from '../../context';
import {ShopifyHeader} from '../../base_types';
import {ShopifyHeader} from '../../base-types';

import {GraphqlClient, AccessTokenHeader} from './graphql_client';

Expand Down
2 changes: 1 addition & 1 deletion src/clients/rest/__tests__/rest_client.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import querystring from 'querystring';

import {ShopifyHeader} from '../../../base_types';
import {ShopifyHeader} from '../../../base-types';
import {DataType, GetRequestParams} from '../../http_client/types';
import {RestClient} from '../rest_client';
import {RestRequestReturn, PageInfo} from '../types';
Expand Down
2 changes: 1 addition & 1 deletion src/clients/rest/rest_client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import querystring from 'querystring';

import {Context} from '../../context';
import {ShopifyHeader} from '../../base_types';
import {ShopifyHeader} from '../../base-types';
import {HttpClient} from '../http_client/http_client';
import {RequestParams, GetRequestParams} from '../http_client/types';
import * as ShopifyErrors from '../../error';
Expand Down
2 changes: 1 addition & 1 deletion src/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as ShopifyErrors from './error';
import {SessionStorage} from './auth/session/session_storage';
import {MemorySessionStorage} from './auth/session/storage/memory';
import {ApiVersion, ContextParams} from './base_types';
import {ApiVersion, ContextParams} from './base-types';
import {AuthScopes} from './auth/scopes';

interface ContextInterface extends ContextParams {
Expand Down
103 changes: 103 additions & 0 deletions src/rest-resources/2021-04/abandoned_checkout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import Base, {ResourcePath} from '../../base-rest-resource';
import {SessionInterface} from '../../auth/session/types';
import {ApiVersion} from '../../base-types';

import {Currency} from './currency';
import {Customer} from './customer';
import {DiscountCode} from './discount_code';

interface CheckoutsArgs {
[key: string]: unknown;
session: SessionInterface;
since_id?: unknown;
created_at_min?: unknown;
created_at_max?: unknown;
updated_at_min?: unknown;
updated_at_max?: unknown;
status?: unknown;
limit?: unknown;
}

export class AbandonedCheckout extends Base {
public static API_VERSION = ApiVersion.April21;

protected static NAME = 'abandoned_checkout';
protected static PLURAL_NAME = 'abandoned_checkouts';
protected static HAS_ONE: {[key: string]: typeof Base} = {
currency: Currency,
customer: Customer
};
protected static HAS_MANY: {[key: string]: typeof Base} = {
discount_codes: DiscountCode
};
protected static PATHS: ResourcePath[] = [
{http_method: "get", operation: "checkouts", ids: [], path: "checkouts.json"},
{http_method: "get", operation: "checkouts", ids: [], path: "checkouts.json"}
];

public static async checkouts(
{
session,
since_id = null,
created_at_min = null,
created_at_max = null,
updated_at_min = null,
updated_at_max = null,
status = null,
limit = null,
...otherArgs
}: CheckoutsArgs
): Promise<unknown> {
const response = await AbandonedCheckout.request({
http_method: "get",
operation: "checkouts",
session: session,
urlIds: {},
params: {since_id: since_id, created_at_min: created_at_min, created_at_max: created_at_max, updated_at_min: updated_at_min, updated_at_max: updated_at_max, status: status, limit: limit, ...otherArgs},
body: {},
entity: null,
});

return response ? response.body : null;
}

public abandoned_checkout_url: string | null;
public billing_address: {[key: string]: unknown} | null;
public buyer_accepts_marketing: boolean | null;
public buyer_accepts_sms_marketing: boolean | null;
public cart_token: string | null;
public closed_at: string | null;
public completed_at: string | null;
public created_at: string | null;
public currency: Currency | null | {[key: string]: any};
public customer: Customer | null | {[key: string]: any};
public customer_locale: string | null;
public device_id: number | null;
public discount_codes: DiscountCode[] | null | {[key: string]: any};
public email: string | null;
public gateway: string | null;
public id: number | null;
public landing_site: string | null;
public line_items: {[key: string]: unknown} | null;
public location_id: number | null;
public note: string | null;
public phone: string | null;
public presentment_currency: string | null;
public referring_site: string | null;
public shipping_address: {[key: string]: unknown} | null;
public shipping_lines: {[key: string]: unknown} | null;
public sms_marketing_phone: string | null;
public source_name: string | null;
public subtotal_price: string | null;
public tax_lines: {[key: string]: unknown} | null;
public taxes_included: boolean | null;
public token: string | null;
public total_discounts: string | null;
public total_duties: string | null;
public total_line_items_price: string | null;
public total_price: string | null;
public total_tax: string | null;
public total_weight: number | null;
public updated_at: string | null;
public user_id: number | null;
}
39 changes: 39 additions & 0 deletions src/rest-resources/2021-04/access_scope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Base, {ResourcePath} from '../../base-rest-resource';
import {SessionInterface} from '../../auth/session/types';
import {ApiVersion} from '../../base-types';

interface AllArgs {
[key: string]: unknown;
session: SessionInterface;
}

export class AccessScope extends Base {
public static API_VERSION = ApiVersion.April21;

protected static NAME = 'access_scope';
protected static PLURAL_NAME = 'access_scopes';
protected static HAS_ONE: {[key: string]: typeof Base} = {};
protected static HAS_MANY: {[key: string]: typeof Base} = {};
protected static CUSTOM_PREFIX: string | null = "/admin/oauth";
protected static PATHS: ResourcePath[] = [
{http_method: "get", operation: "get", ids: [], path: "access_scopes.json"}
];

public static async all(
{
session,
...otherArgs
}: AllArgs
): Promise<AccessScope[]> {
const response = await AccessScope.baseFind({
session: session,
urlIds: {},
params: {...otherArgs},
});

return response as AccessScope[];
}

public handle: string | null;
public access_scopes: {[key: string]: unknown}[] | null;
}
Loading