@stonecrop/nuxt 0.7.3 → 0.7.5
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/README.md +105 -1
- package/bin/init.mjs +104 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +84 -5
- package/package.json +25 -10
- package/src/cli/detect.ts +125 -0
- package/src/cli/index.ts +184 -0
- package/src/cli/installers/casl.ts +51 -0
- package/src/cli/installers/doctypes.ts +206 -0
- package/src/cli/installers/frontend.ts +68 -0
- package/src/cli/installers/grafserv.ts +308 -0
- package/src/cli/installers/graphql-client.ts +36 -0
- package/src/cli/installers/index.ts +10 -0
- package/src/cli/installers/rockfoil.ts +51 -0
- package/src/cli/prompts.ts +204 -0
- package/src/cli/utils/config.ts +260 -0
- package/src/cli/utils/index.ts +15 -0
- package/src/cli/utils/package.ts +128 -0
- package/src/cli/utils/plugin.ts +107 -0
- package/templates/Example.json +85 -0
- package/templates/example-table.json +60 -0
- package/templates/plugins.ts +81 -0
- package/templates/resolvers.ts +256 -0
- package/templates/schema.graphql +129 -0
package/README.md
CHANGED
|
@@ -28,7 +28,39 @@ Stonecrop is a **schema-driven UI framework** that generates forms, tables, and
|
|
|
28
28
|
|
|
29
29
|
## Quick Setup
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
### Option 1: Interactive Installer (Recommended)
|
|
32
|
+
|
|
33
|
+
Use the Stonecrop CLI to interactively install features:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx @stonecrop/nuxt init
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This will prompt you to select which features to install:
|
|
40
|
+
- **@stonecrop/nuxt** - Frontend module with schema-driven UI
|
|
41
|
+
- **@stonecrop/graphql-client** - GraphQL client with Stonecrop integration
|
|
42
|
+
- **@stonecrop/nuxt-grafserv** - GraphQL server with Grafserv
|
|
43
|
+
- **@stonecrop/casl-middleware** - CASL authorization
|
|
44
|
+
- **@stonecrop/rockfoil** - PostGraphile middleware for database-driven GraphQL
|
|
45
|
+
- **Sample doctypes** - Example doctype files to get started
|
|
46
|
+
|
|
47
|
+
You can also use flags for non-interactive installation:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install everything
|
|
51
|
+
npx @stonecrop/nuxt init --frontend --graphql-client --graphql --casl --rockfoil --doctypes --yes
|
|
52
|
+
|
|
53
|
+
# Install just the frontend module
|
|
54
|
+
npx @stonecrop/nuxt init --frontend
|
|
55
|
+
|
|
56
|
+
# Add GraphQL server to existing setup
|
|
57
|
+
npx @stonecrop/nuxt init --graphql
|
|
58
|
+
|
|
59
|
+
# Add PostGraphile middleware
|
|
60
|
+
npx @stonecrop/nuxt init --rockfoil
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Option 2: Manual Installation
|
|
32
64
|
|
|
33
65
|
```bash
|
|
34
66
|
npx nuxi module add @stonecrop/nuxt
|
|
@@ -297,6 +329,78 @@ npm run test
|
|
|
297
329
|
npm run test:watch
|
|
298
330
|
```
|
|
299
331
|
|
|
332
|
+
### Testing the CLI Locally
|
|
333
|
+
|
|
334
|
+
To test the `npx @stonecrop/nuxt init` command from another directory outside this project:
|
|
335
|
+
|
|
336
|
+
**1. Build the monorepo (from stonecrop root):**
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
cd /path/to/stonecrop
|
|
340
|
+
rush update
|
|
341
|
+
rush build
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
**2. Create a test Nuxt project (in a separate directory):**
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
cd /tmp # or any directory outside stonecrop
|
|
348
|
+
npx nuxi init my-test-app
|
|
349
|
+
cd my-test-app
|
|
350
|
+
npm install
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**3. Run the CLI using the local package:**
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
# Option A: Run from within the nuxt package directory (simplest)
|
|
357
|
+
# This ensures Node can find the dependencies
|
|
358
|
+
cd /path/to/stonecrop/nuxt
|
|
359
|
+
node bin/init.mjs init --cwd /tmp/my-test-app
|
|
360
|
+
|
|
361
|
+
# Option B: Use pnpm link (from the test project)
|
|
362
|
+
cd /path/to/stonecrop/nuxt
|
|
363
|
+
pnpm link --global
|
|
364
|
+
cd /tmp/my-test-app
|
|
365
|
+
pnpm link --global @stonecrop/nuxt
|
|
366
|
+
npx stonecrop-nuxt init
|
|
367
|
+
|
|
368
|
+
# Option C: Use npm pack to create a tarball (simulates real npm install)
|
|
369
|
+
cd /path/to/stonecrop/nuxt
|
|
370
|
+
npm pack
|
|
371
|
+
cd /tmp/my-test-app
|
|
372
|
+
npm install /path/to/stonecrop/nuxt/stonecrop-nuxt-0.6.3.tgz
|
|
373
|
+
npx stonecrop-nuxt init
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
> **Note:** Option A uses `--cwd` to specify the target directory while running from within
|
|
377
|
+
> the nuxt package where dependencies are available. Options B and C install the package
|
|
378
|
+
> into the test project so dependencies are resolved correctly.
|
|
379
|
+
|
|
380
|
+
**4. Interactive testing:**
|
|
381
|
+
|
|
382
|
+
The CLI will detect that you're in a Nuxt project and prompt for features:
|
|
383
|
+
|
|
384
|
+
```
|
|
385
|
+
🌱 Stonecrop Nuxt Installer
|
|
386
|
+
|
|
387
|
+
✔ Nuxt project detected
|
|
388
|
+
|
|
389
|
+
? Select features to install
|
|
390
|
+
◉ @stonecrop/nuxt - Frontend module
|
|
391
|
+
◯ @stonecrop/nuxt-grafserv - GraphQL server
|
|
392
|
+
◯ @stonecrop/casl-middleware - Authorization
|
|
393
|
+
◉ Sample doctypes
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**5. Verify the installation:**
|
|
397
|
+
|
|
398
|
+
After running the installer, check:
|
|
399
|
+
- `package.json` has the new dependencies
|
|
400
|
+
- `nuxt.config.ts` has the module configuration
|
|
401
|
+
- `doctypes/` folder contains sample schemas (if selected)
|
|
402
|
+
- `server/` folder contains GraphQL files (if selected)
|
|
403
|
+
|
|
300
404
|
<!-- Badges -->
|
|
301
405
|
[npm-version-src]: https://img.shields.io/npm/v/@stonecrop/nuxt/latest.svg?style=flat&colorA=020420&colorB=00DC82
|
|
302
406
|
[npm-version-href]: https://npmjs.com/package/@stonecrop/nuxt
|
package/bin/init.mjs
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @stonecrop/nuxt CLI entry point
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx @stonecrop/nuxt init # Interactive mode
|
|
7
|
+
* npx @stonecrop/nuxt init --help # Show help
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { defineCommand, runMain } from 'citty'
|
|
11
|
+
import consola from 'consola'
|
|
12
|
+
import { createJiti } from 'jiti'
|
|
13
|
+
import { fileURLToPath } from 'node:url'
|
|
14
|
+
import { dirname, join } from 'node:path'
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
17
|
+
|
|
18
|
+
// Use jiti to load TypeScript CLI code
|
|
19
|
+
const jiti = createJiti(import.meta.url, {
|
|
20
|
+
interopDefault: true,
|
|
21
|
+
esmResolve: true,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const { runInstaller } = await jiti.import(join(__dirname, '..', 'src', 'cli', 'index.ts'))
|
|
25
|
+
|
|
26
|
+
const main = defineCommand({
|
|
27
|
+
meta: {
|
|
28
|
+
name: 'stonecrop-nuxt',
|
|
29
|
+
version: '0.6.3',
|
|
30
|
+
description: 'Install Stonecrop modules into your Nuxt project',
|
|
31
|
+
},
|
|
32
|
+
subCommands: {
|
|
33
|
+
init: defineCommand({
|
|
34
|
+
meta: {
|
|
35
|
+
name: 'init',
|
|
36
|
+
description: 'Initialize Stonecrop in your Nuxt project',
|
|
37
|
+
},
|
|
38
|
+
args: {
|
|
39
|
+
frontend: {
|
|
40
|
+
type: 'boolean',
|
|
41
|
+
description: 'Install @stonecrop/nuxt frontend module',
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
'graphql-client': {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
description: 'Install @stonecrop/graphql-client',
|
|
47
|
+
default: false,
|
|
48
|
+
},
|
|
49
|
+
graphql: {
|
|
50
|
+
type: 'boolean',
|
|
51
|
+
description: 'Install @stonecrop/nuxt-grafserv GraphQL server',
|
|
52
|
+
default: false,
|
|
53
|
+
},
|
|
54
|
+
casl: {
|
|
55
|
+
type: 'boolean',
|
|
56
|
+
description: 'Install @stonecrop/casl-middleware authorization',
|
|
57
|
+
default: false,
|
|
58
|
+
},
|
|
59
|
+
rockfoil: {
|
|
60
|
+
type: 'boolean',
|
|
61
|
+
description: 'Install @stonecrop/rockfoil PostGraphile middleware',
|
|
62
|
+
default: false,
|
|
63
|
+
},
|
|
64
|
+
doctypes: {
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
description: 'Scaffold sample doctypes',
|
|
67
|
+
default: false,
|
|
68
|
+
},
|
|
69
|
+
cwd: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'Working directory (defaults to current directory)',
|
|
72
|
+
default: process.cwd(),
|
|
73
|
+
},
|
|
74
|
+
yes: {
|
|
75
|
+
type: 'boolean',
|
|
76
|
+
alias: 'y',
|
|
77
|
+
description: 'Skip confirmation prompts',
|
|
78
|
+
default: false,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
async run({ args }) {
|
|
82
|
+
try {
|
|
83
|
+
await runInstaller({
|
|
84
|
+
cwd: args.cwd,
|
|
85
|
+
features: {
|
|
86
|
+
frontend: args.frontend,
|
|
87
|
+
graphqlClient: args['graphql-client'],
|
|
88
|
+
graphql: args.graphql,
|
|
89
|
+
casl: args.casl,
|
|
90
|
+
rockfoil: args.rockfoil,
|
|
91
|
+
doctypes: args.doctypes,
|
|
92
|
+
},
|
|
93
|
+
skipConfirm: args.yes,
|
|
94
|
+
})
|
|
95
|
+
} catch (error) {
|
|
96
|
+
consola.error('Installation failed:', error)
|
|
97
|
+
process.exit(1)
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
runMain(main)
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,9 +1,63 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
1
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
2
2
|
import { readdir, readFile } from 'node:fs/promises';
|
|
3
|
-
import { extname } from 'node:path';
|
|
4
|
-
import { createResolver, defineNuxtModule, useLogger, addLayout, extendPages, addServerHandler, addPlugin } from '@nuxt/kit';
|
|
3
|
+
import { dirname, extname } from 'node:path';
|
|
4
|
+
import { createResolver, defineNuxtModule, useLogger, addVitePlugin, addLayout, extendPages, addServerHandler, addPlugin } from '@nuxt/kit';
|
|
5
|
+
|
|
6
|
+
function createSymlinkedPackagesPlugin(options) {
|
|
7
|
+
const { rootDir, packages, logger } = options;
|
|
8
|
+
return {
|
|
9
|
+
name: "stonecrop-symlinked-packages",
|
|
10
|
+
config() {
|
|
11
|
+
const allowPaths = /* @__PURE__ */ new Set();
|
|
12
|
+
const nuxtModulePath = `${rootDir}/node_modules/@stonecrop/nuxt`;
|
|
13
|
+
try {
|
|
14
|
+
if (existsSync(nuxtModulePath)) {
|
|
15
|
+
const realNuxtModulePath = realpathSync(nuxtModulePath);
|
|
16
|
+
if (realNuxtModulePath !== nuxtModulePath) {
|
|
17
|
+
const monorepoRoot = dirname(realNuxtModulePath);
|
|
18
|
+
allowPaths.add(monorepoRoot);
|
|
19
|
+
logger?.(`@stonecrop/nuxt is symlinked, adding monorepo root: ${monorepoRoot}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
logger?.(`Error checking @stonecrop/nuxt symlink: ${e instanceof Error ? e.message : String(e)}`);
|
|
24
|
+
}
|
|
25
|
+
for (const pkg of packages) {
|
|
26
|
+
const pkgPath = `${rootDir}/node_modules/${pkg}`;
|
|
27
|
+
try {
|
|
28
|
+
if (existsSync(pkgPath)) {
|
|
29
|
+
const realPath = realpathSync(pkgPath);
|
|
30
|
+
if (realPath !== pkgPath) {
|
|
31
|
+
allowPaths.add(realPath);
|
|
32
|
+
logger?.(`Adding symlinked package to fs.allow: ${realPath}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (allowPaths.size > 0) {
|
|
39
|
+
logger?.(`Vite fs.allow updated with ${allowPaths.size} path(s)`);
|
|
40
|
+
return {
|
|
41
|
+
server: {
|
|
42
|
+
fs: {
|
|
43
|
+
allow: [...allowPaths]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
5
51
|
|
|
6
52
|
const { resolve } = createResolver(import.meta.url);
|
|
53
|
+
const STONECROP_PACKAGES = [
|
|
54
|
+
"@stonecrop/aform",
|
|
55
|
+
"@stonecrop/atable",
|
|
56
|
+
"@stonecrop/stonecrop",
|
|
57
|
+
"@stonecrop/node-editor",
|
|
58
|
+
"@stonecrop/utilities",
|
|
59
|
+
"@stonecrop/themes"
|
|
60
|
+
];
|
|
7
61
|
const module$1 = defineNuxtModule({
|
|
8
62
|
meta: {
|
|
9
63
|
name: "@stonecrop/nuxt",
|
|
@@ -16,8 +70,33 @@ const module$1 = defineNuxtModule({
|
|
|
16
70
|
doctypesDir: void 0
|
|
17
71
|
};
|
|
18
72
|
},
|
|
19
|
-
async setup(
|
|
73
|
+
async setup(options, nuxt) {
|
|
20
74
|
const logger = useLogger("@stonecrop/nuxt", { level: nuxt.options.dev ? 3 : 0 });
|
|
75
|
+
nuxt.options.build.transpile = nuxt.options.build.transpile || [];
|
|
76
|
+
for (const pkg of STONECROP_PACKAGES) {
|
|
77
|
+
if (!nuxt.options.build.transpile.includes(pkg)) {
|
|
78
|
+
nuxt.options.build.transpile.push(pkg);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
logger.log("Added Stonecrop packages to build.transpile for SSR CSS handling");
|
|
82
|
+
nuxt.hook("nitro:config", (config) => {
|
|
83
|
+
config.externals = config.externals || {};
|
|
84
|
+
config.externals.inline = config.externals.inline || [];
|
|
85
|
+
for (const pkg of STONECROP_PACKAGES) {
|
|
86
|
+
if (!config.externals.inline.includes(pkg)) {
|
|
87
|
+
config.externals.inline.push(pkg);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
logger.log("Added Stonecrop packages to Nitro externals.inline for CSS bundling");
|
|
91
|
+
});
|
|
92
|
+
if (nuxt.options.dev) {
|
|
93
|
+
const symlinkedPackagesPlugin = createSymlinkedPackagesPlugin({
|
|
94
|
+
rootDir: nuxt.options.rootDir,
|
|
95
|
+
packages: STONECROP_PACKAGES,
|
|
96
|
+
logger: (msg) => logger.log(msg)
|
|
97
|
+
});
|
|
98
|
+
addVitePlugin(symlinkedPackagesPlugin);
|
|
99
|
+
}
|
|
21
100
|
const layoutsDir = resolve("runtime/layouts");
|
|
22
101
|
const homepage = resolve(layoutsDir, "StonecropHome.vue");
|
|
23
102
|
addLayout(homepage, "home");
|
|
@@ -94,7 +173,7 @@ const module$1 = defineNuxtModule({
|
|
|
94
173
|
}
|
|
95
174
|
}
|
|
96
175
|
}
|
|
97
|
-
if (
|
|
176
|
+
if (options.docbuilder) {
|
|
98
177
|
logger.log("DocBuilder enabled, adding routes and handlers");
|
|
99
178
|
const pagesDir = resolve("runtime/pages");
|
|
100
179
|
const docBuilderIndex = resolve(pagesDir, "DocBuilderIndex.vue");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/nuxt",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Nuxt module for Stonecrop",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
"url": "https://github.com/agritheory/stonecrop",
|
|
14
14
|
"directory": "nuxt"
|
|
15
15
|
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"stonecrop-nuxt": "./bin/init.mjs"
|
|
18
|
+
},
|
|
16
19
|
"exports": {
|
|
17
20
|
".": {
|
|
18
21
|
"types": "./dist/types.d.mts",
|
|
@@ -28,19 +31,27 @@
|
|
|
28
31
|
}
|
|
29
32
|
},
|
|
30
33
|
"files": [
|
|
31
|
-
"dist"
|
|
34
|
+
"dist",
|
|
35
|
+
"bin",
|
|
36
|
+
"templates",
|
|
37
|
+
"src/cli"
|
|
32
38
|
],
|
|
33
39
|
"dependencies": {
|
|
34
40
|
"@nuxt/kit": "^4.2.2",
|
|
35
41
|
"pinia": "^3.0.4",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"@stonecrop/
|
|
42
|
-
"@stonecrop/
|
|
43
|
-
"@stonecrop/
|
|
42
|
+
"citty": "^0.1.6",
|
|
43
|
+
"consola": "^3.4.0",
|
|
44
|
+
"jiti": "^2.4.2",
|
|
45
|
+
"pathe": "^2.0.3",
|
|
46
|
+
"prompts": "^2.4.2",
|
|
47
|
+
"@stonecrop/aform": "0.7.5",
|
|
48
|
+
"@stonecrop/atable": "0.7.5",
|
|
49
|
+
"@stonecrop/graphql-middleware": "0.7.5",
|
|
50
|
+
"@stonecrop/casl-middleware": "0.7.5",
|
|
51
|
+
"@stonecrop/node-editor": "0.7.5",
|
|
52
|
+
"@stonecrop/schema": "0.7.5",
|
|
53
|
+
"@stonecrop/nuxt-grafserv": "0.7.5",
|
|
54
|
+
"@stonecrop/stonecrop": "0.7.5"
|
|
44
55
|
},
|
|
45
56
|
"devDependencies": {
|
|
46
57
|
"@eslint/js": "^9.39.2",
|
|
@@ -50,6 +61,8 @@
|
|
|
50
61
|
"@nuxt/module-builder": "^1.0.2",
|
|
51
62
|
"@nuxt/schema": "^4.2.2",
|
|
52
63
|
"@nuxt/test-utils": "^3.23.0",
|
|
64
|
+
"@vitest/coverage-istanbul": "^4.0.17",
|
|
65
|
+
"@types/prompts": "^2.4.9",
|
|
53
66
|
"browserslist": "latest",
|
|
54
67
|
"baseline-browser-mapping": "latest",
|
|
55
68
|
"eslint": "^9.39.2",
|
|
@@ -57,6 +70,7 @@
|
|
|
57
70
|
"eslint-plugin-vue": "^10.6.2",
|
|
58
71
|
"globals": "^17.0.0",
|
|
59
72
|
"nuxt": "^4.2.2",
|
|
73
|
+
"postgraphile": "^5.0.0-rc.4",
|
|
60
74
|
"typescript": "^5.9.3",
|
|
61
75
|
"typescript-eslint": "^8.53.0",
|
|
62
76
|
"vue": "^3.5.26",
|
|
@@ -82,6 +96,7 @@
|
|
|
82
96
|
"lint": "eslint .",
|
|
83
97
|
"test": "vitest run",
|
|
84
98
|
"test:ui": "vitest --ui",
|
|
99
|
+
"test:coverage": "vitest run --coverage",
|
|
85
100
|
"test:watch": "vitest watch",
|
|
86
101
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
87
102
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection utilities for existing Stonecrop setup
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync } from 'node:fs'
|
|
6
|
+
import { join } from 'pathe'
|
|
7
|
+
import { hasModule, findNuxtConfig } from './utils/config'
|
|
8
|
+
import { hasPackage, readPackageJson } from './utils/package'
|
|
9
|
+
|
|
10
|
+
export interface DetectedFeatures {
|
|
11
|
+
/** Is this a valid Nuxt project? */
|
|
12
|
+
isNuxtProject: boolean
|
|
13
|
+
/** Is @stonecrop/nuxt installed? */
|
|
14
|
+
hasFrontend: boolean
|
|
15
|
+
/** Is @stonecrop/nuxt-grafserv installed? */
|
|
16
|
+
hasGraphql: boolean
|
|
17
|
+
/** Is @stonecrop/graphql-client installed? */
|
|
18
|
+
hasGraphqlClient: boolean
|
|
19
|
+
/** Is @stonecrop/casl-middleware installed? */
|
|
20
|
+
hasCasl: boolean
|
|
21
|
+
/** Is @stonecrop/rockfoil installed? */
|
|
22
|
+
hasRockfoil: boolean
|
|
23
|
+
/** Does the doctypes directory exist? */
|
|
24
|
+
hasDoctypes: boolean
|
|
25
|
+
/** Does the server directory exist? */
|
|
26
|
+
hasServerDir: boolean
|
|
27
|
+
/** Does server/schema.graphql exist? */
|
|
28
|
+
hasSchema: boolean
|
|
29
|
+
/** Does server/resolvers.ts exist? */
|
|
30
|
+
hasResolvers: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Detect what Stonecrop features are already installed in the project
|
|
35
|
+
*/
|
|
36
|
+
export async function detectFeatures(cwd: string): Promise<DetectedFeatures> {
|
|
37
|
+
const result: DetectedFeatures = {
|
|
38
|
+
isNuxtProject: false,
|
|
39
|
+
hasFrontend: false,
|
|
40
|
+
hasGraphql: false,
|
|
41
|
+
hasGraphqlClient: false,
|
|
42
|
+
hasCasl: false,
|
|
43
|
+
hasRockfoil: false,
|
|
44
|
+
hasDoctypes: false,
|
|
45
|
+
hasServerDir: false,
|
|
46
|
+
hasSchema: false,
|
|
47
|
+
hasResolvers: false,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check if this is a Nuxt project
|
|
51
|
+
const nuxtConfig = findNuxtConfig(cwd)
|
|
52
|
+
const pkg = await readPackageJson(cwd)
|
|
53
|
+
|
|
54
|
+
if (!nuxtConfig || !pkg) {
|
|
55
|
+
return result
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check for Nuxt in dependencies
|
|
59
|
+
const hasNuxt = !!(pkg.dependencies?.nuxt || pkg.devDependencies?.nuxt)
|
|
60
|
+
result.isNuxtProject = hasNuxt
|
|
61
|
+
|
|
62
|
+
if (!hasNuxt) {
|
|
63
|
+
return result
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check for installed packages
|
|
67
|
+
result.hasFrontend = await hasPackage(cwd, '@stonecrop/nuxt')
|
|
68
|
+
result.hasGraphql = await hasPackage(cwd, '@stonecrop/nuxt-grafserv')
|
|
69
|
+
result.hasGraphqlClient = await hasPackage(cwd, '@stonecrop/graphql-client')
|
|
70
|
+
result.hasCasl = await hasPackage(cwd, '@stonecrop/casl-middleware')
|
|
71
|
+
result.hasRockfoil = await hasPackage(cwd, '@stonecrop/rockfoil')
|
|
72
|
+
|
|
73
|
+
// Also check nuxt.config for module registration
|
|
74
|
+
if (!result.hasFrontend) {
|
|
75
|
+
result.hasFrontend = await hasModule(cwd, '@stonecrop/nuxt')
|
|
76
|
+
}
|
|
77
|
+
if (!result.hasGraphql) {
|
|
78
|
+
result.hasGraphql = await hasModule(cwd, '@stonecrop/nuxt-grafserv')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Check for directories and files
|
|
82
|
+
result.hasDoctypes = existsSync(join(cwd, 'doctypes'))
|
|
83
|
+
result.hasServerDir = existsSync(join(cwd, 'server'))
|
|
84
|
+
result.hasSchema = existsSync(join(cwd, 'server', 'schema.graphql'))
|
|
85
|
+
result.hasResolvers =
|
|
86
|
+
existsSync(join(cwd, 'server', 'resolvers.ts')) || existsSync(join(cwd, 'server', 'resolvers.js'))
|
|
87
|
+
|
|
88
|
+
return result
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Check if the current directory is a valid Nuxt project
|
|
93
|
+
*/
|
|
94
|
+
export async function isNuxtProject(cwd: string): Promise<boolean> {
|
|
95
|
+
const features = await detectFeatures(cwd)
|
|
96
|
+
return features.isNuxtProject
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get a summary of what's already installed
|
|
101
|
+
*/
|
|
102
|
+
export function getInstalledSummary(features: DetectedFeatures): string[] {
|
|
103
|
+
const installed: string[] = []
|
|
104
|
+
|
|
105
|
+
if (features.hasFrontend) {
|
|
106
|
+
installed.push('@stonecrop/nuxt (frontend module)')
|
|
107
|
+
}
|
|
108
|
+
if (features.hasGraphqlClient) {
|
|
109
|
+
installed.push('@stonecrop/graphql-client (GraphQL client)')
|
|
110
|
+
}
|
|
111
|
+
if (features.hasGraphql) {
|
|
112
|
+
installed.push('@stonecrop/nuxt-grafserv (GraphQL server)')
|
|
113
|
+
}
|
|
114
|
+
if (features.hasCasl) {
|
|
115
|
+
installed.push('@stonecrop/casl-middleware (authorization)')
|
|
116
|
+
}
|
|
117
|
+
if (features.hasRockfoil) {
|
|
118
|
+
installed.push('@stonecrop/rockfoil (PostGraphile middleware)')
|
|
119
|
+
}
|
|
120
|
+
if (features.hasDoctypes) {
|
|
121
|
+
installed.push('doctypes/ directory')
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return installed
|
|
125
|
+
}
|