Skip to content

Commit 4ab98db

Browse files
fix: fine tuning and fixes (#319)
Co-authored-by: Alan Poulain <[email protected]>
1 parent f1acad7 commit 4ab98db

File tree

15 files changed

+125
-127
lines changed

15 files changed

+125
-127
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"eslint-check": "eslint-config-prettier src/index.js",
5454
"build": "babel src -d lib --ignore '*.test.js'",
5555
"watch": "babel --watch src -d lib --ignore '*.test.js'",
56-
"test-gen": "rm -rf ./tmp && yarn build && ./lib/index.js https://demo.api-platform.com ./tmp/react -g react && ./lib/index.js https://demo.api-platform.com ./tmp/react-native -g react-native && ./lib/index.js https://demo.api-platform.com ./tmp/vue -g vue",
56+
"test-gen": "rm -rf ./tmp && yarn build && ./lib/index.js https://demo.api-platform.com ./tmp/react -g react && ./lib/index.js https://demo.api-platform.com ./tmp/react-native -g react-native && ./lib/index.js https://demo.api-platform.com ./tmp/next -g next && ./lib/index.js https://demo.api-platform.com ./tmp/vue -g vue",
5757
"test-gen-custom": "rm -rf ./tmp && yarn build && babel src/generators/ReactGenerator.js src/generators/BaseGenerator.js -d ./tmp/gens && cp -r ./templates/react ./templates/react-common ./templates/entrypoint.js ./tmp/gens && ./lib/index.js https://demo.api-platform.com ./tmp/react-custom -g \"$(pwd)/tmp/gens/ReactGenerator.js\" -t ./tmp/gens",
5858
"test-gen-swagger": "rm -rf ./tmp && yarn build && ./lib/index.js https://demo.api-platform.com/docs.json ./tmp/react -f swagger && ./lib/index.js https://demo.api-platform.com/docs.json ./tmp/react-native -g react-native -f swagger && ./lib/index.js https://demo.api-platform.com/docs.json ./tmp/vue -g vue -f swagger",
5959
"test-gen-env": "rm -rf ./tmp && yarn build && API_PLATFORM_CLIENT_GENERATOR_ENTRYPOINT=https://demo.api-platform.com API_PLATFORM_CLIENT_GENERATOR_OUTPUT=./tmp ./lib/index.js"

src/generators/BaseGenerator.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ export default class {
3737
}
3838
}
3939

