Skip to content
This repository was archived by the owner on Dec 10, 2024. It is now read-only.

Commit 84a2008

Browse files
feat: pergel core (#54)
* feat: add checkOptions function to module setup * feat: pergelSetup * feat: pergel modules * update README.md with TODO list
1 parent 7b4f26d commit 84a2008

15 files changed

+638
-99
lines changed

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default antfu(
2727
'n/prefer-global/process': 'off',
2828
'node/prefer-global/process': 'off',
2929
'ts/consistent-type-definitions': 'off',
30+
'ts/ban-ts-comment': 'off',
3031
},
3132
},
3233
{

packages/nuxt/.eslintignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/nuxt/.eslintrc

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/nuxt/README.md

Lines changed: 4 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,6 @@
1-
<!--
2-
Get your module up and running quickly.
1+
## Pergel Nuxt Module
32

4-
Find and replace all on all files (CMD+SHIFT+F):
5-
- Name: My Module
6-
- Package name: my-module
7-
- Description: My new Nuxt module
8-
-->
3+
# TODO
94

10-
# My Module
11-
12-
[![npm version][npm-version-src]][npm-version-href]
13-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
14-
[![License][license-src]][license-href]
15-
[![Nuxt][nuxt-src]][nuxt-href]
16-
17-
My new Nuxt module for doing amazing things.
18-
19-
- [&nbsp;Release Notes](/CHANGELOG.md)
20-
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/my-module?file=playground%2Fapp.vue) -->
21-
<!-- - [📖 &nbsp;Documentation](https://example.com) -->
22-
23-
## Features
24-
25-
<!-- Highlight some of the features your module provide here -->
26-
-&nbsp;Foo
27-
- 🚠 &nbsp;Bar
28-
- 🌲 &nbsp;Baz
29-
30-
## Quick Setup
31-
32-
1. Add `my-module` dependency to your project
33-
34-
```bash
35-
# Using pnpm
36-
pnpm add -D my-module
37-
38-
# Using yarn
39-
yarn add --dev my-module
40-
41-
# Using npm
42-
npm install --save-dev my-module
43-
```
44-
45-
2. Add `my-module` to the `modules` section of `nuxt.config.ts`
46-
47-
```js
48-
export default defineNuxtConfig({
49-
modules: [
50-
'my-module'
51-
]
52-
})
53-
```
54-
55-
That's it! You can now use My Module in your Nuxt app ✨
56-
57-
## Development
58-
59-
```bash
60-
# Install dependencies
61-
npm install
62-
63-
# Generate type stubs
64-
npm run dev:prepare
65-
66-
# Develop with the playground
67-
npm run dev
68-
69-
# Build the playground
70-
npm run dev:build
71-
72-
# Run ESLint
73-
npm run lint
74-
75-
# Run Vitest
76-
npm run test
77-
npm run test:watch
78-
79-
# Release new version
80-
npm run release
81-
```
82-
83-
<!-- Badges -->
84-
[npm-version-src]: https://img.shields.io/npm/v/my-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
85-
[npm-version-href]: https://npmjs.com/package/my-module
86-
87-
[npm-downloads-src]: https://img.shields.io/npm/dm/my-module.svg?style=flat&colorA=18181B&colorB=28CF8D
88-
[npm-downloads-href]: https://npmjs.com/package/my-module
89-
90-
[license-src]: https://img.shields.io/npm/l/my-module.svg?style=flat&colorA=18181B&colorB=28CF8D
91-
[license-href]: https://npmjs.com/package/my-module
92-
93-
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
94-
[nuxt-href]: https://nuxt.com
5+
- [] Add tests
6+
- [] Add docs

packages/nuxt/build.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { defineBuildConfig } from 'unbuild'
33
import pkg from './package.json'
44

55
const external = [
6-
// eslint-disable-next-line ts/ban-ts-comment
6+
77
// @ts-expect-error
88
...Object.keys(pkg.peerDependencies || {}),
99
]
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { join } from 'node:path'
2+
import { readdirSync } from 'node:fs'
3+
import type { Nuxt } from '@nuxt/schema'
4+
import type { Resolver } from '@nuxt/kit'
5+
import consola from 'consola'
6+
import type { PergelModule, ResolvedPergelOptions } from './types'
7+
import { generatePergelTemplate } from './utils/pergelFunctionTemplate'
8+
9+
export async function setupModules(data: {
10+
resolver: Resolver
11+
nuxt: Nuxt
12+
options: ResolvedPergelOptions
13+
}) {
14+
const projects = data.options.rootOptions.projects
15+
const modulesMap = new Map<string, PergelModule<any>>()
16+
17+
for await (const [projectKey, modules] of Object.entries(projects)) {
18+
for await (const [moduleKey, moduleValue] of Object.entries(modules)) {
19+
if (typeof moduleValue === 'boolean' && moduleValue === false)
20+
continue
21+
22+
if (
23+
(typeof moduleValue === 'object' && moduleValue === null)
24+
|| (typeof moduleValue === 'object' && !moduleValue)
25+
)
26+
continue
27+
28+
if (typeof moduleValue === 'string' && moduleValue === '')
29+
continue
30+
modulesMap.set(`${projectKey}/${moduleKey}`, moduleValue as any)
31+
}
32+
}
33+
34+
const modulesArray = Array.from(modulesMap)
35+
36+
data.options._contents = []
37+
for await (const m of modulesArray) {
38+
const [projectname, moduleName] = m[0].split('/')
39+
40+
data.options.resolvedModule.name = moduleName
41+
data.options.resolvedModule.projectName = projectname
42+
43+
data.options.resolvedModule.projectDir = join(data.options.resolvedOptions.resolveDir.pergelRoot, projectname)
44+
data.options.resolvedModule.moduleDir = join(data.options.resolvedOptions.resolveDir.pergelRoot, projectname, moduleName)
45+
46+
data.options.resolvedModule.templateDir.project = join(data.options.resolvedOptions.dir.pergel, projectname)
47+
data.options.resolvedModule.templateDir.module = join(data.options.resolvedOptions.dir.pergel, projectname, moduleName)
48+
49+
data.options.resolvedModule.dir.project = join(data.options.resolvedOptions.dir.pergel, projectname)
50+
data.options.resolvedModule.dir.module = join(data.options.resolvedOptions.dir.pergel, projectname, moduleName)
51+
52+
const selectedModule = data.nuxt._pergel.modules.find(module => module === moduleName)
53+
if (Array.isArray(m) && selectedModule) {
54+
let pergelModule: PergelModule
55+
56+
try {
57+
const getIndexExt = () => {
58+
const datas = readdirSync(data.resolver.resolve(join('runtime/modules', moduleName)))
59+
const indexExt = datas.find(file => file.includes('index') && !file.includes('.d.'))
60+
if (!indexExt)
61+
throw new Error(`Module ${moduleName} does not have index file`)
62+
63+
return indexExt
64+
}
65+
const indexPath = getIndexExt()
66+
67+
pergelModule = await import(
68+
data.resolver.resolve(join('runtime/modules', moduleName, indexPath))
69+
).then(m => m.default).catch((res) => {
70+
consola.error(`Module ${moduleName} failed to import`)
71+
consola.error(res)
72+
})
73+
}
74+
catch (error) {
75+
consola.error(`Module ${moduleName} failed to import`)
76+
throw error
77+
}
78+
79+
// Throw error if input is not a function
80+
if (typeof pergelModule !== 'function')
81+
throw new TypeError(`Nuxt module should be a function: ${pergelModule}`)
82+
83+
const resolvedModule = await pergelModule(data.options, data.nuxt)
84+
85+
if (resolvedModule === false /* setup aborted */ || resolvedModule === undefined /* setup failed */ || typeof resolvedModule === 'string' /* setup failed */) {
86+
consola.error(`Module ${moduleName} failed to setup`)
87+
continue
88+
}
89+
}
90+
}
91+
92+
for (const item of data.options._contents) {
93+
if (!item.projectName || !item.moduleName) {
94+
throw new Error(`Project name or module name is missing in
95+
${JSON.stringify(item).replace(/"/g, '')}
96+
`)
97+
}
98+
}
99+
100+
generatePergelTemplate({
101+
nuxt: data.nuxt,
102+
options: data.options,
103+
})
104+
}

packages/nuxt/src/core/setupPergel.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { join, resolve } from 'node:path'
2+
import type { Nuxt } from '@nuxt/schema'
3+
import { addTemplate } from '@nuxt/kit'
4+
import defu from 'defu'
5+
import type { PergelOptions, ResolvedPergelOptions } from './types'
6+
import { rootFolderSync } from './utils/rootFolderSync'
7+
8+
export async function setupPergel(options: PergelOptions, nuxt: Nuxt) {
9+
const rootDir = options.rootDir ? options.rootDir : './'
10+
const pergelDir = join(rootDir, options.pergelDir ?? 'pergel')
11+
const readmePath = join(pergelDir, 'README.yaml')
12+
13+
const resolveDir = resolve(join(nuxt.options.rootDir, rootDir))
14+
const resolvePergelDir = resolve(join(nuxt.options.rootDir, pergelDir))
15+
const resolveReadmePath = resolve(join(nuxt.options.rootDir, readmePath))
16+
17+
const { projectNames } = rootFolderSync(resolvePergelDir, options)
18+
19+
const pergelType = addTemplate({
20+
filename: 'pergel/types.ts',
21+
write: true,
22+
getContents: () => {
23+
return /* TypeScript */ `
24+
export type ProjectName = ${projectNames.map((projectName) => {
25+
return `'${projectName}'`
26+
}).join(' | ')}
27+
export type Module = ${nuxt._pergel.modules.map((module) => { return `'${module}'` }).join(' | ')}
28+
29+
export type PergelGlobalContextOmitModule = Omit<PergelGlobalContext, 'moduleName'>
30+
31+
export interface PergelGlobalContext {
32+
projectName: ProjectName
33+
moduleName: Module
34+
}
35+
`.trim().replace(/ {10}/g, '')
36+
},
37+
})
38+
39+
nuxt.options.alias['#pergel'] = pergelType.dst
40+
nuxt.options.nitro.alias ??= {}
41+
nuxt.options.nitro.alias['#pergel'] = pergelType.dst
42+
43+
const resolvedOptions = defu(options, {
44+
projects: {
45+
},
46+
esnext: true,
47+
pergelDir,
48+
rootDir,
49+
} as PergelOptions)
50+
51+
const resolvedPergelOptions = defu({
52+
rootOptions: resolvedOptions,
53+
resolvedOptions: {
54+
projectNames,
55+
dir: {
56+
pergel: resolvedOptions.pergelDir ?? 'pergel',
57+
readme: join('pergel', 'README.yaml'),
58+
root: options.rootDir ?? './',
59+
},
60+
resolveDir: {
61+
root: resolveDir,
62+
pergelRoot: resolve(resolveDir, resolvedOptions.pergelDir ?? 'pergel'),
63+
readmeDir: resolve(resolveReadmePath),
64+
},
65+
templateDir: {
66+
root: 'pergel',
67+
},
68+
},
69+
resolvedModule: {
70+
dir: {
71+
project: '',
72+
module: '',
73+
},
74+
moduleDir: '',
75+
name: '',
76+
projectDir: '',
77+
projectName: '',
78+
templateDir: {
79+
module: '',
80+
project: '',
81+
root: 'pergel',
82+
},
83+
},
84+
} as ResolvedPergelOptions, {
85+
rootOptions: resolvedOptions,
86+
resolvedOptions: {
87+
projectNames,
88+
dir: {
89+
pergel: resolvedOptions.pergelDir ?? 'pergel',
90+
readme: join('pergel', 'README.yaml'),
91+
root: options.rootDir ?? './',
92+
},
93+
resolveDir: {
94+
readmeDir: resolve(resolveReadmePath),
95+
root: resolveDir,
96+
pergelRoot: resolve(resolveDir, resolvedOptions.pergelDir ?? 'pergel'),
97+
},
98+
templateDir: {
99+
root: 'pergel',
100+
},
101+
},
102+
resolvedModule: {
103+
104+
},
105+
} as ResolvedPergelOptions)
106+
107+
return {
108+
resolvedPergelOptions,
109+
}
110+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import consola from 'consola'
2+
import type { PergelOptions } from '../types'
3+
4+
export async function checkOptions(
5+
options: PergelOptions,
6+
) {
7+
let status = true
8+
9+
// project1, newProject, etc.
10+
const projectNames = Object.keys(options.projects)
11+
12+
if (projectNames.length === 0) {
13+
consola.error('No projects found in pergel config')
14+
status = false
15+
}
16+
17+
return {
18+
status,
19+
}
20+
}

0 commit comments

Comments
 (0)