Skip to content

Migrate templates from Nuxt 2 to Nuxt 3 #356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
111c3fe
Add FooCreate
ValentinCrochemore Dec 20, 2022
b9fbd60
Add FooForm
ValentinCrochemore Dec 20, 2022
03027c5
Add FooList
ValentinCrochemore Dec 20, 2022
706abcf
Add FooShow
ValentinCrochemore Dec 20, 2022
b2e15ab
Add FooUpdate
ValentinCrochemore Dec 20, 2022
84ca6d4
Add FormRepeater
ValentinCrochemore Dec 20, 2022
ec61bfd
Add Mercure composables
ValentinCrochemore Dec 20, 2022
ddc8908
Add pages
ValentinCrochemore Dec 20, 2022
fa9d1bb
Add stores
ValentinCrochemore Dec 20, 2022
8664c4b
Add types
ValentinCrochemore Dec 20, 2022
3d15a3d
Add utils
ValentinCrochemore Dec 20, 2022
50c49c7
Delete useless files
ValentinCrochemore Dec 20, 2022
a3924b2
Fix some bugs
ValentinCrochemore Dec 22, 2022
0721a94
Add files to generate
ValentinCrochemore Dec 22, 2022
f0a04a7
Import defineStore as it is not auto imported
ValentinCrochemore Dec 22, 2022
f5b79e4
Update Nuxt Generator
ValentinCrochemore Dec 22, 2022
f72548c
Update Nuxt generator test
ValentinCrochemore Dec 22, 2022
997a701
Remove lodash
ValentinCrochemore Dec 22, 2022
2aca9ab
Change link label
ValentinCrochemore Dec 22, 2022
d6cf383
Add a nuxt.config.ts for e2e test
ValentinCrochemore Dec 22, 2022
605e98f
Update command for e2e test
ValentinCrochemore Dec 22, 2022
4d5280b
Change update & create functions names
ValentinCrochemore Dec 28, 2022
66785d3
Rename relations variables
ValentinCrochemore Dec 28, 2022
7ee76ee
Merge branch 'main' into feat/update-nuxt-templates
ValentinCrochemore Jan 6, 2023
fb47b0e
Update e2e script
ValentinCrochemore Jan 6, 2023
24e6ca2
Fix router paths
ValentinCrochemore Jan 6, 2023
7540e39
Fix tailwind config for e2e tests
ValentinCrochemore Jan 6, 2023
ee165af
Fix e2e test
ValentinCrochemore Jan 6, 2023
c868a15
Use files from common & vue-common
ValentinCrochemore Jan 6, 2023
59e915d
Fixes
ValentinCrochemore Jan 6, 2023
497e017
Rewrite test so errors are more easy to locate
ValentinCrochemore Jan 6, 2023
9121963
Add qs in e2e test
ValentinCrochemore Jan 6, 2023
9f53b0d
Remove tailwinf files from generator
ValentinCrochemore Jan 6, 2023
5400b4a
fixes
alanpoulain Jan 10, 2023
4017db4
Manage api calls with useFetch instead of native fetch
ValentinCrochemore Jan 13, 2023
803fd74
Fix access properties of values if null
ValentinCrochemore Jan 16, 2023
684f84c
Fix pagination
ValentinCrochemore Jan 16, 2023
a099ded
Fix reload on show page
ValentinCrochemore Jan 16, 2023
97208c0
Fix reload update page
ValentinCrochemore Jan 17, 2023
ea63439
fixes
alanpoulain Jan 17, 2023
aadf191
Reset stores when leaving FooList
ValentinCrochemore Jan 17, 2023
3cdd33f
Remove FetchError
ValentinCrochemore Jan 18, 2023
fcb1ffd
Updates for Nuxt preview mode
ValentinCrochemore Jan 20, 2023
26e0d9a
fix: use params instead of query to solve SSR issues
alanpoulain Jan 20, 2023
4c282bf
Add util function to get the id instead of accessing it directly
ValentinCrochemore Jan 24, 2023
92c620b
fix: minor fixes
alanpoulain Jan 24, 2023
8198f96
fix: disable SSR for now
alanpoulain Jan 25, 2023
bf563fe
fix: show test
alanpoulain Jan 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
299 changes: 181 additions & 118 deletions src/generators/NuxtGenerator.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,74 @@
import handlebars from "handlebars";
import hbh_comparison from "handlebars-helpers/lib/comparison.js";
import hbh_array from "handlebars-helpers/lib/array.js";
import hbh_string from "handlebars-helpers/lib/string.js";
import chalk from "chalk";
import BaseVueGenerator from "./VueBaseGenerator.js";
import BaseGenerator from "./BaseGenerator.js";