40-
createFileFromPattern(pattern, dir, lc, context) {
40+
createFileFromPattern(pattern, dir, value, context, templateValue = "foo") {
4141
this.createFile(
42-
sprintf(pattern, "foo"),
43-
sprintf(`${dir}/${pattern}`, lc),
42+
sprintf(pattern, templateValue),
43+
sprintf(`${dir}/${pattern}`, value),
4444
context
4545
);
4646
}

src/generators/NextGenerator.js

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import chalk from "chalk";
2+
import handlebars from "handlebars";
3+
import hbh_comparison from "handlebars-helpers/lib/comparison";
24
import BaseGenerator from "./BaseGenerator";
35

46
export default class NextGenerator extends BaseGenerator {
@@ -15,8 +17,9 @@ export default class NextGenerator extends BaseGenerator {
1517
"components/foo/Form.tsx",
1618

1719
// types
18-
"types/Collection.ts",
20+
"types/collection.ts",
1921
"types/foo.ts",
22+
"types/item.ts",
2023

2124
// pages
2225
"pages/foos/[id]/index.tsx",
@@ -28,6 +31,8 @@ export default class NextGenerator extends BaseGenerator {
2831
"utils/dataAccess.ts",
2932
"utils/mercure.ts",
3033
]);
34+
35+
handlebars.registerHelper("compare", hbh_comparison.compare);
3136
}
3237

3338
help(resource) {
@@ -66,22 +71,25 @@ export default class NextGenerator extends BaseGenerator {
6671

6772
// Copy with patterned name
6873
this.createDir(`${dir}/components/${context.lc}`);
69-
this.createDir(`${dir}/pages/${context.lc}s`);
70-
this.createDir(`${dir}/pages/${context.lc}s/[id]`);
74+
this.createDir(`${dir}/pages/${context.name}`);
75+
this.createDir(`${dir}/pages/${context.name}/[id]`);
7176
[
7277
// components
7378
"components/%s/List.tsx",
7479
"components/%s/Show.tsx",
7580
"components/%s/Form.tsx",
76-
77-
// pages
78-
"pages/%ss/[id]/index.tsx",
79-
"pages/%ss/[id]/edit.tsx",
80-
"pages/%ss/index.tsx",
81-
"pages/%ss/create.tsx",
8281
].forEach((pattern) =>
8382
this.createFileFromPattern(pattern, dir, context.lc, context)
8483
);
84+
[
85+
// pages
86+
"pages/%s/[id]/index.tsx",
87+
"pages/%s/[id]/edit.tsx",
88+
"pages/%s/index.tsx",
89+
"pages/%s/create.tsx",
90+
].forEach((pattern) =>
91+
this.createFileFromPattern(pattern, dir, context.name, context, "foos")
92+
);
8593

8694
// interface pattern should be camel cased
8795
this.createFile("types/foo.ts", `${dir}/types/${context.ucf}.ts`, context);
@@ -93,7 +101,8 @@ export default class NextGenerator extends BaseGenerator {
93101
"components/common/ReferenceLinks.tsx",
94102

95103
// types
96-
"types/Collection.ts",
104+
"types/collection.ts",
105+
"types/item.ts",
97106

98107
// utils
99108
"utils/dataAccess.ts",

src/generators/NextGenerator.test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe("generate", () => {
2525
description: "An URL",
2626
}),
2727
];
28-
const resource = new Resource("abc", "http://example.com/foos", {
28+
const resource = new Resource("abcs", "http://example.com/foos", {
2929
id: "abc",
3030
title: "abc",
3131
readableFields: fields,
@@ -46,7 +46,8 @@ describe("generate", () => {
4646
"/components/common/ReferenceLinks.tsx",
4747
"/components/common/Pagination.tsx",
4848
"/types/Abc.ts",
49-
"/types/Collection.ts",
49+
"/types/collection.ts",
50+
"/types/item.ts",
5051
"/pages/abcs/[id]/index.tsx",
5152
"/pages/abcs/[id]/edit.tsx",
5253
"/pages/abcs/index.tsx",

templates/next/components/common/Pagination.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Link from "next/link";
2-
import { PagedCollection } from "../../types/Collection";
2+
import { PagedCollection } from "../../types/collection";
33

44
interface Props {
55
collection: PagedCollection<unknown>;

templates/next/components/foo/Form.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,18 @@ export const Form: FunctionComponent<Props> = ({ {{{lc}}} }) => {
7474
<input
7575
name="{{name}}"
7676
id="{{lc}}_{{name}}"
77-
value={ values.{{name}} ?? "" }
77+
{{#compare type "==" "dateTime" }}
78+
value={values.{{name}}?.toLocaleString() ?? ""}
79+
{{/compare}}
80+
{{#compare type "!=" "dateTime" }}
81+
value={values.{{name}} ?? ""}
82+
{{/compare}}
7883
type="{{type}}"
7984
{{#if step}}step="{{{step}}}"{{/if}}
8085
placeholder="{{{description}}}"
8186
{{#if required}}required={true}{{/if}}
8287
className={`form-control${errors.{{name}} && touched.{{name}} ? ' is-invalid' : ''}`}
83-
aria-invalid={errors.{{name}} && touched.{{name~}} }
88+
aria-invalid={errors.{{name}} && touched.{{name~}} ? 'true' : null}
8489
onChange={handleChange}
8590
onBlur={handleBlur}
8691
/>

templates/next/components/foo/Show.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import { FunctionComponent, useState } from 'react';
2-
import Link from 'next/link';
1+
import { FunctionComponent, useState } from "react";
2+
import Link from "next/link";
33
import { useRouter } from "next/router";
4+
import Head from "next/head";
45
import { fetch } from "../../utils/dataAccess";
5-
import ReferenceLinks from '../common/ReferenceLinks';
6-
import { {{{ucf}}} } from '../../types/{{{ucf}}}';
7-
import Head from 'next/head'
6+
import ReferenceLinks from "../common/ReferenceLinks";
7+
import { {{{ucf}}} } from "../../types/{{{ucf}}}";
88

99
interface Props {
1010
{{{lc}}}: {{{ucf}}};
11+
text: string;
1112
}
1213

13-
export const Show: FunctionComponent<Props> = ({ {{{lc}}} }) => {
14+
export const Show: FunctionComponent<Props> = ({ {{{lc}}}, text }) => {
1415
const [error, setError] = useState(null);
1516
const router = useRouter();
1617

@@ -30,11 +31,7 @@ export const Show: FunctionComponent<Props> = ({ {{{lc}}} }) => {
3031
<div>
3132
<Head>
3233
<title>{`Show {{{ucf}}} ${ {{~lc}}['@id']}`}</title>
33-
<script
34-
type="application/ld+json"
35-
>
36-
{text}
37-
</script>
34+
<script type="application/ld+json" dangerouslySetInnerHTML={ { __html: text } } />
3835
</Head>
3936
<h1>{`Show {{{ucf}}} ${ {{~lc}}['@id']}`}</h1>
4037
<table className="table table-responsive table-striped table-hover">

templates/next/pages/foos/[id]/edit.tsx

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { GetStaticPaths, GetStaticProps, NextComponentType, NextPageContext } from "next";
2-
import { Form } from "../../../components/{{{lc}}}/Form";
3-
import { {{{ucf}}} } from "../../../types/{{{ucf}}}";
4-
import { fetch } from "../../../utils/dataAccess";
52
import Head from "next/head";
63
import DefaultErrorPage from "next/error";
4+
import { Form } from "../../../components/{{{lc}}}/Form";
5+
import { {{{ucf}}} } from "../../../types/{{{ucf}}}";
6+
import { fetch, getPaths } from "../../../utils/dataAccess";
77

88
interface Props {
99
{{{lc}}}: {{{ucf}}};
@@ -27,43 +27,19 @@ const Page: NextComponentType<NextPageContext, Props, Props> = ({ {{{lc}}} }) =>
2727
};
2828

2929
export const getStaticProps: GetStaticProps = async ({ params }) => {
30+
const response = await fetch(`/{{{name}}}/${params.id}`);
31+
3032
return {
3133
props: {
32-
{{{lc}}}: await fetch(`/{{{name}}}/${params.id}`),
34+
{{{lc}}}: response.data,
3335
},
3436
revalidate: 1,
3537
};
3638
}
3739

3840
export const getStaticPaths: GetStaticPaths = async () => {
39-
try {
40-
const response = await fetch("/{{{name}}}");
41-
} catch (e) {
42-
console.error(e);
43-
44-
return {
45-
paths: [],
46-
fallback: true,
47-
};
48-
}
49-
50-
const view = response.data['{{{hydraPrefix}}}view'];
51-
const paths = response.data["{{{hydraPrefix}}}member"].map(({{{lc}}}) => `${ {{~lc}}['@id'] }/edit`);
52-
53-
if (view) {
54-
try {
55-
const {
56-
'{{{hydraPrefix}}}last': last
57-
} = view;
58-
for (let page = 2; page <= parseInt(last.replace(/^\/{{{name}}}\?page=(\d+)/, '$1')); page++) {
59-
paths.concat(
60-
await fetch(`/{{{name}}}?page=${page}`).data["{{{hydraPrefix}}}member"].map(({{{lc}}}) => `${ {{~lc}}['@id'] }/edit`)
61-
);
62-
}
63-
} catch (e) {
64-
console.error(e);
65-
}
66-
}
41+
const response = await fetch("/{{{name}}}");
42+
const paths = await getPaths(response, "{{{name}}}", true);
6743

6844
return {
6945
paths,

templates/next/pages/foos/[id]/index.tsx

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import { GetStaticPaths, GetStaticProps, NextComponentType, NextPageContext } from "next";
2-
import { Show } from "../../../components/{{{lc}}}/Show";
3-
import { {{{ucf}}} } from "../../../types/{{{ucf}}}";
4-
import { fetch } from "../../../utils/dataAccess";
52
import Head from "next/head";
63
import DefaultErrorPage from "next/error";
4+
import { Show } from "../../../components/{{{lc}}}/Show";
5+
import { {{{ucf}}} } from "../../../types/{{{ucf}}}";
6+
import { fetch, getPaths } from "../../../utils/dataAccess";
77
import { useMercure } from "../../../utils/mercure";
88

99
interface Props {
1010
{{{lc}}}: {{{ucf}}};
1111
hubURL: null | string;
12+
text: string;
1213
};
1314

14-
const Page: NextComponentType<NextPageContext, Props, Props> = (props) => {
15-
const {{{lc}}} = props.hubURL === null ? props.{{{lc}}} : useMercure(props.{{{lc}}}, props.hubURL);
15+
const Page: NextComponentType<NextPageContext, Props, Props> = ({ {{{lc}}}, hubURL, text }) => {
16+
const {{{lc}}}Data = useMercure({{{lc}}}, hubURL);
1617

17-
if (!{{{lc}}}) {
18+
if (!{{{lc}}}Data) {
1819
return <DefaultErrorPage statusCode={404} />;
1920
}
2021

@@ -25,7 +26,7 @@ const Page: NextComponentType<NextPageContext, Props, Props> = (props) => {
2526
<title>{`Show {{{ucf}}} ${ {{~lc}}['@id'] }`}</title>
2627
</Head>
2728
</div>
28-
<Show {{{lc}}}={ {{{lc}}} } text={ props.text } />
29+
<Show {{{lc}}}={ {{{lc}}}Data } text={text} />
2930
</div>
3031
);
3132
};
@@ -44,34 +45,8 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
4445
}
4546

4647
export const getStaticPaths: GetStaticPaths = async () => {
47-
try {
48-
const response = await fetch("/{{{name}}}");
49-
} catch (e) {
50-
console.error(e);
51-
52-
return {
53-
paths: [],
54-
fallback: true,
55-
};
56-
}
57-
58-
const view = response.data['{{{hydraPrefix}}}view'];
59-
const paths = response.data["{{{hydraPrefix}}}member"].map(({{{lc}}}) => `${ {{~lc}}['@id'] }`);
60-
61-
if (view) {
62-
try {
63-
const {
64-
'{{{hydraPrefix}}}last': last
65-
} = view;
66-
for (let page = 2; page <= parseInt(last.replace(/^\/{{{name}}}\?page=(\d+)/, '$1')); page++) {
67-
paths.concat(
68-
await fetch(`/{{{name}}}?page=${page}`).data["{{{hydraPrefix}}}member"].map(({{{lc}}}) => `${ {{~lc}}['@id'] }`)
69-
);
70-
}
71-
} catch (e) {
72-
console.error(e);
73-
}
74-
}
48+
const response = await fetch("/{{{name}}}");
49+
const paths = await getPaths(response, "{{{name}}}", false);
7550

7651
return {
7752
paths,

templates/next/pages/foos/create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NextComponentType, NextPageContext } from "next";
2-
import { Form } from "../../components/{{{lc}}}/Form";
32
import Head from "next/head";
3+
import { Form } from "../../components/{{{lc}}}/Form";
44

55
const Page: NextComponentType<NextPageContext> = () => (
66
<div>

templates/next/pages/foos/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { GetServerSideProps, NextComponentType, NextPageContext } from "next";
2+
import Head from "next/head";
23
import { List } from "../../components/{{{lc}}}/List";
3-
import { PagedCollection } from "../../types/Collection";
4+
import { PagedCollection } from "../../types/collection";
45
import { {{{ucf}}} } from "../../types/{{{ucf}}}";
56
import { fetch } from "../../utils/dataAccess";
6-
import Head from "next/head";
77
import Pagination from "../../components/common/Pagination";
88
import { useMercure } from "../../utils/mercure";
99

1010
interface Props {
1111
collection: PagedCollection<{{{ucf}}}>;
12-
hubURL: string;
12+
hubURL: string | null;
1313
}
1414

1515
const Page: NextComponentType<NextPageContext, Props, Props> = (props) => {

templates/next/types/Collection.ts renamed to templates/next/types/collection.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import has from "lodash/has"
2+
13
export interface PagedCollection<T> {
24
"@context"?: string;
35
"@id"?: string;
@@ -10,3 +12,6 @@ export interface PagedCollection<T> {
1012
"{{{hydraPrefix}}}search"?: object;
1113
"{{{hydraPrefix}}}totalItems"?: number;
1214
}
15+
16+
export const isPagedCollection = <T>(data: any): data is PagedCollection<T> =>
17+
has(data, "{{{hydraPrefix}}}member") && Array.isArray(data["{{{hydraPrefix}}}member"])

templates/next/types/item.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import has from "lodash/has"
2+
3+
export const isItem = <T>(data: any): data is T => has(data, "@id")

0 commit comments

Comments
 (0)