@venizia/ardor 0.3.1 → 0.3.4
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/dist/vulcan-preset/app/files/.configs/builders/Dockerfile +68 -0
- package/dist/vulcan-preset/app/files/.configs/builders/nginx.conf.template +31 -0
- package/dist/vulcan-preset/{files → app/files/.configs/builders}/vite.config.mts +8 -2
- package/dist/vulcan-preset/{files/.configs → app/files/.configs/lints}/oxlint.config.mts +1 -1
- package/dist/vulcan-preset/app/files/src/application.test.ts +37 -0
- package/dist/vulcan-preset/app/files/src/components/shadcn/button.tsx +26 -0
- package/dist/vulcan-preset/app/files/src/components/shadcn/card.tsx +10 -0
- package/dist/vulcan-preset/app/files/src/index.html +14 -0
- package/dist/vulcan-preset/{files → app/files}/src/main.tsx +5 -5
- package/dist/vulcan-preset/app/files/src/pages/home.tsx +57 -0
- package/dist/vulcan-preset/app/files/src/themes/index.css +71 -0
- package/dist/vulcan-preset/app/files/src/utilities/tw.utility.ts +4 -0
- package/dist/vulcan-preset/{files → app/files}/tsconfig.json +3 -7
- package/dist/vulcan-preset/app/preset.json +85 -0
- package/dist/vulcan-preset/lib/files/.configs/formatters/oxfmt.config.mts +4 -0
- package/dist/vulcan-preset/lib/files/.configs/lints/eslint.config.mjs +5 -0
- package/dist/vulcan-preset/lib/files/.configs/lints/oxlint.config.mts +4 -0
- package/dist/vulcan-preset/lib/files/src/feature.test.ts +37 -0
- package/dist/vulcan-preset/lib/files/src/feature.ts +6 -0
- package/dist/vulcan-preset/lib/files/src/index.ts +1 -0
- package/dist/vulcan-preset/lib/files/tsconfig.json +17 -0
- package/dist/vulcan-preset/lib/preset.json +55 -0
- package/package.json +8 -7
- package/dist/vulcan-preset/files/README.md +0 -7
- package/dist/vulcan-preset/files/index.html +0 -12
- package/dist/vulcan-preset/files/src/pages/product-create.tsx +0 -10
- package/dist/vulcan-preset/files/src/pages/product-edit.tsx +0 -10
- package/dist/vulcan-preset/files/src/pages/product-form.tsx +0 -32
- package/dist/vulcan-preset/files/src/pages/product-list.tsx +0 -42
- package/dist/vulcan-preset/preset.json +0 -71
- /package/dist/vulcan-preset/{files/.configs → app/files/.configs/formatters}/oxfmt.config.mts +0 -0
- /package/dist/vulcan-preset/{files/.configs → app/files/.configs/lints}/eslint.config.mjs +0 -0
- /package/dist/vulcan-preset/{files → app/files}/_env.example +0 -0
- /package/dist/vulcan-preset/{files → app/files}/src/application.ts +0 -0
- /package/dist/vulcan-preset/{files → app/files}/src/configurations/admin.configuration.ts +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# The image of {{app}}: the app compiled by Vite, served by nginx.
|
|
2
|
+
#
|
|
3
|
+
# Build it from the monorepo root, so the workspace packages and the lockfile are in the context:
|
|
4
|
+
#
|
|
5
|
+
# docker build -f {{appPath}}/.configs/builders/Dockerfile -t {{app}} \
|
|
6
|
+
# --build-arg APP_BUILD_COMMIT="$(git rev-parse HEAD)" \
|
|
7
|
+
# --build-arg APP_BUILD_BRANCH="$(git rev-parse --abbrev-ref HEAD)" .
|
|
8
|
+
# docker run --rm -p 8080:8080 -e API_UPSTREAM=http://api:3000 {{app}}
|
|
9
|
+
#
|
|
10
|
+
# The preset cannot know which workspace packages this app needs, so the whole context is copied (the
|
|
11
|
+
# .dockerignore at the root filters it), then installed and built. A project can list the packages by
|
|
12
|
+
# hand instead, copying each package.json first, so a change in a source file does not redo the install.
|
|
13
|
+
|
|
14
|
+
# -------------------------------------------------------------------------------
|
|
15
|
+
# Dependencies stage
|
|
16
|
+
# -------------------------------------------------------------------------------
|
|
17
|
+
FROM docker.io/oven/bun:1.4.3-alpine AS deps
|
|
18
|
+
|
|
19
|
+
# A private registry, when the build runs where the public one is not reachable. Empty by default.
|
|
20
|
+
ARG BUN_CONFIG_REGISTRY=
|
|
21
|
+
ENV BUN_CONFIG_REGISTRY=${BUN_CONFIG_REGISTRY}
|
|
22
|
+
|
|
23
|
+
RUN mkdir -p /home/bun/app && chown -R bun:bun /home/bun/app
|
|
24
|
+
WORKDIR /home/bun/app
|
|
25
|
+
USER bun
|
|
26
|
+
|
|
27
|
+
COPY --chown=bun . .
|
|
28
|
+
# An environment file in the context would stay in the COPY layer, whatever is deleted afterwards: stop
|
|
29
|
+
# here, and keep them out with the root .dockerignore (`**/.env`, `**/.env.*`, `!**/.env.example`).
|
|
30
|
+
RUN leaked="$(find . -name '.env*' ! -name '.env.example' -not -path '*/node_modules/*')"; \
|
|
31
|
+
if [ -n "$leaked" ]; then echo "Secrets in the build context: $leaked - add **/.env and **/.env.* to the root .dockerignore" >&2; exit 1; fi
|
|
32
|
+
RUN bun install --frozen-lockfile --ignore-scripts
|
|
33
|
+
|
|
34
|
+
# -------------------------------------------------------------------------------
|
|
35
|
+
# Build stage
|
|
36
|
+
# -------------------------------------------------------------------------------
|
|
37
|
+
FROM deps AS builder
|
|
38
|
+
|
|
39
|
+
# The image has no .git (the .dockerignore drops it), so the commit comes in as a build argument. A build
|
|
40
|
+
# without it stops here: an image must always say which commit it runs.
|
|
41
|
+
ARG APP_BUILD_COMMIT=
|
|
42
|
+
ARG APP_BUILD_BRANCH=
|
|
43
|
+
ARG APP_BUILD_VERSION=
|
|
44
|
+
RUN test -n "$APP_BUILD_COMMIT" || { echo "Pass --build-arg APP_BUILD_COMMIT=\$(git rev-parse HEAD)" >&2; exit 1; }
|
|
45
|
+
|
|
46
|
+
WORKDIR /home/bun/app/{{appPath}}
|
|
47
|
+
RUN bun run compile
|
|
48
|
+
|
|
49
|
+
# -------------------------------------------------------------------------------
|
|
50
|
+
# Production stage
|
|
51
|
+
# -------------------------------------------------------------------------------
|
|
52
|
+
FROM docker.io/nginxinc/nginx-unprivileged:1.30.4-alpine AS production
|
|
53
|
+
|
|
54
|
+
ARG APP_BUILD_COMMIT=
|
|
55
|
+
LABEL org.opencontainers.image.revision="${APP_BUILD_COMMIT}"
|
|
56
|
+
|
|
57
|
+
# The base image's entrypoint turns every /etc/nginx/templates/*.template into /etc/nginx/conf.d/*,
|
|
58
|
+
# replacing ${API_UPSTREAM} and leaving nginx's own variables ($uri, $host) as they are.
|
|
59
|
+
COPY --from=builder /home/bun/app/{{appPath}}/.configs/builders/nginx.conf.template /etc/nginx/templates/default.conf.template
|
|
60
|
+
COPY --from=builder --chown=101:101 /home/bun/app/{{appPath}}/dist /usr/share/nginx/html
|
|
61
|
+
|
|
62
|
+
# Where /api goes: a compose service name, a cluster service, an address.
|
|
63
|
+
ENV API_UPSTREAM=http://api:3000
|
|
64
|
+
|
|
65
|
+
# No ENTRYPOINT on purpose: the base image's /docker-entrypoint.sh renders the templates.
|
|
66
|
+
EXPOSE 8080
|
|
67
|
+
|
|
68
|
+
CMD ["nginx", "-g", "daemon off;"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# The nginx configuration of {{app}}, rendered by the base image at start: ${API_UPSTREAM} is the
|
|
2
|
+
# only variable replaced; $uri and $host are nginx's own.
|
|
3
|
+
server {
|
|
4
|
+
listen 8080;
|
|
5
|
+
server_name _;
|
|
6
|
+
|
|
7
|
+
root /usr/share/nginx/html;
|
|
8
|
+
index index.html;
|
|
9
|
+
|
|
10
|
+
# The backend. The path is kept: /api/hello reaches ${API_UPSTREAM}/api/hello.
|
|
11
|
+
location /api/ {
|
|
12
|
+
proxy_pass ${API_UPSTREAM};
|
|
13
|
+
proxy_http_version 1.1;
|
|
14
|
+
proxy_set_header Host $host;
|
|
15
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
16
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# The built files carry a content hash in their name, so a browser may keep them for good.
|
|
20
|
+
location /assets/ {
|
|
21
|
+
expires 1y;
|
|
22
|
+
add_header Cache-Control "public, immutable";
|
|
23
|
+
try_files $uri =404;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# A route of the app, opened or reloaded directly, is served by the app.
|
|
27
|
+
location / {
|
|
28
|
+
add_header Cache-Control "no-cache";
|
|
29
|
+
try_files $uri $uri/ /index.html;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
1
2
|
import { IgnisArtifactsVitePlugin } from '@venizia/ignis-boot/vite';
|
|
2
3
|
import react from '@vitejs/plugin-react';
|
|
3
4
|
import { defineConfig, loadEnv } from 'vite';
|
|
@@ -9,15 +10,20 @@ export default defineConfig(({ mode }) => {
|
|
|
9
10
|
const proxy: Record<string, string> = apiUrl === '' ? {} : { '/api': apiUrl };
|
|
10
11
|
|
|
11
12
|
return {
|
|
13
|
+
// The app's own files are in src/, index.html included, so nothing but .configs/, src/, package.json,
|
|
14
|
+
// tsconfig.json and .env.example sits at the app root; `.env` files are read from that root.
|
|
15
|
+
root: 'src',
|
|
16
|
+
envDir: '..',
|
|
12
17
|
// 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' } },
|
|
18
|
+
plugins: [IgnisArtifactsVitePlugin.create({ root: 'src' }), react(), tailwindcss()],
|
|
15
19
|
server: {
|
|
16
20
|
port: Number(env.PORT ?? '{{devPort}}'),
|
|
17
21
|
strictPort: true,
|
|
18
22
|
proxy,
|
|
19
23
|
},
|
|
20
24
|
build: {
|
|
25
|
+
outDir: '../dist',
|
|
26
|
+
emptyOutDir: true,
|
|
21
27
|
rolldownOptions: {
|
|
22
28
|
output: {
|
|
23
29
|
// React, react-admin and the router weigh about 500 KB before any application code. Two
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from 'bun:test';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
BaseArdorApplication,
|
|
7
|
+
CoreBindings,
|
|
8
|
+
type IApplicationInfo,
|
|
9
|
+
type IArtifactIndex,
|
|
10
|
+
} from '@venizia/ardor';
|
|
11
|
+
|
|
12
|
+
import { AdminConfiguration } from '#src/configurations/admin.configuration';
|
|
13
|
+
|
|
14
|
+
// The class list is given by hand: the one `application.ts` uses is built by Vite, not by Bun.
|
|
15
|
+
class TestApplication extends BaseArdorApplication {
|
|
16
|
+
getAppInfo(): IApplicationInfo {
|
|
17
|
+
return { name: 'test', version: '0.0.0', description: 'A test of the container' };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override artifacts(): Array<IArtifactIndex> {
|
|
21
|
+
return [{ configurations: [AdminConfiguration] }];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
bindContext(): void {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('AdminConfiguration', () => {
|
|
28
|
+
test('binds the REST data provider options under their key', async () => {
|
|
29
|
+
const application = new TestApplication();
|
|
30
|
+
|
|
31
|
+
await application.start();
|
|
32
|
+
|
|
33
|
+
expect(application.get({ key: CoreBindings.REST_DATA_PROVIDER_OPTIONS })).toMatchObject({
|
|
34
|
+
url: '/api',
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import type { ComponentProps } from 'react';
|
|
3
|
+
|
|
4
|
+
import { cn } from '#src/utilities/tw.utility';
|
|
5
|
+
|
|
6
|
+
// Also applied to a router `Link`, so a link can look like a button.
|
|
7
|
+
export const buttonVariants = cva(
|
|
8
|
+
'inline-flex h-9 shrink-0 items-center justify-center gap-2 rounded-md px-4 text-sm font-medium whitespace-nowrap transition-colors outline-none focus-visible:outline-2 focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4',
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
13
|
+
outline: 'border bg-card hover:bg-accent hover:text-accent-foreground',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: { variant: 'default' },
|
|
17
|
+
},
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const Button = ({
|
|
21
|
+
className,
|
|
22
|
+
variant,
|
|
23
|
+
...props
|
|
24
|
+
}: ComponentProps<'button'> & VariantProps<typeof buttonVariants>) => (
|
|
25
|
+
<button className={cn(buttonVariants({ variant }), className)} {...props} />
|
|
26
|
+
);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
|
|
3
|
+
import { cn } from '#src/utilities/tw.utility';
|
|
4
|
+
|
|
5
|
+
export const Card = ({ className, ...props }: ComponentProps<'div'>) => (
|
|
6
|
+
<div
|
|
7
|
+
className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)}
|
|
8
|
+
{...props}
|
|
9
|
+
/>
|
|
10
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
<meta name="color-scheme" content="light dark" />
|
|
7
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2092%20123'%3E%3Cpath%20d%3D'M46%202C46%202%204%2052%204%2080a42%2042%200%200%200%2084%200C88%2060%2070%2036%2046%202Z'%20fill%3D'%230091EA'%2F%3E%3Cpath%20d%3D'M30%2092c-6-14-2-32%2014-38-4%2012%204%2022%2014%2024%2010%202%2016-6%2016-14%206%2014%202%2030-10%2038-12%208-28%204-34-10Z'%20fill%3D'%237DF3FF'%2F%3E%3C%2Fsvg%3E" />
|
|
8
|
+
<title>{{app}}</title>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module" src="/main.tsx"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -4,10 +4,10 @@ import { configureStore } from '@reduxjs/toolkit';
|
|
|
4
4
|
import { ArdorApplication } from '@venizia/ardor';
|
|
5
5
|
import { createRoot } from 'react-dom/client';
|
|
6
6
|
|
|
7
|
-
import { Application } from '
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import
|
|
7
|
+
import { Application } from '#src/application';
|
|
8
|
+
import { Home } from '#src/pages/home';
|
|
9
|
+
|
|
10
|
+
import './themes/index.css';
|
|
11
11
|
|
|
12
12
|
const application = new Application();
|
|
13
13
|
const store = configureStore({
|
|
@@ -21,6 +21,6 @@ createRoot(document.getElementById('root')!).render(
|
|
|
21
21
|
container={application}
|
|
22
22
|
reduxStore={store}
|
|
23
23
|
suspense={<p>Loading</p>}
|
|
24
|
-
|
|
24
|
+
dashboard={Home}
|
|
25
25
|
/>,
|
|
26
26
|
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type IDataProvider } from '@venizia/ardor';
|
|
2
|
+
import { useQuery } from '@tanstack/react-query';
|
|
3
|
+
import { useDataProvider } from 'ra-core';
|
|
4
|
+
|
|
5
|
+
import { Button } from '#src/components/shadcn/button';
|
|
6
|
+
import { Card } from '#src/components/shadcn/card';
|
|
7
|
+
|
|
8
|
+
// The ARDOR drop. Its own colours: they read on the light and the dark surface alike.
|
|
9
|
+
const Logo = () => (
|
|
10
|
+
<svg aria-hidden="true" viewBox="0 0 92 123" className="h-14 w-auto">
|
|
11
|
+
<path d="M46 2C46 2 4 52 4 80a42 42 0 0 0 84 0C88 60 70 36 46 2Z" fill="#0091EA" />
|
|
12
|
+
<path
|
|
13
|
+
d="M30 92c-6-14-2-32 14-38-4 12 4 22 14 24 10 2 16-6 16-14 6 14 2 30-10 38-12 8-28 4-34-10Z"
|
|
14
|
+
fill="#7DF3FF"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// What the app shows: the name, and what the backend answers to `GET /api/hello`. The call goes through
|
|
20
|
+
// the data provider's `send`, which adds the `/api` prefix and the headers every request of the app has.
|
|
21
|
+
export const Home = () => {
|
|
22
|
+
const dataProvider = useDataProvider<IDataProvider>();
|
|
23
|
+
const hello = useQuery({
|
|
24
|
+
queryKey: ['hello'],
|
|
25
|
+
queryFn: () =>
|
|
26
|
+
dataProvider.send<{ message: string }>({ resource: 'hello', params: { method: 'GET' } }),
|
|
27
|
+
retry: false,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className="relative grid min-h-svh place-items-center overflow-hidden p-4">
|
|
32
|
+
<div
|
|
33
|
+
aria-hidden="true"
|
|
34
|
+
className="pointer-events-none absolute inset-x-0 top-0 -z-10 h-96 bg-(image:--brand-gradient) opacity-25 blur-3xl [mask-image:radial-gradient(60%_100%_at_50%_0%,black,transparent)] dark:opacity-20"
|
|
35
|
+
/>
|
|
36
|
+
<Card className="flex w-full max-w-md flex-col items-center gap-6 rounded-2xl px-8 py-12 text-center shadow-[0_12px_32px_-16px_rgb(2_119_189/0.35)]">
|
|
37
|
+
<Logo />
|
|
38
|
+
<h1 className="text-4xl font-semibold tracking-tight">{'{{app}}'}</h1>
|
|
39
|
+
{hello.isPending ? (
|
|
40
|
+
<div className="h-6 w-48 animate-pulse rounded-md bg-muted" />
|
|
41
|
+
) : hello.isError ? (
|
|
42
|
+
<div className="flex flex-col items-center gap-3 text-sm text-muted-foreground">
|
|
43
|
+
<p>The backend is not reachable. Start it from its folder:</p>
|
|
44
|
+
<code className="rounded-md bg-muted px-3 py-1.5 font-mono text-foreground">
|
|
45
|
+
bun run server:dev
|
|
46
|
+
</code>
|
|
47
|
+
<Button variant="outline" onClick={() => hello.refetch()}>
|
|
48
|
+
Try again
|
|
49
|
+
</Button>
|
|
50
|
+
</div>
|
|
51
|
+
) : (
|
|
52
|
+
<p className="text-lg text-muted-foreground">{hello.data.data.message}</p>
|
|
53
|
+
)}
|
|
54
|
+
</Card>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
/* Dark follows the system preference: no class and no toggle. */
|
|
4
|
+
@custom-variant dark (@media (prefers-color-scheme: dark));
|
|
5
|
+
|
|
6
|
+
/* ARDOR's Tide palette (blues over deep water, no teal), as shadcn tokens. The primary is white-on-blue
|
|
7
|
+
AA (4.8:1); accent text is the deep blue on light and the light blue on dark, never #0277bd as small text
|
|
8
|
+
on dark. Components read the tokens, so a new theme is this block and nothing else. */
|
|
9
|
+
:root {
|
|
10
|
+
color-scheme: light dark;
|
|
11
|
+
--background: #f4f7f8;
|
|
12
|
+
--foreground: #0b1418;
|
|
13
|
+
--card: #ffffff;
|
|
14
|
+
--card-foreground: #0b1418;
|
|
15
|
+
--muted: #e8eff2;
|
|
16
|
+
--muted-foreground: #4b5b63;
|
|
17
|
+
--border: #d8e2e6;
|
|
18
|
+
--input: #c4d1d7;
|
|
19
|
+
--primary: #0277bd;
|
|
20
|
+
--primary-foreground: #ffffff;
|
|
21
|
+
--accent: #e0f2fc;
|
|
22
|
+
--accent-foreground: #01579b;
|
|
23
|
+
--ring: #38bdf8;
|
|
24
|
+
--radius: 0.75rem;
|
|
25
|
+
/* The brand gradient: the wash behind the card, nothing else. */
|
|
26
|
+
--brand-gradient: linear-gradient(90deg, #0091ea, #38bdf8, #7df3ff);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media (prefers-color-scheme: dark) {
|
|
30
|
+
:root {
|
|
31
|
+
--background: #07090b;
|
|
32
|
+
--foreground: #d5dee0;
|
|
33
|
+
--card: #0d1317;
|
|
34
|
+
--card-foreground: #d5dee0;
|
|
35
|
+
--muted: #131b20;
|
|
36
|
+
--muted-foreground: #8e9ca3;
|
|
37
|
+
--border: #1d2830;
|
|
38
|
+
--input: #2a3841;
|
|
39
|
+
--accent: #0c2433;
|
|
40
|
+
--accent-foreground: #38bdf8;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@theme inline {
|
|
45
|
+
--color-background: var(--background);
|
|
46
|
+
--color-foreground: var(--foreground);
|
|
47
|
+
--color-card: var(--card);
|
|
48
|
+
--color-card-foreground: var(--card-foreground);
|
|
49
|
+
--color-muted: var(--muted);
|
|
50
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
51
|
+
--color-border: var(--border);
|
|
52
|
+
--color-input: var(--input);
|
|
53
|
+
--color-primary: var(--primary);
|
|
54
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
55
|
+
--color-accent: var(--accent);
|
|
56
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
57
|
+
--color-ring: var(--ring);
|
|
58
|
+
--radius-lg: var(--radius);
|
|
59
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
60
|
+
--font-sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@layer base {
|
|
64
|
+
* {
|
|
65
|
+
@apply border-border outline-ring;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
body {
|
|
69
|
+
@apply bg-background font-sans text-foreground antialiased;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -4,18 +4,14 @@
|
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"target": "ESNext",
|
|
6
6
|
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
|
7
|
-
"types": ["vite/client"],
|
|
7
|
+
"types": ["vite/client", "bun"],
|
|
8
8
|
"noEmit": true,
|
|
9
9
|
"isolatedModules": true,
|
|
10
10
|
|
|
11
11
|
// Restated, not inherited: Bun ignores an `extends` that names a package.
|
|
12
12
|
"experimentalDecorators": true,
|
|
13
13
|
"emitDecoratorMetadata": true,
|
|
14
|
-
"useDefineForClassFields": false
|
|
15
|
-
|
|
16
|
-
"paths": {
|
|
17
|
-
"@/*": ["./src/*"]
|
|
18
|
-
}
|
|
14
|
+
"useDefineForClassFields": false
|
|
19
15
|
},
|
|
20
|
-
"include": ["src", "vite.config.mts"]
|
|
16
|
+
"include": ["src", ".configs/builders/vite.config.mts"]
|
|
21
17
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presetVersion": 1,
|
|
3
|
+
"side": "frontend",
|
|
4
|
+
"summary": "An ARDOR app on Vite and React: the app name and the message of GET /api/hello, styled with Tailwind CSS and shadcn components, REST data provider and i18n, no sign-in.",
|
|
5
|
+
"devPort": 5173,
|
|
6
|
+
"imports": {
|
|
7
|
+
"#src/*.json": "./src/*.json",
|
|
8
|
+
"#src/*": "./src/*.js"
|
|
9
|
+
},
|
|
10
|
+
"urls": [
|
|
11
|
+
"/"
|
|
12
|
+
],
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@reduxjs/toolkit": "^2.12.0",
|
|
15
|
+
"@tanstack/react-query": "^5.101.2",
|
|
16
|
+
"@venizia/ardor": "0.3.4",
|
|
17
|
+
"@venizia/ignis-connectors": "0.3.4",
|
|
18
|
+
"@venizia/ignis-filter": "0.3.4",
|
|
19
|
+
"@venizia/ignis-helpers": "0.3.4",
|
|
20
|
+
"@venizia/ignis-inversion": "0.3.5",
|
|
21
|
+
"@venizia/ignis-kernel": "0.3.4",
|
|
22
|
+
"class-variance-authority": "^0.7.1",
|
|
23
|
+
"clsx": "^2.1.1",
|
|
24
|
+
"ra-core": "^5.15.0",
|
|
25
|
+
"ra-i18n-polyglot": "^5.15.0",
|
|
26
|
+
"react": "^19.2.7",
|
|
27
|
+
"react-dom": "^19.2.7",
|
|
28
|
+
"react-redux": "^9.3.0",
|
|
29
|
+
"react-router-dom": "^7.9.4",
|
|
30
|
+
"reflect-metadata": "^0.2.2",
|
|
31
|
+
"tailwind-merge": "^3.7.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
35
|
+
"@types/bun": "^1.4.1",
|
|
36
|
+
"@types/react": "^19",
|
|
37
|
+
"@types/react-dom": "^19",
|
|
38
|
+
"@venizia/dev-configs": "0.3.4",
|
|
39
|
+
"@venizia/ignis-boot": "0.3.4",
|
|
40
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
41
|
+
"eslint": "^10.10.0",
|
|
42
|
+
"oxfmt": "0.73.0",
|
|
43
|
+
"oxlint": "1.88.0",
|
|
44
|
+
"oxlint-tsgolint": "7.0.2004",
|
|
45
|
+
"tailwindcss": "^4.3.3",
|
|
46
|
+
"typescript": "^6.0.3",
|
|
47
|
+
"vite": "^8.2.2"
|
|
48
|
+
},
|
|
49
|
+
"peers": {
|
|
50
|
+
"@venizia/dev-configs": "^0.3.4",
|
|
51
|
+
"@venizia/ignis-connectors": "^0.3.0",
|
|
52
|
+
"@venizia/ignis-filter": "^0.3.0",
|
|
53
|
+
"@venizia/ignis-helpers": "^0.3.0",
|
|
54
|
+
"@venizia/ignis-inversion": "^0.3.0",
|
|
55
|
+
"@venizia/ignis-kernel": "^0.3.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"server:dev": "vite --config .configs/builders/vite.config.mts",
|
|
59
|
+
"compile": "vite build --config .configs/builders/vite.config.mts",
|
|
60
|
+
"typecheck": "bun check --no-pretty -p tsconfig.json",
|
|
61
|
+
"lint": "devz lint",
|
|
62
|
+
"lint:fix": "devz lint --fix",
|
|
63
|
+
"test": "bun test",
|
|
64
|
+
"clean": "devz clean"
|
|
65
|
+
},
|
|
66
|
+
"checks": [
|
|
67
|
+
"typecheck",
|
|
68
|
+
"lint",
|
|
69
|
+
"test",
|
|
70
|
+
"compile"
|
|
71
|
+
],
|
|
72
|
+
"files": "./files",
|
|
73
|
+
"atlas": [
|
|
74
|
+
{
|
|
75
|
+
"name": "ardor",
|
|
76
|
+
"repo": "VENIZIA-AI/ardor",
|
|
77
|
+
"ref": "develop"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "ignis",
|
|
81
|
+
"repo": "VENIZIA-AI/ignis",
|
|
82
|
+
"ref": "develop"
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from 'bun:test';
|
|
4
|
+
import {
|
|
5
|
+
BaseArdorApplication,
|
|
6
|
+
Features,
|
|
7
|
+
type IApplicationInfo,
|
|
8
|
+
type IFeatureBase,
|
|
9
|
+
} from '@venizia/ardor';
|
|
10
|
+
|
|
11
|
+
import { feature } from '#src/feature';
|
|
12
|
+
|
|
13
|
+
class ProbeApplication extends BaseArdorApplication {
|
|
14
|
+
getAppInfo(): IApplicationInfo {
|
|
15
|
+
return { name: 'probe', version: '0.0.0', description: 'mounts the {{lib}} feature' };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override features(): Array<IFeatureBase> {
|
|
19
|
+
return [feature];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
bindContext(): void {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('the {{lib}} feature', () => {
|
|
26
|
+
test('is named {{lib}}', () => {
|
|
27
|
+
expect(feature.name).toBe('{{lib}}');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('an application that lists it starts and reads it back from the container', async () => {
|
|
31
|
+
const application = new ProbeApplication();
|
|
32
|
+
|
|
33
|
+
await application.start();
|
|
34
|
+
|
|
35
|
+
expect(Features.read({ container: application })).toEqual([feature]);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Features } from '@venizia/ardor';
|
|
2
|
+
|
|
3
|
+
// {{package}} as one ARDOR feature, mounted by the apps that list it in `features()`. Empty until the
|
|
4
|
+
// first module moves in: each module adds its routes, resources and messages here, and nothing in the
|
|
5
|
+
// package depends on an app.
|
|
6
|
+
export const feature = Features.define({ name: '{{lib}}' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './feature';
|
|
@@ -0,0 +1,17 @@
|
|
|
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": ["bun"],
|
|
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
|
+
"include": ["src"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"presetVersion": 1,
|
|
3
|
+
"summary": "An ARDOR feature package: one Features.define, a test that mounts it in a probe application, typecheck, lint and test. No bundler and no dev server.",
|
|
4
|
+
"dependencies": {},
|
|
5
|
+
"devDependencies": {
|
|
6
|
+
"@types/bun": "^1.4.1",
|
|
7
|
+
"@types/react": "^19",
|
|
8
|
+
"@venizia/ardor": "^0.3.4",
|
|
9
|
+
"@venizia/dev-configs": "0.3.4",
|
|
10
|
+
"eslint": "^10.10.0",
|
|
11
|
+
"oxfmt": "0.73.0",
|
|
12
|
+
"oxlint": "1.88.0",
|
|
13
|
+
"oxlint-tsgolint": "7.0.2004",
|
|
14
|
+
"react": "^19.2.7",
|
|
15
|
+
"react-dom": "^19.2.7",
|
|
16
|
+
"react-router-dom": "^7.9.4",
|
|
17
|
+
"reflect-metadata": "^0.2.2",
|
|
18
|
+
"typescript": "^6.0.3"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"@venizia/ardor": "^0.3.4",
|
|
22
|
+
"react": "^19.2.7",
|
|
23
|
+
"react-dom": "^19.2.7",
|
|
24
|
+
"react-router-dom": "^7.9.4",
|
|
25
|
+
"reflect-metadata": "^0.2.2"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"typecheck": "bun check --no-pretty -p tsconfig.json",
|
|
29
|
+
"lint": "devz lint",
|
|
30
|
+
"lint:fix": "devz lint --fix",
|
|
31
|
+
"test": "bun test",
|
|
32
|
+
"clean": "devz clean"
|
|
33
|
+
},
|
|
34
|
+
"checks": [
|
|
35
|
+
"typecheck",
|
|
36
|
+
"lint",
|
|
37
|
+
"test"
|
|
38
|
+
],
|
|
39
|
+
"imports": {
|
|
40
|
+
"#src/*.json": "./src/*.json",
|
|
41
|
+
"#src/*": "./src/*.js"
|
|
42
|
+
},
|
|
43
|
+
"exports": {
|
|
44
|
+
".": "./src/index.ts"
|
|
45
|
+
},
|
|
46
|
+
"packageFields": {
|
|
47
|
+
"type": "module",
|
|
48
|
+
"sideEffects": false,
|
|
49
|
+
"engines": {
|
|
50
|
+
"bun": ">=1.4"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"files": "./files",
|
|
54
|
+
"atlas": []
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venizia/ardor",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
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",
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
},
|
|
60
60
|
"sideEffects": false,
|
|
61
61
|
"vulcan": {
|
|
62
|
-
"preset": "./dist/vulcan-preset/preset.json"
|
|
62
|
+
"preset": "./dist/vulcan-preset/app/preset.json",
|
|
63
|
+
"lib": "./dist/vulcan-preset/lib/preset.json"
|
|
63
64
|
},
|
|
64
65
|
"files": [
|
|
65
66
|
"README.md",
|
|
@@ -112,11 +113,11 @@
|
|
|
112
113
|
"@types/bun": "^1.4.1",
|
|
113
114
|
"@types/react": "^19",
|
|
114
115
|
"@types/react-dom": "^19",
|
|
115
|
-
"@venizia/dev-configs": "^0.3.
|
|
116
|
-
"@venizia/ignis-connectors": "^0.3.
|
|
117
|
-
"@venizia/ignis-filter": "^0.3.
|
|
118
|
-
"@venizia/ignis-inversion": "^0.3.
|
|
119
|
-
"@venizia/ignis-kernel": "^0.3.
|
|
116
|
+
"@venizia/dev-configs": "^0.3.4",
|
|
117
|
+
"@venizia/ignis-connectors": "^0.3.4",
|
|
118
|
+
"@venizia/ignis-filter": "^0.3.4",
|
|
119
|
+
"@venizia/ignis-inversion": "^0.3.5",
|
|
120
|
+
"@venizia/ignis-kernel": "^0.3.4",
|
|
120
121
|
"eslint": "^10.10.0",
|
|
121
122
|
"oxfmt": "0.73.0",
|
|
122
123
|
"oxlint": "1.88.0",
|
|
@@ -1,7 +0,0 @@
|
|
|
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.mts`).
|
|
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`.
|
|
@@ -1,12 +0,0 @@
|
|
|
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>
|
|
@@ -1,32 +0,0 @@
|
|
|
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
|
-
);
|
|
@@ -1,42 +0,0 @@
|
|
|
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
|
-
);
|
|
@@ -1,71 +0,0 @@
|
|
|
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
|
-
"urls": [
|
|
7
|
-
"/"
|
|
8
|
-
],
|
|
9
|
-
"dependencies": {
|
|
10
|
-
"@reduxjs/toolkit": "^2.12.0",
|
|
11
|
-
"@tanstack/react-query": "^5.101.2",
|
|
12
|
-
"@venizia/ardor": "0.3.1",
|
|
13
|
-
"@venizia/ignis-connectors": "0.3.1",
|
|
14
|
-
"@venizia/ignis-filter": "0.3.1",
|
|
15
|
-
"@venizia/ignis-helpers": "0.3.1",
|
|
16
|
-
"@venizia/ignis-inversion": "0.3.1",
|
|
17
|
-
"@venizia/ignis-kernel": "0.3.1",
|
|
18
|
-
"ra-core": "^5.15.0",
|
|
19
|
-
"ra-i18n-polyglot": "^5.15.0",
|
|
20
|
-
"react": "^19.2.7",
|
|
21
|
-
"react-dom": "^19.2.7",
|
|
22
|
-
"react-redux": "^9.3.0",
|
|
23
|
-
"react-router-dom": "^7.9.4",
|
|
24
|
-
"reflect-metadata": "^0.2.2"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/react": "^19",
|
|
28
|
-
"@types/react-dom": "^19",
|
|
29
|
-
"@venizia/dev-configs": "0.3.1",
|
|
30
|
-
"@venizia/ignis-boot": "0.3.1",
|
|
31
|
-
"@vitejs/plugin-react": "^6.1.1",
|
|
32
|
-
"eslint": "^10.10.0",
|
|
33
|
-
"oxfmt": "0.73.0",
|
|
34
|
-
"oxlint": "1.88.0",
|
|
35
|
-
"oxlint-tsgolint": "7.0.2004",
|
|
36
|
-
"typescript": "^6.0.3",
|
|
37
|
-
"vite": "^8.2.2"
|
|
38
|
-
},
|
|
39
|
-
"peers": {
|
|
40
|
-
"@venizia/ignis-connectors": "^0.3.0",
|
|
41
|
-
"@venizia/ignis-filter": "^0.3.0",
|
|
42
|
-
"@venizia/ignis-helpers": "^0.3.0",
|
|
43
|
-
"@venizia/ignis-inversion": "^0.3.0",
|
|
44
|
-
"@venizia/ignis-kernel": "^0.3.0"
|
|
45
|
-
},
|
|
46
|
-
"scripts": {
|
|
47
|
-
"dev": "vite",
|
|
48
|
-
"build": "vite build",
|
|
49
|
-
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
50
|
-
"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}\"",
|
|
51
|
-
"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}\""
|
|
52
|
-
},
|
|
53
|
-
"checks": [
|
|
54
|
-
"typecheck",
|
|
55
|
-
"lint",
|
|
56
|
-
"build"
|
|
57
|
-
],
|
|
58
|
-
"files": "./files",
|
|
59
|
-
"atlas": [
|
|
60
|
-
{
|
|
61
|
-
"name": "ardor",
|
|
62
|
-
"repo": "VENIZIA-AI/ardor",
|
|
63
|
-
"ref": "develop"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
"name": "ignis",
|
|
67
|
-
"repo": "VENIZIA-AI/ignis",
|
|
68
|
-
"ref": "develop"
|
|
69
|
-
}
|
|
70
|
-
]
|
|
71
|
-
}
|
/package/dist/vulcan-preset/{files/.configs → app/files/.configs/formatters}/oxfmt.config.mts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|