@venizia/ardor 0.1.4 → 0.3.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/README.md +1 -1
- package/dist/vulcan-preset/files/.configs/eslint.config.mjs +5 -0
- package/dist/vulcan-preset/files/.configs/oxfmt.config.mts +4 -0
- package/dist/vulcan-preset/files/.configs/oxlint.config.mts +4 -0
- package/dist/vulcan-preset/files/README.md +7 -0
- package/dist/vulcan-preset/files/_env.example +1 -0
- package/dist/vulcan-preset/files/index.html +12 -0
- package/dist/vulcan-preset/files/src/application.ts +19 -0
- package/dist/vulcan-preset/files/src/configurations/admin.configuration.ts +44 -0
- package/dist/vulcan-preset/files/src/main.tsx +26 -0
- package/dist/vulcan-preset/files/src/pages/product-create.tsx +10 -0
- package/dist/vulcan-preset/files/src/pages/product-edit.tsx +10 -0
- package/dist/vulcan-preset/files/src/pages/product-form.tsx +32 -0
- package/dist/vulcan-preset/files/src/pages/product-list.tsx +42 -0
- package/dist/vulcan-preset/files/tsconfig.json +21 -0
- package/dist/vulcan-preset/files/vite.config.ts +21 -0
- package/dist/vulcan-preset/preset.json +68 -0
- package/package.json +16 -13
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ The full guide, including the root component and the typed hooks, is in the
|
|
|
95
95
|
## Migrating from `@minimaltech/ra-core-infra`
|
|
96
96
|
|
|
97
97
|
ARDOR is that package, split and rebranded. See
|
|
98
|
-
[the migration guide](https://ardor.venizia.ai/guides/
|
|
98
|
+
[the migration guide](https://ardor.venizia.ai/guides/migrations/from-ra-core-infra) -
|
|
99
99
|
the move is four mechanical edits plus four symbol renames.
|
|
100
100
|
|
|
101
101
|
## License
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# {{app}}
|
|
2
|
+
|
|
3
|
+
The {{app}} admin of {{project}}, built on ARDOR: Vite, React and react-admin.
|
|
4
|
+
|
|
5
|
+
`bun run dev` serves `http://localhost:{{devPort}}`. `/api` is proxied to the backend app chosen when this app was added (`apiUrl` in `vite.config.ts`).
|
|
6
|
+
|
|
7
|
+
The `products` resource reads `GET /api/products` (a JSON array and a `Content-Range` header) and writes `POST /api/products` and `PATCH /api/products/:id`. Point it at your own resource by renaming `products` in `src/main.tsx`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
PORT={{devPort}}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>{{app}}</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
|
|
3
|
+
import AutoArtifacts from '@venizia/ignis-boot/auto';
|
|
4
|
+
|
|
5
|
+
import { BaseArdorApplication, type IApplicationInfo, type IArtifactIndex } from '@venizia/ardor';
|
|
6
|
+
|
|
7
|
+
// The decorated classes live in their own files and this module imports none of them: the build lists
|
|
8
|
+
// every one under src/ in `AutoArtifacts`.
|
|
9
|
+
export class Application extends BaseArdorApplication {
|
|
10
|
+
getAppInfo(): IApplicationInfo {
|
|
11
|
+
return { name: '{{app}}', version: '0.0.0', description: 'The {{app}} admin of {{project}}' };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override artifacts(): Array<IArtifactIndex> {
|
|
15
|
+
return [AutoArtifacts];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
bindContext(): void {}
|
|
19
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BaseArdorApplication as TArdorApplication,
|
|
3
|
+
configuration,
|
|
4
|
+
CoreBindings,
|
|
5
|
+
DefaultI18nProvider,
|
|
6
|
+
DefaultRestDataProvider,
|
|
7
|
+
englishMessages,
|
|
8
|
+
inject,
|
|
9
|
+
provide,
|
|
10
|
+
} from '@venizia/ardor';
|
|
11
|
+
|
|
12
|
+
// The two providers an application without sign-in needs. start() binds each @provide method under its
|
|
13
|
+
// key; the auth provider stays unbound, so every page is public.
|
|
14
|
+
@configuration()
|
|
15
|
+
export class AdminConfiguration {
|
|
16
|
+
constructor(
|
|
17
|
+
@inject({ key: CoreBindings.APPLICATION_INSTANCE })
|
|
18
|
+
private readonly application: TArdorApplication,
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
@provide({ key: CoreBindings.REST_DATA_PROVIDER_OPTIONS })
|
|
22
|
+
restDataProviderOptions() {
|
|
23
|
+
// No sign-in: no request carries an Authorization header.
|
|
24
|
+
return { url: '/api', noAuthPathRegex: /./ };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@provide({ key: CoreBindings.I18N_PROVIDER_OPTIONS })
|
|
28
|
+
i18nProviderOptions() {
|
|
29
|
+
return {
|
|
30
|
+
i18nSources: { en: englishMessages },
|
|
31
|
+
languages: [{ locale: 'en', name: 'English' }],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@provide({ key: CoreBindings.DEFAULT_REST_DATA_PROVIDER })
|
|
36
|
+
restDataProvider() {
|
|
37
|
+
return this.application.instantiate(DefaultRestDataProvider).value(this.application);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@provide({ key: CoreBindings.DEFAULT_I18N_PROVIDER })
|
|
41
|
+
i18nProvider() {
|
|
42
|
+
return this.application.instantiate(DefaultI18nProvider).value(this.application);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
|
|
3
|
+
import { configureStore } from '@reduxjs/toolkit';
|
|
4
|
+
import { ArdorApplication } from '@venizia/ardor';
|
|
5
|
+
import { createRoot } from 'react-dom/client';
|
|
6
|
+
|
|
7
|
+
import { Application } from '@/application';
|
|
8
|
+
import { ProductCreate } from '@/pages/product-create';
|
|
9
|
+
import { ProductEdit } from '@/pages/product-edit';
|
|
10
|
+
import { ProductList } from '@/pages/product-list';
|
|
11
|
+
|
|
12
|
+
const application = new Application();
|
|
13
|
+
const store = configureStore({
|
|
14
|
+
reducer: { app: (state: { ready: boolean } = { ready: true }) => state },
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
await application.start();
|
|
18
|
+
|
|
19
|
+
createRoot(document.getElementById('root')!).render(
|
|
20
|
+
<ArdorApplication
|
|
21
|
+
container={application}
|
|
22
|
+
reduxStore={store}
|
|
23
|
+
suspense={<p>Loading</p>}
|
|
24
|
+
resources={[{ name: 'products', list: ProductList, create: ProductCreate, edit: ProductEdit }]}
|
|
25
|
+
/>,
|
|
26
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Form, useInput } from 'ra-core';
|
|
2
|
+
|
|
3
|
+
const TextInput = (props: { source: string; label: string }) => {
|
|
4
|
+
const { field } = useInput({ source: props.source });
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
<label>
|
|
8
|
+
{props.label} <input {...field} value={field.value ?? ''} />
|
|
9
|
+
</label>
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const NumberInput = (props: { source: string; label: string }) => {
|
|
14
|
+
const { field } = useInput({
|
|
15
|
+
source: props.source,
|
|
16
|
+
parse: (value: string) => (value === '' ? null : Number(value)),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<label>
|
|
21
|
+
{props.label} <input {...field} type="number" value={field.value ?? ''} />
|
|
22
|
+
</label>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const ProductForm = () => (
|
|
27
|
+
<Form>
|
|
28
|
+
<TextInput source="name" label="Name" />
|
|
29
|
+
<NumberInput source="price" label="Price" />
|
|
30
|
+
<button type="submit">Save</button>
|
|
31
|
+
</Form>
|
|
32
|
+
);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Link } from 'react-router-dom';
|
|
2
|
+
import { ListBase, useCreatePath, useListContext } from 'ra-core';
|
|
3
|
+
|
|
4
|
+
interface IProduct {
|
|
5
|
+
id: number;
|
|
6
|
+
name: string;
|
|
7
|
+
price: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Rows = () => {
|
|
11
|
+
const { data, total, isPending } = useListContext<IProduct>();
|
|
12
|
+
const createPath = useCreatePath();
|
|
13
|
+
|
|
14
|
+
if (isPending) {
|
|
15
|
+
return <p>Loading</p>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<main>
|
|
20
|
+
<h1>
|
|
21
|
+
Products <small>({total} total)</small>
|
|
22
|
+
</h1>
|
|
23
|
+
<Link to={createPath({ resource: 'products', type: 'create' })}>Create</Link>
|
|
24
|
+
<ul>
|
|
25
|
+
{(data ?? []).map((product) => (
|
|
26
|
+
<li key={product.id}>
|
|
27
|
+
<Link to={createPath({ resource: 'products', type: 'edit', id: product.id })}>
|
|
28
|
+
{product.name}
|
|
29
|
+
</Link>{' '}
|
|
30
|
+
- {product.price}
|
|
31
|
+
</li>
|
|
32
|
+
))}
|
|
33
|
+
</ul>
|
|
34
|
+
</main>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const ProductList = () => (
|
|
39
|
+
<ListBase resource="products" perPage={10}>
|
|
40
|
+
<Rows />
|
|
41
|
+
</ListBase>
|
|
42
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "@venizia/dev-configs/tsconfig.react.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
7
|
+
"types": ["vite/client"],
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"isolatedModules": true,
|
|
10
|
+
|
|
11
|
+
// Restated, not inherited: Bun ignores an `extends` that names a package.
|
|
12
|
+
"experimentalDecorators": true,
|
|
13
|
+
"emitDecoratorMetadata": true,
|
|
14
|
+
"useDefineForClassFields": false,
|
|
15
|
+
|
|
16
|
+
"paths": {
|
|
17
|
+
"@/*": ["./src/*"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"include": ["src", "vite.config.ts"]
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IgnisArtifactsVitePlugin } from '@venizia/ignis-boot/vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import { defineConfig, loadEnv } from 'vite';
|
|
4
|
+
|
|
5
|
+
export default defineConfig(({ mode }) => {
|
|
6
|
+
const env = loadEnv(mode, '.', '');
|
|
7
|
+
// The backend app `vulcan add --api` chose; empty when there is none, and then nothing is proxied.
|
|
8
|
+
const apiUrl: string = '{{apiUrl}}';
|
|
9
|
+
const proxy: Record<string, string> = apiUrl === '' ? {} : { '/api': apiUrl };
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
// Builds the class list of src/ into the bundle, so a decorated class is bound without being imported.
|
|
13
|
+
plugins: [IgnisArtifactsVitePlugin.create(), react()],
|
|
14
|
+
resolve: { alias: { '@': '/src' } },
|
|
15
|
+
server: {
|
|
16
|
+
port: Number(env.PORT ?? '{{devPort}}'),
|
|
17
|
+
strictPort: true,
|
|
18
|
+
proxy,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presetVersion": 1,
|
|
3
|
+
"side": "frontend",
|
|
4
|
+
"summary": "An ARDOR admin on Vite and React: one products resource with list, create and edit pages, REST data provider and i18n, no sign-in.",
|
|
5
|
+
"devPort": 5173,
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@reduxjs/toolkit": "^2.12.0",
|
|
8
|
+
"@tanstack/react-query": "^5.101.2",
|
|
9
|
+
"@venizia/ardor": "0.3.0",
|
|
10
|
+
"@venizia/ignis-connectors": "0.3.0",
|
|
11
|
+
"@venizia/ignis-filter": "0.3.0",
|
|
12
|
+
"@venizia/ignis-helpers": "0.3.0",
|
|
13
|
+
"@venizia/ignis-inversion": "0.3.0",
|
|
14
|
+
"@venizia/ignis-kernel": "0.3.0",
|
|
15
|
+
"ra-core": "^5.15.0",
|
|
16
|
+
"ra-i18n-polyglot": "^5.15.0",
|
|
17
|
+
"react": "^19.2.7",
|
|
18
|
+
"react-dom": "^19.2.7",
|
|
19
|
+
"react-redux": "^9.3.0",
|
|
20
|
+
"react-router-dom": "^7.9.4",
|
|
21
|
+
"reflect-metadata": "^0.2.2"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/react": "^19",
|
|
25
|
+
"@types/react-dom": "^19",
|
|
26
|
+
"@venizia/dev-configs": "0.3.1",
|
|
27
|
+
"@venizia/ignis-boot": "0.3.0",
|
|
28
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
29
|
+
"eslint": "^10.10.0",
|
|
30
|
+
"oxfmt": "0.73.0",
|
|
31
|
+
"oxlint": "1.88.0",
|
|
32
|
+
"oxlint-tsgolint": "7.0.2004",
|
|
33
|
+
"typescript": "^6.0.3",
|
|
34
|
+
"vite": "^8.2.2"
|
|
35
|
+
},
|
|
36
|
+
"peers": {
|
|
37
|
+
"@venizia/ignis-connectors": "^0.3.0",
|
|
38
|
+
"@venizia/ignis-filter": "^0.3.0",
|
|
39
|
+
"@venizia/ignis-helpers": "^0.3.0",
|
|
40
|
+
"@venizia/ignis-inversion": "^0.3.0",
|
|
41
|
+
"@venizia/ignis-kernel": "^0.3.0"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"dev": "vite",
|
|
45
|
+
"build": "vite build",
|
|
46
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
47
|
+
"lint": "oxlint -c .configs/oxlint.config.mts --deny-warnings && eslint -c .configs/eslint.config.mjs . && oxfmt -c .configs/oxfmt.config.mts --check \"**/*.{js,mjs,ts,mts,tsx}\"",
|
|
48
|
+
"lint:fix": "oxlint -c .configs/oxlint.config.mts --fix && eslint -c .configs/eslint.config.mjs . --fix && oxfmt -c .configs/oxfmt.config.mts \"**/*.{js,mjs,ts,mts,tsx}\""
|
|
49
|
+
},
|
|
50
|
+
"checks": [
|
|
51
|
+
"typecheck",
|
|
52
|
+
"lint",
|
|
53
|
+
"build"
|
|
54
|
+
],
|
|
55
|
+
"files": "./files",
|
|
56
|
+
"atlas": [
|
|
57
|
+
{
|
|
58
|
+
"name": "ardor",
|
|
59
|
+
"repo": "VENIZIA-AI/ardor",
|
|
60
|
+
"ref": "develop"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "ignis",
|
|
64
|
+
"repo": "VENIZIA-AI/ignis",
|
|
65
|
+
"ref": "develop"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venizia/ardor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "ARDOR - frontend application framework for the VENIZIA family. One entry point over ardor-kernel, ardor-react and ardor-admin: IGNIS inversion of control, a REST data layer, auth and i18n providers, and the React bindings for a react-admin application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ardor",
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
"./package.json": "./package.json"
|
|
59
59
|
},
|
|
60
60
|
"sideEffects": false,
|
|
61
|
+
"vulcan": {
|
|
62
|
+
"preset": "./dist/vulcan-preset/preset.json"
|
|
63
|
+
},
|
|
61
64
|
"files": [
|
|
62
65
|
"README.md",
|
|
63
66
|
"LICENSE.md",
|
|
@@ -73,18 +76,18 @@
|
|
|
73
76
|
"prepublishOnly": "make rebuild"
|
|
74
77
|
},
|
|
75
78
|
"dependencies": {
|
|
76
|
-
"@venizia/ardor-admin": "0.
|
|
77
|
-
"@venizia/ardor-kernel": "0.
|
|
78
|
-
"@venizia/ardor-react": "0.
|
|
79
|
+
"@venizia/ardor-admin": "0.3.0",
|
|
80
|
+
"@venizia/ardor-kernel": "0.3.0",
|
|
81
|
+
"@venizia/ardor-react": "0.3.0"
|
|
79
82
|
},
|
|
80
83
|
"peerDependencies": {
|
|
81
84
|
"@reduxjs/toolkit": ">=2.12.0",
|
|
82
85
|
"@tanstack/react-query": ">=5.101.2",
|
|
83
|
-
"@venizia/ignis-connectors": "^0.
|
|
84
|
-
"@venizia/ignis-filter": "^0.
|
|
85
|
-
"@venizia/ignis-helpers": "^0.
|
|
86
|
-
"@venizia/ignis-inversion": "^0.
|
|
87
|
-
"@venizia/ignis-kernel": "^0.
|
|
86
|
+
"@venizia/ignis-connectors": "^0.3.0",
|
|
87
|
+
"@venizia/ignis-filter": "^0.3.0",
|
|
88
|
+
"@venizia/ignis-helpers": "^0.3.0",
|
|
89
|
+
"@venizia/ignis-inversion": "^0.3.0",
|
|
90
|
+
"@venizia/ignis-kernel": "^0.3.0",
|
|
88
91
|
"ra-core": ">=5.15.0",
|
|
89
92
|
"ra-i18n-polyglot": ">=5.15.0",
|
|
90
93
|
"react": ">=18.0",
|
|
@@ -110,10 +113,10 @@
|
|
|
110
113
|
"@types/react": "^19",
|
|
111
114
|
"@types/react-dom": "^19",
|
|
112
115
|
"@venizia/dev-configs": "0.3.1",
|
|
113
|
-
"@venizia/ignis-connectors": "0.
|
|
114
|
-
"@venizia/ignis-filter": "0.
|
|
115
|
-
"@venizia/ignis-inversion": "0.
|
|
116
|
-
"@venizia/ignis-kernel": "0.
|
|
116
|
+
"@venizia/ignis-connectors": "0.3.0",
|
|
117
|
+
"@venizia/ignis-filter": "0.3.0",
|
|
118
|
+
"@venizia/ignis-inversion": "0.3.0",
|
|
119
|
+
"@venizia/ignis-kernel": "0.3.0",
|
|
117
120
|
"eslint": "^10.10.0",
|
|
118
121
|
"oxfmt": "0.73.0",
|
|
119
122
|
"oxlint": "1.88.0",
|