Skip to content
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

feat: Add Pinia support #12707

Merged
merged 4 commits into from
Mar 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions app-vite/bin/quasar-info
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ print({ key: 'Important local packages', section: true })
'eslint-plugin-quasar',
'vue',
'vue-router',
'pinia',
'vuex',
'vite',
'eslint',
Expand Down
20 changes: 18 additions & 2 deletions app-vite/bin/quasar-new
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const fse = require('fs-extra')

const { log, warn } = require('../lib/helpers/logger')
const appPaths = require('../lib/app-paths')
const getPackageJson = require('../lib/helpers/get-package-json')
const defaultFilePath = 'default'

if (argv._.length < 2) {
Expand Down Expand Up @@ -114,6 +115,8 @@ if (type.length === 1) {
type = fullCmd[type]
}

const storeProvider = getPackageJson('vuex') !== void 0 ? 'vuex' : 'pinia'

function getPaths (asset, names) {
return names.map(name => {
const hasExtension = !asset.ext || (asset.ext && name.endsWith(asset.ext))
Expand All @@ -133,8 +136,16 @@ function createFile (asset, file) {
}

fse.mkdirp(path.dirname(file))
let templatePath = path.join('templates/app', format)

if (type === 'store') {
templatePath = path.join(templatePath, 'store', storeProvider)
} else {
templatePath = path.join(templatePath, type + (asset.ext || ''))
}

fse.copy(
appPaths.resolve.cli(path.join('templates/app', format, type + (asset.ext || ''))),
appPaths.resolve.cli(templatePath),
file,
err => {
if (err) {
Expand Down Expand Up @@ -198,10 +209,15 @@ const filesToCreate = getPaths(asset, names)
if (asset.install) {
const folder = appPaths.resolve.app(asset.folder)

if (getPackageJson(storeProvider) === void 0) {
// TODO: Automatically install the package for the user
warn(`Don't forget to install "${storeProvider}" package.`)
}

if (!fs.existsSync(folder)) {
fse.mkdirp(folder)
fse.copy(
appPaths.resolve.cli(`templates/store/${format}`),
appPaths.resolve.cli(`templates/store/${storeProvider}/${format}`),
folder,
err => {
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion app-vite/lib/helpers/types-feature-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = function regenerateTypesFeatureFlags(quasarConf) {
const [isFeatureInstalled, sourceFlagPath, destFlagPath] = feature === 'store'
? [
quasarConf.store,
appPaths.resolve.cli('templates/store/ts/store-flag.d.ts'),
appPaths.resolve.cli('templates/store/store-flag.d.ts'),
appPaths.resolve.app(getStoreFlagPath(quasarConf.sourceFiles.store))
]
: [
Expand Down
2 changes: 1 addition & 1 deletion app-vite/lib/quasar-config-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ class QuasarConfFile {
return { error: 'Files validation not passed successfully' }
}

// do we have vuex?
// do we have a store?
const storePath = appPaths.resolve.app(cfg.sourceFiles.store)
cfg.store = resolveExtension(storePath) !== void 0

Expand Down
1 change: 1 addition & 0 deletions app-vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"devDependencies": {
"electron-builder": "22.14.13",
"electron-packager": "^15.3.0",
"pinia": "^2.0.0",
"quasar": "^2.0.4",
"ts-essentials": "^9.1.2",
"vue": "^3.0.0",
Expand Down
15 changes: 15 additions & 0 deletions app-vite/templates/app/default/store/pinia/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++;
},
},
});
15 changes: 15 additions & 0 deletions app-vite/templates/app/ts/store/pinia/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++;
},
},
});
2 changes: 1 addition & 1 deletion app-vite/templates/entry/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default async function (createAppFn, quasarUserOptions<%= ctx.mode.ssr ?
? await createStore({<%= ctx.mode.ssr ? 'ssrContext' : '' %>})
: createStore

// obtain Vuex injection key in case we use TypeScript
// obtain Vuex injection key in case we use TypeScript, not used for Pinia
const { storeKey } = await import('app/<%= sourceFiles.store %>');
<% } %>
const router = typeof createRouter === 'function'
Expand Down
20 changes: 20 additions & 0 deletions app-vite/templates/store/pinia/default/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'

/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/

export default store((/* { ssrContext } */) => {
const pinia = createPinia()

// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)

return pinia
})
20 changes: 20 additions & 0 deletions app-vite/templates/store/pinia/ts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'

/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/

export default store((/* { ssrContext } */) => {
const pinia = createPinia()

// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)

return pinia
})
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ export default store(function (/* { ssrContext } */) {

export function useStore() {
return vuexUseStore(storeKey)
}
}
11 changes: 8 additions & 3 deletions app-vite/types/store.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import { HasStore } from "quasar";
import { Pinia } from "pinia";
import { Store } from "vuex";
import { HasSsrParam } from "./ssr";

// If Pinia is installed, its type will be resolved, thus it will be used.
// Otherwise, if Vuex is installed, it will be used. If nothing is installed, 'any' will be used.
type StoreInstance<S = any> = unknown extends Pinia ? Store<S> : Pinia;

export type HasStoreParam<S = any> = HasStore<{
/**
* The state of the Vuex store, gets filled in by Vuex itself
* The store instance.
*/
store: Store<S>;
store: StoreInstance<S>;
}>;

export type StoreParams = {} & HasSsrParam;

export type StoreCallback = (
params: StoreParams
) => Store<any> | Promise<Store<any>>;
) => StoreInstance | Promise<StoreInstance>;
1 change: 1 addition & 0 deletions app-webpack/bin/quasar-info
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ print({ key: 'Important local packages', section: true })
'eslint-plugin-quasar',
'vue',
'vue-router',
'pinia',
'vuex',
'electron',
'electron-packager',
Expand Down
20 changes: 18 additions & 2 deletions app-webpack/bin/quasar-new
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const fse = require('fs-extra')

const { log, warn } = require('../lib/helpers/logger')
const appPaths = require('../lib/app-paths')
const getPackageJson = require('../lib/helpers/get-package-json')
const defaultFilePath = 'default'

if (argv._.length < 2) {
Expand Down Expand Up @@ -114,6 +115,8 @@ if (type.length === 1) {
type = fullCmd[type]
}

const storeProvider = getPackageJson('vuex') !== void 0 ? 'vuex' : 'pinia'

function getPaths (asset, names) {
return names.map(name => {
const hasExtension = !asset.ext || (asset.ext && name.endsWith(asset.ext))
Expand All @@ -133,8 +136,16 @@ function createFile (asset, file) {
}

fse.mkdirp(path.dirname(file))
let templatePath = path.join('templates/app', format)

if (type === 'store') {
templatePath = path.join(templatePath, 'store', storeProvider)
} else {
templatePath = path.join(templatePath, type + (asset.ext || ''))
}

fse.copy(
appPaths.resolve.cli(path.join('templates/app', format, type + (asset.ext || ''))),
appPaths.resolve.cli(templatePath),
file,
err => {
if (err) {
Expand Down Expand Up @@ -198,10 +209,15 @@ const filesToCreate = getPaths(asset, names)
if (asset.install) {
const folder = appPaths.resolve.app(asset.folder)

if (getPackageJson(storeProvider) === void 0) {
// TODO: Automatically install the package for the user
warn(`Don't forget to install "${storeProvider}" package.`)
}

if (!fs.existsSync(folder)) {
fse.mkdirp(folder)
fse.copy(
appPaths.resolve.cli(`templates/store/${format}`),
appPaths.resolve.cli(`templates/store/${storeProvider}/${format}`),
folder,
err => {
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion app-webpack/lib/helpers/types-feature-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = function regenerateTypesFeatureFlags(quasarConf) {
const [isFeatureInstalled, sourceFlagPath, destFlagPath] = feature === 'store'
? [
quasarConf.store,
appPaths.resolve.cli('templates/store/ts/store-flag.d.ts'),
appPaths.resolve.cli('templates/store/store-flag.d.ts'),
appPaths.resolve.app(getStoreFlagPath(quasarConf.sourceFiles.store))
]
: [
Expand Down
2 changes: 1 addition & 1 deletion app-webpack/lib/quasar-conf-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ class QuasarConfFile {

appFilesValidations(cfg)

// do we got vuex?
// do we have a store?
const storePath = appPaths.resolve.app(cfg.sourceFiles.store)
cfg.store = (
fs.existsSync(storePath) ||
Expand Down
2 changes: 1 addition & 1 deletion app-webpack/lib/webpack/create-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ module.exports = function (cfg, configName) {
.merge(resolveModules)

chain.module.noParse(
/^(vue|vue-router|vuex|vuex-router-sync|@quasar[\\/]extras|quasar[\\/]dist)$/
/^(vue|vue-router|pinia|vuex|vuex-router-sync|@quasar[\\/]extras|quasar[\\/]dist)$/
)

const vueRule = chain.module.rule('vue')
Expand Down
1 change: 1 addition & 0 deletions app-webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"devDependencies": {
"electron-builder": "22.14.13",
"electron-packager": "^15.3.0",
"pinia": "^2.0.0",
"quasar": "^2.0.4",
"ts-essentials": "^9.1.2",
"vue": "^3.0.0",
Expand Down
15 changes: 15 additions & 0 deletions app-webpack/templates/app/default/store/pinia/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++;
},
},
});
15 changes: 15 additions & 0 deletions app-webpack/templates/app/ts/store/pinia/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.counter++;
},
},
});
2 changes: 1 addition & 1 deletion app-webpack/templates/entry/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default async function (createAppFn, quasarUserOptions<%= ctx.mode.ssr ?
? await createStore({<%= ctx.mode.ssr ? 'ssrContext' : '' %>})
: createStore

// obtain Vuex injection key in case we use TypeScript
// obtain Vuex injection key in case we use TypeScript, not used for Pinia
const { storeKey } = await import('app/<%= sourceFiles.store %>');
<% } %>
const router = typeof createRouter === 'function'
Expand Down
10 changes: 0 additions & 10 deletions app-webpack/templates/store/default/store-flag.d.ts

This file was deleted.

20 changes: 20 additions & 0 deletions app-webpack/templates/store/pinia/default/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'

/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/

export default store((/* { ssrContext } */) => {
const pinia = createPinia()

// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)

return pinia
})
20 changes: 20 additions & 0 deletions app-webpack/templates/store/pinia/ts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'

/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/

export default store((/* { ssrContext } */) => {
const pinia = createPinia()

// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)

return pinia
})
Loading