odoro 1.0.0 → 1.0.2
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 +73 -0
- package/dist/cli.js +3 -3
- package/dist/{commands-PT3NS65O.js → commands-AHMXBWQQ.js} +25 -5
- package/dist/{create-IOFAPDBO.js → create-GD6O2TPL.js} +118 -70
- package/dist/{package-6ADADETZ.js → package-VMTZDORI.js} +1 -1
- package/dist/registry/index.d.ts +2 -2
- package/package.json +1 -1
- package/templates/react-ts/_variantes/avec-moteur/src/fond.tsx +118 -0
- package/templates/react-ts/_variantes/sans-libs/src/App.tsx +245 -45
- package/templates/react-ts/_variantes/sans-libs/src/fond.tsx +23 -0
- package/templates/react-ts/_variantes/sans-libs/src/styles.css +357 -42
- package/templates/react-ts/_variantes/sans-routeur/src/App.tsx +305 -62
- package/templates/react-ts/public/favicon.svg +2 -3
- package/templates/react-ts/src/App.tsx +443 -43
- package/templates/react-ts/src/fond.tsx +42 -0
- package/templates/react-ts/src/router.tsx +72 -0
- package/templates/react-ts/src/styles.css +4 -5
- package/templates/react-ts-server/_variantes/avec-moteur/client/src/fond.tsx +118 -0
- package/templates/react-ts-server/_variantes/sans-libs/client/src/App.tsx +245 -45
- package/templates/react-ts-server/_variantes/sans-libs/client/src/fond.tsx +23 -0
- package/templates/react-ts-server/_variantes/sans-libs/client/src/styles.css +357 -42
- package/templates/react-ts-server/_variantes/sans-routeur/client/src/App.tsx +305 -62
- package/templates/react-ts-server/client/public/favicon.svg +2 -3
- package/templates/react-ts-server/client/src/App.tsx +443 -43
- package/templates/react-ts-server/client/src/fond.tsx +42 -0
- package/templates/react-ts-server/client/src/router.tsx +72 -0
- package/templates/react-ts-server/client/src/styles.css +4 -5
- package/templates/react-ts/src/routes/About.tsx +0 -19
- package/templates/react-ts/src/routes/Home.tsx +0 -80
- package/templates/react-ts/src/routes/NotFound.tsx +0 -14
- package/templates/react-ts-server/client/src/routes/About.tsx +0 -19
- package/templates/react-ts-server/client/src/routes/Home.tsx +0 -148
- package/templates/react-ts-server/client/src/routes/NotFound.tsx +0 -14
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react'
|
|
2
|
-
|
|
3
|
-
import { Reveal, Stagger, useAnimate } from '@odoro-cli/libs/motion'
|
|
4
|
-
import { Link } from '@odoro-cli/libs/router'
|
|
5
|
-
import { Button } from '@odoro-cli/libs/ui'
|
|
6
|
-
|
|
7
|
-
/** Trois arguments mis en avant sur la page d'accueil. */
|
|
8
|
-
const FEATURES = [
|
|
9
|
-
{
|
|
10
|
-
title: 'Routeur',
|
|
11
|
-
body: 'Segments dynamiques, routes imbriquees, chargement paresseux et transitions de page.',
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
title: 'Animations',
|
|
15
|
-
body: "Une couche mince sur le moteur du navigateur. Les animations reduites sont respectees d'office.",
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
title: 'Styles',
|
|
19
|
-
body: 'Des tokens en source de verite, une feuille statique, aucun scan a l execution.',
|
|
20
|
-
},
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
/** Page d'accueil. */
|
|
24
|
-
export function Home() {
|
|
25
|
-
const [ref, controls] = useAnimate<HTMLSpanElement>()
|
|
26
|
-
const [count, setCount] = useState(0)
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div className="o-flex o-flex-col o-gap-12">
|
|
30
|
-
<Reveal>
|
|
31
|
-
<h1 className="o-text-4xl o-font-bold o-tracking-tight">
|
|
32
|
-
Un point de depart maitrise.
|
|
33
|
-
</h1>
|
|
34
|
-
<p className="o-mt-4 o-text-lg o-text-zinc-500 dark:o-text-zinc-400 o-max-w-prose">
|
|
35
|
-
Ce projet a ete genere par <code className="o-font-mono">odoro create</code>. Le
|
|
36
|
-
routeur, le moteur d animation et le systeme de style viennent tous de la meme
|
|
37
|
-
librairie.
|
|
38
|
-
</p>
|
|
39
|
-
</Reveal>
|
|
40
|
-
|
|
41
|
-
<Stagger step={80} className="o-grid o-grid-cols-1 md:o-grid-cols-3 o-gap-4">
|
|
42
|
-
{FEATURES.map((feature) => (
|
|
43
|
-
<article
|
|
44
|
-
key={feature.title}
|
|
45
|
-
className="o-rounded-lg o-border-w-1 o-border-zinc-200 dark:o-border-zinc-800 o-bg-white dark:o-bg-zinc-900 o-p-5"
|
|
46
|
-
>
|
|
47
|
-
<h2 className="o-font-semibold">{feature.title}</h2>
|
|
48
|
-
<p className="o-mt-2 o-text-sm o-text-zinc-500 dark:o-text-zinc-400">
|
|
49
|
-
{feature.body}
|
|
50
|
-
</p>
|
|
51
|
-
</article>
|
|
52
|
-
))}
|
|
53
|
-
</Stagger>
|
|
54
|
-
|
|
55
|
-
<div className="o-flex o-items-center o-gap-4">
|
|
56
|
-
<Button
|
|
57
|
-
onClick={() => {
|
|
58
|
-
setCount((value) => value + 1)
|
|
59
|
-
void controls.play(
|
|
60
|
-
[
|
|
61
|
-
{ transform: 'translateY(0)' },
|
|
62
|
-
{ transform: 'translateY(-0.4rem)' },
|
|
63
|
-
{ transform: 'translateY(0)' },
|
|
64
|
-
],
|
|
65
|
-
{ duration: 'fast', easing: 'emphasized' },
|
|
66
|
-
)
|
|
67
|
-
}}
|
|
68
|
-
>
|
|
69
|
-
Compter
|
|
70
|
-
</Button>
|
|
71
|
-
<span ref={ref} className="o-inline-block o-text-lg o-tabular-nums">
|
|
72
|
-
{count}
|
|
73
|
-
</span>
|
|
74
|
-
<Link to="/a-propos" className="o-text-sm">
|
|
75
|
-
En savoir plus
|
|
76
|
-
</Link>
|
|
77
|
-
</div>
|
|
78
|
-
</div>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Link } from '@odoro-cli/libs/router'
|
|
2
|
-
|
|
3
|
-
/** Page affichee pour toute route inconnue. */
|
|
4
|
-
export function NotFound() {
|
|
5
|
-
return (
|
|
6
|
-
<div className="o-flex o-flex-col o-gap-4" role="alert">
|
|
7
|
-
<h1 className="o-text-3xl o-font-bold">404</h1>
|
|
8
|
-
<p className="o-text-zinc-500 dark:o-text-zinc-400">Cette page n existe pas.</p>
|
|
9
|
-
<p>
|
|
10
|
-
<Link to="/">Retour a l accueil</Link>
|
|
11
|
-
</p>
|
|
12
|
-
</div>
|
|
13
|
-
)
|
|
14
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Reveal } from '@odoro-cli/libs/motion'
|
|
2
|
-
import { Link } from '@odoro-cli/libs/router'
|
|
3
|
-
|
|
4
|
-
/** Page « a propos », qui demontre la navigation entre routes. */
|
|
5
|
-
export function About() {
|
|
6
|
-
return (
|
|
7
|
-
<Reveal className="o-flex o-flex-col o-gap-6">
|
|
8
|
-
<h1 className="o-text-3xl o-font-bold o-tracking-tight">A propos</h1>
|
|
9
|
-
<p className="o-text-zinc-500 dark:o-text-zinc-400 o-max-w-prose">
|
|
10
|
-
Cette page est servie par le routeur d Odoro. La navigation ne recharge pas le
|
|
11
|
-
document : elle passe par l historique du navigateur, restaure la position de
|
|
12
|
-
defilement et joue une transition de page quand le navigateur la prend en charge.
|
|
13
|
-
</p>
|
|
14
|
-
<p>
|
|
15
|
-
<Link to="/">Retour a l accueil</Link>
|
|
16
|
-
</p>
|
|
17
|
-
</Reveal>
|
|
18
|
-
)
|
|
19
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react'
|
|
2
|
-
|
|
3
|
-
import { Reveal, Stagger } from '@odoro-cli/libs/motion'
|
|
4
|
-
import { Link } from '@odoro-cli/libs/router'
|
|
5
|
-
import { Button } from '@odoro-cli/libs/ui'
|
|
6
|
-
|
|
7
|
-
/** Reponse de la route de sante du serveur. */
|
|
8
|
-
interface Health {
|
|
9
|
-
status: string
|
|
10
|
-
environment: string
|
|
11
|
-
uptime: number
|
|
12
|
-
timestamp: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/** Etat de l'appel a l'API. */
|
|
16
|
-
type Fetching =
|
|
17
|
-
| { state: 'inactif' }
|
|
18
|
-
| { state: 'en-cours' }
|
|
19
|
-
| { state: 'ok'; health: Health }
|
|
20
|
-
| { state: 'echec'; message: string }
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Interroge la route de sante du serveur.
|
|
24
|
-
*
|
|
25
|
-
* L'URL est relative : en developpement le moteur transmet l'appel au serveur,
|
|
26
|
-
* en production c'est le meme serveur qui repond. Il n'y a donc jamais d'URL
|
|
27
|
-
* d'API a configurer cote client.
|
|
28
|
-
*/
|
|
29
|
-
async function fetchHealth(signal: AbortSignal): Promise<Health> {
|
|
30
|
-
const response = await fetch('/api/health', { signal })
|
|
31
|
-
if (!response.ok) throw new Error(`Le serveur a repondu ${response.status}.`)
|
|
32
|
-
return (await response.json()) as Health
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** Panneau montrant l'etat de la liaison avec l'API. */
|
|
36
|
-
function ApiStatus() {
|
|
37
|
-
const [result, setResult] = useState<Fetching>({ state: 'inactif' })
|
|
38
|
-
const [attempt, setAttempt] = useState(0)
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
const controller = new AbortController()
|
|
42
|
-
setResult({ state: 'en-cours' })
|
|
43
|
-
|
|
44
|
-
fetchHealth(controller.signal).then(
|
|
45
|
-
(health) => setResult({ state: 'ok', health }),
|
|
46
|
-
(cause: unknown) => {
|
|
47
|
-
if (controller.signal.aborted) return
|
|
48
|
-
setResult({
|
|
49
|
-
state: 'echec',
|
|
50
|
-
message: cause instanceof Error ? cause.message : String(cause),
|
|
51
|
-
})
|
|
52
|
-
},
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
return () => controller.abort()
|
|
56
|
-
}, [attempt])
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
<section className="o-rounded-lg o-border-w-1 o-border-zinc-200 dark:o-border-zinc-800 o-bg-white dark:o-bg-zinc-900 o-p-5">
|
|
60
|
-
<div className="o-flex o-items-center o-justify-between o-gap-4">
|
|
61
|
-
<h2 className="o-font-semibold">Liaison avec l’API</h2>
|
|
62
|
-
<Button
|
|
63
|
-
size="sm"
|
|
64
|
-
tone="secondary"
|
|
65
|
-
loading={result.state === 'en-cours'}
|
|
66
|
-
onClick={() => setAttempt((value) => value + 1)}
|
|
67
|
-
>
|
|
68
|
-
Reinterroger
|
|
69
|
-
</Button>
|
|
70
|
-
</div>
|
|
71
|
-
|
|
72
|
-
<div className="o-mt-3 o-text-sm" role="status">
|
|
73
|
-
{result.state === 'inactif' || result.state === 'en-cours' ? (
|
|
74
|
-
<p className="o-text-zinc-500 dark:o-text-zinc-400">
|
|
75
|
-
Interrogation de /api/health...
|
|
76
|
-
</p>
|
|
77
|
-
) : result.state === 'echec' ? (
|
|
78
|
-
<p className="o-text-red-600 dark:o-text-red-400">
|
|
79
|
-
Serveur injoignable : {result.message}. Verifiez qu’il tourne bien sur
|
|
80
|
-
le port 3001.
|
|
81
|
-
</p>
|
|
82
|
-
) : (
|
|
83
|
-
<dl className="o-grid o-grid-cols-2 o-gap-2 o-tabular-nums">
|
|
84
|
-
<dt className="o-text-zinc-500 dark:o-text-zinc-400">Etat</dt>
|
|
85
|
-
<dd className="o-text-emerald-600 dark:o-text-emerald-400">
|
|
86
|
-
{result.health.status}
|
|
87
|
-
</dd>
|
|
88
|
-
<dt className="o-text-zinc-500 dark:o-text-zinc-400">Environnement</dt>
|
|
89
|
-
<dd>{result.health.environment}</dd>
|
|
90
|
-
<dt className="o-text-zinc-500 dark:o-text-zinc-400">En ligne depuis</dt>
|
|
91
|
-
<dd>{result.health.uptime} s</dd>
|
|
92
|
-
</dl>
|
|
93
|
-
)}
|
|
94
|
-
</div>
|
|
95
|
-
</section>
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Trois arguments mis en avant sur la page d'accueil. */
|
|
100
|
-
const FEATURES = [
|
|
101
|
-
{
|
|
102
|
-
title: 'Une seule origine',
|
|
103
|
-
body: 'Les appels /api sont transmis au serveur : aucune question de CORS, aucune URL a configurer.',
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
title: 'Un seul deploiement',
|
|
107
|
-
body: 'En production, le serveur sert l API et le client compile. Une image, un processus.',
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
title: 'Un environnement verifie',
|
|
111
|
-
body: 'Les variables sont validees au demarrage. Une configuration incomplete arrete le serveur tout de suite.',
|
|
112
|
-
},
|
|
113
|
-
]
|
|
114
|
-
|
|
115
|
-
/** Page d'accueil. */
|
|
116
|
-
export function Home() {
|
|
117
|
-
return (
|
|
118
|
-
<div className="o-flex o-flex-col o-gap-12">
|
|
119
|
-
<Reveal>
|
|
120
|
-
<h1 className="o-text-4xl o-font-bold o-tracking-tight">Client et serveur.</h1>
|
|
121
|
-
<p className="o-mt-4 o-text-lg o-text-zinc-500 dark:o-text-zinc-400 o-max-w-prose">
|
|
122
|
-
Ce projet reunit une application React et une API Express dans un seul depot. Le
|
|
123
|
-
panneau ci-dessous interroge le serveur pour de vrai.
|
|
124
|
-
</p>
|
|
125
|
-
</Reveal>
|
|
126
|
-
|
|
127
|
-
<ApiStatus />
|
|
128
|
-
|
|
129
|
-
<Stagger step={80} className="o-grid o-grid-cols-1 md:o-grid-cols-3 o-gap-4">
|
|
130
|
-
{FEATURES.map((feature) => (
|
|
131
|
-
<article
|
|
132
|
-
key={feature.title}
|
|
133
|
-
className="o-rounded-lg o-border-w-1 o-border-zinc-200 dark:o-border-zinc-800 o-bg-white dark:o-bg-zinc-900 o-p-5"
|
|
134
|
-
>
|
|
135
|
-
<h2 className="o-font-semibold">{feature.title}</h2>
|
|
136
|
-
<p className="o-mt-2 o-text-sm o-text-zinc-500 dark:o-text-zinc-400">
|
|
137
|
-
{feature.body}
|
|
138
|
-
</p>
|
|
139
|
-
</article>
|
|
140
|
-
))}
|
|
141
|
-
</Stagger>
|
|
142
|
-
|
|
143
|
-
<p>
|
|
144
|
-
<Link to="/a-propos">En savoir plus</Link>
|
|
145
|
-
</p>
|
|
146
|
-
</div>
|
|
147
|
-
)
|
|
148
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Link } from '@odoro-cli/libs/router'
|
|
2
|
-
|
|
3
|
-
/** Page affichee pour toute route inconnue. */
|
|
4
|
-
export function NotFound() {
|
|
5
|
-
return (
|
|
6
|
-
<div className="o-flex o-flex-col o-gap-4" role="alert">
|
|
7
|
-
<h1 className="o-text-3xl o-font-bold">404</h1>
|
|
8
|
-
<p className="o-text-zinc-500 dark:o-text-zinc-400">Cette page n existe pas.</p>
|
|
9
|
-
<p>
|
|
10
|
-
<Link to="/">Retour a l accueil</Link>
|
|
11
|
-
</p>
|
|
12
|
-
</div>
|
|
13
|
-
)
|
|
14
|
-
}
|