create-rudder-app 1.1.2 → 1.2.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/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/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,663 +0,0 @@
|
|
|
1
|
-
// Polymorphic relations demo — every polymorphic relation type
|
|
2
|
-
// (morphMany / morphTo / morphToMany / morphedByMany) via @rudderjs/orm.
|
|
3
|
-
//
|
|
4
|
-
// Scaffolds four Models (Post / Video / Comment / Tag), the React view, the
|
|
5
|
-
// Prisma block (Comment with camelCase commentableId/commentableType + Tag
|
|
6
|
-
// with the shared `taggable` pivot), the controller view, and a self-contained
|
|
7
|
-
// API surface (state, create, comment, morphTo resolution, tag attach/detach,
|
|
8
|
-
// and morphedByMany inverse fan-out).
|
|
9
|
-
export function postModelTs() {
|
|
10
|
-
return `import { Model } from '@rudderjs/orm'
|
|
11
|
-
import { Comment } from './Comment.js'
|
|
12
|
-
import { Tag } from './Tag.js'
|
|
13
|
-
|
|
14
|
-
export class Post extends Model {
|
|
15
|
-
static table = 'post'
|
|
16
|
-
static fillable = ['title']
|
|
17
|
-
|
|
18
|
-
static override relations = {
|
|
19
|
-
comments: { type: 'morphMany' as const, model: () => Comment, morphName: 'commentable' },
|
|
20
|
-
tags: { type: 'morphToMany' as const, model: () => Tag, pivotTable: 'taggable', morphName: 'taggable' },
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
id!: number
|
|
24
|
-
title!: string
|
|
25
|
-
createdAt!: Date
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
28
|
-
}
|
|
29
|
-
export function videoModelTs() {
|
|
30
|
-
return `import { Model } from '@rudderjs/orm'
|
|
31
|
-
import { Comment } from './Comment.js'
|
|
32
|
-
import { Tag } from './Tag.js'
|
|
33
|
-
|
|
34
|
-
export class Video extends Model {
|
|
35
|
-
static table = 'video'
|
|
36
|
-
static fillable = ['url']
|
|
37
|
-
|
|
38
|
-
static override relations = {
|
|
39
|
-
comments: { type: 'morphMany' as const, model: () => Comment, morphName: 'commentable' },
|
|
40
|
-
tags: { type: 'morphToMany' as const, model: () => Tag, pivotTable: 'taggable', morphName: 'taggable' },
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
id!: number
|
|
44
|
-
url!: string
|
|
45
|
-
createdAt!: Date
|
|
46
|
-
}
|
|
47
|
-
`;
|
|
48
|
-
}
|
|
49
|
-
export function commentModelTs() {
|
|
50
|
-
return `import { Model } from '@rudderjs/orm'
|
|
51
|
-
import { Post } from './Post.js'
|
|
52
|
-
import { Video } from './Video.js'
|
|
53
|
-
|
|
54
|
-
export class Comment extends Model {
|
|
55
|
-
static table = 'comment'
|
|
56
|
-
static fillable = ['body', 'commentableId', 'commentableType']
|
|
57
|
-
|
|
58
|
-
static override relations = {
|
|
59
|
-
commentable: { type: 'morphTo' as const, morphName: 'commentable', types: () => [Post, Video] },
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
id!: number
|
|
63
|
-
body!: string
|
|
64
|
-
commentableId!: number
|
|
65
|
-
commentableType!: string
|
|
66
|
-
createdAt!: Date
|
|
67
|
-
}
|
|
68
|
-
`;
|
|
69
|
-
}
|
|
70
|
-
export function tagModelTs() {
|
|
71
|
-
return `import { Model } from '@rudderjs/orm'
|
|
72
|
-
import { Post } from './Post.js'
|
|
73
|
-
import { Video } from './Video.js'
|
|
74
|
-
|
|
75
|
-
export class Tag extends Model {
|
|
76
|
-
static table = 'tag'
|
|
77
|
-
static fillable = ['name']
|
|
78
|
-
|
|
79
|
-
static override relations = {
|
|
80
|
-
posts: {
|
|
81
|
-
type: 'morphedByMany' as const,
|
|
82
|
-
model: () => Post,
|
|
83
|
-
pivotTable: 'taggable',
|
|
84
|
-
morphName: 'taggable',
|
|
85
|
-
},
|
|
86
|
-
videos: {
|
|
87
|
-
type: 'morphedByMany' as const,
|
|
88
|
-
model: () => Video,
|
|
89
|
-
pivotTable: 'taggable',
|
|
90
|
-
morphName: 'taggable',
|
|
91
|
-
},
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
id!: number
|
|
95
|
-
name!: string
|
|
96
|
-
}
|
|
97
|
-
`;
|
|
98
|
-
}
|
|
99
|
-
export function polymorphicPrismaBlock() {
|
|
100
|
-
return `// module: Polymorphic demo (Post / Video / Comment / Tag + Taggable pivot)
|
|
101
|
-
// commentableId/commentableType + taggableId/taggableType follow @rudderjs/orm's
|
|
102
|
-
// camelCase convention.
|
|
103
|
-
model Post {
|
|
104
|
-
id Int @id @default(autoincrement())
|
|
105
|
-
title String
|
|
106
|
-
createdAt DateTime @default(now())
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
model Video {
|
|
110
|
-
id Int @id @default(autoincrement())
|
|
111
|
-
url String
|
|
112
|
-
createdAt DateTime @default(now())
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
model Comment {
|
|
116
|
-
id Int @id @default(autoincrement())
|
|
117
|
-
body String
|
|
118
|
-
commentableId Int
|
|
119
|
-
commentableType String
|
|
120
|
-
createdAt DateTime @default(now())
|
|
121
|
-
|
|
122
|
-
@@index([commentableType, commentableId])
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Polymorphic many-to-many. One Tag table shared by both Post and Video
|
|
126
|
-
// through a single Taggable pivot. The pivot carries tagId (strong side) +
|
|
127
|
-
// taggableId/taggableType (polymorphic side).
|
|
128
|
-
model Tag {
|
|
129
|
-
id Int @id @default(autoincrement())
|
|
130
|
-
name String @unique
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
model Taggable {
|
|
134
|
-
tagId Int
|
|
135
|
-
taggableId Int
|
|
136
|
-
taggableType String
|
|
137
|
-
|
|
138
|
-
@@id([tagId, taggableId, taggableType])
|
|
139
|
-
@@index([taggableId, taggableType])
|
|
140
|
-
}
|
|
141
|
-
`;
|
|
142
|
-
}
|
|
143
|
-
export function demosPolymorphicView() {
|
|
144
|
-
return `import '@/index.css'
|
|
145
|
-
import { SiteHeader } from 'App/Components/SiteHeader.js'
|
|
146
|
-
import { useState } from 'react'
|
|
147
|
-
|
|
148
|
-
interface CommentDto {
|
|
149
|
-
id: number
|
|
150
|
-
body: string
|
|
151
|
-
commentableId: number
|
|
152
|
-
commentableType: string
|
|
153
|
-
createdAt: string
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
interface TagDto {
|
|
157
|
-
id: number
|
|
158
|
-
name: string
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
interface PostDto {
|
|
162
|
-
id: number
|
|
163
|
-
title: string
|
|
164
|
-
comments: CommentDto[]
|
|
165
|
-
tags: TagDto[]
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
interface VideoDto {
|
|
169
|
-
id: number
|
|
170
|
-
url: string
|
|
171
|
-
comments: CommentDto[]
|
|
172
|
-
tags: TagDto[]
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
interface ResolvedParent {
|
|
176
|
-
type: 'Post' | 'Video'
|
|
177
|
-
id: number
|
|
178
|
-
title: string
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
interface InverseFanOut {
|
|
182
|
-
posts: Array<{ id: number; title: string }>
|
|
183
|
-
videos: Array<{ id: number; url: string }>
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
interface PolymorphicDemoProps {
|
|
187
|
-
posts: PostDto[]
|
|
188
|
-
videos: VideoDto[]
|
|
189
|
-
tags: TagDto[]
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export default function PolymorphicDemo(props: PolymorphicDemoProps) {
|
|
193
|
-
const [posts, setPosts] = useState<PostDto[]>(props.posts)
|
|
194
|
-
const [videos, setVideos] = useState<VideoDto[]>(props.videos)
|
|
195
|
-
const [tags, setTags] = useState<TagDto[]>(props.tags)
|
|
196
|
-
const [resolved, setResolved] = useState<ResolvedParent | null>(null)
|
|
197
|
-
const [inverse, setInverse] = useState<{ tag: TagDto; data: InverseFanOut } | null>(null)
|
|
198
|
-
const [loading, setLoading] = useState(false)
|
|
199
|
-
|
|
200
|
-
async function refresh() {
|
|
201
|
-
const res = await fetch('/api/polymorphic/state')
|
|
202
|
-
const json = await res.json() as { posts: PostDto[]; videos: VideoDto[]; tags: TagDto[] }
|
|
203
|
-
setPosts(json.posts)
|
|
204
|
-
setVideos(json.videos)
|
|
205
|
-
setTags(json.tags)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async function addPost() {
|
|
209
|
-
const title = prompt('Post title?')
|
|
210
|
-
if (!title) return
|
|
211
|
-
setLoading(true)
|
|
212
|
-
try {
|
|
213
|
-
await fetch('/api/polymorphic/posts', {
|
|
214
|
-
method: 'POST',
|
|
215
|
-
headers: { 'Content-Type': 'application/json' },
|
|
216
|
-
body: JSON.stringify({ title }),
|
|
217
|
-
})
|
|
218
|
-
await refresh()
|
|
219
|
-
} finally { setLoading(false) }
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async function addVideo() {
|
|
223
|
-
const url = prompt('Video URL?')
|
|
224
|
-
if (!url) return
|
|
225
|
-
setLoading(true)
|
|
226
|
-
try {
|
|
227
|
-
await fetch('/api/polymorphic/videos', {
|
|
228
|
-
method: 'POST',
|
|
229
|
-
headers: { 'Content-Type': 'application/json' },
|
|
230
|
-
body: JSON.stringify({ url }),
|
|
231
|
-
})
|
|
232
|
-
await refresh()
|
|
233
|
-
} finally { setLoading(false) }
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async function addComment(type: 'post' | 'video', id: number) {
|
|
237
|
-
const body = prompt(\`Comment on \${type} #\${id}?\`)
|
|
238
|
-
if (!body) return
|
|
239
|
-
setLoading(true)
|
|
240
|
-
try {
|
|
241
|
-
await fetch(\`/api/polymorphic/\${type}s/\${id}/comments\`, {
|
|
242
|
-
method: 'POST',
|
|
243
|
-
headers: { 'Content-Type': 'application/json' },
|
|
244
|
-
body: JSON.stringify({ body }),
|
|
245
|
-
})
|
|
246
|
-
await refresh()
|
|
247
|
-
} finally { setLoading(false) }
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
async function resolveParent(commentId: number) {
|
|
251
|
-
setLoading(true)
|
|
252
|
-
try {
|
|
253
|
-
const res = await fetch(\`/api/polymorphic/comments/\${commentId}/parent\`)
|
|
254
|
-
setResolved(await res.json() as ResolvedParent)
|
|
255
|
-
} finally { setLoading(false) }
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
async function addTag() {
|
|
259
|
-
const name = prompt('Tag name?')
|
|
260
|
-
if (!name) return
|
|
261
|
-
setLoading(true)
|
|
262
|
-
try {
|
|
263
|
-
await fetch('/api/polymorphic/tags', {
|
|
264
|
-
method: 'POST',
|
|
265
|
-
headers: { 'Content-Type': 'application/json' },
|
|
266
|
-
body: JSON.stringify({ name }),
|
|
267
|
-
})
|
|
268
|
-
await refresh()
|
|
269
|
-
} finally { setLoading(false) }
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async function attachTag(type: 'post' | 'video', parentId: number) {
|
|
273
|
-
if (tags.length === 0) { alert('Create a tag first.'); return }
|
|
274
|
-
const tagName = prompt(\`Attach which tag? (\${tags.map(t => t.name).join(', ')})\`)
|
|
275
|
-
if (!tagName) return
|
|
276
|
-
const tag = tags.find(t => t.name === tagName)
|
|
277
|
-
if (!tag) { alert('No tag with that name.'); return }
|
|
278
|
-
setLoading(true)
|
|
279
|
-
try {
|
|
280
|
-
await fetch(\`/api/polymorphic/\${type}s/\${parentId}/tags\`, {
|
|
281
|
-
method: 'POST',
|
|
282
|
-
headers: { 'Content-Type': 'application/json' },
|
|
283
|
-
body: JSON.stringify({ tagId: tag.id }),
|
|
284
|
-
})
|
|
285
|
-
await refresh()
|
|
286
|
-
} finally { setLoading(false) }
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
async function detachTag(type: 'post' | 'video', parentId: number, tagId: number) {
|
|
290
|
-
setLoading(true)
|
|
291
|
-
try {
|
|
292
|
-
await fetch(\`/api/polymorphic/\${type}s/\${parentId}/tags/\${tagId}\`, { method: 'DELETE' })
|
|
293
|
-
await refresh()
|
|
294
|
-
} finally { setLoading(false) }
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
async function resolveInverse(tag: TagDto) {
|
|
298
|
-
setLoading(true)
|
|
299
|
-
try {
|
|
300
|
-
const res = await fetch(\`/api/polymorphic/tags/\${tag.id}/items\`)
|
|
301
|
-
setInverse({ tag, data: await res.json() as InverseFanOut })
|
|
302
|
-
} finally { setLoading(false) }
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
return (
|
|
306
|
-
<div className="page">
|
|
307
|
-
<SiteHeader />
|
|
308
|
-
|
|
309
|
-
<section className="hero">
|
|
310
|
-
<h1 className="hero-title">Polymorphic relations</h1>
|
|
311
|
-
<p className="hero-lead">
|
|
312
|
-
One <code className="inline-code">Comment</code> table belonging to either a <code className="inline-code">Post</code> or a <code className="inline-code">Video</code> via <code className="inline-code">commentableId</code> + <code className="inline-code">commentableType</code>. One <code className="inline-code">Tag</code> table shared by both Posts and Videos through a single <code className="inline-code">taggable</code> pivot — <code className="inline-code">morphToMany</code> on the owning side, <code className="inline-code">morphedByMany</code> on the inverse.
|
|
313
|
-
</p>
|
|
314
|
-
<p className="hero-meta">
|
|
315
|
-
Models: <code className="inline-code">Post.morphMany('comments')</code> + <code className="inline-code">Post.morphToMany('tags')</code>, <code className="inline-code">Video.morphMany('comments')</code> + <code className="inline-code">Video.morphToMany('tags')</code>, <code className="inline-code">Comment.morphTo('commentable', [Post, Video])</code>, <code className="inline-code">Tag.morphedByMany('posts'|'videos')</code>. Writes use <code className="inline-code">Model.morph()</code> + <code className="inline-code">Model.morphToMany().attach()</code>.
|
|
316
|
-
</p>
|
|
317
|
-
</section>
|
|
318
|
-
|
|
319
|
-
<section className="feature-section">
|
|
320
|
-
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem', maxWidth: '60rem', margin: '0 auto' }}>
|
|
321
|
-
<div className="demo-card">
|
|
322
|
-
<div className="demo-card-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
323
|
-
<h2 className="demo-card-title">Posts</h2>
|
|
324
|
-
<button className="button-primary" onClick={addPost} disabled={loading}>+ Post</button>
|
|
325
|
-
</div>
|
|
326
|
-
<div className="demo-card-body">
|
|
327
|
-
{posts.length === 0 && <p className="empty-state">No posts yet.</p>}
|
|
328
|
-
{posts.map(p => (
|
|
329
|
-
<div key={p.id} style={{ borderBottom: '1px solid var(--border, #e5e7eb)', padding: '0.75rem 0' }}>
|
|
330
|
-
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
331
|
-
<strong>#{p.id} — {p.title}</strong>
|
|
332
|
-
<span style={{ display: 'flex', gap: '0.25rem' }}>
|
|
333
|
-
<button onClick={() => addComment('post', p.id)} disabled={loading} style={{ fontSize: '0.75rem', padding: '0.25rem 0.5rem' }}>+ Comment</button>
|
|
334
|
-
<button onClick={() => attachTag('post', p.id)} disabled={loading} style={{ fontSize: '0.75rem', padding: '0.25rem 0.5rem' }}>+ Tag</button>
|
|
335
|
-
</span>
|
|
336
|
-
</div>
|
|
337
|
-
{p.tags.length > 0 && (
|
|
338
|
-
<div style={{ marginTop: '0.4rem', display: 'flex', flexWrap: 'wrap', gap: '0.25rem' }}>
|
|
339
|
-
{p.tags.map(t => (
|
|
340
|
-
<button
|
|
341
|
-
key={t.id}
|
|
342
|
-
onClick={() => detachTag('post', p.id, t.id)}
|
|
343
|
-
disabled={loading}
|
|
344
|
-
title="Click to detach"
|
|
345
|
-
style={{ fontSize: '0.7rem', padding: '0.15rem 0.5rem', borderRadius: '999px', background: '#dbeafe', color: '#1e40af', border: '1px solid #93c5fd', cursor: 'pointer' }}
|
|
346
|
-
>
|
|
347
|
-
{t.name} ×
|
|
348
|
-
</button>
|
|
349
|
-
))}
|
|
350
|
-
</div>
|
|
351
|
-
)}
|
|
352
|
-
<ul style={{ marginTop: '0.5rem', paddingLeft: '1rem', fontSize: '0.85rem' }}>
|
|
353
|
-
{p.comments.map(c => (
|
|
354
|
-
<li key={c.id} style={{ marginBottom: '0.25rem' }}>
|
|
355
|
-
{c.body} <button onClick={() => resolveParent(c.id)} style={{ fontSize: '0.7rem', marginLeft: '0.5rem' }}>resolve</button>
|
|
356
|
-
</li>
|
|
357
|
-
))}
|
|
358
|
-
{p.comments.length === 0 && <li style={{ color: 'var(--text-muted, #888)' }}>(no comments)</li>}
|
|
359
|
-
</ul>
|
|
360
|
-
</div>
|
|
361
|
-
))}
|
|
362
|
-
</div>
|
|
363
|
-
</div>
|
|
364
|
-
|
|
365
|
-
<div className="demo-card">
|
|
366
|
-
<div className="demo-card-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
367
|
-
<h2 className="demo-card-title">Videos</h2>
|
|
368
|
-
<button className="button-primary" onClick={addVideo} disabled={loading}>+ Video</button>
|
|
369
|
-
</div>
|
|
370
|
-
<div className="demo-card-body">
|
|
371
|
-
{videos.length === 0 && <p className="empty-state">No videos yet.</p>}
|
|
372
|
-
{videos.map(v => (
|
|
373
|
-
<div key={v.id} style={{ borderBottom: '1px solid var(--border, #e5e7eb)', padding: '0.75rem 0' }}>
|
|
374
|
-
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
375
|
-
<strong>#{v.id} — {v.url}</strong>
|
|
376
|
-
<span style={{ display: 'flex', gap: '0.25rem' }}>
|
|
377
|
-
<button onClick={() => addComment('video', v.id)} disabled={loading} style={{ fontSize: '0.75rem', padding: '0.25rem 0.5rem' }}>+ Comment</button>
|
|
378
|
-
<button onClick={() => attachTag('video', v.id)} disabled={loading} style={{ fontSize: '0.75rem', padding: '0.25rem 0.5rem' }}>+ Tag</button>
|
|
379
|
-
</span>
|
|
380
|
-
</div>
|
|
381
|
-
{v.tags.length > 0 && (
|
|
382
|
-
<div style={{ marginTop: '0.4rem', display: 'flex', flexWrap: 'wrap', gap: '0.25rem' }}>
|
|
383
|
-
{v.tags.map(t => (
|
|
384
|
-
<button
|
|
385
|
-
key={t.id}
|
|
386
|
-
onClick={() => detachTag('video', v.id, t.id)}
|
|
387
|
-
disabled={loading}
|
|
388
|
-
title="Click to detach"
|
|
389
|
-
style={{ fontSize: '0.7rem', padding: '0.15rem 0.5rem', borderRadius: '999px', background: '#fce7f3', color: '#9d174d', border: '1px solid #f9a8d4', cursor: 'pointer' }}
|
|
390
|
-
>
|
|
391
|
-
{t.name} ×
|
|
392
|
-
</button>
|
|
393
|
-
))}
|
|
394
|
-
</div>
|
|
395
|
-
)}
|
|
396
|
-
<ul style={{ marginTop: '0.5rem', paddingLeft: '1rem', fontSize: '0.85rem' }}>
|
|
397
|
-
{v.comments.map(c => (
|
|
398
|
-
<li key={c.id} style={{ marginBottom: '0.25rem' }}>
|
|
399
|
-
{c.body} <button onClick={() => resolveParent(c.id)} style={{ fontSize: '0.7rem', marginLeft: '0.5rem' }}>resolve</button>
|
|
400
|
-
</li>
|
|
401
|
-
))}
|
|
402
|
-
{v.comments.length === 0 && <li style={{ color: 'var(--text-muted, #888)' }}>(no comments)</li>}
|
|
403
|
-
</ul>
|
|
404
|
-
</div>
|
|
405
|
-
))}
|
|
406
|
-
</div>
|
|
407
|
-
</div>
|
|
408
|
-
</div>
|
|
409
|
-
|
|
410
|
-
<div className="demo-card" style={{ maxWidth: '60rem', margin: '1rem auto 0' }}>
|
|
411
|
-
<div className="demo-card-header" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
412
|
-
<h2 className="demo-card-title">Tags (shared)</h2>
|
|
413
|
-
<button className="button-primary" onClick={addTag} disabled={loading}>+ Tag</button>
|
|
414
|
-
</div>
|
|
415
|
-
<div className="demo-card-body">
|
|
416
|
-
{tags.length === 0 && <p className="empty-state">No tags yet.</p>}
|
|
417
|
-
{tags.length > 0 && (
|
|
418
|
-
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.4rem' }}>
|
|
419
|
-
{tags.map(t => (
|
|
420
|
-
<button
|
|
421
|
-
key={t.id}
|
|
422
|
-
onClick={() => resolveInverse(t)}
|
|
423
|
-
disabled={loading}
|
|
424
|
-
title="Show every Post + Video tagged with this"
|
|
425
|
-
style={{ fontSize: '0.8rem', padding: '0.25rem 0.6rem', borderRadius: '999px', background: '#f3f4f6', border: '1px solid #d1d5db', cursor: 'pointer' }}
|
|
426
|
-
>
|
|
427
|
-
{t.name}
|
|
428
|
-
</button>
|
|
429
|
-
))}
|
|
430
|
-
</div>
|
|
431
|
-
)}
|
|
432
|
-
</div>
|
|
433
|
-
</div>
|
|
434
|
-
|
|
435
|
-
{resolved && (
|
|
436
|
-
<div className="demo-card" style={{ maxWidth: '40rem', margin: '1rem auto 0' }}>
|
|
437
|
-
<div className="demo-card-header"><h2 className="demo-card-title">morphTo resolved</h2></div>
|
|
438
|
-
<div className="demo-card-body">
|
|
439
|
-
<code className="inline-code">comment.related('commentable').first()</code> ⇒ <strong>{resolved.type}</strong> #{resolved.id} — {resolved.title}
|
|
440
|
-
</div>
|
|
441
|
-
</div>
|
|
442
|
-
)}
|
|
443
|
-
|
|
444
|
-
{inverse && (
|
|
445
|
-
<div className="demo-card" style={{ maxWidth: '60rem', margin: '1rem auto 0' }}>
|
|
446
|
-
<div className="demo-card-header"><h2 className="demo-card-title">morphedByMany resolved — tag "{inverse.tag.name}"</h2></div>
|
|
447
|
-
<div className="demo-card-body">
|
|
448
|
-
<p style={{ fontSize: '0.85rem', color: 'var(--text-muted, #888)' }}>
|
|
449
|
-
<code className="inline-code">tag.related('posts').get()</code> + <code className="inline-code">tag.related('videos').get()</code> — one pivot, two scoped reads.
|
|
450
|
-
</p>
|
|
451
|
-
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1rem', marginTop: '0.5rem' }}>
|
|
452
|
-
<div>
|
|
453
|
-
<strong style={{ fontSize: '0.85rem' }}>Posts ({inverse.data.posts.length})</strong>
|
|
454
|
-
<ul style={{ paddingLeft: '1rem', fontSize: '0.85rem' }}>
|
|
455
|
-
{inverse.data.posts.map(p => <li key={p.id}>#{p.id} — {p.title}</li>)}
|
|
456
|
-
{inverse.data.posts.length === 0 && <li style={{ color: 'var(--text-muted, #888)' }}>(none)</li>}
|
|
457
|
-
</ul>
|
|
458
|
-
</div>
|
|
459
|
-
<div>
|
|
460
|
-
<strong style={{ fontSize: '0.85rem' }}>Videos ({inverse.data.videos.length})</strong>
|
|
461
|
-
<ul style={{ paddingLeft: '1rem', fontSize: '0.85rem' }}>
|
|
462
|
-
{inverse.data.videos.map(v => <li key={v.id}>#{v.id} — {v.url}</li>)}
|
|
463
|
-
{inverse.data.videos.length === 0 && <li style={{ color: 'var(--text-muted, #888)' }}>(none)</li>}
|
|
464
|
-
</ul>
|
|
465
|
-
</div>
|
|
466
|
-
</div>
|
|
467
|
-
</div>
|
|
468
|
-
</div>
|
|
469
|
-
)}
|
|
470
|
-
</section>
|
|
471
|
-
</div>
|
|
472
|
-
)
|
|
473
|
-
}
|
|
474
|
-
`;
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Inlined into routes/web.ts demos block. Loads parents + hydrates each parent's
|
|
478
|
-
* comments + tags via the polymorphic relations. Returns plain objects (Vike
|
|
479
|
-
* refuses to serialize Model instances across the SSR boundary).
|
|
480
|
-
*/
|
|
481
|
-
export function demosPolymorphicWebBlock() {
|
|
482
|
-
return `Route.get('/demos/polymorphic', async () => {
|
|
483
|
-
const [posts, videos, tags] = await Promise.all([Post.all(), Video.all(), Tag.all()])
|
|
484
|
-
type WithRelated = { related(n: string): { get(): Promise<unknown[]> } }
|
|
485
|
-
const hydrate = async (parent: Post | Video) => {
|
|
486
|
-
const r = parent as unknown as WithRelated
|
|
487
|
-
const [comments, ptags] = await Promise.all([
|
|
488
|
-
r.related('comments').get() as Promise<Comment[]>,
|
|
489
|
-
r.related('tags').get() as Promise<Tag[]>,
|
|
490
|
-
])
|
|
491
|
-
return {
|
|
492
|
-
...parent,
|
|
493
|
-
comments: comments.map(c => ({ ...c })),
|
|
494
|
-
tags: ptags.map(t => ({ ...t })),
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
return view('demos.polymorphic', {
|
|
498
|
-
posts: await Promise.all(posts.map(hydrate)),
|
|
499
|
-
videos: await Promise.all(videos.map(hydrate)),
|
|
500
|
-
tags: tags.map(t => ({ ...t })),
|
|
501
|
-
})
|
|
502
|
-
})`;
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Inlined into routes/api.ts demos block. Endpoints: state, create-post,
|
|
506
|
-
* create-video, comment-on-post, comment-on-video, morphTo resolution,
|
|
507
|
-
* create-tag, attach/detach tag (post + video), morphedByMany inverse.
|
|
508
|
-
*/
|
|
509
|
-
export function demosPolymorphicApiBlock() {
|
|
510
|
-
return `// ── /demos/polymorphic — every polymorphic relation type via @rudderjs/orm ──
|
|
511
|
-
|
|
512
|
-
// GET /api/polymorphic/state — posts + videos with comments + tags + the flat tag list.
|
|
513
|
-
router.get('/api/polymorphic/state', async (_req, res) => {
|
|
514
|
-
const [posts, videos, tags] = await Promise.all([Post.all(), Video.all(), Tag.all()])
|
|
515
|
-
const hydrate = async (parent: Post | Video) => {
|
|
516
|
-
const r = parent as unknown as { related(n: string): { get(): Promise<unknown[]> } }
|
|
517
|
-
const [comments, ptags] = await Promise.all([
|
|
518
|
-
r.related('comments').get() as Promise<Comment[]>,
|
|
519
|
-
r.related('tags').get() as Promise<Tag[]>,
|
|
520
|
-
])
|
|
521
|
-
return {
|
|
522
|
-
...parent,
|
|
523
|
-
comments: comments.map(c => ({ ...c })),
|
|
524
|
-
tags: ptags.map(t => ({ ...t })),
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
res.json({
|
|
528
|
-
posts: await Promise.all(posts.map(hydrate)),
|
|
529
|
-
videos: await Promise.all(videos.map(hydrate)),
|
|
530
|
-
tags: tags.map(t => ({ ...t })),
|
|
531
|
-
})
|
|
532
|
-
})
|
|
533
|
-
|
|
534
|
-
// POST /api/polymorphic/posts — create a post.
|
|
535
|
-
router.post('/api/polymorphic/posts', async (req, res) => {
|
|
536
|
-
const { title } = (req.body ?? {}) as { title?: string }
|
|
537
|
-
if (!title) return res.status(400).json({ error: 'title required' })
|
|
538
|
-
const post = await Post.create({ title })
|
|
539
|
-
res.status(201).json({ ...post })
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
// POST /api/polymorphic/videos — create a video.
|
|
543
|
-
router.post('/api/polymorphic/videos', async (req, res) => {
|
|
544
|
-
const { url } = (req.body ?? {}) as { url?: string }
|
|
545
|
-
if (!url) return res.status(400).json({ error: 'url required' })
|
|
546
|
-
const video = await Video.create({ url })
|
|
547
|
-
res.status(201).json({ ...video })
|
|
548
|
-
})
|
|
549
|
-
|
|
550
|
-
// POST /api/polymorphic/(posts|videos)/:id/comments — Model.morph() write.
|
|
551
|
-
router.post('/api/polymorphic/posts/:id/comments', async (req, res) => {
|
|
552
|
-
const idParam = req.params['id']
|
|
553
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
554
|
-
const post = await Post.find(Number(idParam))
|
|
555
|
-
if (!post) return res.status(404).json({ error: 'post not found' })
|
|
556
|
-
const { body } = (req.body ?? {}) as { body?: string }
|
|
557
|
-
if (!body) return res.status(400).json({ error: 'body required' })
|
|
558
|
-
const comment = await Comment.create({ body, ...Model.morph('commentable', post) })
|
|
559
|
-
res.status(201).json({ ...comment })
|
|
560
|
-
})
|
|
561
|
-
|
|
562
|
-
router.post('/api/polymorphic/videos/:id/comments', async (req, res) => {
|
|
563
|
-
const idParam = req.params['id']
|
|
564
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
565
|
-
const video = await Video.find(Number(idParam))
|
|
566
|
-
if (!video) return res.status(404).json({ error: 'video not found' })
|
|
567
|
-
const { body } = (req.body ?? {}) as { body?: string }
|
|
568
|
-
if (!body) return res.status(400).json({ error: 'body required' })
|
|
569
|
-
const comment = await Comment.create({ body, ...Model.morph('commentable', video) })
|
|
570
|
-
res.status(201).json({ ...comment })
|
|
571
|
-
})
|
|
572
|
-
|
|
573
|
-
// GET /api/polymorphic/comments/:id/parent — morphTo resolution.
|
|
574
|
-
router.get('/api/polymorphic/comments/:id/parent', async (req, res) => {
|
|
575
|
-
const idParam = req.params['id']
|
|
576
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
577
|
-
const comment = await Comment.find(Number(idParam))
|
|
578
|
-
if (!comment) return res.status(404).json({ error: 'comment not found' })
|
|
579
|
-
|
|
580
|
-
const parent = await (comment as unknown as { related(n: string): { first(): Promise<Post | Video | null> } })
|
|
581
|
-
.related('commentable').first()
|
|
582
|
-
if (!parent) return res.status(404).json({ error: 'parent not found' })
|
|
583
|
-
|
|
584
|
-
res.json({
|
|
585
|
-
type: comment.commentableType,
|
|
586
|
-
id: parent.id,
|
|
587
|
-
title: 'title' in parent ? parent.title : parent.url,
|
|
588
|
-
})
|
|
589
|
-
})
|
|
590
|
-
|
|
591
|
-
// ── morphToMany / morphedByMany — Tag endpoints ────────────────────────────
|
|
592
|
-
|
|
593
|
-
// POST /api/polymorphic/tags — create a tag.
|
|
594
|
-
router.post('/api/polymorphic/tags', async (req, res) => {
|
|
595
|
-
const { name } = (req.body ?? {}) as { name?: string }
|
|
596
|
-
if (!name) return res.status(400).json({ error: 'name required' })
|
|
597
|
-
const tag = await Tag.create({ name })
|
|
598
|
-
res.status(201).json({ ...tag })
|
|
599
|
-
})
|
|
600
|
-
|
|
601
|
-
// POST /api/polymorphic/posts/:id/tags — morphToMany attach. The pivot row
|
|
602
|
-
// carries taggableType='Post' automatically.
|
|
603
|
-
router.post('/api/polymorphic/posts/:id/tags', async (req, res) => {
|
|
604
|
-
const idParam = req.params['id']
|
|
605
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
606
|
-
const post = await Post.find(Number(idParam))
|
|
607
|
-
if (!post) return res.status(404).json({ error: 'post not found' })
|
|
608
|
-
const { tagId } = (req.body ?? {}) as { tagId?: number }
|
|
609
|
-
if (typeof tagId !== 'number') return res.status(400).json({ error: 'tagId required' })
|
|
610
|
-
await Model.morphToMany(post, 'tags').attach([tagId])
|
|
611
|
-
res.json({ ok: true })
|
|
612
|
-
})
|
|
613
|
-
|
|
614
|
-
router.post('/api/polymorphic/videos/:id/tags', async (req, res) => {
|
|
615
|
-
const idParam = req.params['id']
|
|
616
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
617
|
-
const video = await Video.find(Number(idParam))
|
|
618
|
-
if (!video) return res.status(404).json({ error: 'video not found' })
|
|
619
|
-
const { tagId } = (req.body ?? {}) as { tagId?: number }
|
|
620
|
-
if (typeof tagId !== 'number') return res.status(400).json({ error: 'tagId required' })
|
|
621
|
-
await Model.morphToMany(video, 'tags').attach([tagId])
|
|
622
|
-
res.json({ ok: true })
|
|
623
|
-
})
|
|
624
|
-
|
|
625
|
-
// DELETE /api/polymorphic/(posts|videos)/:id/tags/:tagId — morphToMany detach
|
|
626
|
-
// scoped to the parent's discriminator (videos sharing the tag are untouched).
|
|
627
|
-
router.delete('/api/polymorphic/posts/:id/tags/:tagId', async (req, res) => {
|
|
628
|
-
const id = req.params['id']; const tagId = req.params['tagId']
|
|
629
|
-
if (!id || !tagId) return res.status(400).json({ error: 'id/tagId required' })
|
|
630
|
-
const post = await Post.find(Number(id))
|
|
631
|
-
if (!post) return res.status(404).json({ error: 'post not found' })
|
|
632
|
-
await Model.morphToMany(post, 'tags').detach([Number(tagId)])
|
|
633
|
-
res.json({ ok: true })
|
|
634
|
-
})
|
|
635
|
-
|
|
636
|
-
router.delete('/api/polymorphic/videos/:id/tags/:tagId', async (req, res) => {
|
|
637
|
-
const id = req.params['id']; const tagId = req.params['tagId']
|
|
638
|
-
if (!id || !tagId) return res.status(400).json({ error: 'id/tagId required' })
|
|
639
|
-
const video = await Video.find(Number(id))
|
|
640
|
-
if (!video) return res.status(404).json({ error: 'video not found' })
|
|
641
|
-
await Model.morphToMany(video, 'tags').detach([Number(tagId)])
|
|
642
|
-
res.json({ ok: true })
|
|
643
|
-
})
|
|
644
|
-
|
|
645
|
-
// GET /api/polymorphic/tags/:id/items — morphedByMany inverse fan-out.
|
|
646
|
-
// One pivot, two scoped reads (one per concrete inverse class).
|
|
647
|
-
router.get('/api/polymorphic/tags/:id/items', async (req, res) => {
|
|
648
|
-
const idParam = req.params['id']
|
|
649
|
-
if (!idParam) return res.status(400).json({ error: 'id required' })
|
|
650
|
-
const tag = await Tag.find(Number(idParam))
|
|
651
|
-
if (!tag) return res.status(404).json({ error: 'tag not found' })
|
|
652
|
-
const r = tag as unknown as { related(n: string): { get(): Promise<unknown[]> } }
|
|
653
|
-
const [posts, videos] = await Promise.all([
|
|
654
|
-
r.related('posts').get() as Promise<Post[]>,
|
|
655
|
-
r.related('videos').get() as Promise<Video[]>,
|
|
656
|
-
])
|
|
657
|
-
res.json({
|
|
658
|
-
posts: posts.map(p => ({ ...p })),
|
|
659
|
-
videos: videos.map(v => ({ ...v })),
|
|
660
|
-
})
|
|
661
|
-
})`;
|
|
662
|
-
}
|
|
663
|
-
//# sourceMappingURL=polymorphic.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"polymorphic.js","sourceRoot":"","sources":["../../../src/templates/demos/polymorphic.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,yEAAyE;AACzE,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,sCAAsC;AAEtC,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;;CAiBR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO;;;;;;;;;;;;;;;;;;CAkBR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCR,CAAA;AACD,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0UR,CAAA;AACD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;GAoBN,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuJN,CAAA;AACH,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../src/templates/demos/queue.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,IAAI,MAAM,CA6DvC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAyBnC;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAO3C"}
|