@rivetjs/nx 0.0.0-stage → 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +63 -2
- package/executors/build/executor.d.ts +12 -0
- package/executors/build/executor.js +50 -0
- package/executors/build/schema.d.ts +18 -0
- package/executors/build/schema.json +18 -0
- package/executors/check/executor.d.ts +11 -0
- package/executors/check/executor.js +31 -0
- package/executors/check/schema.d.ts +12 -0
- package/executors/check/schema.json +18 -0
- package/executors/dev/executor.d.ts +14 -0
- package/executors/dev/executor.js +32 -0
- package/executors/dev/schema.d.ts +16 -0
- package/executors/dev/schema.json +17 -0
- package/executors/package/executor.d.ts +20 -0
- package/executors/package/executor.js +65 -0
- package/executors/package/schema.d.ts +10 -0
- package/executors/package/schema.json +18 -0
- package/executors/prerender/executor.d.ts +8 -0
- package/executors/prerender/executor.js +13 -0
- package/executors/prerender/schema.d.ts +6 -0
- package/executors/prerender/schema.json +12 -0
- package/executors/preview/executor.d.ts +12 -0
- package/executors/preview/executor.js +52 -0
- package/executors/preview/schema.d.ts +10 -0
- package/executors/preview/schema.json +14 -0
- package/executors/run.d.ts +33 -0
- package/executors/run.js +88 -0
- package/executors/test/executor.d.ts +8 -0
- package/executors/test/executor.js +27 -0
- package/executors/test/schema.d.ts +24 -0
- package/executors/test/schema.json +21 -0
- package/executors/typecheck/executor.d.ts +9 -0
- package/executors/typecheck/executor.js +14 -0
- package/executors/typecheck/schema.d.ts +6 -0
- package/executors/typecheck/schema.json +12 -0
- package/executors.json +49 -0
- package/generators/api-route/files/__fileName__.ts.template +11 -0
- package/generators/api-route/generator.d.ts +5 -0
- package/generators/api-route/generator.js +30 -0
- package/generators/api-route/schema.d.ts +9 -0
- package/generators/api-route/schema.json +31 -0
- package/generators/application/files/tests/minimal/src/routes/index.test.tsx.template +9 -0
- package/generators/application/files/tests/server/src/routes/index.server.test.tsx.template +8 -0
- package/generators/application/files/tests/static/src/components/Counter.test.tsx.template +10 -0
- package/generators/application/files/tests/ui/src/components/LikeButton.server.test.tsx.template +7 -0
- package/generators/application/files/vitest/vitest.config.ts.template +16 -0
- package/generators/application/generator.d.ts +20 -0
- package/generators/application/generator.js +161 -0
- package/generators/application/schema.d.ts +24 -0
- package/generators/application/schema.json +57 -0
- package/generators/component/files/basic/__fileName__.tsx.template +24 -0
- package/generators/component/files/overlay/__fileName__.tsx.template +32 -0
- package/generators/component/files/story/__storyName__.tsx.template +24 -0
- package/generators/component/files/test-basic/__fileName__.test.tsx.template +10 -0
- package/generators/component/files/test-overlay/__fileName__.test.tsx.template +10 -0
- package/generators/component/generator.d.ts +5 -0
- package/generators/component/generator.js +45 -0
- package/generators/component/schema.d.ts +17 -0
- package/generators/component/schema.json +35 -0
- package/generators/i18n-setup/files/i18n.config.ts.template +10 -0
- package/generators/i18n-setup/generator.d.ts +7 -0
- package/generators/i18n-setup/generator.js +65 -0
- package/generators/i18n-setup/schema.d.ts +13 -0
- package/generators/i18n-setup/schema.json +24 -0
- package/generators/init/generator.d.ts +8 -0
- package/generators/init/generator.js +48 -0
- package/generators/init/schema.d.ts +13 -0
- package/generators/init/schema.json +19 -0
- package/generators/layout/files/_layout.tsx.template +12 -0
- package/generators/layout/generator.d.ts +5 -0
- package/generators/layout/generator.js +23 -0
- package/generators/layout/schema.d.ts +9 -0
- package/generators/layout/schema.json +26 -0
- package/generators/library/files/lib/README.md.template +18 -0
- package/generators/library/files/lib/package.json.template +12 -0
- package/generators/library/files/lib/src/__className__.tsx.template +16 -0
- package/generators/library/files/lib/src/index.ts.template +1 -0
- package/generators/library/files/lib/tsconfig.json.template +21 -0
- package/generators/library/files/publishable/tsconfig.lib.json.template +13 -0
- package/generators/library/files/subpath/src/__subpath__/__subpathClass__.tsx.template +10 -0
- package/generators/library/files/subpath/src/__subpath__/index.ts.template +1 -0
- package/generators/library/files/vitest/src/__className__.test.tsx.template +13 -0
- package/generators/library/generator.d.ts +13 -0
- package/generators/library/generator.js +116 -0
- package/generators/library/schema.d.ts +19 -0
- package/generators/library/schema.json +32 -0
- package/generators/preset/generator.d.ts +5 -0
- package/generators/preset/generator.js +29 -0
- package/generators/preset/schema.d.ts +16 -0
- package/generators/preset/schema.json +30 -0
- package/generators/route/files/__fileName__.tsx.template +43 -0
- package/generators/route/generator.d.ts +10 -0
- package/generators/route/generator.js +67 -0
- package/generators/route/schema.d.ts +15 -0
- package/generators/route/schema.json +29 -0
- package/generators/ui-setup/generator.d.ts +7 -0
- package/generators/ui-setup/generator.js +55 -0
- package/generators/ui-setup/schema.d.ts +7 -0
- package/generators/ui-setup/schema.json +21 -0
- package/generators.json +66 -0
- package/index.d.ts +22 -0
- package/index.js +24 -0
- package/migrations/0.0.1/example-noop.d.ts +2 -0
- package/migrations/0.0.1/example-noop.js +3 -0
- package/migrations.json +10 -0
- package/package.json +74 -4
- package/plugin.d.ts +12 -0
- package/plugin.js +44 -0
- package/utils/deploy.d.ts +14 -0
- package/utils/deploy.js +86 -0
- package/utils/detect.d.ts +42 -0
- package/utils/detect.js +60 -0
- package/utils/facts.d.ts +8 -0
- package/utils/facts.js +42 -0
- package/utils/project.d.ts +28 -0
- package/utils/project.js +67 -0
- package/utils/starter.d.ts +9 -0
- package/utils/starter.js +34 -0
- package/utils/targets.d.ts +22 -0
- package/utils/targets.js +117 -0
- package/utils/versions.d.ts +13 -0
- package/utils/versions.js +31 -0
- package/utils/vite-config.d.ts +8 -0
- package/utils/vite-config.js +104 -0
- package/utils/workspace.d.ts +13 -0
- package/utils/workspace.js +63 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "RivetUiSetup",
|
|
4
|
+
"title": "Set up @rivetjs/ui",
|
|
5
|
+
"description": "Adds @rivetjs/ui to a Rivet app: Tailwind v4 in the Vite config, the ui styles in src/styles.css, and the dependencies (ui, kit, lucide).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"project": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The Rivet app.",
|
|
11
|
+
"$default": { "$source": "argv", "index": 0 },
|
|
12
|
+
"x-dropdown": "projects",
|
|
13
|
+
"x-prompt": "Which project?"
|
|
14
|
+
},
|
|
15
|
+
"rivetVersion": { "type": "string", "description": "@rivetjs/* dependency spec (default: this plugin's version)." },
|
|
16
|
+
"skipPackageJson": { "type": "boolean", "default": false, "x-priority": "internal", "description": "Do not change package.json files." },
|
|
17
|
+
"skipFormat": { "type": "boolean", "default": false, "x-priority": "internal", "description": "Skip formatting files." }
|
|
18
|
+
},
|
|
19
|
+
"required": ["project"],
|
|
20
|
+
"additionalProperties": false
|
|
21
|
+
}
|
package/generators.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rivetjs/nx",
|
|
3
|
+
"version": "0.1",
|
|
4
|
+
"generators": {
|
|
5
|
+
"preset": {
|
|
6
|
+
"factory": "./generators/preset/generator",
|
|
7
|
+
"schema": "./generators/preset/schema.json",
|
|
8
|
+
"description": "Workspace preset: npx create-nx-workspace --preset=@rivetjs/nx (init + a first Rivet app).",
|
|
9
|
+
"x-use-standalone-layout": false,
|
|
10
|
+
"hidden": true
|
|
11
|
+
},
|
|
12
|
+
"init": {
|
|
13
|
+
"factory": "./generators/init/generator",
|
|
14
|
+
"schema": "./generators/init/schema.json",
|
|
15
|
+
"description": "Add @rivetjs/nx to a workspace: Rivet tooling dependencies, the inference plugin in nx.json.",
|
|
16
|
+
"hidden": true
|
|
17
|
+
},
|
|
18
|
+
"application": {
|
|
19
|
+
"factory": "./generators/application/generator",
|
|
20
|
+
"schema": "./generators/application/schema.json",
|
|
21
|
+
"aliases": ["app"],
|
|
22
|
+
"x-type": "application",
|
|
23
|
+
"description": "Create a Rivet app from a create-rivet starter (static, server, ui, minimal)."
|
|
24
|
+
},
|
|
25
|
+
"library": {
|
|
26
|
+
"factory": "./generators/library/generator",
|
|
27
|
+
"schema": "./generators/library/schema.json",
|
|
28
|
+
"aliases": ["lib"],
|
|
29
|
+
"x-type": "library",
|
|
30
|
+
"description": "Create a Rivet component library (tree-shakeable subpath exports, Vitest, optional package build)."
|
|
31
|
+
},
|
|
32
|
+
"component": {
|
|
33
|
+
"factory": "./generators/component/generator",
|
|
34
|
+
"schema": "./generators/component/schema.json",
|
|
35
|
+
"aliases": ["c"],
|
|
36
|
+
"description": "Add a resumable component (+ test, optional story route)."
|
|
37
|
+
},
|
|
38
|
+
"route": {
|
|
39
|
+
"factory": "./generators/route/generator",
|
|
40
|
+
"schema": "./generators/route/schema.json",
|
|
41
|
+
"aliases": ["r", "page"],
|
|
42
|
+
"description": "Add a file route: dynamic segments, serverLoad, serverActions, serverGuard, folder layout."
|
|
43
|
+
},
|
|
44
|
+
"layout": {
|
|
45
|
+
"factory": "./generators/layout/generator",
|
|
46
|
+
"schema": "./generators/layout/schema.json",
|
|
47
|
+
"description": "Add a _layout.tsx to a routes folder (optional serverGuard)."
|
|
48
|
+
},
|
|
49
|
+
"api-route": {
|
|
50
|
+
"factory": "./generators/api-route/generator",
|
|
51
|
+
"schema": "./generators/api-route/schema.json",
|
|
52
|
+
"aliases": ["endpoint"],
|
|
53
|
+
"description": "Add an endpoint route (onGet / onPost / … request handlers)."
|
|
54
|
+
},
|
|
55
|
+
"ui-setup": {
|
|
56
|
+
"factory": "./generators/ui-setup/generator",
|
|
57
|
+
"schema": "./generators/ui-setup/schema.json",
|
|
58
|
+
"description": "Add @rivetjs/ui + Tailwind v4 + its styles to an app."
|
|
59
|
+
},
|
|
60
|
+
"i18n-setup": {
|
|
61
|
+
"factory": "./generators/i18n-setup/generator",
|
|
62
|
+
"schema": "./generators/i18n-setup/schema.json",
|
|
63
|
+
"description": "Add compile-time i18n (@rivetjs/i18n): config, catalogs, Vite plugin."
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { createNodes, createNodesV2, createRivetProject, CONFIG_GLOB, type RivetPluginOptions } from "./plugin.js";
|
|
2
|
+
export { rivetTargets, targetNames, DEFAULT_TARGET_NAMES } from "./utils/targets.js";
|
|
3
|
+
export { detectProject, routerMode, i18nLocales, type ProjectFacts } from "./utils/detect.js";
|
|
4
|
+
export { initGenerator, type InitGeneratorSchema } from "./generators/init/generator.js";
|
|
5
|
+
export { presetGenerator, type PresetGeneratorSchema } from "./generators/preset/generator.js";
|
|
6
|
+
export { applicationGenerator, normalizeApplicationOptions, type ApplicationGeneratorSchema } from "./generators/application/generator.js";
|
|
7
|
+
export { libraryGenerator, libraryExports, type LibraryGeneratorSchema } from "./generators/library/generator.js";
|
|
8
|
+
export { componentGenerator, type ComponentGeneratorSchema } from "./generators/component/generator.js";
|
|
9
|
+
export { routeGenerator, type RouteGeneratorSchema } from "./generators/route/generator.js";
|
|
10
|
+
export { layoutGenerator, type LayoutGeneratorSchema } from "./generators/layout/generator.js";
|
|
11
|
+
export { apiRouteGenerator, type ApiRouteGeneratorSchema } from "./generators/api-route/generator.js";
|
|
12
|
+
export { uiSetupGenerator, type UiSetupGeneratorSchema } from "./generators/ui-setup/generator.js";
|
|
13
|
+
export { i18nSetupGenerator, type I18nSetupGeneratorSchema } from "./generators/i18n-setup/generator.js";
|
|
14
|
+
export { default as buildExecutor, buildSteps, type BuildExecutorSchema } from "./executors/build/executor.js";
|
|
15
|
+
export { default as devExecutor, devStep, type DevExecutorSchema } from "./executors/dev/executor.js";
|
|
16
|
+
export { default as previewExecutor, previewStep, type PreviewExecutorSchema } from "./executors/preview/executor.js";
|
|
17
|
+
export { default as prerenderExecutor, prerenderStep, type PrerenderExecutorSchema } from "./executors/prerender/executor.js";
|
|
18
|
+
export { default as checkExecutor, checkSteps, type CheckExecutorSchema } from "./executors/check/executor.js";
|
|
19
|
+
export { default as testExecutor, testStep, type TestExecutorSchema } from "./executors/test/executor.js";
|
|
20
|
+
export { default as typecheckExecutor, typecheckSteps, type TypecheckExecutorSchema } from "./executors/typecheck/executor.js";
|
|
21
|
+
export { default as packageExecutor, distManifest, type PackageExecutorSchema } from "./executors/package/executor.js";
|
|
22
|
+
export { default as exampleNoopMigration } from "./migrations/0.0.1/example-noop.js";
|
package/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @rivetjs/nx: Nx plugin for Rivet. Generators (generators.json), executors (executors.json), inferred tasks
|
|
2
|
+
// (`@rivetjs/nx/plugin`), migrations (migrations.json). Dev tooling only: no Rivet runtime entry imports it.
|
|
3
|
+
export { createNodes, createNodesV2, createRivetProject, CONFIG_GLOB } from "./plugin.js";
|
|
4
|
+
export { rivetTargets, targetNames, DEFAULT_TARGET_NAMES } from "./utils/targets.js";
|
|
5
|
+
export { detectProject, routerMode, i18nLocales } from "./utils/detect.js";
|
|
6
|
+
export { initGenerator } from "./generators/init/generator.js";
|
|
7
|
+
export { presetGenerator } from "./generators/preset/generator.js";
|
|
8
|
+
export { applicationGenerator, normalizeApplicationOptions } from "./generators/application/generator.js";
|
|
9
|
+
export { libraryGenerator, libraryExports } from "./generators/library/generator.js";
|
|
10
|
+
export { componentGenerator } from "./generators/component/generator.js";
|
|
11
|
+
export { routeGenerator } from "./generators/route/generator.js";
|
|
12
|
+
export { layoutGenerator } from "./generators/layout/generator.js";
|
|
13
|
+
export { apiRouteGenerator } from "./generators/api-route/generator.js";
|
|
14
|
+
export { uiSetupGenerator } from "./generators/ui-setup/generator.js";
|
|
15
|
+
export { i18nSetupGenerator } from "./generators/i18n-setup/generator.js";
|
|
16
|
+
export { default as buildExecutor, buildSteps } from "./executors/build/executor.js";
|
|
17
|
+
export { default as devExecutor, devStep } from "./executors/dev/executor.js";
|
|
18
|
+
export { default as previewExecutor, previewStep } from "./executors/preview/executor.js";
|
|
19
|
+
export { default as prerenderExecutor, prerenderStep } from "./executors/prerender/executor.js";
|
|
20
|
+
export { default as checkExecutor, checkSteps } from "./executors/check/executor.js";
|
|
21
|
+
export { default as testExecutor, testStep } from "./executors/test/executor.js";
|
|
22
|
+
export { default as typecheckExecutor, typecheckSteps } from "./executors/typecheck/executor.js";
|
|
23
|
+
export { default as packageExecutor, distManifest } from "./executors/package/executor.js";
|
|
24
|
+
export { default as exampleNoopMigration } from "./migrations/0.0.1/example-noop.js";
|
package/migrations.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,76 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivetjs/nx",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Nx plugin for Rivet: generators, executors and inferred tasks for Rivet apps and libraries.",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"rivet",
|
|
9
|
+
"nx",
|
|
10
|
+
"nx-plugin",
|
|
11
|
+
"generators",
|
|
12
|
+
"executors",
|
|
13
|
+
"vite",
|
|
14
|
+
"jsx",
|
|
15
|
+
"ssr",
|
|
16
|
+
"resumable"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"default": "./index.js"
|
|
22
|
+
},
|
|
23
|
+
"./plugin": {
|
|
24
|
+
"types": "./plugin.d.ts",
|
|
25
|
+
"default": "./plugin.js"
|
|
26
|
+
},
|
|
27
|
+
"./package.json": "./package.json",
|
|
28
|
+
"./generators.json": "./generators.json",
|
|
29
|
+
"./executors.json": "./executors.json",
|
|
30
|
+
"./migrations.json": "./migrations.json",
|
|
31
|
+
"./generators/*/schema.json": "./generators/*/schema.json",
|
|
32
|
+
"./executors/*/schema.json": "./executors/*/schema.json"
|
|
33
|
+
},
|
|
34
|
+
"generators": "./generators.json",
|
|
35
|
+
"executors": "./executors.json",
|
|
36
|
+
"nx-migrations": {
|
|
37
|
+
"migrations": "./migrations.json"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@nx/devkit": "23.2.1",
|
|
41
|
+
"create-rivet": "0.1.0-alpha.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"nx": ">=23 <24"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=24"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/N1XUS/rivetjs.git",
|
|
52
|
+
"directory": "libs/nx"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/N1XUS/rivetjs/tree/main/libs/nx#readme",
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/N1XUS/rivetjs/issues"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
},
|
|
61
|
+
"files": [
|
|
62
|
+
"LICENSE",
|
|
63
|
+
"README.md",
|
|
64
|
+
"executors",
|
|
65
|
+
"executors.json",
|
|
66
|
+
"generators",
|
|
67
|
+
"generators.json",
|
|
68
|
+
"index.d.ts",
|
|
69
|
+
"index.js",
|
|
70
|
+
"migrations",
|
|
71
|
+
"migrations.json",
|
|
72
|
+
"plugin.d.ts",
|
|
73
|
+
"plugin.js",
|
|
74
|
+
"utils"
|
|
75
|
+
]
|
|
76
|
+
}
|
package/plugin.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CreateNodes, type CreateNodesContext, type CreateNodesResult } from "@nx/devkit";
|
|
2
|
+
import { type RivetPluginOptions } from "./utils/targets.js";
|
|
3
|
+
export type { RivetPluginOptions } from "./utils/targets.js";
|
|
4
|
+
/** Vite and Vitest config files (one project per folder; a vitest config defers to a sibling vite config). */
|
|
5
|
+
export declare const CONFIG_GLOB = "**/{vite,vitest}.config.{ts,mts,js,mjs}";
|
|
6
|
+
/** The inferred project of one config file (`file` workspace-relative); `{}` when it is not a Rivet project. */
|
|
7
|
+
export declare function createRivetProject(file: string, options: RivetPluginOptions | undefined, context: CreateNodesContext): CreateNodesResult;
|
|
8
|
+
/** Nx 23 plugin API (`createNodes` with the v2 signature). */
|
|
9
|
+
export declare const createNodes: CreateNodes<RivetPluginOptions>;
|
|
10
|
+
/** Same as {@link createNodes}: the name older Nx releases (20–22) look for. */
|
|
11
|
+
export declare const createNodesV2: CreateNodes<RivetPluginOptions>;
|
|
12
|
+
export declare const name = "@rivetjs/nx";
|
package/plugin.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Inferred tasks (Nx project crystal): `{ "plugins": [{ "plugin": "@rivetjs/nx/plugin", "options": { … } }] }` in nx.json.
|
|
2
|
+
// Every folder with a Rivet Vite config (`rivetRouter()` / `@rivetjs/compiler/vite`) or a Rivet Vitest config
|
|
3
|
+
// (`rivetTest()`) next to a package.json / project.json becomes a project with build / dev / preview / test / check /
|
|
4
|
+
// typecheck targets (`utils/targets.ts`). Configs are read as text, never executed.
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { basename, dirname, join } from "node:path";
|
|
7
|
+
import { createNodesFromFiles } from "@nx/devkit";
|
|
8
|
+
import { VITE_CONFIGS } from "./utils/detect.js";
|
|
9
|
+
import { projectFacts } from "./utils/facts.js";
|
|
10
|
+
import { rivetTargets } from "./utils/targets.js";
|
|
11
|
+
/** Vite and Vitest config files (one project per folder; a vitest config defers to a sibling vite config). */
|
|
12
|
+
export const CONFIG_GLOB = "**/{vite,vitest}.config.{ts,mts,js,mjs}";
|
|
13
|
+
/** The inferred project of one config file (`file` workspace-relative); `{}` when it is not a Rivet project. */
|
|
14
|
+
export function createRivetProject(file, options, context) {
|
|
15
|
+
const root = dirname(file);
|
|
16
|
+
const abs = join(context.workspaceRoot, root);
|
|
17
|
+
if (!existsSync(join(abs, "package.json")) && !existsSync(join(abs, "project.json")))
|
|
18
|
+
return {};
|
|
19
|
+
// One result per folder: a vitest config with a sibling vite config is read through the vite config's result.
|
|
20
|
+
if (basename(file).startsWith("vitest.") && VITE_CONFIGS.some((name) => existsSync(join(abs, name))))
|
|
21
|
+
return {};
|
|
22
|
+
const facts = projectFacts(abs);
|
|
23
|
+
if (!facts)
|
|
24
|
+
return {};
|
|
25
|
+
const production = Boolean(context.nxJsonConfiguration.namedInputs?.["production"]);
|
|
26
|
+
return {
|
|
27
|
+
projects: {
|
|
28
|
+
[root]: {
|
|
29
|
+
root,
|
|
30
|
+
...(facts.kind === "lib" ? {} : { projectType: "application" }),
|
|
31
|
+
targets: rivetTargets(facts, options, { production }),
|
|
32
|
+
metadata: { technologies: ["rivet"] },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Nx 23 plugin API (`createNodes` with the v2 signature). */
|
|
38
|
+
export const createNodes = [
|
|
39
|
+
CONFIG_GLOB,
|
|
40
|
+
(files, options, context) => createNodesFromFiles((file, opts, ctx) => createRivetProject(file, opts, ctx), files, options ?? {}, context),
|
|
41
|
+
];
|
|
42
|
+
/** Same as {@link createNodes}: the name older Nx releases (20–22) look for. */
|
|
43
|
+
export const createNodesV2 = createNodes;
|
|
44
|
+
export const name = "@rivetjs/nx";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Tree } from "@nx/devkit";
|
|
2
|
+
import type { PackageJson, TemplateId } from "create-rivet";
|
|
3
|
+
import { DEPLOY_TARGETS, deployProblem, findDeployTarget, type DeployTarget } from "create-rivet/deploy";
|
|
4
|
+
export { DEPLOY_TARGETS, deployProblem, findDeployTarget, type DeployTarget };
|
|
5
|
+
/** The npm scripts create-rivet's overlay adds for `adapter` (`deploy`, `preview`, `start`); `{}` for other adapters. */
|
|
6
|
+
export declare function deployScripts(adapter: string | undefined): Record<string, string>;
|
|
7
|
+
/** Folders the router's platform packaging writes outside `dist/` (`libs/router/adapters/pack.ts`): build outputs. */
|
|
8
|
+
export declare function deployOutputs(adapter: string | undefined): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Applies create-rivet's deploy overlay for `target` to the project at `root`: `edit` runs on a scratch copy of the
|
|
11
|
+
* project (the overlay edits files on disk), then the files it wrote or removed are mirrored into the tree. `pkg`
|
|
12
|
+
* gets the overlay's dependencies (scripts are dropped: Nx targets). Throws create-rivet's `deployProblem`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyDeploy(tree: Tree, root: string, template: TemplateId, target: DeployTarget, project: string, pkg: PackageJson): PackageJson;
|
package/utils/deploy.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// `--deploy <target>` in an Nx workspace: create-rivet's own deploy overlay (`create-rivet/deploy`), so a Nx app and
|
|
2
|
+
// `npm create rivet -- --deploy <target>` get the same vite.config adapter, .gitignore lines, netlify.toml, README
|
|
3
|
+
// section, removed files and dependencies. Only the npm scripts the overlay adds become Nx targets instead
|
|
4
|
+
// (`deployScripts` → `utils/targets.ts`), and the README / netlify.toml commands name those targets.
|
|
5
|
+
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { dirname, join } from "node:path";
|
|
8
|
+
import { DEPLOY_TARGETS, deployOverlay, deployProblem, findDeployTarget } from "create-rivet/deploy";
|
|
9
|
+
export { DEPLOY_TARGETS, deployProblem, findDeployTarget };
|
|
10
|
+
/** The npm scripts create-rivet's overlay adds for `adapter` (`deploy`, `preview`, `start`); `{}` for other adapters. */
|
|
11
|
+
export function deployScripts(adapter) {
|
|
12
|
+
const target = adapter ? findDeployTarget(adapter) : undefined;
|
|
13
|
+
if (!target)
|
|
14
|
+
return {};
|
|
15
|
+
const pkg = deployOverlay(target.id).manifest?.({}) ?? {};
|
|
16
|
+
return pkg["scripts"] ?? {};
|
|
17
|
+
}
|
|
18
|
+
/** Folders the router's platform packaging writes outside `dist/` (`libs/router/adapters/pack.ts`): build outputs. */
|
|
19
|
+
export function deployOutputs(adapter) {
|
|
20
|
+
if (adapter === "vercel" || adapter === "vercel-edge")
|
|
21
|
+
return ["{projectRoot}/.vercel/output"];
|
|
22
|
+
if (adapter === "netlify")
|
|
23
|
+
return ["{projectRoot}/.netlify/v1"];
|
|
24
|
+
if (adapter === "cloudflare")
|
|
25
|
+
return ["{projectRoot}/.wrangler/deploy"];
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
/** Every file under `root` in the tree (workspace-relative paths). */
|
|
29
|
+
function treeFiles(tree, root) {
|
|
30
|
+
const out = [];
|
|
31
|
+
const walk = (dir) => {
|
|
32
|
+
for (const name of tree.children(dir)) {
|
|
33
|
+
const path = join(dir, name);
|
|
34
|
+
if (tree.isFile(path))
|
|
35
|
+
out.push(path);
|
|
36
|
+
else
|
|
37
|
+
walk(path);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
walk(root);
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
/** npm script → the Nx target that replaces it (bun / deno `start` = the `preview` target). */
|
|
44
|
+
const TARGET_OF = { build: "build", deploy: "deploy", preview: "preview", start: "preview" };
|
|
45
|
+
/**
|
|
46
|
+
* Applies create-rivet's deploy overlay for `target` to the project at `root`: `edit` runs on a scratch copy of the
|
|
47
|
+
* project (the overlay edits files on disk), then the files it wrote or removed are mirrored into the tree. `pkg`
|
|
48
|
+
* gets the overlay's dependencies (scripts are dropped: Nx targets). Throws create-rivet's `deployProblem`.
|
|
49
|
+
*/
|
|
50
|
+
export function applyDeploy(tree, root, template, target, project, pkg) {
|
|
51
|
+
const problem = deployProblem(target, template);
|
|
52
|
+
if (problem)
|
|
53
|
+
throw new Error(`application: ${problem}`);
|
|
54
|
+
const overlay = deployOverlay(target, "npm");
|
|
55
|
+
const next = overlay.manifest ? overlay.manifest(pkg) : pkg;
|
|
56
|
+
delete next["scripts"];
|
|
57
|
+
const scratch = mkdtempSync(join(tmpdir(), "rivet-nx-deploy-"));
|
|
58
|
+
try {
|
|
59
|
+
for (const file of treeFiles(tree, root)) {
|
|
60
|
+
const at = join(scratch, file.slice(root.length + 1));
|
|
61
|
+
mkdirSync(dirname(at), { recursive: true });
|
|
62
|
+
writeFileSync(at, tree.read(file));
|
|
63
|
+
}
|
|
64
|
+
const result = overlay.edit?.(scratch);
|
|
65
|
+
for (const file of result?.written ?? [])
|
|
66
|
+
tree.write(join(root, file), readFileSync(join(scratch, file)));
|
|
67
|
+
for (const file of result?.removed ?? [])
|
|
68
|
+
tree.delete(join(root, file));
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
// The overlay's commands run npm scripts; in Nx they are targets.
|
|
74
|
+
const nx = (text) => text.replace(/\bnpm run (\w+)/g, (all, script) => (TARGET_OF[script] ? `nx ${TARGET_OF[script]} ${project}` : all));
|
|
75
|
+
const netlify = join(root, "netlify.toml");
|
|
76
|
+
if (tree.exists(netlify))
|
|
77
|
+
tree.write(netlify, tree.read(netlify, "utf8").replace(/command = "npm run build"/, `command = "npx nx build ${project}"`));
|
|
78
|
+
const readme = join(root, "README.md");
|
|
79
|
+
if (tree.exists(readme)) {
|
|
80
|
+
const text = tree.read(readme, "utf8");
|
|
81
|
+
const at = text.indexOf("\n## Deploy: ");
|
|
82
|
+
if (at >= 0)
|
|
83
|
+
tree.write(readme, text.slice(0, at) + nx(text.slice(at)));
|
|
84
|
+
}
|
|
85
|
+
return next;
|
|
86
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Vite config file names Vite itself looks for, in its order. */
|
|
2
|
+
export declare const VITE_CONFIGS: readonly ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"];
|
|
3
|
+
/** Vitest config file names. */
|
|
4
|
+
export declare const VITEST_CONFIGS: readonly ["vitest.config.ts", "vitest.config.mts", "vitest.config.js", "vitest.config.mjs"];
|
|
5
|
+
export interface ProjectFacts {
|
|
6
|
+
/** `app`: file-routed (`rivetRouter`); `spa`: `rivet()` compiler plugin without the router; `lib`: Rivet test setup only. */
|
|
7
|
+
kind: "app" | "spa" | "lib";
|
|
8
|
+
/** `rivetRouter({ mode: "static" })`: pages are prerendered at build time. */
|
|
9
|
+
static: boolean;
|
|
10
|
+
/** `rivetRouter({ mode: "csr" })`: browser-rendered app, no server build. */
|
|
11
|
+
csr: boolean;
|
|
12
|
+
/** A vitest config (or a vite config `test` block) with `rivetTest()`. */
|
|
13
|
+
test: boolean;
|
|
14
|
+
/** The project has a `tsconfig.json`. */
|
|
15
|
+
tsconfig: boolean;
|
|
16
|
+
/** Locales of `@rivetjs/i18n` (`i18n.config.ts` `locales: [...]`): one client build each. */
|
|
17
|
+
locales?: string[];
|
|
18
|
+
/** Platform target of `rivetRouter({ adapter: "vercel" | { name: "vercel", … } })` (create-rivet `--deploy`). */
|
|
19
|
+
adapter?: string;
|
|
20
|
+
/** The project's own preview server (`serve.js`). */
|
|
21
|
+
serveScript: boolean;
|
|
22
|
+
/** The project's own prerender step (`prerender.js`). */
|
|
23
|
+
prerenderScript: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ConfigTexts {
|
|
26
|
+
vite?: string;
|
|
27
|
+
vitest?: string;
|
|
28
|
+
i18n?: string;
|
|
29
|
+
files: {
|
|
30
|
+
tsconfig: boolean;
|
|
31
|
+
serveScript: boolean;
|
|
32
|
+
prerenderScript: boolean;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** `rivetRouter({ … mode: "static" … })` (the router's `mode` option; the first `rivetRouter(` call). */
|
|
36
|
+
export declare function routerMode(vite: string): string | undefined;
|
|
37
|
+
/** `rivetRouter({ adapter: "x" })` or `rivetRouter({ adapter: { name: "x", … } })`: the platform target name. */
|
|
38
|
+
export declare function routerAdapter(vite: string): string | undefined;
|
|
39
|
+
/** `locales: ["en", "de"]` of an i18n config. */
|
|
40
|
+
export declare function i18nLocales(config: string): string[] | undefined;
|
|
41
|
+
/** The facts of a project from its config texts; `undefined` when it is not a Rivet project. */
|
|
42
|
+
export declare function detectProject(texts: ConfigTexts): ProjectFacts | undefined;
|
package/utils/detect.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// What kind of Rivet project a folder holds, read from its config files' text (no config is executed: inference
|
|
2
|
+
// must stay fast and side-effect free). Used by the inference plugin, the executors and the generators.
|
|
3
|
+
/** Vite config file names Vite itself looks for, in its order. */
|
|
4
|
+
export const VITE_CONFIGS = ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"];
|
|
5
|
+
/** Vitest config file names. */
|
|
6
|
+
export const VITEST_CONFIGS = ["vitest.config.ts", "vitest.config.mts", "vitest.config.js", "vitest.config.mjs"];
|
|
7
|
+
const ROUTER = /@rivetjs\/router\/vite|\brivetRouter\s*\(/;
|
|
8
|
+
const COMPILER = /@rivetjs\/compiler\/vite/;
|
|
9
|
+
const TESTING = /@rivetjs\/testing\/vite|\brivetTest\s*\(/;
|
|
10
|
+
const I18N = /@rivetjs\/i18n\/vite/;
|
|
11
|
+
/** `rivetRouter({ … mode: "static" … })` (the router's `mode` option; the first `rivetRouter(` call). */
|
|
12
|
+
export function routerMode(vite) {
|
|
13
|
+
const at = vite.search(/\brivetRouter\s*\(/);
|
|
14
|
+
if (at < 0)
|
|
15
|
+
return undefined;
|
|
16
|
+
const call = vite.slice(at, at + 2000);
|
|
17
|
+
return /\bmode\s*:\s*["'`](\w+)["'`]/.exec(call)?.[1];
|
|
18
|
+
}
|
|
19
|
+
/** `rivetRouter({ adapter: "x" })` or `rivetRouter({ adapter: { name: "x", … } })`: the platform target name. */
|
|
20
|
+
export function routerAdapter(vite) {
|
|
21
|
+
const at = vite.search(/\brivetRouter\s*\(/);
|
|
22
|
+
if (at < 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
const call = vite.slice(at, at + 2000);
|
|
25
|
+
return /\badapter\s*:\s*(?:\{[^}]*?\bname\s*:\s*)?["'`]([\w-]+)["'`]/.exec(call)?.[1];
|
|
26
|
+
}
|
|
27
|
+
/** `locales: ["en", "de"]` of an i18n config. */
|
|
28
|
+
export function i18nLocales(config) {
|
|
29
|
+
const list = /\blocales\s*:\s*\[([^\]]*)\]/.exec(config)?.[1];
|
|
30
|
+
if (list === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const locales = [...list.matchAll(/["'`]([^"'`]+)["'`]/g)].map((match) => match[1]);
|
|
33
|
+
return locales.length ? locales : undefined;
|
|
34
|
+
}
|
|
35
|
+
/** The facts of a project from its config texts; `undefined` when it is not a Rivet project. */
|
|
36
|
+
export function detectProject(texts) {
|
|
37
|
+
const vite = texts.vite ?? "";
|
|
38
|
+
const router = ROUTER.test(vite);
|
|
39
|
+
const compiler = COMPILER.test(vite);
|
|
40
|
+
const test = TESTING.test(texts.vitest ?? "") || (TESTING.test(vite) && /\btest\s*:/.test(vite));
|
|
41
|
+
if (!router && !compiler && !test)
|
|
42
|
+
return undefined;
|
|
43
|
+
const mode = router ? routerMode(vite) : undefined;
|
|
44
|
+
const facts = {
|
|
45
|
+
kind: router ? "app" : compiler ? "spa" : "lib",
|
|
46
|
+
static: mode === "static",
|
|
47
|
+
csr: mode === "csr",
|
|
48
|
+
test,
|
|
49
|
+
tsconfig: texts.files.tsconfig,
|
|
50
|
+
serveScript: texts.files.serveScript,
|
|
51
|
+
prerenderScript: texts.files.prerenderScript,
|
|
52
|
+
};
|
|
53
|
+
const adapter = router ? routerAdapter(vite) : undefined;
|
|
54
|
+
if (adapter)
|
|
55
|
+
facts.adapter = adapter;
|
|
56
|
+
const locales = I18N.test(vite) && texts.i18n ? i18nLocales(texts.i18n) : undefined;
|
|
57
|
+
if (locales)
|
|
58
|
+
facts.locales = locales;
|
|
59
|
+
return facts;
|
|
60
|
+
}
|
package/utils/facts.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Tree } from "@nx/devkit";
|
|
2
|
+
import { type ProjectFacts } from "./detect.js";
|
|
3
|
+
/** Facts of the project in `dir` (absolute) on disk. */
|
|
4
|
+
export declare function projectFacts(dir: string): ProjectFacts | undefined;
|
|
5
|
+
/** Facts of the project at `root` (workspace-relative) in a generator tree. */
|
|
6
|
+
export declare function treeFacts(tree: Tree, root: string): ProjectFacts | undefined;
|
|
7
|
+
/** The Vite config path of a project (workspace-relative in a tree), if any. */
|
|
8
|
+
export declare function viteConfigPath(tree: Tree, root: string): string | undefined;
|
package/utils/facts.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Project facts from the file system (executors, the inference plugin) or an Nx `Tree` (generators).
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { detectProject, VITE_CONFIGS, VITEST_CONFIGS } from "./detect.js";
|
|
5
|
+
const disk = {
|
|
6
|
+
exists: (path) => existsSync(path),
|
|
7
|
+
read: (path) => (existsSync(path) ? readFileSync(path, "utf8") : undefined),
|
|
8
|
+
};
|
|
9
|
+
function treeReader(tree) {
|
|
10
|
+
return { exists: (path) => tree.exists(path), read: (path) => (tree.exists(path) ? (tree.read(path, "utf8") ?? undefined) : undefined) };
|
|
11
|
+
}
|
|
12
|
+
/** The first existing file of `names` in `dir`. */
|
|
13
|
+
function first(reader, dir, names) {
|
|
14
|
+
return names.map((name) => join(dir, name)).find((path) => reader.exists(path));
|
|
15
|
+
}
|
|
16
|
+
function factsWith(reader, dir) {
|
|
17
|
+
const vite = first(reader, dir, VITE_CONFIGS);
|
|
18
|
+
const vitest = first(reader, dir, VITEST_CONFIGS);
|
|
19
|
+
const i18n = first(reader, dir, ["i18n.config.ts", "i18n.config.js", "i18n.config.mts", "i18n.config.mjs"]);
|
|
20
|
+
return detectProject({
|
|
21
|
+
...(vite ? { vite: reader.read(vite) } : {}),
|
|
22
|
+
...(vitest ? { vitest: reader.read(vitest) } : {}),
|
|
23
|
+
...(i18n ? { i18n: reader.read(i18n) } : {}),
|
|
24
|
+
files: {
|
|
25
|
+
tsconfig: reader.exists(join(dir, "tsconfig.json")),
|
|
26
|
+
serveScript: reader.exists(join(dir, "serve.js")),
|
|
27
|
+
prerenderScript: reader.exists(join(dir, "prerender.js")),
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Facts of the project in `dir` (absolute) on disk. */
|
|
32
|
+
export function projectFacts(dir) {
|
|
33
|
+
return factsWith(disk, dir);
|
|
34
|
+
}
|
|
35
|
+
/** Facts of the project at `root` (workspace-relative) in a generator tree. */
|
|
36
|
+
export function treeFacts(tree, root) {
|
|
37
|
+
return factsWith(treeReader(tree), root);
|
|
38
|
+
}
|
|
39
|
+
/** The Vite config path of a project (workspace-relative in a tree), if any. */
|
|
40
|
+
export function viteConfigPath(tree, root) {
|
|
41
|
+
return first(treeReader(tree), root, VITE_CONFIGS);
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Tree } from "@nx/devkit";
|
|
2
|
+
import type { ProjectFacts } from "./detect.js";
|
|
3
|
+
export interface RivetProject {
|
|
4
|
+
name: string;
|
|
5
|
+
root: string;
|
|
6
|
+
/** `<root>/src` (or the project's sourceRoot). */
|
|
7
|
+
src: string;
|
|
8
|
+
/** `<src>/routes`. */
|
|
9
|
+
routes: string;
|
|
10
|
+
facts: ProjectFacts | undefined;
|
|
11
|
+
/** A library (`projectType: library`, or no Vite config). */
|
|
12
|
+
library: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function rivetProject(tree: Tree, name: string): RivetProject;
|
|
15
|
+
/** Throws unless the project is a file-routed Rivet app (`rivetRouter()` in its Vite config). */
|
|
16
|
+
export declare function routedApp(tree: Tree, name: string, generator: string): RivetProject;
|
|
17
|
+
/** Route path → segments: `blog/[slug]` → `["blog", "[slug]"]` (leading `/`, `src/routes/`, extension and `index` dropped). */
|
|
18
|
+
export declare function routeSegments(path: string): string[];
|
|
19
|
+
/** Params of route segments: `[slug]` → `{ name: "slug", kind: "one" }`. */
|
|
20
|
+
export interface RouteParam {
|
|
21
|
+
name: string;
|
|
22
|
+
kind: "one" | "optional" | "rest";
|
|
23
|
+
}
|
|
24
|
+
export declare function routeParams(segments: string[]): RouteParam[];
|
|
25
|
+
/** `PascalCase` name of route segments (`blog/[slug]` → `BlogSlug`; root → `Home`). */
|
|
26
|
+
export declare function routeComponentName(segments: string[]): string;
|
|
27
|
+
/** `../` from a file in `dir` (workspace-relative) back to `to`. */
|
|
28
|
+
export declare function relativeImport(fromDir: string, to: string): string;
|