@okam/directus-next-component 1.1.0 → 1.2.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/components/DirectusLink/index.d.ts +3 -0
- package/components/DirectusLink/index.js +14 -0
- package/components/DirectusLink/index.mjs +15 -0
- package/components/DirectusLink/interface.d.ts +9 -0
- package/hooks/directus-file.d.ts +3 -0
- package/hooks/directus-file.js +25 -0
- package/hooks/directus-file.mjs +26 -0
- package/hooks/directus-link.d.ts +3 -0
- package/hooks/directus-link.js +47 -0
- package/hooks/directus-link.mjs +48 -0
- package/hooks/navigation-items.d.ts +9 -0
- package/hooks/navigation-items.js +44 -0
- package/hooks/navigation-items.mjs +45 -0
- package/index.d.ts +9 -0
- package/index.js +10 -0
- package/index.mjs +10 -0
- package/lib/directus-next-rewrite.d.ts +7 -0
- package/lib/directus-next-rewrite.js +87 -0
- package/lib/directus-next-rewrite.mjs +87 -0
- package/lib/hello-server.d.ts +1 -0
- package/lib/hello-server.js +7 -0
- package/lib/hello-server.mjs +7 -0
- package/lib/withDirectus.d.ts +6 -0
- package/lib/withDirectus.js +12 -0
- package/lib/withDirectus.mjs +13 -0
- package/package.json +19 -1
- package/server.d.ts +7 -0
- package/server.js +18 -0
- package/server.mjs +18 -0
- package/types/files.d.ts +18 -0
- package/types/links.d.ts +20 -0
- package/types/navigation-items.d.ts +27 -0
- package/types/page-settings.d.ts +17 -0
- package/.eslintrc.js +0 -21
- package/CHANGELOG.md +0 -20
- package/README.md +0 -29
- package/project.json +0 -32
- package/src/index.ts +0 -1
- package/src/lib/directus-next-rewrite.ts +0 -106
- package/src/lib/hello-server.tsx +0 -4
- package/src/lib/withDirectus.ts +0 -20
- package/src/server.ts +0 -4
- package/tsconfig.json +0 -17
- package/tsconfig.lib.json +0 -25
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const stackUi = require("@okam/stack-ui");
|
|
4
|
+
const Link = require("next/link.js");
|
|
5
|
+
const directusLink = require("../../hooks/directus-link.js");
|
|
6
|
+
const DirectusLink = (props) => {
|
|
7
|
+
const { type, componentsConfig } = props;
|
|
8
|
+
const linkProps = directusLink(props);
|
|
9
|
+
if (!type || !linkProps.href) return null;
|
|
10
|
+
const LinkComponent = componentsConfig == null ? void 0 : componentsConfig[type];
|
|
11
|
+
if (!LinkComponent) return /* @__PURE__ */ jsxRuntime.jsx(stackUi.Anchor, { as: Link, ...linkProps });
|
|
12
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LinkComponent, { ...props });
|
|
13
|
+
};
|
|
14
|
+
module.exports = DirectusLink;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Anchor } from "@okam/stack-ui";
|
|
3
|
+
import Link from "next/link.js";
|
|
4
|
+
import useDirectusLink from "../../hooks/directus-link.mjs";
|
|
5
|
+
const DirectusLink = (props) => {
|
|
6
|
+
const { type, componentsConfig } = props;
|
|
7
|
+
const linkProps = useDirectusLink(props);
|
|
8
|
+
if (!type || !linkProps.href) return null;
|
|
9
|
+
const LinkComponent = componentsConfig == null ? void 0 : componentsConfig[type];
|
|
10
|
+
if (!LinkComponent) return /* @__PURE__ */ jsx(Anchor, { as: Link, ...linkProps });
|
|
11
|
+
return /* @__PURE__ */ jsx(LinkComponent, { ...props });
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
DirectusLink as default
|
|
15
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TDefaultComponent, TAnchorProps } from '@okam/stack-ui';
|
|
2
|
+
import type { ComponentType } from 'react';
|
|
3
|
+
import type { TLinks } from '../../types/links';
|
|
4
|
+
export interface TDirectusLinkProps extends Omit<TDefaultComponent, 'children'>, Omit<Partial<TLinks>, 'tokens'> {
|
|
5
|
+
componentsConfig?: TDirectusLinkComponentsConfig;
|
|
6
|
+
propsConfig?: TDirectusLinkPropsConfig;
|
|
7
|
+
}
|
|
8
|
+
export type TDirectusLinkComponentsConfig = Record<string, ComponentType<TDirectusLinkProps>>;
|
|
9
|
+
export type TDirectusLinkPropsConfig<ReturnProps extends TAnchorProps = TAnchorProps> = Record<string, (props: TDirectusLinkProps) => ReturnProps>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const IMG_DOMAIN = process.env.NEXT_PUBLIC_IMG_DOMAIN;
|
|
3
|
+
const IMG_PORT = process.env.NEXT_PUBLIC_IMG_PORT;
|
|
4
|
+
const IMG_PROTOCOL = process.env.NEXT_PUBLIC_IMG_PROTOCOL;
|
|
5
|
+
function getDirectusUrl(file, baseUrl) {
|
|
6
|
+
const { id, filename_download, filenameDownload } = file ?? {};
|
|
7
|
+
const { protocol = IMG_PROTOCOL, port = IMG_PORT, hostname = IMG_DOMAIN } = baseUrl ?? {};
|
|
8
|
+
if (!hostname || !id) return null;
|
|
9
|
+
try {
|
|
10
|
+
const url = new URL(
|
|
11
|
+
`/assets/${id}/${filename_download ?? filenameDownload ?? ""}`,
|
|
12
|
+
`${protocol ?? "https"}://${hostname}${port ? `:${port}` : ""}`
|
|
13
|
+
);
|
|
14
|
+
return url;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.warn(error);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function useDirectusFile(file, baseUrl) {
|
|
21
|
+
if (!file) return null;
|
|
22
|
+
const url = getDirectusUrl(file, baseUrl);
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
module.exports = useDirectusFile;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const IMG_DOMAIN = process.env.NEXT_PUBLIC_IMG_DOMAIN;
|
|
2
|
+
const IMG_PORT = process.env.NEXT_PUBLIC_IMG_PORT;
|
|
3
|
+
const IMG_PROTOCOL = process.env.NEXT_PUBLIC_IMG_PROTOCOL;
|
|
4
|
+
function getDirectusUrl(file, baseUrl) {
|
|
5
|
+
const { id, filename_download, filenameDownload } = file ?? {};
|
|
6
|
+
const { protocol = IMG_PROTOCOL, port = IMG_PORT, hostname = IMG_DOMAIN } = baseUrl ?? {};
|
|
7
|
+
if (!hostname || !id) return null;
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(
|
|
10
|
+
`/assets/${id}/${filename_download ?? filenameDownload ?? ""}`,
|
|
11
|
+
`${protocol ?? "https"}://${hostname}${port ? `:${port}` : ""}`
|
|
12
|
+
);
|
|
13
|
+
return url;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.warn(error);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function useDirectusFile(file, baseUrl) {
|
|
20
|
+
if (!file) return null;
|
|
21
|
+
const url = getDirectusUrl(file, baseUrl);
|
|
22
|
+
return url;
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
useDirectusFile as default
|
|
26
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const directusFile = require("./directus-file.js");
|
|
3
|
+
const defaultPropsConfig = {
|
|
4
|
+
collection: ({ collection, target }) => {
|
|
5
|
+
var _a, _b;
|
|
6
|
+
return {
|
|
7
|
+
href: ((_b = (_a = collection == null ? void 0 : collection.translations) == null ? void 0 : _a[0]) == null ? void 0 : _b.path) ?? void 0,
|
|
8
|
+
target: target ?? void 0
|
|
9
|
+
};
|
|
10
|
+
},
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
12
|
+
"external-link": ({ external_link: externalLink, target }) => ({
|
|
13
|
+
href: externalLink ?? void 0,
|
|
14
|
+
target: target ?? void 0
|
|
15
|
+
}),
|
|
16
|
+
file: ({ file }) => {
|
|
17
|
+
const { filename_download: filenameDownload } = file ?? {};
|
|
18
|
+
const href = directusFile(file);
|
|
19
|
+
return {
|
|
20
|
+
href: (href == null ? void 0 : href.toString()) ?? void 0,
|
|
21
|
+
download: filenameDownload ?? true
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
anchor: ({ anchor }) => ({ href: anchor ?? void 0 })
|
|
25
|
+
};
|
|
26
|
+
function useDirectusLink(props) {
|
|
27
|
+
const { type, label, prefetch, replace, scroll, variant, tokens, themeName, customTheme, propsConfig } = props;
|
|
28
|
+
if (!type) return {};
|
|
29
|
+
const finalConfig = { ...defaultPropsConfig, ...propsConfig ?? {} };
|
|
30
|
+
const { href, ...rest } = finalConfig[type](props);
|
|
31
|
+
if (!href) return {};
|
|
32
|
+
return {
|
|
33
|
+
themeName,
|
|
34
|
+
tokens: { ...tokens, ...variant ? { type: variant } : {} },
|
|
35
|
+
customTheme,
|
|
36
|
+
nextLinkProps: {
|
|
37
|
+
href,
|
|
38
|
+
prefetch: prefetch ?? void 0,
|
|
39
|
+
scroll: scroll ?? void 0,
|
|
40
|
+
replace: replace ?? void 0
|
|
41
|
+
},
|
|
42
|
+
href,
|
|
43
|
+
children: label,
|
|
44
|
+
...rest
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
module.exports = useDirectusLink;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import useDirectusFile from "./directus-file.mjs";
|
|
2
|
+
const defaultPropsConfig = {
|
|
3
|
+
collection: ({ collection, target }) => {
|
|
4
|
+
var _a, _b;
|
|
5
|
+
return {
|
|
6
|
+
href: ((_b = (_a = collection == null ? void 0 : collection.translations) == null ? void 0 : _a[0]) == null ? void 0 : _b.path) ?? void 0,
|
|
7
|
+
target: target ?? void 0
|
|
8
|
+
};
|
|
9
|
+
},
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
11
|
+
"external-link": ({ external_link: externalLink, target }) => ({
|
|
12
|
+
href: externalLink ?? void 0,
|
|
13
|
+
target: target ?? void 0
|
|
14
|
+
}),
|
|
15
|
+
file: ({ file }) => {
|
|
16
|
+
const { filename_download: filenameDownload } = file ?? {};
|
|
17
|
+
const href = useDirectusFile(file);
|
|
18
|
+
return {
|
|
19
|
+
href: (href == null ? void 0 : href.toString()) ?? void 0,
|
|
20
|
+
download: filenameDownload ?? true
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
anchor: ({ anchor }) => ({ href: anchor ?? void 0 })
|
|
24
|
+
};
|
|
25
|
+
function useDirectusLink(props) {
|
|
26
|
+
const { type, label, prefetch, replace, scroll, variant, tokens, themeName, customTheme, propsConfig } = props;
|
|
27
|
+
if (!type) return {};
|
|
28
|
+
const finalConfig = { ...defaultPropsConfig, ...propsConfig ?? {} };
|
|
29
|
+
const { href, ...rest } = finalConfig[type](props);
|
|
30
|
+
if (!href) return {};
|
|
31
|
+
return {
|
|
32
|
+
themeName,
|
|
33
|
+
tokens: { ...tokens, ...variant ? { type: variant } : {} },
|
|
34
|
+
customTheme,
|
|
35
|
+
nextLinkProps: {
|
|
36
|
+
href,
|
|
37
|
+
prefetch: prefetch ?? void 0,
|
|
38
|
+
scroll: scroll ?? void 0,
|
|
39
|
+
replace: replace ?? void 0
|
|
40
|
+
},
|
|
41
|
+
href,
|
|
42
|
+
children: label,
|
|
43
|
+
...rest
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
useDirectusLink as default
|
|
48
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Nullable } from '@okam/stack-ui';
|
|
2
|
+
import type { TDirectusLinkProps } from '../components/DirectusLink/interface';
|
|
3
|
+
import type { TNavigationItems, TNavigationItemsTree } from '../types/navigation-items';
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param navigationItems A tree of navigation items, with parents and children
|
|
7
|
+
* @returns A tree of navigation items with ready-to-use DirectusLink components
|
|
8
|
+
*/
|
|
9
|
+
export default function useNavigationItems<Depth extends number, Link, NavigationItems extends TNavigationItems<NavigationItems, Link, Depth> = TNavigationItems<unknown, Link, Depth>>(items: Nullable<Nullable<TNavigationItems<NavigationItems, Link, Depth>>[]>, onNavigationItem: (item: Nullable<TNavigationItems<NavigationItems, Link, Depth>>) => Nullable<TDirectusLinkProps>): Nullable<Nullable<TNavigationItemsTree>[]>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
3
|
+
const index = require("../components/DirectusLink/index.js");
|
|
4
|
+
function createParentTree(item, onNavigationItem, depth = -1) {
|
|
5
|
+
const { parent } = item ?? {};
|
|
6
|
+
const link = onNavigationItem(item);
|
|
7
|
+
const { id } = link ?? {};
|
|
8
|
+
if (!id) return null;
|
|
9
|
+
return {
|
|
10
|
+
link: /* @__PURE__ */ jsxRuntime.jsx(index, { ...link }),
|
|
11
|
+
linkProps: link,
|
|
12
|
+
parent: createParentTree(parent, onNavigationItem, depth - 1),
|
|
13
|
+
depth
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function createChildrenTree(item, onNavigationItem, depth = 1) {
|
|
17
|
+
const { children } = item ?? {};
|
|
18
|
+
const link = onNavigationItem(item);
|
|
19
|
+
const { id } = link ?? {};
|
|
20
|
+
if (!id) return null;
|
|
21
|
+
return {
|
|
22
|
+
link: /* @__PURE__ */ jsxRuntime.jsx(index, { ...link }),
|
|
23
|
+
linkProps: link,
|
|
24
|
+
children: children == null ? void 0 : children.map((child) => createChildrenTree(child, onNavigationItem, depth + 1)),
|
|
25
|
+
depth
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function useNavigationItems(items, onNavigationItem) {
|
|
29
|
+
const tree = items == null ? void 0 : items.map((item) => {
|
|
30
|
+
const { children, parent } = item ?? {};
|
|
31
|
+
const link = onNavigationItem(item);
|
|
32
|
+
const parentTree = createParentTree(parent, onNavigationItem);
|
|
33
|
+
const childrenTree = children == null ? void 0 : children.map((child) => createChildrenTree(child, onNavigationItem));
|
|
34
|
+
return {
|
|
35
|
+
depth: 0,
|
|
36
|
+
parent: parentTree,
|
|
37
|
+
children: childrenTree,
|
|
38
|
+
link: /* @__PURE__ */ jsxRuntime.jsx(index, { ...link }),
|
|
39
|
+
linkProps: link
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
return tree;
|
|
43
|
+
}
|
|
44
|
+
module.exports = useNavigationItems;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import DirectusLink from "../components/DirectusLink/index.mjs";
|
|
3
|
+
function createParentTree(item, onNavigationItem, depth = -1) {
|
|
4
|
+
const { parent } = item ?? {};
|
|
5
|
+
const link = onNavigationItem(item);
|
|
6
|
+
const { id } = link ?? {};
|
|
7
|
+
if (!id) return null;
|
|
8
|
+
return {
|
|
9
|
+
link: /* @__PURE__ */ jsx(DirectusLink, { ...link }),
|
|
10
|
+
linkProps: link,
|
|
11
|
+
parent: createParentTree(parent, onNavigationItem, depth - 1),
|
|
12
|
+
depth
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function createChildrenTree(item, onNavigationItem, depth = 1) {
|
|
16
|
+
const { children } = item ?? {};
|
|
17
|
+
const link = onNavigationItem(item);
|
|
18
|
+
const { id } = link ?? {};
|
|
19
|
+
if (!id) return null;
|
|
20
|
+
return {
|
|
21
|
+
link: /* @__PURE__ */ jsx(DirectusLink, { ...link }),
|
|
22
|
+
linkProps: link,
|
|
23
|
+
children: children == null ? void 0 : children.map((child) => createChildrenTree(child, onNavigationItem, depth + 1)),
|
|
24
|
+
depth
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function useNavigationItems(items, onNavigationItem) {
|
|
28
|
+
const tree = items == null ? void 0 : items.map((item) => {
|
|
29
|
+
const { children, parent } = item ?? {};
|
|
30
|
+
const link = onNavigationItem(item);
|
|
31
|
+
const parentTree = createParentTree(parent, onNavigationItem);
|
|
32
|
+
const childrenTree = children == null ? void 0 : children.map((child) => createChildrenTree(child, onNavigationItem));
|
|
33
|
+
return {
|
|
34
|
+
depth: 0,
|
|
35
|
+
parent: parentTree,
|
|
36
|
+
children: childrenTree,
|
|
37
|
+
link: /* @__PURE__ */ jsx(DirectusLink, { ...link }),
|
|
38
|
+
linkProps: link
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
return tree;
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
useNavigationItems as default
|
|
45
|
+
};
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { default as DirectusLink } from './components/DirectusLink';
|
|
2
|
+
export { default as useDirectusFile } from './hooks/directus-file';
|
|
3
|
+
export { default as useDirectusLink } from './hooks/directus-link';
|
|
4
|
+
export { default as useNavigationItems } from './hooks/navigation-items';
|
|
5
|
+
export type { TFiles } from './types/files';
|
|
6
|
+
export type { TPageSettings } from './types/page-settings';
|
|
7
|
+
export type { TNavigationItems, TNavigationItemsTree } from './types/navigation-items';
|
|
8
|
+
export type { TLinks } from './types/links';
|
|
9
|
+
export type { TDirectusLinkProps } from './components/DirectusLink/interface';
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const index = require("./components/DirectusLink/index.js");
|
|
4
|
+
const directusFile = require("./hooks/directus-file.js");
|
|
5
|
+
const directusLink = require("./hooks/directus-link.js");
|
|
6
|
+
const navigationItems = require("./hooks/navigation-items.js");
|
|
7
|
+
exports.DirectusLink = index;
|
|
8
|
+
exports.useDirectusFile = directusFile;
|
|
9
|
+
exports.useDirectusLink = directusLink;
|
|
10
|
+
exports.useNavigationItems = navigationItems;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { default as default2 } from "./components/DirectusLink/index.mjs";
|
|
2
|
+
import { default as default3 } from "./hooks/directus-file.mjs";
|
|
3
|
+
import { default as default4 } from "./hooks/directus-link.mjs";
|
|
4
|
+
import { default as default5 } from "./hooks/navigation-items.mjs";
|
|
5
|
+
export {
|
|
6
|
+
default2 as DirectusLink,
|
|
7
|
+
default3 as useDirectusFile,
|
|
8
|
+
default4 as useDirectusLink,
|
|
9
|
+
default5 as useNavigationItems
|
|
10
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const server_js = require("next/server.js");
|
|
4
|
+
const radash = require("radash");
|
|
5
|
+
async function fetchPageSettings(pathName, lang = "fr-CA") {
|
|
6
|
+
const graphqlEndpoint = process.env.NEXT_PUBLIC_GRAPHQL_URL;
|
|
7
|
+
const graphqlApiKey = process.env.NEXT_PUBLIC_API_TOKEN;
|
|
8
|
+
if (!graphqlEndpoint || !graphqlApiKey) {
|
|
9
|
+
throw new Error("Missing graphql configuration: NEXT_PUBLIC_GRAPHQL_URL or NEXT_API_TOKEN_ADMIN");
|
|
10
|
+
}
|
|
11
|
+
let langCodeFilter = "_eq";
|
|
12
|
+
if (lang.length === 2) {
|
|
13
|
+
langCodeFilter = "_contains";
|
|
14
|
+
}
|
|
15
|
+
const query = `
|
|
16
|
+
query PageSettings($path: String = null, $lang: String = "fr-CA") {
|
|
17
|
+
page_settings(
|
|
18
|
+
filter: { translations: { path: { _eq: $path }, languages_code: {code: {${langCodeFilter}: $lang}} }},
|
|
19
|
+
limit: 1
|
|
20
|
+
) {
|
|
21
|
+
belongs_to_key
|
|
22
|
+
belongs_to_collection
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
const graphqlBody = {
|
|
27
|
+
query,
|
|
28
|
+
variables: {
|
|
29
|
+
lang,
|
|
30
|
+
path: pathName
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch(graphqlEndpoint, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Authorization: `Bearer ${graphqlApiKey}`
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify(graphqlBody)
|
|
42
|
+
});
|
|
43
|
+
const { data } = await response.json();
|
|
44
|
+
const key = radash.get(data, "page_settings.0.belongs_to_key");
|
|
45
|
+
const collection = radash.get(data, "page_settings.0.belongs_to_collection");
|
|
46
|
+
if (key == null || collection == null) {
|
|
47
|
+
throw new Error("No page settings found");
|
|
48
|
+
}
|
|
49
|
+
return `/${collection}/${key}`;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.error("GraphQL Error", e.message);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function removeLocaleFromPathName(pathName, locale) {
|
|
56
|
+
if (pathName.includes(locale)) {
|
|
57
|
+
return pathName.replace(`/${locale}`, "");
|
|
58
|
+
}
|
|
59
|
+
return pathName;
|
|
60
|
+
}
|
|
61
|
+
async function directusRouteMiddleware(request, locales) {
|
|
62
|
+
const { pathname } = request.nextUrl;
|
|
63
|
+
const locale = locales.find((l) => pathname.startsWith(`/${l}`));
|
|
64
|
+
const pathNameWithoutLocale = locale ? removeLocaleFromPathName(pathname, locale) : pathname;
|
|
65
|
+
const route = await fetchPageSettings(pathNameWithoutLocale, locale);
|
|
66
|
+
if (route === null) {
|
|
67
|
+
return server_js.NextResponse.next();
|
|
68
|
+
}
|
|
69
|
+
const url = request.nextUrl.clone();
|
|
70
|
+
url.pathname = route;
|
|
71
|
+
return server_js.NextResponse.rewrite(url);
|
|
72
|
+
}
|
|
73
|
+
const config = {
|
|
74
|
+
matcher: [
|
|
75
|
+
/*
|
|
76
|
+
* Match all request paths except for the ones starting with:
|
|
77
|
+
* - api (API routes)
|
|
78
|
+
* - _next/static (static files)
|
|
79
|
+
* - _next/image (image optimization files)
|
|
80
|
+
* - favicon.ico (favicon file)
|
|
81
|
+
*/
|
|
82
|
+
"/((?!api|_next/static|_next/image|favicon.ico).*)"
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
exports.config = config;
|
|
86
|
+
exports.directusRouteMiddleware = directusRouteMiddleware;
|
|
87
|
+
exports.fetchPageSettings = fetchPageSettings;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { NextResponse } from "next/server.js";
|
|
2
|
+
import { get } from "radash";
|
|
3
|
+
async function fetchPageSettings(pathName, lang = "fr-CA") {
|
|
4
|
+
const graphqlEndpoint = process.env.NEXT_PUBLIC_GRAPHQL_URL;
|
|
5
|
+
const graphqlApiKey = process.env.NEXT_PUBLIC_API_TOKEN;
|
|
6
|
+
if (!graphqlEndpoint || !graphqlApiKey) {
|
|
7
|
+
throw new Error("Missing graphql configuration: NEXT_PUBLIC_GRAPHQL_URL or NEXT_API_TOKEN_ADMIN");
|
|
8
|
+
}
|
|
9
|
+
let langCodeFilter = "_eq";
|
|
10
|
+
if (lang.length === 2) {
|
|
11
|
+
langCodeFilter = "_contains";
|
|
12
|
+
}
|
|
13
|
+
const query = `
|
|
14
|
+
query PageSettings($path: String = null, $lang: String = "fr-CA") {
|
|
15
|
+
page_settings(
|
|
16
|
+
filter: { translations: { path: { _eq: $path }, languages_code: {code: {${langCodeFilter}: $lang}} }},
|
|
17
|
+
limit: 1
|
|
18
|
+
) {
|
|
19
|
+
belongs_to_key
|
|
20
|
+
belongs_to_collection
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
const graphqlBody = {
|
|
25
|
+
query,
|
|
26
|
+
variables: {
|
|
27
|
+
lang,
|
|
28
|
+
path: pathName
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(graphqlEndpoint, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: {
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
Authorization: `Bearer ${graphqlApiKey}`
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify(graphqlBody)
|
|
40
|
+
});
|
|
41
|
+
const { data } = await response.json();
|
|
42
|
+
const key = get(data, "page_settings.0.belongs_to_key");
|
|
43
|
+
const collection = get(data, "page_settings.0.belongs_to_collection");
|
|
44
|
+
if (key == null || collection == null) {
|
|
45
|
+
throw new Error("No page settings found");
|
|
46
|
+
}
|
|
47
|
+
return `/${collection}/${key}`;
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error("GraphQL Error", e.message);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function removeLocaleFromPathName(pathName, locale) {
|
|
54
|
+
if (pathName.includes(locale)) {
|
|
55
|
+
return pathName.replace(`/${locale}`, "");
|
|
56
|
+
}
|
|
57
|
+
return pathName;
|
|
58
|
+
}
|
|
59
|
+
async function directusRouteMiddleware(request, locales) {
|
|
60
|
+
const { pathname } = request.nextUrl;
|
|
61
|
+
const locale = locales.find((l) => pathname.startsWith(`/${l}`));
|
|
62
|
+
const pathNameWithoutLocale = locale ? removeLocaleFromPathName(pathname, locale) : pathname;
|
|
63
|
+
const route = await fetchPageSettings(pathNameWithoutLocale, locale);
|
|
64
|
+
if (route === null) {
|
|
65
|
+
return NextResponse.next();
|
|
66
|
+
}
|
|
67
|
+
const url = request.nextUrl.clone();
|
|
68
|
+
url.pathname = route;
|
|
69
|
+
return NextResponse.rewrite(url);
|
|
70
|
+
}
|
|
71
|
+
const config = {
|
|
72
|
+
matcher: [
|
|
73
|
+
/*
|
|
74
|
+
* Match all request paths except for the ones starting with:
|
|
75
|
+
* - api (API routes)
|
|
76
|
+
* - _next/static (static files)
|
|
77
|
+
* - _next/image (image optimization files)
|
|
78
|
+
* - favicon.ico (favicon file)
|
|
79
|
+
*/
|
|
80
|
+
"/((?!api|_next/static|_next/image|favicon.ico).*)"
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
export {
|
|
84
|
+
config,
|
|
85
|
+
directusRouteMiddleware,
|
|
86
|
+
fetchPageSettings
|
|
87
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function HelloServer(): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
async function HelloServer() {
|
|
5
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h1", { children: "Hello Server" });
|
|
6
|
+
}
|
|
7
|
+
exports.HelloServer = HelloServer;
|
package/package.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@okam/directus-next-component",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"main": "./index.js",
|
|
5
|
+
"types": "./index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./index.mjs",
|
|
9
|
+
"require": "./index.js"
|
|
10
|
+
},
|
|
11
|
+
"./server": {
|
|
12
|
+
"import": "./server.mjs",
|
|
13
|
+
"require": "./server.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"registry": "https://registry.npmjs.org"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"url": "https://github.com/OKAMca/stack.git"
|
|
21
|
+
}
|
|
4
22
|
}
|
package/server.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './lib/hello-server';
|
|
2
|
+
export { default as withDirectus } from './lib/withDirectus';
|
|
3
|
+
export * from './lib/directus-next-rewrite';
|
|
4
|
+
export { default as DirectusLink } from './components/DirectusLink';
|
|
5
|
+
export { default as useDirectusFile } from './hooks/directus-file';
|
|
6
|
+
export { default as useDirectusLink } from './hooks/directus-link';
|
|
7
|
+
export { default as useNavigationItems } from './hooks/navigation-items';
|
package/server.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const helloServer = require("./lib/hello-server.js");
|
|
4
|
+
const withDirectus = require("./lib/withDirectus.js");
|
|
5
|
+
const directusNextRewrite = require("./lib/directus-next-rewrite.js");
|
|
6
|
+
const index = require("./components/DirectusLink/index.js");
|
|
7
|
+
const directusFile = require("./hooks/directus-file.js");
|
|
8
|
+
const directusLink = require("./hooks/directus-link.js");
|
|
9
|
+
const navigationItems = require("./hooks/navigation-items.js");
|
|
10
|
+
exports.HelloServer = helloServer.HelloServer;
|
|
11
|
+
exports.withDirectus = withDirectus;
|
|
12
|
+
exports.config = directusNextRewrite.config;
|
|
13
|
+
exports.directusRouteMiddleware = directusNextRewrite.directusRouteMiddleware;
|
|
14
|
+
exports.fetchPageSettings = directusNextRewrite.fetchPageSettings;
|
|
15
|
+
exports.DirectusLink = index;
|
|
16
|
+
exports.useDirectusFile = directusFile;
|
|
17
|
+
exports.useDirectusLink = directusLink;
|
|
18
|
+
exports.useNavigationItems = navigationItems;
|
package/server.mjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HelloServer } from "./lib/hello-server.mjs";
|
|
2
|
+
import { default as default2 } from "./lib/withDirectus.mjs";
|
|
3
|
+
import { config, directusRouteMiddleware, fetchPageSettings } from "./lib/directus-next-rewrite.mjs";
|
|
4
|
+
import { default as default3 } from "./components/DirectusLink/index.mjs";
|
|
5
|
+
import { default as default4 } from "./hooks/directus-file.mjs";
|
|
6
|
+
import { default as default5 } from "./hooks/directus-link.mjs";
|
|
7
|
+
import { default as default6 } from "./hooks/navigation-items.mjs";
|
|
8
|
+
export {
|
|
9
|
+
default3 as DirectusLink,
|
|
10
|
+
HelloServer,
|
|
11
|
+
config,
|
|
12
|
+
directusRouteMiddleware,
|
|
13
|
+
fetchPageSettings,
|
|
14
|
+
default4 as useDirectusFile,
|
|
15
|
+
default5 as useDirectusLink,
|
|
16
|
+
default6 as useNavigationItems,
|
|
17
|
+
default2 as withDirectus
|
|
18
|
+
};
|
package/types/files.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type TFiles = {
|
|
2
|
+
id: string;
|
|
3
|
+
filename_disk?: string | null;
|
|
4
|
+
filename_download?: string | null;
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated
|
|
7
|
+
*/
|
|
8
|
+
filenameDownload?: string | null;
|
|
9
|
+
title?: string | null;
|
|
10
|
+
type?: string | null;
|
|
11
|
+
width?: number | null;
|
|
12
|
+
height?: number | null;
|
|
13
|
+
duration?: number | null;
|
|
14
|
+
embed?: string | null;
|
|
15
|
+
description?: string | null;
|
|
16
|
+
focal_point_x?: number | null;
|
|
17
|
+
focal_point_y?: number | null;
|
|
18
|
+
};
|
package/types/links.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TFiles } from './files';
|
|
2
|
+
import type { TPageSettings } from './page-settings';
|
|
3
|
+
/**
|
|
4
|
+
* Represent the directus `links` collection, not the props of the DirectusLink component
|
|
5
|
+
*/
|
|
6
|
+
export type TLinks = {
|
|
7
|
+
anchor?: string | null;
|
|
8
|
+
external_link?: string | null;
|
|
9
|
+
id?: string;
|
|
10
|
+
label?: string | null;
|
|
11
|
+
prefetch?: boolean | null;
|
|
12
|
+
replace?: boolean | null;
|
|
13
|
+
scroll?: boolean | null;
|
|
14
|
+
target?: string | null;
|
|
15
|
+
tokens?: any | null;
|
|
16
|
+
type?: string | null;
|
|
17
|
+
variant?: string | null;
|
|
18
|
+
collection?: TPageSettings | null;
|
|
19
|
+
file?: TFiles | null;
|
|
20
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { Nullable } from '@okam/stack-ui';
|
|
3
|
+
import type { TDirectusLinkProps } from '../components/DirectusLink/interface';
|
|
4
|
+
export type TNavigationItemsTree = {
|
|
5
|
+
/**
|
|
6
|
+
* Pre-rendered DirectusLink component for quick usage
|
|
7
|
+
*/
|
|
8
|
+
link: Nullable<React.ReactElement>;
|
|
9
|
+
linkProps: Nullable<TDirectusLinkProps>;
|
|
10
|
+
children?: Nullable<Nullable<TNavigationItemsTree>[]>;
|
|
11
|
+
parent?: Nullable<TNavigationItemsTree>;
|
|
12
|
+
/**
|
|
13
|
+
* Starts at 0.
|
|
14
|
+
* For each level of parent, goes down by 1
|
|
15
|
+
* For each level of children, goes up by 1
|
|
16
|
+
*/
|
|
17
|
+
depth: number;
|
|
18
|
+
};
|
|
19
|
+
type DepthLimit = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
20
|
+
export type TNavigationItemsParents<NavigationItems, Link, Depth extends number> = Depth extends never ? Link : {
|
|
21
|
+
parent?: Nullable<TNavigationItemsParents<NavigationItems, Link, Depth>>;
|
|
22
|
+
} & Link;
|
|
23
|
+
export type TNavigationItemsChildren<NavigationItems, Link, Depth extends number> = Depth extends never ? Link : {
|
|
24
|
+
children?: Nullable<Nullable<TNavigationItemsChildren<NavigationItems, Link, DepthLimit[Depth]>>[]>;
|
|
25
|
+
} & Link;
|
|
26
|
+
export type TNavigationItems<NavigationItems, Link, Depth extends number> = TNavigationItemsChildren<NavigationItems, Link, Depth> & TNavigationItemsParents<NavigationItems, Link, Depth>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type TPageSettings = {
|
|
2
|
+
id: string;
|
|
3
|
+
belongs_to_collection?: string | null;
|
|
4
|
+
translations?: Array<{
|
|
5
|
+
slug?: string | null;
|
|
6
|
+
title?: string | null;
|
|
7
|
+
path?: string | null;
|
|
8
|
+
languages_code?: {
|
|
9
|
+
code: string;
|
|
10
|
+
} | null;
|
|
11
|
+
} | null> | null;
|
|
12
|
+
route?: {
|
|
13
|
+
translations?: Array<{
|
|
14
|
+
route?: string | null;
|
|
15
|
+
} | null> | null;
|
|
16
|
+
} | null;
|
|
17
|
+
};
|
package/.eslintrc.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# directus-next-component
|
|
2
|
-
|
|
3
|
-
This library was generated with [Nx](https://nx.dev).
|
|
4
|
-
|
|
5
|
-
## directusRouteMiddleware usage
|
|
6
|
-
|
|
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
|
-
|
|
9
|
-
```jsx
|
|
10
|
-
// middleware.ts
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
directusRouteMiddleware,
|
|
14
|
-
config as directusRouteMiddlewareConfig,
|
|
15
|
-
} from '@okam/directus-next-component/src/server'
|
|
16
|
-
import type { NextRequest } from 'next/server'
|
|
17
|
-
|
|
18
|
-
export function middleware(request: NextRequest) {
|
|
19
|
-
const { locale } = request.nextUrl
|
|
20
|
-
return directusRouteMiddleware(request, [locale])
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const config = {
|
|
24
|
-
...directusRouteMiddlewareConfig,
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
After, modify the `next.config.js` file to add `withDirectus` in the plugins.
|
package/project.json
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
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
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities
|
|
@@ -1,106 +0,0 @@
|
|
|
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
|
-
}
|
package/src/lib/hello-server.tsx
DELETED
package/src/lib/withDirectus.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
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
DELETED
package/tsconfig.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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
|
-
}
|
package/tsconfig.lib.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
}
|