export default class NuxtGenerator extends BaseVueGenerator {
export default class NuxtGenerator extends BaseGenerator {
constructor(params) {
super(params);

this.registerTemplates("common/", [
// types
"types/collection.ts",
"types/error.ts",
"types/foo.ts",
"types/item.ts",
"types/view.ts",

// utils
"utils/config.ts",
"utils/date.ts",
"utils/error.ts",
"utils/mercure.ts",
]);

this.registerTemplates("vue-common/", [
// composables
"composables/mercureItem.ts",
"composables/mercureList.ts",
]);

this.registerTemplates(`nuxt/`, [
// common components
"components/common/FormRepeater.vue",

// components
"components/ActionCell.vue",
"components/Alert.vue",
"components/ConfirmDelete.vue",
"components/DataFilter.vue",
"components/InputDate.vue",
"components/Loading.vue",
"components/Toolbar.vue",
"components/foo/Filter.vue",
"components/foo/Form.vue",

// mixins
"mixins/create.js",
"mixins/list.js",
"mixins/notification.js",
"mixins/show.js",
"mixins/update.js",
"components/foo/FooCreate.vue",
"components/foo/FooForm.vue",
"components/foo/FooList.vue",
"components/foo/FooShow.vue",
"components/foo/FooUpdate.vue",

// composables
"composables/api.ts",

// pages
"pages/index.vue",
"pages/foos/create.vue",
"pages/foos/index.vue",
"pages/foos/_id/edit.vue",
"pages/foos/_id/index.vue",

// store
"store/crud.js",
"store/notifications.js",
"store/foo.js",
"pages/foos/[id]/edit.vue",
"pages/foos/[id]/index.vue",
"pages/foos/page/[page].vue",

// stores
"stores/foo/create.ts",
"stores/foo/delete.ts",
"stores/foo/list.ts",
"stores/foo/show.ts",
"stores/foo/update.ts",

// types
"types/api.ts",

// utils
"utils/resource.ts",
]);

handlebars.registerHelper("compare", hbh_comparison.compare);
handlebars.registerHelper("forEach", hbh_array.forEach);
handlebars.registerHelper("lowercase", hbh_string.lowercase);
}

help(resource) {
Expand All @@ -44,115 +78,144 @@ export default class NuxtGenerator extends BaseVueGenerator {
);
}

generateFiles(api, resource, dir, params) {
const context = super.getContextForResource(resource, params);
const lc = context.lc;

[
`${dir}/config`,
`${dir}/error`,
`${dir}/mixins`,
`${dir}/services`,
`${dir}/store`,
`${dir}/utils`,
`${dir}/validators`,
].forEach((dir) => this.createDir(dir, false));

// error
this.createFile(
"error/SubmissionError.js",
`${dir}/error/SubmissionError.js`,
{},
false
);

// mixins
[
"mixins/create.js",
"mixins/list.js",
"mixins/notification.js",
"mixins/show.js",
"mixins/update.js",
].forEach((file) =>
this.createFile(file, `${dir}/${file}`, context, false)
);

// stores
this.createFile(
`store/modules/notifications.js`,
`${dir}/store/notifications.js`,
{ hydraPrefix: this.hydraPrefix },
false
);

this.createFile(
`store/crud.js`,
`${dir}/store/crud.js`,
{ hydraPrefix: this.hydraPrefix },
false
);

// validators
this.createFile(
"validators/date.js",
`${dir}/validators/date.js`,
{ hydraPrefix: this.hydraPrefix },
false
);

// utils
["dates.js", "fetch.js", "hydra.js"].forEach((file) =>
this.createFile(`utils/${file}`, `${dir}/utils/${file}`, {}, false)
);
getContextForResource(resource) {
const lc = resource.title.toLowerCase();
const titleUcFirst =
resource.title.charAt(0).toUpperCase() + resource.title.slice(1);
const fields = this.parseFields(resource);
const hasIsRelation = fields.some((field) => field.isRelation);
const hasIsRelations = fields.some((field) => field.isRelations);
const hasRelations = hasIsRelation || hasIsRelations;

const formFields = this.buildFields(fields);

return {
title: resource.title,
name: resource.name,
lc,
uc: resource.title.toUpperCase(),
fields,
hasIsRelation,
hasIsRelations,
hasRelations,
formFields,
hydraPrefix: this.hydraPrefix,
titleUcFirst,
};
}

this.createEntrypoint(api.entrypoint, `${dir}/config/entrypoint.js`);
generate(api, resource, dir) {
const context = this.getContextForResource(resource);
const { lc, titleUcFirst } = context;

[
`${dir}/assets`,
`${dir}/assets/css`,
`${dir}/components`,
`${dir}/components/common`,
`${dir}/components/${lc}`,
`${dir}/composables`,
`${dir}/pages`,
`${dir}/pages/${lc}s`,
`${dir}/pages/${lc}s/_id`,
].forEach((dir) => {
this.createDir(dir);
});

this.createFile("services/api.js", `${dir}/services/api.js`, {}, false);
`${dir}/pages/${lc}s/[id]`,
`${dir}/pages/${lc}s/page`,
`${dir}/stores`,
`${dir}/stores/${lc}`,
`${dir}/types`,
`${dir}/utils`,
].forEach((dir) => this.createDir(dir, false));

[
// components
"components/%s/Filter.vue",
"components/%s/Form.vue",
"components/%s/%sCreate.vue",
"components/%s/%sForm.vue",
"components/%s/%sList.vue",
"components/%s/%sShow.vue",
"components/%s/%sUpdate.vue",

// pages
"pages/%ss/create.vue",
"pages/%ss/index.vue",
"pages/%ss/_id/edit.vue",
"pages/%ss/_id/index.vue",

// service
"services/%s.js",

// store
"store/%s.js",
"pages/%ss/[id]/edit.vue",
"pages/%ss/[id]/index.vue",
"pages/%ss/page/[page].vue",

// stores
"stores/%s/create.ts",
"stores/%s/delete.ts",
"stores/%s/list.ts",
"stores/%s/show.ts",
"stores/%s/update.ts",

// types
"types/%s.ts",
].forEach((pattern) =>
this.createFileFromPattern(pattern, dir, [lc], context)
this.createFileFromPattern(pattern, dir, [lc, titleUcFirst], context)
);

// components
[
"ActionCell.vue",
"Alert.vue",
"ConfirmDelete.vue",
"DataFilter.vue",
"InputDate.vue",
"Loading.vue",
"Toolbar.vue",
].forEach((file) =>
this.createFile(
`components/${file}`,
`${dir}/components/${file}`,
context,
false
)
// components
"components/common/FormRepeater.vue",

// composables
"composables/api.ts",
"composables/mercureItem.ts",
"composables/mercureList.ts",

// pages
"pages/index.vue",

// types
"types/api.ts",
"types/collection.ts",
"types/error.ts",
"types/item.ts",
"types/view.ts",

// utils
"utils/date.ts",
"utils/error.ts",
"utils/mercure.ts",

// utils
"utils/resource.ts",
].forEach((path) =>
this.createFile(path, `${dir}/${path}`, context, false)
);

// config
this.createConfigFile(`${dir}/utils/config.ts`, {
entrypoint: api.entrypoint,
});
}

parseFields(resource) {
const fields = [
...resource.writableFields,
...resource.readableFields,
].reduce((list, field) => {
if (list[field.name]) {
return list;
}

const isReferences = Boolean(
field.reference && field.maxCardinality !== 1
);
const isEmbeddeds = Boolean(field.embedded && field.maxCardinality !== 1);

return {
...list,
[field.name]: {
...field,
readonly: false,
isReferences,
isEmbeddeds,
isRelation: field.reference || field.embedded,
isRelations: isEmbeddeds || isReferences,
},
};
}, {});

return Object.values(fields);
}
}
Loading