From f04c61776cbb7905577865639d1403a1a02428b9 Mon Sep 17 00:00:00 2001 From: JohnAlbin Date: Wed, 7 Feb 2024 19:45:12 -0600 Subject: [PATCH] refactor(next-drupal)!: move non-DrupalClient code to src/deprecated BREAKING CHANGE: The JsonApiWithAuthOptions type has been renamed to JsonApiWithAuthOption. The JsonApiWithLocaleOptions type is now considered deprecated for DrupalClient usage and can be replaced with the JsonApiOptions type. --- .../example-search-api/pages/advanced.tsx | 19 +- packages/next-drupal/jest.config.cjs | 16 +- packages/next-drupal/src/client.ts | 46 +- packages/next-drupal/src/deprecated.ts | 19 + .../src/{ => deprecated}/get-access-token.ts | 2 +- .../src/{ => deprecated}/get-cache.ts | 0 .../src/{ => deprecated}/get-menu.ts | 7 +- .../src/{ => deprecated}/get-paths.ts | 2 +- .../get-resource-collection.ts | 8 +- .../src/{ => deprecated}/get-resource-type.ts | 2 +- .../src/{ => deprecated}/get-resource.ts | 8 +- .../src/{ => deprecated}/get-search-index.ts | 7 +- .../src/{ => deprecated}/get-view.ts | 3 +- .../src/{ => deprecated}/preview.ts | 2 +- .../src/{ => deprecated}/translate-path.ts | 2 +- .../{navigation => deprecated}/use-menu.ts | 2 +- .../next-drupal/src/{ => deprecated}/utils.ts | 2 +- packages/next-drupal/src/index.ts | 23 +- packages/next-drupal/src/jsonapi-errors.ts | 15 +- packages/next-drupal/src/navigation.ts | 2 +- packages/next-drupal/src/types.ts | 478 ------------------ packages/next-drupal/src/types/client.ts | 197 ++++++++ packages/next-drupal/src/types/deprecated.ts | 3 + packages/next-drupal/src/types/drupal.ts | 154 ++++++ packages/next-drupal/src/types/index.ts | 4 + packages/next-drupal/src/types/options.ts | 39 ++ packages/next-drupal/src/types/resource.ts | 66 +++ packages/next-drupal/tests/utils.ts | 2 +- 28 files changed, 558 insertions(+), 572 deletions(-) create mode 100644 packages/next-drupal/src/deprecated.ts rename packages/next-drupal/src/{ => deprecated}/get-access-token.ts (95%) rename packages/next-drupal/src/{ => deprecated}/get-cache.ts (100%) rename packages/next-drupal/src/{ => deprecated}/get-menu.ts (90%) rename packages/next-drupal/src/{ => deprecated}/get-paths.ts (97%) rename packages/next-drupal/src/{ => deprecated}/get-resource-collection.ts (91%) rename packages/next-drupal/src/{ => deprecated}/get-resource-type.ts (91%) rename packages/next-drupal/src/{ => deprecated}/get-resource.ts (97%) rename packages/next-drupal/src/{ => deprecated}/get-search-index.ts (90%) rename packages/next-drupal/src/{ => deprecated}/get-view.ts (90%) rename packages/next-drupal/src/{ => deprecated}/preview.ts (96%) rename packages/next-drupal/src/{ => deprecated}/translate-path.ts (93%) rename packages/next-drupal/src/{navigation => deprecated}/use-menu.ts (96%) rename packages/next-drupal/src/{ => deprecated}/utils.ts (98%) delete mode 100644 packages/next-drupal/src/types.ts create mode 100644 packages/next-drupal/src/types/client.ts create mode 100644 packages/next-drupal/src/types/deprecated.ts create mode 100644 packages/next-drupal/src/types/drupal.ts create mode 100644 packages/next-drupal/src/types/index.ts create mode 100644 packages/next-drupal/src/types/options.ts create mode 100644 packages/next-drupal/src/types/resource.ts diff --git a/examples/example-search-api/pages/advanced.tsx b/examples/example-search-api/pages/advanced.tsx index c8424837..a939ad6d 100644 --- a/examples/example-search-api/pages/advanced.tsx +++ b/examples/example-search-api/pages/advanced.tsx @@ -6,7 +6,7 @@ import { DrupalNode, getSearchIndexFromContext, deserialize, - JsonApiSearchApiResponse, + DrupalSearchApiJsonApiResponse, DrupalSearchApiFacet, } from "next-drupal" import { GetStaticPropsResult } from "next" @@ -209,14 +209,15 @@ export default function AdvancedPage({ export async function getStaticProps( context ): Promise> { - const results = await getSearchIndexFromContext( - "property", - context, - { - deserialize: false, - params, - } - ) + const results = + await getSearchIndexFromContext( + "property", + context, + { + deserialize: false, + params, + } + ) return { props: { diff --git a/packages/next-drupal/jest.config.cjs b/packages/next-drupal/jest.config.cjs index 628ca568..58004753 100644 --- a/packages/next-drupal/jest.config.cjs +++ b/packages/next-drupal/jest.config.cjs @@ -13,15 +13,19 @@ module.exports = { coverageProvider: "v8", collectCoverage: true, collectCoverageFrom: ["./src/**"], - coveragePathIgnorePatterns: ["./src/get-*"], + coveragePathIgnorePatterns: [ + "./src/deprecated/*", + "./src/deprecated.ts", + "./src/navigation.ts", + "./src/types/*", + ], coverageReporters: ["lcov", "text", "text-summary"], coverageThreshold: { global: { - // @TODO Make these thresholds strict once #608 is completed. - statements: 50, // 55.1, - branches: 80, // 84.16, - functions: 70, // 72.41, - lines: 50, // 55.1, + statements: 82.07, + branches: 86.9, + functions: 80.76, + lines: 82.07, }, }, } diff --git a/packages/next-drupal/src/client.ts b/packages/next-drupal/src/client.ts index bd0cebe9..ed383140 100644 --- a/packages/next-drupal/src/client.ts +++ b/packages/next-drupal/src/client.ts @@ -23,14 +23,14 @@ import type { FetchOptions, JsonApiCreateFileResourceBody, JsonApiCreateResourceBody, + JsonApiOptions, JsonApiParams, JsonApiResource, JsonApiResourceWithPath, JsonApiResponse, JsonApiUpdateResourceBody, - JsonApiWithAuthOptions, + JsonApiWithAuthOption, JsonApiWithCacheOptions, - JsonApiWithLocaleOptions, Locale, PathAlias, PathPrefix, @@ -312,7 +312,7 @@ export class DrupalClient { async createResource( type: string, body: JsonApiCreateResourceBody, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { options = { deserialize: true, @@ -350,7 +350,7 @@ export class DrupalClient { async createFileResource( type: string, body: JsonApiCreateFileResourceBody, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { options = { deserialize: true, @@ -396,7 +396,7 @@ export class DrupalClient { type: string, uuid: string, body: JsonApiUpdateResourceBody, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { options = { deserialize: true, @@ -435,7 +435,7 @@ export class DrupalClient { async deleteResource( type: string, uuid: string, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { options = { withAuth: true, @@ -467,9 +467,7 @@ export class DrupalClient { async getResource( type: string, uuid: string, - options?: JsonApiWithLocaleOptions & - JsonApiWithAuthOptions & - JsonApiWithCacheOptions + options?: JsonApiOptions & JsonApiWithCacheOptions ): Promise { options = { deserialize: true, @@ -523,8 +521,7 @@ export class DrupalClient { options?: { pathPrefix?: PathPrefix isVersionable?: boolean - } & JsonApiWithLocaleOptions & - JsonApiWithAuthOptions + } & JsonApiOptions ): Promise { const type = typeof input === "string" ? input : input.jsonapi.resourceName @@ -605,8 +602,7 @@ export class DrupalClient { path: string, options?: { isVersionable?: boolean - } & JsonApiWithLocaleOptions & - JsonApiWithAuthOptions + } & JsonApiOptions ): Promise { options = { deserialize: true, @@ -716,8 +712,7 @@ export class DrupalClient { type: string, options?: { deserialize?: boolean - } & JsonApiWithLocaleOptions & - JsonApiWithAuthOptions + } & JsonApiOptions ): Promise { options = { withAuth: this.withAuth, @@ -754,8 +749,7 @@ export class DrupalClient { context: GetStaticPropsContext, options?: { deserialize?: boolean - } & JsonApiWithLocaleOptions & - JsonApiWithAuthOptions + } & JsonApiOptions ): Promise { options = { deserialize: true, @@ -778,7 +772,7 @@ export class DrupalClient { options?: { params?: JsonApiParams pathPrefix?: PathPrefix - } & JsonApiWithAuthOptions + } & JsonApiWithAuthOption ): Promise["paths"]> { options = { withAuth: this.withAuth, @@ -893,7 +887,7 @@ export class DrupalClient { async translatePath( path: string, - options?: JsonApiWithAuthOptions + options?: JsonApiWithAuthOption ): Promise { options = { withAuth: this.withAuth, @@ -926,7 +920,7 @@ export class DrupalClient { context: GetStaticPropsContext, options?: { pathPrefix?: PathPrefix - } & JsonApiWithAuthOptions + } & JsonApiWithAuthOption ): Promise { options = { pathPrefix: "/", @@ -1160,9 +1154,7 @@ export class DrupalClient { async getMenu( name: string, - options?: JsonApiWithLocaleOptions & - JsonApiWithAuthOptions & - JsonApiWithCacheOptions + options?: JsonApiOptions & JsonApiWithCacheOptions ): Promise<{ items: T[] tree: T[] @@ -1246,7 +1238,7 @@ export class DrupalClient { async getView( name: string, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise> { options = { withAuth: this.withAuth, @@ -1291,7 +1283,7 @@ export class DrupalClient { async getSearchIndex( name: string, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { options = { withAuth: this.withAuth, @@ -1327,7 +1319,7 @@ export class DrupalClient { async getSearchIndexFromContext( name: string, context: GetStaticPropsContext, - options?: JsonApiWithLocaleOptions & JsonApiWithAuthOptions + options?: JsonApiOptions ): Promise { return await this.getSearchIndex(name, { ...options, @@ -1493,7 +1485,7 @@ export class DrupalClient { private getAuthFromContextAndOptions( context: GetStaticPropsContext, - options: JsonApiWithAuthOptions + options: JsonApiWithAuthOption ) { // If not in preview or withAuth is provided, use that. if (!context.preview) { diff --git a/packages/next-drupal/src/deprecated.ts b/packages/next-drupal/src/deprecated.ts new file mode 100644 index 00000000..8693c514 --- /dev/null +++ b/packages/next-drupal/src/deprecated.ts @@ -0,0 +1,19 @@ +export * from "./deprecated/get-access-token" +export * from "./deprecated/get-menu" +export * from "./deprecated/get-paths" +export * from "./deprecated/get-resource-collection" +export * from "./deprecated/preview" +export * from "./deprecated/get-resource-type" +export * from "./deprecated/get-resource" +export * from "./deprecated/get-search-index" +export * from "./deprecated/get-view" +export * from "./deprecated/translate-path" +export { + deserialize, + buildUrl, + getJsonApiIndex, + getJsonApiPathForResourceType, + syncDrupalPreviewRoutes, +} from "./deprecated/utils" + +export type * from "./types/deprecated" diff --git a/packages/next-drupal/src/get-access-token.ts b/packages/next-drupal/src/deprecated/get-access-token.ts similarity index 95% rename from packages/next-drupal/src/get-access-token.ts rename to packages/next-drupal/src/deprecated/get-access-token.ts index 6e718b00..017a6660 100644 --- a/packages/next-drupal/src/get-access-token.ts +++ b/packages/next-drupal/src/deprecated/get-access-token.ts @@ -1,5 +1,5 @@ import { cache } from "./get-cache" -import type { AccessToken } from "./types" +import type { AccessToken } from "../types" const CACHE_KEY = "NEXT_DRUPAL_ACCESS_TOKEN" diff --git a/packages/next-drupal/src/get-cache.ts b/packages/next-drupal/src/deprecated/get-cache.ts similarity index 100% rename from packages/next-drupal/src/get-cache.ts rename to packages/next-drupal/src/deprecated/get-cache.ts diff --git a/packages/next-drupal/src/get-menu.ts b/packages/next-drupal/src/deprecated/get-menu.ts similarity index 90% rename from packages/next-drupal/src/get-menu.ts rename to packages/next-drupal/src/deprecated/get-menu.ts index bee99b21..17262968 100644 --- a/packages/next-drupal/src/get-menu.ts +++ b/packages/next-drupal/src/deprecated/get-menu.ts @@ -1,9 +1,6 @@ import { buildHeaders, buildUrl, deserialize } from "./utils" -import type { - AccessToken, - DrupalMenuLinkContent, - JsonApiWithLocaleOptions, -} from "./types" +import type { AccessToken, DrupalMenuLinkContent } from "../types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" export async function getMenu( name: string, diff --git a/packages/next-drupal/src/get-paths.ts b/packages/next-drupal/src/deprecated/get-paths.ts similarity index 97% rename from packages/next-drupal/src/get-paths.ts rename to packages/next-drupal/src/deprecated/get-paths.ts index 62f4b341..a2bbfe01 100644 --- a/packages/next-drupal/src/get-paths.ts +++ b/packages/next-drupal/src/deprecated/get-paths.ts @@ -1,6 +1,6 @@ import { getResourceCollection } from "./get-resource-collection" import type { GetStaticPathsContext, GetStaticPathsResult } from "next" -import type { AccessToken, JsonApiParams, Locale } from "./types" +import type { AccessToken, JsonApiParams, Locale } from "../types" export async function getPathsFromContext( types: string | string[], diff --git a/packages/next-drupal/src/get-resource-collection.ts b/packages/next-drupal/src/deprecated/get-resource-collection.ts similarity index 91% rename from packages/next-drupal/src/get-resource-collection.ts rename to packages/next-drupal/src/deprecated/get-resource-collection.ts index 9c182351..209cd3da 100644 --- a/packages/next-drupal/src/get-resource-collection.ts +++ b/packages/next-drupal/src/deprecated/get-resource-collection.ts @@ -5,12 +5,8 @@ import { getJsonApiPathForResourceType, } from "./utils" import type { GetStaticPropsContext } from "next" -import type { - AccessToken, - JsonApiParams, - JsonApiResource, - JsonApiWithLocaleOptions, -} from "./types" +import type { AccessToken, JsonApiParams, JsonApiResource } from "../types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" export async function getResourceCollection( type: string, diff --git a/packages/next-drupal/src/get-resource-type.ts b/packages/next-drupal/src/deprecated/get-resource-type.ts similarity index 91% rename from packages/next-drupal/src/get-resource-type.ts rename to packages/next-drupal/src/deprecated/get-resource-type.ts index fb3ee9d4..85f52044 100644 --- a/packages/next-drupal/src/get-resource-type.ts +++ b/packages/next-drupal/src/deprecated/get-resource-type.ts @@ -1,6 +1,6 @@ import { translatePathFromContext } from "./translate-path" import type { GetStaticPropsContext } from "next" -import type { AccessToken } from "./types" +import type { AccessToken } from "../types" export async function getResourceTypeFromContext( context: GetStaticPropsContext, diff --git a/packages/next-drupal/src/get-resource.ts b/packages/next-drupal/src/deprecated/get-resource.ts similarity index 97% rename from packages/next-drupal/src/get-resource.ts rename to packages/next-drupal/src/deprecated/get-resource.ts index cc6e28f9..7da11f90 100644 --- a/packages/next-drupal/src/get-resource.ts +++ b/packages/next-drupal/src/deprecated/get-resource.ts @@ -7,12 +7,8 @@ import { getPathFromContext, } from "./utils" import type { GetStaticPropsContext } from "next" -import type { - AccessToken, - JsonApiParams, - JsonApiResource, - JsonApiWithLocaleOptions, -} from "./types" +import type { AccessToken, JsonApiParams, JsonApiResource } from "../types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" export async function getResourceFromContext( type: string, diff --git a/packages/next-drupal/src/get-search-index.ts b/packages/next-drupal/src/deprecated/get-search-index.ts similarity index 90% rename from packages/next-drupal/src/get-search-index.ts rename to packages/next-drupal/src/deprecated/get-search-index.ts index a40a5433..f97d2faf 100644 --- a/packages/next-drupal/src/get-search-index.ts +++ b/packages/next-drupal/src/deprecated/get-search-index.ts @@ -1,10 +1,7 @@ import { buildHeaders, buildUrl, deserialize } from "./utils" import type { GetStaticPropsContext } from "next" -import type { - AccessToken, - JsonApiResource, - JsonApiWithLocaleOptions, -} from "./types" +import type { AccessToken, JsonApiResource } from "../types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" export async function getSearchIndex( name: string, diff --git a/packages/next-drupal/src/get-view.ts b/packages/next-drupal/src/deprecated/get-view.ts similarity index 90% rename from packages/next-drupal/src/get-view.ts rename to packages/next-drupal/src/deprecated/get-view.ts index 8241b0c6..2b7cb0ca 100644 --- a/packages/next-drupal/src/get-view.ts +++ b/packages/next-drupal/src/deprecated/get-view.ts @@ -1,5 +1,6 @@ import { buildHeaders, buildUrl, deserialize } from "./utils" -import type { AccessToken, JsonApiWithLocaleOptions } from "./types" +import type { AccessToken } from "../types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" export async function getView( name: string, diff --git a/packages/next-drupal/src/preview.ts b/packages/next-drupal/src/deprecated/preview.ts similarity index 96% rename from packages/next-drupal/src/preview.ts rename to packages/next-drupal/src/deprecated/preview.ts index 224077b0..7e4d096f 100644 --- a/packages/next-drupal/src/preview.ts +++ b/packages/next-drupal/src/deprecated/preview.ts @@ -1,6 +1,6 @@ import { getResourceByPath } from "./get-resource" import type { NextApiRequest, NextApiResponse } from "next" -import type { JsonApiWithLocaleOptions } from "./types" +import type { JsonApiWithLocaleOptions } from "../types/deprecated" interface PreviewOptions { errorMessages?: { diff --git a/packages/next-drupal/src/translate-path.ts b/packages/next-drupal/src/deprecated/translate-path.ts similarity index 93% rename from packages/next-drupal/src/translate-path.ts rename to packages/next-drupal/src/deprecated/translate-path.ts index ace83fc0..0651957d 100644 --- a/packages/next-drupal/src/translate-path.ts +++ b/packages/next-drupal/src/deprecated/translate-path.ts @@ -1,6 +1,6 @@ import { buildHeaders, buildUrl, getPathFromContext } from "./utils" import type { GetStaticPropsContext } from "next" -import type { AccessToken, DrupalTranslatedPath } from "./types" +import type { AccessToken, DrupalTranslatedPath } from "../types" export async function translatePath( path: string, diff --git a/packages/next-drupal/src/navigation/use-menu.ts b/packages/next-drupal/src/deprecated/use-menu.ts similarity index 96% rename from packages/next-drupal/src/navigation/use-menu.ts rename to packages/next-drupal/src/deprecated/use-menu.ts index cbc4b3f6..25c82c2d 100644 --- a/packages/next-drupal/src/navigation/use-menu.ts +++ b/packages/next-drupal/src/deprecated/use-menu.ts @@ -1,6 +1,6 @@ import { useRouter } from "next/router" import { useEffect, useState } from "react" -import { getMenu } from "../get-menu" +import { getMenu } from "./get-menu" import type { DrupalMenuLinkContent } from "../types" export function useMenu( diff --git a/packages/next-drupal/src/utils.ts b/packages/next-drupal/src/deprecated/utils.ts similarity index 98% rename from packages/next-drupal/src/utils.ts rename to packages/next-drupal/src/deprecated/utils.ts index dd8330ec..8e86f6b9 100644 --- a/packages/next-drupal/src/utils.ts +++ b/packages/next-drupal/src/deprecated/utils.ts @@ -2,7 +2,7 @@ import { Jsona } from "jsona" import { stringify } from "qs" import { getAccessToken } from "./get-access-token" import type { GetStaticPropsContext } from "next" -import type { AccessToken, Locale } from "./types" +import type { AccessToken, Locale } from "../types" const JSONAPI_PREFIX = process.env.DRUPAL_JSONAPI_PREFIX || "/jsonapi" diff --git a/packages/next-drupal/src/index.ts b/packages/next-drupal/src/index.ts index fb7c2513..860e0b0e 100644 --- a/packages/next-drupal/src/index.ts +++ b/packages/next-drupal/src/index.ts @@ -1,21 +1,6 @@ -export * from "./get-access-token" -export * from "./get-menu" -export * from "./get-paths" -export * from "./get-resource-collection" -export * from "./preview" -export * from "./get-resource-type" -export * from "./get-resource" -export * from "./get-search-index" -export * from "./get-view" -export * from "./types" -export * from "./translate-path" -export { - deserialize, - buildUrl, - getJsonApiIndex, - getJsonApiPathForResourceType, - syncDrupalPreviewRoutes, -} from "./utils" - export * from "./client" export * from "./jsonapi-errors" + +export type * from "./types" + +export * from "./deprecated" diff --git a/packages/next-drupal/src/jsonapi-errors.ts b/packages/next-drupal/src/jsonapi-errors.ts index d26f6f9c..e2c4c322 100644 --- a/packages/next-drupal/src/jsonapi-errors.ts +++ b/packages/next-drupal/src/jsonapi-errors.ts @@ -1,4 +1,17 @@ -import type { JsonApiError } from "./types" +// https://jsonapi.org/format/#error-objects +export interface JsonApiError { + id?: string + status?: string + code?: string + title?: string + detail?: string + links?: JsonApiLinks +} + +// https://jsonapi.org/format/#document-links +export interface JsonApiLinks { + [key: string]: string | Record +} export class JsonApiErrors extends Error { errors: JsonApiError[] | string diff --git a/packages/next-drupal/src/navigation.ts b/packages/next-drupal/src/navigation.ts index 33d5f232..33b89724 100644 --- a/packages/next-drupal/src/navigation.ts +++ b/packages/next-drupal/src/navigation.ts @@ -1 +1 @@ -export { useMenu } from "./navigation/use-menu" +export { useMenu } from "./deprecated/use-menu" diff --git a/packages/next-drupal/src/types.ts b/packages/next-drupal/src/types.ts deleted file mode 100644 index 0e5c9730..00000000 --- a/packages/next-drupal/src/types.ts +++ /dev/null @@ -1,478 +0,0 @@ -export type DrupalClientOptions = { - /** - * Set the JSON:API prefix. - * - * * **Default value**: `/jsonapi` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#apiprefix) - */ - apiPrefix?: string - - /** - * Set debug to true to enable debug messages. - * - * * **Default value**: `false` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#debug) - */ - debug?: boolean - - /** - * Set the default frontPage. - * - * * **Default value**: `/home` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#frontpage) - */ - frontPage?: string - - /** - * Set custom headers for the fetcher. - * - * * **Default value**: { "Content-Type": "application/vnd.api+json", Accept: "application/vnd.api+json" } - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#headers) - */ - headers?: HeadersInit - - /** - * Override the default data serializer. You can use this to add your own JSON:API data deserializer. - * - * * **Default value**: `jsona` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#serializer) - */ - serializer?: Serializer - /** - * Override the default fetcher. Use this to add your own fetcher ex. axios. - * - * * **Default value**: `fetch` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#fetcher) - */ - fetcher?: Fetcher - - /** - * Override the default cache. - * - * * **Default value**: `node-cache` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#cache) - */ - cache?: DataCache - - /** - * If set to true, JSON:API errors are thrown in non-production environments. The errors are shown in the Next.js overlay. - * - * **Default value**: `true` - * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#throwjsonapierrors) - */ - throwJsonApiErrors?: boolean - - /** - * Override the default logger. You can use this to send logs to a third-party service. - * - * * **Default value**: `console` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#logger) - */ - logger?: Logger - - /** - * Override the default auth. You can use this to implement your own authentication mechanism. - * - * [Documentation](https://next-drupal.org/docs/client/configuration#auth) - */ - auth?: DrupalClientAuth - - /** - * Set whether the client should use authenticated requests by default. - * - * * **Default value**: `true` - * * **Required**: **No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#withauth) - */ - withAuth?: boolean - - /** - * By default, the client will make a request to JSON:API to retrieve the index. You can turn this off and use the default entry point from the resource name. - * - * * **Default value**: `false` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#auth) - */ - useDefaultResourceTypeEntry?: boolean - - /** - * The secret to use for preview mode. - * - * * **Default value**: `null` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#previewsecret) - */ - previewSecret?: string - - /** - * A long-lived access token you can set for the client. - * - * * **Default value**: `null` - * * **Required**: *No* - * - * [Documentation](https://next-drupal.org/docs/client/configuration#accesstoken) - */ - accessToken?: AccessToken - - /** - * The scope used for the current access token. - */ - accessTokenScope?: string -} - -export type DrupalClientAuth = - | DrupalClientAuthClientIdSecret - | DrupalClientAuthUsernamePassword - | DrupalClientAuthAccessToken - | (() => string) - | string - -export interface DrupalClientAuthUsernamePassword { - username: string - password: string -} - -export interface DrupalClientAuthClientIdSecret { - clientId: string - clientSecret: string - url?: string - scope?: string -} - -export type DrupalClientAuthAccessToken = AccessToken - -export interface Logger { - log(message): void - - debug(message): void - - warn(message): void - - error(message): void -} - -/** - * The baseUrl of your Drupal site. Do not add the /jsonapi suffix. - * - * **Required**: *yes* - * - * @example - * - * https://example.com - */ -export type BaseUrl = string - -export type Locale = string - -export type PathPrefix = string - -export type JsonApiOptions = { - deserialize?: boolean - params?: JsonApiParams -} - -export type JsonApiWithLocaleOptions = JsonApiOptions & - ( - | { - locale: Locale - defaultLocale: Locale - } - | { - locale?: undefined - defaultLocale?: never - } - ) - -export type JsonApiWithAuthOptions = { - withAuth?: boolean | DrupalClientAuth -} - -export type JsonApiWithCacheOptions = { - withCache?: boolean - cacheKey?: string -} - -// TODO: Properly type this. -/* eslint-disable @typescript-eslint/no-explicit-any */ -export type JsonApiParams = Record - -// https://jsonapi.org/format/#error-objects -export interface JsonApiError { - id?: string - status?: string - code?: string - title?: string - detail?: string - links?: JsonApiLinks -} - -// https://jsonapi.org/format/#document-links -export interface JsonApiLinks { - [key: string]: string | Record -} - -// TODO: any...ugh. -export interface JsonApiResponse extends Record { - jsonapi?: { - version: string - meta: Record[] - } - data: Record[] - errors: JsonApiError[] - meta: { - count: number - [key: string]: any - } - links?: JsonApiLinks - included?: Record[] -} - -export interface JsonApiResourceBodyRelationship { - data: { - type: string - id: string - } -} - -export interface JsonApiCreateResourceBody { - data: { - type?: string - attributes?: Record - relationships?: Record - } -} - -export interface JsonApiCreateFileResourceBody { - data: { - type?: string - attributes: { - type: string - field: string - filename: string - file: Buffer - } - } -} - -export interface JsonApiUpdateResourceBody { - data: { - type?: string - id?: string - attributes?: Record - relationships?: Record - } -} - -export interface JsonApiSearchApiResponse extends JsonApiResponse { - meta: JsonApiResponse["meta"] & { - facets?: DrupalSearchApiFacet[] - } -} - -export interface Serializer { - deserialize( - body: Record, - options?: Record - ): unknown -} - -export type Fetcher = WindowOrWorkerGlobalScope["fetch"] - -export interface DataCache { - get(key): Promise - - set(key, value, ttl?: number): Promise - - del?(keys): Promise -} - -export interface FetchOptions extends RequestInit { - withAuth?: boolean | DrupalClientAuth -} - -export interface DrupalSearchApiFacet { - id: string - label?: string - path?: string - terms?: { - url: string - values: { - value: string - label: string - active?: boolean - count?: number - } - }[] -} - -export interface DrupalTranslatedPath { - resolved: string - isHomePath: boolean - entity: { - canonical: string - type: string - bundle: string - id: string - uuid: string - langcode?: string - path?: string - } - label?: string - jsonapi?: { - individual: string - resourceName: string - pathPrefix: string - basePath: string - entryPoint: string - } - meta?: Record - redirect?: { - from: string - to: string - status: string - }[] -} - -export interface DrupalMenuLinkContent { - description: string - enabled: boolean - expanded: boolean - id: string - menu_name: string - meta: Record - options: Record - parent: string - provider: string - route: { - name: string - parameters: Record - } - title: string - type: string - url: string - weight: string - items?: DrupalMenuLinkContent[] -} - -export type AccessToken = { - token_type: string - expires_in: number - access_token: string - refresh_token?: string -} - -export type PathAlias = { - alias: string - pid: number - langcode: string -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export interface JsonApiResource extends Record { - id: string - type: string - langcode: string - status: boolean -} - -export interface JsonApiResourceWithPath extends JsonApiResource { - path: PathAlias -} - -export type GetResourcePreviewUrlOptions = JsonApiWithLocaleOptions & { - isVersionable?: boolean -} - -export interface DrupalNode extends JsonApiResourceWithPath { - drupal_internal__nid: number - drupal_internal__vid: number - changed: string - created: string - title: string - default_langcode: boolean - sticky: boolean -} - -export interface DrupalParagraph extends JsonApiResource { - drupal_internal__id: number - drupal_internal__revision_id: number -} - -export interface DrupalBlock extends JsonApiResource { - info: string -} - -export interface DrupalMedia extends JsonApiResource { - drupal_internal__mid: string - drupal_internal__vid: string - changed: string - created: string - name: string -} - -export interface DrupalFile extends JsonApiResource { - drupal_internal__fid: string - changed: string - created: string - filename: string - uri: { - value: string - url: string - } - filesize: number - filemime: string - resourceIdObjMeta?: DrupalFileMeta -} - -export interface DrupalFileMeta { - alt?: string - title?: string - width: number - height: number -} - -export interface DrupalTaxonomyTerm extends JsonApiResourceWithPath { - drupal_internal__tid: string - changed: string - default_langcode: boolean - name: string - description: string - weight: number -} - -export interface DrupalUser extends JsonApiResourceWithPath { - drupal_internal__uid: string - changed: string - created: string - default_langcode: boolean - name: string -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export interface DrupalView[]> { - id: string - results: T - meta: JsonApiResponse["meta"] - links: JsonApiResponse["links"] -} diff --git a/packages/next-drupal/src/types/client.ts b/packages/next-drupal/src/types/client.ts new file mode 100644 index 00000000..924caa53 --- /dev/null +++ b/packages/next-drupal/src/types/client.ts @@ -0,0 +1,197 @@ +export type DrupalClientOptions = { + /** + * Set the JSON:API prefix. + * + * * **Default value**: `/jsonapi` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#apiprefix) + */ + apiPrefix?: string + + /** + * Set debug to true to enable debug messages. + * + * * **Default value**: `false` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#debug) + */ + debug?: boolean + + /** + * Set the default frontPage. + * + * * **Default value**: `/home` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#frontpage) + */ + frontPage?: string + + /** + * Set custom headers for the fetcher. + * + * * **Default value**: { "Content-Type": "application/vnd.api+json", Accept: "application/vnd.api+json" } + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#headers) + */ + headers?: HeadersInit + + /** + * Override the default data serializer. You can use this to add your own JSON:API data deserializer. + * + * * **Default value**: `jsona` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#serializer) + */ + serializer?: Serializer + /** + * Override the default fetcher. Use this to add your own fetcher ex. axios. + * + * * **Default value**: `fetch` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#fetcher) + */ + fetcher?: Fetcher + + /** + * Override the default cache. + * + * * **Default value**: `node-cache` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#cache) + */ + cache?: DataCache + + /** + * If set to true, JSON:API errors are thrown in non-production environments. The errors are shown in the Next.js overlay. + * + * **Default value**: `true` + * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#throwjsonapierrors) + */ + throwJsonApiErrors?: boolean + + /** + * Override the default logger. You can use this to send logs to a third-party service. + * + * * **Default value**: `console` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#logger) + */ + logger?: Logger + + /** + * Override the default auth. You can use this to implement your own authentication mechanism. + * + * [Documentation](https://next-drupal.org/docs/client/configuration#auth) + */ + auth?: DrupalClientAuth + + /** + * Set whether the client should use authenticated requests by default. + * + * * **Default value**: `true` + * * **Required**: **No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#withauth) + */ + withAuth?: boolean + + /** + * By default, the client will make a request to JSON:API to retrieve the index. You can turn this off and use the default entry point from the resource name. + * + * * **Default value**: `false` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#auth) + */ + useDefaultResourceTypeEntry?: boolean + + /** + * The secret to use for preview mode. + * + * * **Default value**: `null` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#previewsecret) + */ + previewSecret?: string + + /** + * A long-lived access token you can set for the client. + * + * * **Default value**: `null` + * * **Required**: *No* + * + * [Documentation](https://next-drupal.org/docs/client/configuration#accesstoken) + */ + accessToken?: AccessToken + + /** + * The scope used for the current access token. + */ + accessTokenScope?: string +} + +export type DrupalClientAuth = + | DrupalClientAuthClientIdSecret + | DrupalClientAuthUsernamePassword + | DrupalClientAuthAccessToken + | (() => string) + | string + +export interface DrupalClientAuthUsernamePassword { + username: string + password: string +} + +export interface DrupalClientAuthClientIdSecret { + clientId: string + clientSecret: string + url?: string + scope?: string +} + +export type DrupalClientAuthAccessToken = AccessToken + +export type AccessToken = { + token_type: string + expires_in: number + access_token: string + refresh_token?: string +} + +export interface DataCache { + get(key): Promise + + set(key, value, ttl?: number): Promise + + del?(keys): Promise +} + +export type Fetcher = WindowOrWorkerGlobalScope["fetch"] + +export interface Logger { + log(message): void + + debug(message): void + + warn(message): void + + error(message): void +} + +export interface Serializer { + deserialize( + body: Record, + options?: Record + ): unknown +} diff --git a/packages/next-drupal/src/types/deprecated.ts b/packages/next-drupal/src/types/deprecated.ts new file mode 100644 index 00000000..e79c20c2 --- /dev/null +++ b/packages/next-drupal/src/types/deprecated.ts @@ -0,0 +1,3 @@ +import type { JsonApiOptions } from "./index" + +export type JsonApiWithLocaleOptions = Omit diff --git a/packages/next-drupal/src/types/drupal.ts b/packages/next-drupal/src/types/drupal.ts new file mode 100644 index 00000000..b2a77c93 --- /dev/null +++ b/packages/next-drupal/src/types/drupal.ts @@ -0,0 +1,154 @@ +import type { + JsonApiResource, + JsonApiResourceWithPath, + JsonApiResponse, +} from "./resource" + +export interface DrupalBlock extends JsonApiResource { + info: string +} + +export interface DrupalFile extends JsonApiResource { + drupal_internal__fid: string + changed: string + created: string + filename: string + uri: { + value: string + url: string + } + filesize: number + filemime: string + resourceIdObjMeta?: DrupalFileMeta +} + +export interface DrupalFileMeta { + alt?: string + title?: string + width: number + height: number +} + +export interface DrupalMedia extends JsonApiResource { + drupal_internal__mid: string + drupal_internal__vid: string + changed: string + created: string + name: string +} + +export interface DrupalMenuLinkContent { + description: string + enabled: boolean + expanded: boolean + id: string + menu_name: string + meta: Record + options: Record + parent: string + provider: string + route: { + name: string + parameters: Record + } + title: string + type: string + url: string + weight: string + items?: DrupalMenuLinkContent[] +} + +export interface DrupalNode extends JsonApiResourceWithPath { + drupal_internal__nid: number + drupal_internal__vid: number + changed: string + created: string + title: string + default_langcode: boolean + sticky: boolean +} + +export interface DrupalParagraph extends JsonApiResource { + drupal_internal__id: number + drupal_internal__revision_id: number +} + +export interface DrupalSearchApiJsonApiResponse extends JsonApiResponse { + meta: JsonApiResponse["meta"] & { + facets?: DrupalSearchApiFacet[] + } +} + +export interface DrupalSearchApiFacet { + id: string + label?: string + path?: string + terms?: { + url: string + values: { + value: string + label: string + active?: boolean + count?: number + } + }[] +} + +export interface DrupalTaxonomyTerm extends JsonApiResourceWithPath { + drupal_internal__tid: string + changed: string + default_langcode: boolean + name: string + description: string + weight: number +} + +export interface DrupalTranslatedPath { + resolved: string + isHomePath: boolean + entity: { + canonical: string + type: string + bundle: string + id: string + uuid: string + langcode?: string + path?: string + } + label?: string + jsonapi?: { + individual: string + resourceName: string + pathPrefix: string + basePath: string + entryPoint: string + } + meta?: Record + redirect?: { + from: string + to: string + status: string + }[] +} + +export interface DrupalUser extends JsonApiResourceWithPath { + drupal_internal__uid: string + changed: string + created: string + default_langcode: boolean + name: string +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export interface DrupalView[]> { + id: string + results: T + meta: JsonApiResponse["meta"] + links: JsonApiResponse["links"] +} + +export type PathAlias = { + alias: string + pid: number + langcode: string +} diff --git a/packages/next-drupal/src/types/index.ts b/packages/next-drupal/src/types/index.ts new file mode 100644 index 00000000..f8194aaf --- /dev/null +++ b/packages/next-drupal/src/types/index.ts @@ -0,0 +1,4 @@ +export type * from "./client" +export type * from "./drupal" +export type * from "./options" +export type * from "./resource" diff --git a/packages/next-drupal/src/types/options.ts b/packages/next-drupal/src/types/options.ts new file mode 100644 index 00000000..c03e0d72 --- /dev/null +++ b/packages/next-drupal/src/types/options.ts @@ -0,0 +1,39 @@ +import type { DrupalClientAuth } from "./client" + +export type BaseUrl = string + +export type Locale = string + +export type PathPrefix = string + +export interface FetchOptions extends RequestInit { + withAuth?: boolean | DrupalClientAuth +} + +export type JsonApiOptions = { + deserialize?: boolean + params?: JsonApiParams +} & JsonApiWithAuthOption & + ( + | { + locale: Locale + defaultLocale: Locale + } + | { + locale?: undefined + defaultLocale?: never + } + ) + +export type JsonApiWithAuthOption = { + withAuth?: boolean | DrupalClientAuth +} + +export type JsonApiWithCacheOptions = { + withCache?: boolean + cacheKey?: string +} + +// TODO: Properly type this. +/* eslint-disable @typescript-eslint/no-explicit-any */ +export type JsonApiParams = Record diff --git a/packages/next-drupal/src/types/resource.ts b/packages/next-drupal/src/types/resource.ts new file mode 100644 index 00000000..a6aa12be --- /dev/null +++ b/packages/next-drupal/src/types/resource.ts @@ -0,0 +1,66 @@ +import type { JsonApiError, JsonApiLinks } from "../jsonapi-errors" +import type { PathAlias } from "./drupal" + +// TODO: any...ugh. +export interface JsonApiResponse extends Record { + jsonapi?: { + version: string + meta: Record[] + } + data: Record[] + errors: JsonApiError[] + meta: { + count: number + [key: string]: any + } + links?: JsonApiLinks + included?: Record[] +} + +export interface JsonApiResourceBodyRelationship { + data: { + type: string + id: string + } +} + +export interface JsonApiCreateResourceBody { + data: { + type?: string + attributes?: Record + relationships?: Record + } +} + +export interface JsonApiCreateFileResourceBody { + data: { + type?: string + attributes: { + type: string + field: string + filename: string + file: Buffer + } + } +} + +export interface JsonApiUpdateResourceBody { + data: { + type?: string + id?: string + attributes?: Record + relationships?: Record + } +} + +/* eslint-disable @typescript-eslint/no-explicit-any */ +export interface JsonApiResource extends Record { + id: string + type: string + langcode: string + status: boolean +} + +export interface JsonApiResourceWithPath extends JsonApiResource { + path: PathAlias +} diff --git a/packages/next-drupal/tests/utils.ts b/packages/next-drupal/tests/utils.ts index 762eb6ba..b7fe704f 100644 --- a/packages/next-drupal/tests/utils.ts +++ b/packages/next-drupal/tests/utils.ts @@ -1,4 +1,4 @@ -import { DrupalClient } from "../src/client" +import { DrupalClient } from "../src" // Run all tests against this env until we configure CI to setup a Drupal instance. // TODO: Bootstrap and expose the /drupal env for testing.