@okam/directus-next-component 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +21 -0
- package/CHANGELOG.md +20 -0
- package/README.md +14 -7
- package/package.json +1 -4
- package/project.json +32 -0
- package/src/index.ts +1 -0
- package/src/lib/directus-next-rewrite.ts +106 -0
- package/src/lib/hello-server.tsx +4 -0
- package/src/lib/withDirectus.ts +20 -0
- package/src/server.ts +4 -0
- package/tsconfig.json +17 -0
- package/tsconfig.lib.json +25 -0
- package/index.esm.d.ts +0 -1
- package/index.esm.js +0 -1
- package/src/index.d.ts +0 -0
- package/src/lib/directus-next-rewrite.d.ts +0 -7
- package/src/lib/hello-server.d.ts +0 -1
- package/src/lib/withDirectus.d.ts +0 -6
- package/src/server.d.ts +0 -3
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { getDefaultIgnorePatterns } = require("../../../linter/helpers");
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
extends: ['plugin:@nx/react', '../../../.eslintrc.js', '../../../linter/bases/typescript', '../../../linter/bases/regexp', '../../../linter/bases/jest', '../../../linter/bases/rtl', '../../../linter/bases/storybook', '../../../linter/bases/react', '../../../linter/bases/prettier', 'plugin:storybook/recommended'],
|
|
5
|
+
ignorePatterns: ['!**/*', ...getDefaultIgnorePatterns()],
|
|
6
|
+
overrides: [
|
|
7
|
+
{
|
|
8
|
+
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
|
9
|
+
// We set parserOptions.project for the project to allow TypeScript to create the type-checker behind the scenes when we run linting
|
|
10
|
+
parserOptions: {
|
|
11
|
+
project: `${__dirname}/tsconfig.*?.json`,
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
"@nx/dependency-checks": "error"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
rules: {
|
|
19
|
+
'react/react-in-jsx-scope': 'off',
|
|
20
|
+
},
|
|
21
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
## 1.1.0 (2024-06-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### 🚀 Features
|
|
5
|
+
|
|
6
|
+
- add new libs ([#71](https://github.com/OKAMca/stack/pull/71))
|
|
7
|
+
|
|
8
|
+
- add dynamic page routing from directus page settings ([#97](https://github.com/OKAMca/stack/pull/97))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### 🩹 Fixes
|
|
12
|
+
|
|
13
|
+
- publishing for new libs ([#125](https://github.com/OKAMca/stack/pull/125))
|
|
14
|
+
|
|
15
|
+
- publishing for new libs ([#126](https://github.com/OKAMca/stack/pull/126))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### ❤️ Thank You
|
|
19
|
+
|
|
20
|
+
- Marie-Maxime Tanguay @marie-maxime
|
package/README.md
CHANGED
|
@@ -4,19 +4,26 @@ This library was generated with [Nx](https://nx.dev).
|
|
|
4
4
|
|
|
5
5
|
## directusRouteMiddleware usage
|
|
6
6
|
|
|
7
|
-
Create a middleware.
|
|
7
|
+
Create a middleware.ts file in the project, in the `/src/app` directory of the next application, and add the following code to it.
|
|
8
8
|
|
|
9
9
|
```jsx
|
|
10
|
-
// middleware.
|
|
10
|
+
// middleware.ts
|
|
11
11
|
|
|
12
|
-
import
|
|
12
|
+
import {
|
|
13
|
+
directusRouteMiddleware,
|
|
14
|
+
config as directusRouteMiddlewareConfig,
|
|
15
|
+
} from '@okam/directus-next-component/src/server'
|
|
16
|
+
import type { NextRequest } from 'next/server'
|
|
13
17
|
|
|
14
|
-
export function middleware(request) {
|
|
15
|
-
|
|
18
|
+
export function middleware(request: NextRequest) {
|
|
19
|
+
const { locale } = request.nextUrl
|
|
20
|
+
return directusRouteMiddleware(request, [locale])
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
export config = {
|
|
19
|
-
...directusRouteMiddlewareConfig
|
|
23
|
+
export const config = {
|
|
24
|
+
...directusRouteMiddlewareConfig,
|
|
20
25
|
}
|
|
26
|
+
|
|
21
27
|
```
|
|
22
28
|
|
|
29
|
+
After, modify the `next.config.js` file to add `withDirectus` in the plugins.
|
package/package.json
CHANGED
package/project.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "directus-next-component",
|
|
3
|
+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "libs/directus/directus-next-component/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"targets": {
|
|
8
|
+
"lint": {
|
|
9
|
+
"executor": "@nx/eslint:lint"
|
|
10
|
+
},
|
|
11
|
+
"build": {
|
|
12
|
+
"executor": "@nx/rollup:rollup",
|
|
13
|
+
"outputs": ["{options.outputPath}"],
|
|
14
|
+
"options": {
|
|
15
|
+
"outputPath": "dist/libs/directus/directus-next-component",
|
|
16
|
+
"tsConfig": "libs/directus/directus-next-component/tsconfig.lib.json",
|
|
17
|
+
"project": "libs/directus/directus-next-component/package.json",
|
|
18
|
+
"entryFile": "libs/directus/directus-next-component/src/index.ts",
|
|
19
|
+
"external": "all",
|
|
20
|
+
"rollupConfig": "@nx/react/plugins/bundle-rollup",
|
|
21
|
+
"compiler": "swc",
|
|
22
|
+
"assets": [
|
|
23
|
+
{
|
|
24
|
+
"glob": "libs/directus/directus-next-component/README.md",
|
|
25
|
+
"input": ".",
|
|
26
|
+
"output": "."
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { NextRequest } from 'next/server'
|
|
2
|
+
import { NextResponse } from 'next/server'
|
|
3
|
+
import { get } from 'radash'
|
|
4
|
+
|
|
5
|
+
export async function fetchPageSettings(pathName: string, lang = 'fr-CA') {
|
|
6
|
+
const graphqlEndpoint = process.env.NEXT_PUBLIC_GRAPHQL_URL
|
|
7
|
+
const graphqlApiKey = process.env.NEXT_PUBLIC_API_TOKEN
|
|
8
|
+
|
|
9
|
+
if (!graphqlEndpoint || !graphqlApiKey) {
|
|
10
|
+
throw new Error('Missing graphql configuration: NEXT_PUBLIC_GRAPHQL_URL or NEXT_API_TOKEN_ADMIN')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let langCodeFilter = '_eq'
|
|
14
|
+
|
|
15
|
+
if (lang.length === 2) {
|
|
16
|
+
langCodeFilter = '_contains'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const query = `
|
|
20
|
+
query PageSettings($path: String = null, $lang: String = "fr-CA") {
|
|
21
|
+
page_settings(
|
|
22
|
+
filter: { translations: { path: { _eq: $path }, languages_code: {code: {${langCodeFilter}: $lang}} }},
|
|
23
|
+
limit: 1
|
|
24
|
+
) {
|
|
25
|
+
belongs_to_key
|
|
26
|
+
belongs_to_collection
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`
|
|
30
|
+
|
|
31
|
+
const graphqlBody = {
|
|
32
|
+
query,
|
|
33
|
+
variables: {
|
|
34
|
+
lang,
|
|
35
|
+
path: pathName,
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
// console.info(`Fetching redirects on ${graphqlEndpoint}`)
|
|
41
|
+
const response = await fetch(graphqlEndpoint, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
Authorization: `Bearer ${graphqlApiKey}`,
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify(graphqlBody),
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const { data } = await response.json()
|
|
52
|
+
|
|
53
|
+
const key = get<string>(data, 'page_settings.0.belongs_to_key')
|
|
54
|
+
const collection = get<string>(data, 'page_settings.0.belongs_to_collection')
|
|
55
|
+
|
|
56
|
+
if (key == null || collection == null) {
|
|
57
|
+
throw new Error('No page settings found')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return `/${collection}/${key}`
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error('GraphQL Error', (e as Error).message)
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function removeLocaleFromPathName(pathName: string, locale: string) {
|
|
68
|
+
if (pathName.includes(locale)) {
|
|
69
|
+
return pathName.replace(`/${locale}`, '')
|
|
70
|
+
}
|
|
71
|
+
return pathName
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function directusRouteMiddleware(request: NextRequest, locales: string[]) {
|
|
75
|
+
const { pathname } = request.nextUrl
|
|
76
|
+
|
|
77
|
+
const locale = locales.find((l) => pathname.startsWith(`/${l}`))
|
|
78
|
+
|
|
79
|
+
const pathNameWithoutLocale = locale ? removeLocaleFromPathName(pathname, locale) : pathname
|
|
80
|
+
|
|
81
|
+
// Fetch page settings based on the request path.
|
|
82
|
+
const route = await fetchPageSettings(pathNameWithoutLocale, locale)
|
|
83
|
+
|
|
84
|
+
if (route === null) {
|
|
85
|
+
return NextResponse.next()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Perform a rewrite to the new path.
|
|
89
|
+
const url = request.nextUrl.clone()
|
|
90
|
+
url.pathname = route
|
|
91
|
+
|
|
92
|
+
return NextResponse.rewrite(url)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const config = {
|
|
96
|
+
matcher: [
|
|
97
|
+
/*
|
|
98
|
+
* Match all request paths except for the ones starting with:
|
|
99
|
+
* - api (API routes)
|
|
100
|
+
* - _next/static (static files)
|
|
101
|
+
* - _next/image (image optimization files)
|
|
102
|
+
* - favicon.ico (favicon file)
|
|
103
|
+
*/
|
|
104
|
+
'/((?!api|_next/static|_next/image|favicon.ico).*)',
|
|
105
|
+
],
|
|
106
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NextConfig } from 'next'
|
|
2
|
+
|
|
3
|
+
interface CustomPluginOptions {
|
|
4
|
+
[key: string]: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const withDirectus = (nextConfig: NextConfig = {}, pluginOptions: CustomPluginOptions = {}): NextConfig => {
|
|
8
|
+
// Create a new object for the combined environment variables
|
|
9
|
+
const combinedEnv = {
|
|
10
|
+
...nextConfig.env,
|
|
11
|
+
...pluginOptions,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
...nextConfig,
|
|
16
|
+
env: combinedEnv,
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default withDirectus
|
package/src/server.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"allowJs": false,
|
|
5
|
+
"esModuleInterop": false,
|
|
6
|
+
"allowSyntheticDefaultImports": true,
|
|
7
|
+
"strict": true
|
|
8
|
+
},
|
|
9
|
+
"files": [],
|
|
10
|
+
"include": [],
|
|
11
|
+
"references": [
|
|
12
|
+
{
|
|
13
|
+
"path": "./tsconfig.lib.json"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"extends": "../../../tsconfig.base.json"
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"types": [
|
|
6
|
+
"node",
|
|
7
|
+
"@nx/react/typings/cssmodule.d.ts",
|
|
8
|
+
"@nx/react/typings/image.d.ts",
|
|
9
|
+
"next",
|
|
10
|
+
"@nx/next/typings/image.d.ts"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
13
|
+
"exclude": [
|
|
14
|
+
"jest.config.ts",
|
|
15
|
+
"src/**/*.spec.ts",
|
|
16
|
+
"src/**/*.test.ts",
|
|
17
|
+
"src/**/*.spec.tsx",
|
|
18
|
+
"src/**/*.test.tsx",
|
|
19
|
+
"src/**/*.spec.js",
|
|
20
|
+
"src/**/*.test.js",
|
|
21
|
+
"src/**/*.spec.jsx",
|
|
22
|
+
"src/**/*.test.jsx"
|
|
23
|
+
],
|
|
24
|
+
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
|
|
25
|
+
}
|
package/index.esm.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./src/index";
|
package/index.esm.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
package/src/index.d.ts
DELETED
|
File without changes
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { NextRequest } from 'next/server';
|
|
2
|
-
import { NextResponse } from 'next/server';
|
|
3
|
-
export declare function fetchPageSettings(pathName: string, lang?: string): Promise<string | null>;
|
|
4
|
-
export declare function directusRouteMiddleware(request: NextRequest, locales: string[]): Promise<NextResponse<unknown>>;
|
|
5
|
-
export declare const config: {
|
|
6
|
-
matcher: string[];
|
|
7
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function HelloServer(): Promise<import("react/jsx-runtime").JSX.Element>;
|
package/src/server.d.ts
DELETED