create-rudder-app 1.1.2 → 1.2.1
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/cli-flags.d.ts +0 -9
- package/dist/cli-flags.d.ts.map +1 -1
- package/dist/cli-flags.js +0 -8
- package/dist/cli-flags.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/app/service-provider.d.ts.map +1 -1
- package/dist/templates/app/service-provider.js +0 -15
- package/dist/templates/app/service-provider.js.map +1 -1
- package/dist/templates/components/site-header.d.ts.map +1 -1
- package/dist/templates/components/site-header.js +2 -8
- package/dist/templates/components/site-header.js.map +1 -1
- package/dist/templates/package-json.d.ts.map +1 -1
- package/dist/templates/package-json.js +4 -5
- package/dist/templates/package-json.js.map +1 -1
- package/dist/templates/pages/index.d.ts +13 -0
- package/dist/templates/pages/index.d.ts.map +1 -1
- package/dist/templates/pages/index.js +43 -0
- package/dist/templates/pages/index.js.map +1 -1
- package/dist/templates/routes/api.d.ts.map +1 -1
- package/dist/templates/routes/api.js +0 -99
- package/dist/templates/routes/api.js.map +1 -1
- package/dist/templates/routes/console.d.ts.map +1 -1
- package/dist/templates/routes/console.js +3 -4
- package/dist/templates/routes/console.js.map +1 -1
- package/dist/templates/routes/web.d.ts.map +1 -1
- package/dist/templates/routes/web.js +10 -83
- package/dist/templates/routes/web.js.map +1 -1
- package/dist/templates/routes-manifest.d.ts +2 -2
- package/dist/templates/routes-manifest.d.ts.map +1 -1
- package/dist/templates/routes-manifest.js +19 -22
- package/dist/templates/routes-manifest.js.map +1 -1
- package/dist/templates/views/welcome.d.ts +13 -0
- package/dist/templates/views/welcome.d.ts.map +1 -1
- package/dist/templates/views/welcome.js +53 -0
- package/dist/templates/views/welcome.js.map +1 -1
- package/dist/templates.d.ts +0 -9
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +38 -120
- package/dist/templates.js.map +1 -1
- package/package.json +1 -5
- package/dist/templates/demos/avatar.d.ts +0 -3
- package/dist/templates/demos/avatar.d.ts.map +0 -1
- package/dist/templates/demos/avatar.js +0 -174
- package/dist/templates/demos/avatar.js.map +0 -1
- package/dist/templates/demos/cache.d.ts +0 -3
- package/dist/templates/demos/cache.d.ts.map +0 -1
- package/dist/templates/demos/cache.js +0 -91
- package/dist/templates/demos/cache.js.map +0 -1
- package/dist/templates/demos/contact.d.ts +0 -3
- package/dist/templates/demos/contact.d.ts.map +0 -1
- package/dist/templates/demos/contact.js +0 -99
- package/dist/templates/demos/contact.js.map +0 -1
- package/dist/templates/demos/fibonacci.d.ts +0 -7
- package/dist/templates/demos/fibonacci.d.ts.map +0 -1
- package/dist/templates/demos/fibonacci.js +0 -164
- package/dist/templates/demos/fibonacci.js.map +0 -1
- package/dist/templates/demos/http.d.ts +0 -3
- package/dist/templates/demos/http.d.ts.map +0 -1
- package/dist/templates/demos/http.js +0 -109
- package/dist/templates/demos/http.js.map +0 -1
- package/dist/templates/demos/index-view.d.ts +0 -3
- package/dist/templates/demos/index-view.d.ts.map +0 -1
- package/dist/templates/demos/index-view.js +0 -47
- package/dist/templates/demos/index-view.js.map +0 -1
- package/dist/templates/demos/localization.d.ts +0 -4
- package/dist/templates/demos/localization.d.ts.map +0 -1
- package/dist/templates/demos/localization.js +0 -122
- package/dist/templates/demos/localization.js.map +0 -1
- package/dist/templates/demos/mail.d.ts +0 -4
- package/dist/templates/demos/mail.d.ts.map +0 -1
- package/dist/templates/demos/mail.js +0 -119
- package/dist/templates/demos/mail.js.map +0 -1
- package/dist/templates/demos/notifications.d.ts +0 -4
- package/dist/templates/demos/notifications.d.ts.map +0 -1
- package/dist/templates/demos/notifications.js +0 -125
- package/dist/templates/demos/notifications.js.map +0 -1
- package/dist/templates/demos/pennant.d.ts +0 -8
- package/dist/templates/demos/pennant.d.ts.map +0 -1
- package/dist/templates/demos/pennant.js +0 -135
- package/dist/templates/demos/pennant.js.map +0 -1
- package/dist/templates/demos/polymorphic.d.ts +0 -19
- package/dist/templates/demos/polymorphic.d.ts.map +0 -1
- package/dist/templates/demos/polymorphic.js +0 -663
- package/dist/templates/demos/polymorphic.js.map +0 -1
- package/dist/templates/demos/queue.d.ts +0 -4
- package/dist/templates/demos/queue.d.ts.map +0 -1
- package/dist/templates/demos/queue.js +0 -99
- package/dist/templates/demos/queue.js.map +0 -1
- package/dist/templates/demos/registry.d.ts +0 -26
- package/dist/templates/demos/registry.d.ts.map +0 -1
- package/dist/templates/demos/registry.js +0 -140
- package/dist/templates/demos/registry.js.map +0 -1
- package/dist/templates/demos/rudder-socket.d.ts +0 -2
- package/dist/templates/demos/rudder-socket.d.ts.map +0 -1
- package/dist/templates/demos/rudder-socket.js +0 -95
- package/dist/templates/demos/rudder-socket.js.map +0 -1
- package/dist/templates/demos/sync.d.ts +0 -2
- package/dist/templates/demos/sync.d.ts.map +0 -1
- package/dist/templates/demos/sync.js +0 -90
- package/dist/templates/demos/sync.js.map +0 -1
- package/dist/templates/demos/system-info.d.ts +0 -3
- package/dist/templates/demos/system-info.d.ts.map +0 -1
- package/dist/templates/demos/system-info.js +0 -134
- package/dist/templates/demos/system-info.js.map +0 -1
- package/dist/templates/demos/todos.d.ts +0 -6
- package/dist/templates/demos/todos.d.ts.map +0 -1
- package/dist/templates/demos/todos.js +0 -238
- package/dist/templates/demos/todos.js.map +0 -1
- package/dist/templates/demos/ws.d.ts +0 -2
- package/dist/templates/demos/ws.d.ts.map +0 -1
- package/dist/templates/demos/ws.js +0 -99
- package/dist/templates/demos/ws.js.map +0 -1
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// Mail send demo — defines a Mailable and posts to /api/mail/send.
|
|
2
|
-
// Default driver is `log`, so the email lands in the dev terminal.
|
|
3
|
-
export function demosMailView() {
|
|
4
|
-
return `import { useState } from 'react'
|
|
5
|
-
import '@/index.css'
|
|
6
|
-
import { SiteHeader } from 'App/Components/SiteHeader.js'
|
|
7
|
-
|
|
8
|
-
interface MailResponse {
|
|
9
|
-
ok: boolean
|
|
10
|
-
to: string
|
|
11
|
-
subject: string
|
|
12
|
-
driver: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function MailDemo() {
|
|
16
|
-
const [to, setTo] = useState('user@example.com')
|
|
17
|
-
const [subject, setSubject] = useState('Hello from RudderJS')
|
|
18
|
-
const [data, setData] = useState<MailResponse | null>(null)
|
|
19
|
-
const [loading, setLoading] = useState(false)
|
|
20
|
-
const [error, setError] = useState<string | null>(null)
|
|
21
|
-
|
|
22
|
-
async function send() {
|
|
23
|
-
setLoading(true); setError(null)
|
|
24
|
-
try {
|
|
25
|
-
const res = await fetch('/api/mail/send', {
|
|
26
|
-
method: 'POST',
|
|
27
|
-
headers: { 'Content-Type': 'application/json' },
|
|
28
|
-
body: JSON.stringify({ to, subject }),
|
|
29
|
-
})
|
|
30
|
-
const body = await res.json() as MailResponse | { message: string }
|
|
31
|
-
if (!res.ok) throw new Error((body as { message: string }).message ?? 'Send failed')
|
|
32
|
-
setData(body as MailResponse)
|
|
33
|
-
} catch (e) {
|
|
34
|
-
setError((e as Error).message)
|
|
35
|
-
} finally {
|
|
36
|
-
setLoading(false)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<div className="page">
|
|
42
|
-
<SiteHeader />
|
|
43
|
-
|
|
44
|
-
<section className="hero">
|
|
45
|
-
<h1 className="hero-title">Mail send</h1>
|
|
46
|
-
<p className="hero-lead">
|
|
47
|
-
Sends a <code className="inline-code">DemoMail</code> via{' '}
|
|
48
|
-
<code className="inline-code">@rudderjs/mail</code>. Default driver is{' '}
|
|
49
|
-
<code className="inline-code">log</code> — check the dev server terminal for output.
|
|
50
|
-
</p>
|
|
51
|
-
</section>
|
|
52
|
-
|
|
53
|
-
<section className="feature-section" style={{ maxWidth: '32rem', margin: '0 auto' }}>
|
|
54
|
-
<div className="form-card">
|
|
55
|
-
<div style={{ marginBottom: '1rem' }}>
|
|
56
|
-
<label className="form-label" htmlFor="mail-to">To</label>
|
|
57
|
-
<input id="mail-to" className="form-input" value={to} onChange={e => setTo(e.target.value)} />
|
|
58
|
-
</div>
|
|
59
|
-
<div style={{ marginBottom: '1rem' }}>
|
|
60
|
-
<label className="form-label" htmlFor="mail-subject">Subject</label>
|
|
61
|
-
<input id="mail-subject" className="form-input" value={subject} onChange={e => setSubject(e.target.value)} />
|
|
62
|
-
</div>
|
|
63
|
-
<button className="form-submit" onClick={send} disabled={loading}>
|
|
64
|
-
{loading ? 'Sending…' : 'Send mail'}
|
|
65
|
-
</button>
|
|
66
|
-
{error && (
|
|
67
|
-
<p className="form-error" style={{ marginTop: '1rem' }}>{error}</p>
|
|
68
|
-
)}
|
|
69
|
-
{data && (
|
|
70
|
-
<p className="form-success" style={{ marginTop: '1rem' }}>
|
|
71
|
-
Sent to <code>{data.to}</code> via <code>{data.driver}</code> driver — check the terminal.
|
|
72
|
-
</p>
|
|
73
|
-
)}
|
|
74
|
-
</div>
|
|
75
|
-
</section>
|
|
76
|
-
</div>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
`;
|
|
80
|
-
}
|
|
81
|
-
export function demoMailable() {
|
|
82
|
-
return `import { Mailable } from '@rudderjs/mail'
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Demo mailable — built dynamically from the to/subject the user enters.
|
|
86
|
-
* Replace with whatever copy your real templates need (HTML + text).
|
|
87
|
-
*/
|
|
88
|
-
export class DemoMail extends Mailable {
|
|
89
|
-
constructor(private readonly heading: string) { super() }
|
|
90
|
-
|
|
91
|
-
build(): this {
|
|
92
|
-
return this
|
|
93
|
-
.subject(this.heading)
|
|
94
|
-
.html(\`<h1>\${this.heading}</h1><p>Sent from the RudderJS mail demo.</p>\`)
|
|
95
|
-
.text(\`\${this.heading}\\n\\nSent from the RudderJS mail demo.\`)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
`;
|
|
99
|
-
}
|
|
100
|
-
export function demosMailApiBlock() {
|
|
101
|
-
return `// POST /api/mail/send — sends a DemoMail to the user-supplied address.
|
|
102
|
-
router.post('/api/mail/send', async (req, res) => {
|
|
103
|
-
const body = (req.body ?? {}) as { to?: string; subject?: string }
|
|
104
|
-
if (!body.to || !body.subject) {
|
|
105
|
-
return res.status(422).json({ message: 'Body must be { to, subject }' })
|
|
106
|
-
}
|
|
107
|
-
const { Mail } = await import('@rudderjs/mail')
|
|
108
|
-
const { DemoMail } = await import('../app/Mail/DemoMail.ts')
|
|
109
|
-
const { config } = await import('@rudderjs/core')
|
|
110
|
-
await Mail.to(body.to).send(new DemoMail(body.subject))
|
|
111
|
-
res.json({
|
|
112
|
-
ok: true,
|
|
113
|
-
to: body.to,
|
|
114
|
-
subject: body.subject,
|
|
115
|
-
driver: config<string>('mail.default', 'log'),
|
|
116
|
-
})
|
|
117
|
-
})`;
|
|
118
|
-
}
|
|
119
|
-
//# sourceMappingURL=mail.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mail.js","sourceRoot":"","sources":["../../../src/templates/demos/mail.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,mEAAmE;AAEnE,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ER,CAAA;AACD,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;CAgBR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;;;;;GAgBN,CAAA;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/templates/demos/notifications.ts"],"names":[],"mappings":"AAGA,wBAAgB,sBAAsB,IAAI,MAAM,CAwE/C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAiCzC;AAED,wBAAgB,0BAA0B,IAAI,MAAM,CAcnD"}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
// Notifications demo — multi-channel notification (mail only by default;
|
|
2
|
-
// add 'database' to via() once @rudderjs/notification's Prisma model is in place).
|
|
3
|
-
export function demosNotificationsView() {
|
|
4
|
-
return `import { useState } from 'react'
|
|
5
|
-
import '@/index.css'
|
|
6
|
-
import { SiteHeader } from 'App/Components/SiteHeader.js'
|
|
7
|
-
|
|
8
|
-
interface NotifyResponse {
|
|
9
|
-
ok: boolean
|
|
10
|
-
to: string
|
|
11
|
-
channels: string[]
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export default function NotificationsDemo() {
|
|
15
|
-
const [to, setTo] = useState('user@example.com')
|
|
16
|
-
const [data, setData] = useState<NotifyResponse | null>(null)
|
|
17
|
-
const [loading, setLoading] = useState(false)
|
|
18
|
-
const [error, setError] = useState<string | null>(null)
|
|
19
|
-
|
|
20
|
-
async function notify() {
|
|
21
|
-
setLoading(true); setError(null)
|
|
22
|
-
try {
|
|
23
|
-
const res = await fetch('/api/notifications/send', {
|
|
24
|
-
method: 'POST',
|
|
25
|
-
headers: { 'Content-Type': 'application/json' },
|
|
26
|
-
body: JSON.stringify({ to }),
|
|
27
|
-
})
|
|
28
|
-
const body = await res.json() as NotifyResponse | { message: string }
|
|
29
|
-
if (!res.ok) throw new Error((body as { message: string }).message ?? 'Send failed')
|
|
30
|
-
setData(body as NotifyResponse)
|
|
31
|
-
} catch (e) {
|
|
32
|
-
setError((e as Error).message)
|
|
33
|
-
} finally {
|
|
34
|
-
setLoading(false)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className="page">
|
|
40
|
-
<SiteHeader />
|
|
41
|
-
|
|
42
|
-
<section className="hero">
|
|
43
|
-
<h1 className="hero-title">Notifications</h1>
|
|
44
|
-
<p className="hero-lead">
|
|
45
|
-
Dispatches a <code className="inline-code">WelcomeNotification</code> via{' '}
|
|
46
|
-
<code className="inline-code">notify(notifiable, notification)</code>. The notification's{' '}
|
|
47
|
-
<code className="inline-code">via()</code> picks the channel(s); the mail channel routes
|
|
48
|
-
through the log driver, so output lands in the dev terminal.
|
|
49
|
-
</p>
|
|
50
|
-
</section>
|
|
51
|
-
|
|
52
|
-
<section className="feature-section" style={{ maxWidth: '32rem', margin: '0 auto' }}>
|
|
53
|
-
<div className="form-card">
|
|
54
|
-
<div style={{ marginBottom: '1rem' }}>
|
|
55
|
-
<label className="form-label" htmlFor="notify-to">Email</label>
|
|
56
|
-
<input id="notify-to" className="form-input" value={to} onChange={e => setTo(e.target.value)} />
|
|
57
|
-
</div>
|
|
58
|
-
<button className="form-submit" onClick={notify} disabled={loading}>
|
|
59
|
-
{loading ? 'Sending…' : 'Send notification'}
|
|
60
|
-
</button>
|
|
61
|
-
{error && (
|
|
62
|
-
<p className="form-error" style={{ marginTop: '1rem' }}>{error}</p>
|
|
63
|
-
)}
|
|
64
|
-
{data && (
|
|
65
|
-
<p className="form-success" style={{ marginTop: '1rem' }}>
|
|
66
|
-
Sent to <code>{data.to}</code> via <code>{data.channels.join(', ')}</code> — check the terminal.
|
|
67
|
-
</p>
|
|
68
|
-
)}
|
|
69
|
-
</div>
|
|
70
|
-
</section>
|
|
71
|
-
</div>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
`;
|
|
75
|
-
}
|
|
76
|
-
export function demoNotification() {
|
|
77
|
-
return `import { Notification, type Notifiable } from '@rudderjs/notification'
|
|
78
|
-
import { Mailable } from '@rudderjs/mail'
|
|
79
|
-
|
|
80
|
-
class WelcomeMail extends Mailable {
|
|
81
|
-
constructor(private readonly notifiable: Notifiable) { super() }
|
|
82
|
-
|
|
83
|
-
build(): this {
|
|
84
|
-
return this
|
|
85
|
-
.subject(\`Welcome to RudderJS, \${this.notifiable.name ?? 'friend'}!\`)
|
|
86
|
-
.text(
|
|
87
|
-
\`Hi \${this.notifiable.name ?? 'there'},\\n\\n\` +
|
|
88
|
-
\`Your account is ready. Thanks for joining us.\\n\\n\` +
|
|
89
|
-
\`— The RudderJS Team\`,
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Demo notification — single mail channel by default. Add 'database' once
|
|
96
|
-
* the Notification Prisma model is migrated, or 'broadcast' once @rudderjs/broadcast
|
|
97
|
-
* is wired up.
|
|
98
|
-
*/
|
|
99
|
-
export class WelcomeNotification extends Notification {
|
|
100
|
-
via(_notifiable: Notifiable): string[] {
|
|
101
|
-
return ['mail']
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
toMail(notifiable: Notifiable): WelcomeMail {
|
|
105
|
-
return new WelcomeMail(notifiable)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
`;
|
|
109
|
-
}
|
|
110
|
-
export function demosNotificationsApiBlock() {
|
|
111
|
-
return `// POST /api/notifications/send — dispatches WelcomeNotification to the supplied email.
|
|
112
|
-
// On-demand notifiable: no DB record required.
|
|
113
|
-
router.post('/api/notifications/send', async (req, res) => {
|
|
114
|
-
const body = (req.body ?? {}) as { to?: string }
|
|
115
|
-
if (!body.to) return res.status(422).json({ message: 'Body must be { to }' })
|
|
116
|
-
|
|
117
|
-
const { notify, Notification } = await import('@rudderjs/notification')
|
|
118
|
-
const { WelcomeNotification } = await import('../app/Notifications/WelcomeNotification.ts')
|
|
119
|
-
|
|
120
|
-
const notification = new WelcomeNotification()
|
|
121
|
-
await notify(Notification.route('mail', body.to), notification)
|
|
122
|
-
res.json({ ok: true, to: body.to, channels: notification.via({ id: '0', email: body.to }) })
|
|
123
|
-
})`;
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=notifications.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/templates/demos/notifications.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,mFAAmF;AAEnF,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsER,CAAA;AACD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO;;;;;;;;;;;;GAYN,CAAA;AACH,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare function demosPennantView(): string;
|
|
2
|
-
export declare function demosPennantBetaView(): string;
|
|
3
|
-
/**
|
|
4
|
-
* Lines added to AppServiceProvider's boot() when the pennant demo is selected.
|
|
5
|
-
* Defines the four feature shapes shown in the demo (boolean, value, scoped, lottery).
|
|
6
|
-
*/
|
|
7
|
-
export declare function pennantFeatureDefinitions(): string;
|
|
8
|
-
//# sourceMappingURL=pennant.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pennant.d.ts","sourceRoot":"","sources":["../../../src/templates/demos/pennant.ts"],"names":[],"mappings":"AAIA,wBAAgB,gBAAgB,IAAI,MAAM,CA6FzC;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CA0B7C;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAKlD"}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// Pennant demo — feature flags resolved against the current user. Two routes:
|
|
2
|
-
// /demos/pennant (renders the four card shapes) and /demos/pennant/beta
|
|
3
|
-
// (guarded by FeatureMiddleware to demonstrate the 403 path).
|
|
4
|
-
export function demosPennantView() {
|
|
5
|
-
return `import '@/index.css'
|
|
6
|
-
import { SiteHeader } from 'App/Components/SiteHeader.js'
|
|
7
|
-
|
|
8
|
-
interface PennantProps {
|
|
9
|
-
user: { id: string; name: string; email: string } | null
|
|
10
|
-
values: Record<string, unknown>
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface FeatureCardSpec {
|
|
14
|
-
name: string
|
|
15
|
-
shape: string
|
|
16
|
-
resolver: string
|
|
17
|
-
expected: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const features: FeatureCardSpec[] = [
|
|
21
|
-
{ name: 'dark-mode', shape: 'boolean', resolver: '() => true', expected: 'Always true.' },
|
|
22
|
-
{ name: 'max-uploads', shape: 'value', resolver: '() => 10', expected: 'Returns the literal value, not a boolean.' },
|
|
23
|
-
{ name: 'beta-dashboard', shape: 'scoped', resolver: '(scope) => scope !== null', expected: 'True for any signed-in user; false for anon.' },
|
|
24
|
-
{ name: 'new-checkout', shape: 'lottery', resolver: '() => Lottery.odds(1, 4)', expected: '~25% chance per scope. Stable on subsequent checks.' },
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
export default function PennantDemo({ user, values }: PennantProps) {
|
|
28
|
-
return (
|
|
29
|
-
<div className="page">
|
|
30
|
-
<SiteHeader />
|
|
31
|
-
|
|
32
|
-
<section className="hero">
|
|
33
|
-
<h1 className="hero-title">Feature flags</h1>
|
|
34
|
-
<p className="hero-lead">
|
|
35
|
-
Resolved against the current scope ({user
|
|
36
|
-
? <><strong>{user.name}</strong> · {user.email}</>
|
|
37
|
-
: <em>guest</em>}). Definitions live in{' '}
|
|
38
|
-
<code className="inline-code">app/Providers/AppServiceProvider.ts</code>{' '}
|
|
39
|
-
and resolution happens here via{' '}
|
|
40
|
-
<code className="inline-code">Feature.values([...], scope)</code>.
|
|
41
|
-
</p>
|
|
42
|
-
{!user && (
|
|
43
|
-
<p className="hero-meta">
|
|
44
|
-
Sign in to see <code className="inline-code">beta-dashboard</code> flip to true.
|
|
45
|
-
</p>
|
|
46
|
-
)}
|
|
47
|
-
</section>
|
|
48
|
-
|
|
49
|
-
<section className="feature-section">
|
|
50
|
-
<div className="demo-card-grid">
|
|
51
|
-
{features.map(f => {
|
|
52
|
-
const resolved = values[f.name]
|
|
53
|
-
const display = JSON.stringify(resolved)
|
|
54
|
-
return (
|
|
55
|
-
<div key={f.name} className="demo-card">
|
|
56
|
-
<div className="demo-card-header">
|
|
57
|
-
<h2 className="flag-name">{f.name}</h2>
|
|
58
|
-
<p className="flag-shape">{f.shape}</p>
|
|
59
|
-
</div>
|
|
60
|
-
<div className="demo-card-body">
|
|
61
|
-
<div className="flag-section">
|
|
62
|
-
<div className="flag-section-label">resolver</div>
|
|
63
|
-
<code className="code-inline-block">{f.resolver}</code>
|
|
64
|
-
</div>
|
|
65
|
-
<div className="flag-section">
|
|
66
|
-
<div className="flag-section-label">expected</div>
|
|
67
|
-
<p className="demo-card-desc">{f.expected}</p>
|
|
68
|
-
</div>
|
|
69
|
-
<div className="flag-resolved">
|
|
70
|
-
<div className="flag-section-label">resolved value</div>
|
|
71
|
-
<code className="flag-resolved-value">{display}</code>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
)
|
|
76
|
-
})}
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
<div className="demo-card" style={{ marginTop: '1.5rem' }}>
|
|
80
|
-
<div className="demo-card-header">
|
|
81
|
-
<h2 className="demo-card-title">FeatureMiddleware</h2>
|
|
82
|
-
<p className="demo-card-desc">
|
|
83
|
-
<code className="inline-code">/demos/pennant/beta</code> is wrapped in{' '}
|
|
84
|
-
<code className="inline-code">FeatureMiddleware('beta-dashboard')</code>. The middleware reads{' '}
|
|
85
|
-
<code className="inline-code">req.user</code> as the scope; non-matching scopes get a 403.
|
|
86
|
-
</p>
|
|
87
|
-
</div>
|
|
88
|
-
<a href="/demos/pennant/beta" className="button-primary" style={{ display: 'inline-block', textDecoration: 'none' }}>
|
|
89
|
-
Open /demos/pennant/beta →
|
|
90
|
-
</a>
|
|
91
|
-
</div>
|
|
92
|
-
</section>
|
|
93
|
-
</div>
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
`;
|
|
97
|
-
}
|
|
98
|
-
export function demosPennantBetaView() {
|
|
99
|
-
return `import '@/index.css'
|
|
100
|
-
import { SiteHeader } from 'App/Components/SiteHeader.js'
|
|
101
|
-
|
|
102
|
-
// Override the id-derived URL ('/demos/pennant-beta') so SPA nav matches the
|
|
103
|
-
// controller route, which is '/demos/pennant/beta' (a sub-path under pennant).
|
|
104
|
-
export const route = '/demos/pennant/beta'
|
|
105
|
-
|
|
106
|
-
export default function PennantBeta() {
|
|
107
|
-
return (
|
|
108
|
-
<div className="page">
|
|
109
|
-
<SiteHeader />
|
|
110
|
-
|
|
111
|
-
<section className="hero">
|
|
112
|
-
<h1 className="hero-title">Beta dashboard</h1>
|
|
113
|
-
<p className="hero-lead">
|
|
114
|
-
You only see this page if <code className="inline-code">beta-dashboard</code> is active for your scope.
|
|
115
|
-
The route is wrapped in <code className="inline-code">FeatureMiddleware('beta-dashboard')</code>;
|
|
116
|
-
unauthorized scopes get a 403 before this view ever renders.
|
|
117
|
-
</p>
|
|
118
|
-
<a href="/demos/pennant" className="demo-back-link">← Back to /demos/pennant</a>
|
|
119
|
-
</section>
|
|
120
|
-
</div>
|
|
121
|
-
)
|
|
122
|
-
}
|
|
123
|
-
`;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Lines added to AppServiceProvider's boot() when the pennant demo is selected.
|
|
127
|
-
* Defines the four feature shapes shown in the demo (boolean, value, scoped, lottery).
|
|
128
|
-
*/
|
|
129
|
-
export function pennantFeatureDefinitions() {
|
|
130
|
-
return `Feature.define('dark-mode', () => true)
|
|
131
|
-
Feature.define('max-uploads', () => 10)
|
|
132
|
-
Feature.define('beta-dashboard', (scope) => typeof scope === 'object' && scope !== null)
|
|
133
|
-
Feature.define('new-checkout', () => Lottery.odds(1, 4))`;
|
|
134
|
-
}
|
|
135
|
-
//# sourceMappingURL=pennant.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pennant.js","sourceRoot":"","sources":["../../../src/templates/demos/pennant.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,8DAA8D;AAE9D,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2FR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAwBR,CAAA;AACD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;+DAGsD,CAAA;AAC/D,CAAC"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare function postModelTs(): string;
|
|
2
|
-
export declare function videoModelTs(): string;
|
|
3
|
-
export declare function commentModelTs(): string;
|
|
4
|
-
export declare function tagModelTs(): string;
|
|
5
|
-
export declare function polymorphicPrismaBlock(): string;
|
|
6
|
-
export declare function demosPolymorphicView(): string;
|
|
7
|
-
/**
|
|
8
|
-
* Inlined into routes/web.ts demos block. Loads parents + hydrates each parent's
|
|
9
|
-
* comments + tags via the polymorphic relations. Returns plain objects (Vike
|
|
10
|
-
* refuses to serialize Model instances across the SSR boundary).
|
|
11
|
-
*/
|
|
12
|
-
export declare function demosPolymorphicWebBlock(): string;
|
|
13
|
-
/**
|
|
14
|
-
* Inlined into routes/api.ts demos block. Endpoints: state, create-post,
|
|
15
|
-
* create-video, comment-on-post, comment-on-video, morphTo resolution,
|
|
16
|
-
* create-tag, attach/detach tag (post + video), morphedByMany inverse.
|
|
17
|
-
*/
|
|
18
|
-
export declare function demosPolymorphicApiBlock(): string;
|
|
19
|
-
//# sourceMappingURL=polymorphic.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"polymorphic.d.ts","sourceRoot":"","sources":["../../../src/templates/demos/polymorphic.ts"],"names":[],"mappings":"AASA,wBAAgB,WAAW,IAAI,MAAM,CAmBpC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAmBrC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAoBvC;AAED,wBAAgB,UAAU,IAAI,MAAM,CA4BnC;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CA2C/C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CA4U7C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAsBjD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAyJjD"}
|