betterstart-cli 0.0.117 → 0.0.119
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/assets/adapters/next/templates/init/admin-globals.css +154 -38
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-grid-row.tsx +33 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-gallery-dialog.tsx +3 -3
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-preview.tsx +3 -1
- package/dist/assets/adapters/next/templates/init/hooks/use-field-error-visible.ts +25 -0
- package/dist/assets/adapters/next/templates/init/hooks/use-media.ts +1 -1
- package/dist/assets/adapters/next/templates/init/hooks/use-upload.ts +11 -5
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/query-audit-logs.ts +2 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/record-audit-event.ts +1 -2
- package/dist/assets/adapters/next/templates/init/lib/actions/auth/client.ts +4 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/entity-versions/get-entity-versions.ts +5 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/forms/get-all-form-settings.ts +1 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/create-media.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media-bulk.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +2 -4
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/change-own-password.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-files.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +16 -6
- package/dist/assets/adapters/next/templates/init/lib/actions/users/change-user-password.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/users/create-user.ts +2 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/delete-user.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/users/types.ts +1 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +1 -0
- package/dist/assets/adapters/next/templates/init/lib/db/core/schema.ts +12 -4
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/registry.ts +4 -4
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/runner.ts +3 -7
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-form.tsx +5 -8
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/login-form.tsx +7 -9
- package/dist/assets/adapters/next/templates/init/pages/login-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/reset-password-form.tsx +8 -16
- package/dist/assets/adapters/next/templates/init/pages/reset-password-page-skeleton.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-detail-row.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/settings/audit-log/audit-log-table.tsx +1 -6
- package/dist/assets/adapters/next/templates/init/pages/settings/forms/forms-settings-table.tsx +2 -7
- package/dist/assets/adapters/next/templates/init/pages/settings/webhooks/webhooks-table.tsx +1 -6
- package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/public/placeholder.png +0 -0
- package/dist/assets/adapters/next/templates/init/types/index.ts +2 -0
- package/dist/assets/adapters/next/templates/init/utils/audit/normalize-comparable-value.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/date/format-action-date.ts +12 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/dev-mode-json-schemas.ts +66 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/parse-dev-mode-lifecycle-hooks.ts +11 -0
- package/dist/assets/adapters/next/templates/init/utils/dev-mode/parse-dev-mode-snippets.ts +9 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/set-task-item-checked.ts +13 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/update-nodes-attr.ts +2 -1
- package/dist/assets/adapters/next/templates/init/utils/email/email-theme.ts +13 -0
- package/dist/assets/adapters/next/templates/init/utils/email/render-form-submission-rows.ts +3 -2
- package/dist/assets/adapters/next/templates/init/utils/email/render-notification-email.ts +7 -6
- package/dist/assets/adapters/next/templates/init/utils/email/render-thank-you-email.ts +5 -4
- package/dist/assets/adapters/next/templates/init/utils/error/read-string-property.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/error/recognize.ts +2 -4
- package/dist/assets/adapters/next/templates/init/utils/error/to-action-error.ts +0 -1
- package/dist/assets/adapters/next/templates/init/utils/form/clone-default-value.ts +4 -2
- package/dist/assets/adapters/next/templates/init/utils/shared/is-record.ts +3 -0
- package/dist/assets/adapters/next/templates/init/utils/table/default-get-id.ts +3 -2
- package/dist/assets/shared-assets/react-admin/custom/content-editor/editor-toolbar.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/slash-command-menu.tsx +5 -3
- package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-node/removable-image-node/removable-image-node.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-node/task-item-node/task-item-node-extension.tsx +6 -15
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +1 -6
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +1 -6
- package/dist/assets/shared-assets/react-admin/custom/date-range-picker.tsx +9 -2
- package/dist/assets/shared-assets/react-admin/custom/gallery-field.tsx +3 -3
- package/dist/assets/shared-assets/react-admin/custom/media-field.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/nested-object-list-field.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/custom/progressive-blur.tsx +3 -1
- package/dist/assets/shared-assets/react-admin/ui/badge.tsx +1 -2
- package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +20 -23
- package/dist/assets/shared-assets/react-admin/ui/form.tsx +6 -3
- package/dist/assets/shared-assets/react-admin/ui/input.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/native-select.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/navigation-menu.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/select.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/textarea.tsx +1 -1
- package/dist/{chunk-FGEVDA53.js → chunk-BNHFSHPE.js} +12 -1
- package/dist/chunk-BNHFSHPE.js.map +1 -0
- package/dist/cli.js +909 -598
- package/dist/cli.js.map +1 -1
- package/dist/{read-namespaced-template-KUENIIDC.js → read-namespaced-template-WYIGUH7S.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-FGEVDA53.js.map +0 -1
- /package/dist/{read-namespaced-template-KUENIIDC.js.map → read-namespaced-template-WYIGUH7S.js.map} +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { isRecord } from '@admin/utils/shared/is-record'
|
|
2
|
+
|
|
1
3
|
export function cloneDefaultValue(value: unknown): unknown {
|
|
2
4
|
if (Array.isArray(value)) return value.map(cloneDefaultValue)
|
|
3
5
|
|
|
4
|
-
if (value
|
|
5
|
-
const clonedEntries = Object.entries(value
|
|
6
|
+
if (isRecord(value)) {
|
|
7
|
+
const clonedEntries = Object.entries(value).map(
|
|
6
8
|
([key, childValue]) => [key, cloneDefaultValue(childValue)] as const
|
|
7
9
|
)
|
|
8
10
|
return Object.fromEntries(clonedEntries)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RowData } from '@tanstack/react-table'
|
|
2
|
+
import { isRecord } from '@admin/utils/shared/is-record'
|
|
2
3
|
|
|
3
4
|
export function defaultGetId<TData extends RowData>(row: TData): string | null | undefined {
|
|
4
|
-
|
|
5
|
-
return typeof id === 'string' ? id : null
|
|
5
|
+
if (!isRecord(row)) return null
|
|
6
|
+
return typeof row.id === 'string' ? row.id : null
|
|
6
7
|
}
|
|
@@ -15,7 +15,7 @@ export function EditorToolbar({
|
|
|
15
15
|
role="toolbar"
|
|
16
16
|
aria-label={ariaLabel}
|
|
17
17
|
className={cn(
|
|
18
|
-
'sticky top-0 z-10 flex min-h-12 w-full items-center gap-1 overflow-x-auto overscroll-x-contain border-b border-border bg-card px-2 [scrollbar-width:none] max-
|
|
18
|
+
'sticky top-0 z-10 flex min-h-12 w-full items-center gap-1 overflow-x-auto overscroll-x-contain border-b border-border bg-card px-2 [scrollbar-width:none] max-xs:absolute max-xs:top-auto max-xs:h-[calc(2.75rem+env(safe-area-inset-bottom,0px))] max-xs:flex-nowrap max-xs:justify-start max-xs:border-t max-xs:border-b-0 max-xs:pb-[env(safe-area-inset-bottom,0px)] [&::-webkit-scrollbar]:hidden',
|
|
19
19
|
className
|
|
20
20
|
)}
|
|
21
21
|
>
|
|
@@ -33,6 +33,10 @@ export function SlashCommandMenu({
|
|
|
33
33
|
searchQuery: string
|
|
34
34
|
}) {
|
|
35
35
|
const activeItemRef = React.useRef<HTMLDivElement | null>(null)
|
|
36
|
+
|
|
37
|
+
function assignActiveItem(node: HTMLDivElement | null) {
|
|
38
|
+
activeItemRef.current = node
|
|
39
|
+
}
|
|
36
40
|
const searchInputRef = React.useRef<HTMLInputElement | null>(null)
|
|
37
41
|
const activeCommandId = commands[activeIndex]?.id
|
|
38
42
|
|
|
@@ -159,9 +163,7 @@ export function SlashCommandMenu({
|
|
|
159
163
|
index={index}
|
|
160
164
|
key={command.id}
|
|
161
165
|
data-active={isActive ? 'true' : undefined}
|
|
162
|
-
ref={
|
|
163
|
-
if (isActive) activeItemRef.current = node
|
|
164
|
-
}}
|
|
166
|
+
ref={isActive ? assignActiveItem : undefined}
|
|
165
167
|
onMouseDown={(event) => event.preventDefault()}
|
|
166
168
|
onMouseEnter={() => onActiveIndexChange(index)}
|
|
167
169
|
value={command}
|
|
@@ -120,7 +120,7 @@ export function SourceMode({
|
|
|
120
120
|
return (
|
|
121
121
|
<div
|
|
122
122
|
className={cn(
|
|
123
|
-
'content-editor-wrapper relative flex max-h-[90vh] min-h-
|
|
123
|
+
'content-editor-wrapper relative flex max-h-[90vh] min-h-source-editor resize-y flex-col overflow-hidden rounded-md border bg-background',
|
|
124
124
|
{ 'opacity-50': disabled },
|
|
125
125
|
className
|
|
126
126
|
)}
|
|
@@ -14,6 +14,8 @@ import { cn } from '@admin/utils/shared/cn'
|
|
|
14
14
|
import { NodeViewWrapper } from '@tiptap/react'
|
|
15
15
|
import NextImage from 'next/image'
|
|
16
16
|
|
|
17
|
+
const EDITOR_IMAGE_SIZES = '768px'
|
|
18
|
+
|
|
17
19
|
export const RemovableImageNode: React.FC<NodeViewProps> = (props) => {
|
|
18
20
|
const { editor, node } = props
|
|
19
21
|
const src = getStringAttr(node.attrs.src)
|
|
@@ -118,7 +120,7 @@ export const RemovableImageNode: React.FC<NodeViewProps> = (props) => {
|
|
|
118
120
|
alt={alt}
|
|
119
121
|
title={title || undefined}
|
|
120
122
|
fill
|
|
121
|
-
sizes=
|
|
123
|
+
sizes={EDITOR_IMAGE_SIZES}
|
|
122
124
|
unoptimized
|
|
123
125
|
className="!m-0 !h-full !w-full !max-w-full object-contain"
|
|
124
126
|
onLoad={handleImageLoad}
|
|
@@ -5,6 +5,7 @@ import { getTaskItemCheckboxLabel } from '@admin/utils/editor/get-task-item-chec
|
|
|
5
5
|
import { hasOwnAttribute } from '@admin/utils/editor/has-own-attribute'
|
|
6
6
|
import { isTaskItemChecked } from '@admin/utils/editor/is-task-item-checked'
|
|
7
7
|
import { setElementAttribute } from '@admin/utils/editor/set-element-attribute'
|
|
8
|
+
import { setTaskItemChecked } from '@admin/utils/editor/set-task-item-checked'
|
|
8
9
|
import { getRenderedAttributes } from '@tiptap/core'
|
|
9
10
|
import { TaskItem } from '@tiptap/extension-list'
|
|
10
11
|
import { createRoot } from 'react-dom/client'
|
|
@@ -20,7 +21,7 @@ export const ContentEditorTaskItem = TaskItem.extend({
|
|
|
20
21
|
const checkboxMount = document.createElement('span')
|
|
21
22
|
const content = document.createElement('div')
|
|
22
23
|
const checkboxRoot = createRoot(checkboxMount)
|
|
23
|
-
const staticAttributes = this.options.HTMLAttributes
|
|
24
|
+
const staticAttributes: Record<string, unknown> = this.options.HTMLAttributes
|
|
24
25
|
|
|
25
26
|
checkboxContainer.contentEditable = 'false'
|
|
26
27
|
checkboxContainer.className = 'content-editor-task-item-checkbox'
|
|
@@ -52,17 +53,7 @@ export const ContentEditorTaskItem = TaskItem.extend({
|
|
|
52
53
|
editor
|
|
53
54
|
.chain()
|
|
54
55
|
.focus(undefined, { scrollIntoView: false })
|
|
55
|
-
.command(({ tr }) =>
|
|
56
|
-
const position = getPos()
|
|
57
|
-
if (typeof position !== 'number') return false
|
|
58
|
-
|
|
59
|
-
const taskItem = tr.doc.nodeAt(position)
|
|
60
|
-
tr.setNodeMarkup(position, undefined, {
|
|
61
|
-
...taskItem?.attrs,
|
|
62
|
-
checked
|
|
63
|
-
})
|
|
64
|
-
return true
|
|
65
|
-
})
|
|
56
|
+
.command(({ tr }) => setTaskItemChecked(tr, getPos(), checked))
|
|
66
57
|
.run()
|
|
67
58
|
return
|
|
68
59
|
}
|
|
@@ -89,7 +80,7 @@ export const ContentEditorTaskItem = TaskItem.extend({
|
|
|
89
80
|
listItem.dataset.checked = String(renderedChecked)
|
|
90
81
|
}
|
|
91
82
|
|
|
92
|
-
applyAttributes(HTMLAttributes
|
|
83
|
+
applyAttributes(HTMLAttributes)
|
|
93
84
|
renderCheckbox()
|
|
94
85
|
|
|
95
86
|
let prevRenderedAttributeKeys = new Set(Object.keys(HTMLAttributes))
|
|
@@ -104,10 +95,10 @@ export const ContentEditorTaskItem = TaskItem.extend({
|
|
|
104
95
|
renderedChecked = isTaskItemChecked(updatedNode)
|
|
105
96
|
|
|
106
97
|
const extensionAttributes = editor.extensionManager.attributes
|
|
107
|
-
const newHTMLAttributes = getRenderedAttributes(
|
|
98
|
+
const newHTMLAttributes: Record<string, unknown> = getRenderedAttributes(
|
|
108
99
|
updatedNode,
|
|
109
100
|
extensionAttributes
|
|
110
|
-
)
|
|
101
|
+
)
|
|
111
102
|
const newKeys = new Set(Object.keys(newHTMLAttributes))
|
|
112
103
|
|
|
113
104
|
prevRenderedAttributeKeys.forEach((key) => {
|
|
@@ -93,12 +93,7 @@ export function HeadingDropdownMenu({
|
|
|
93
93
|
}
|
|
94
94
|
></DropdownMenuTrigger>
|
|
95
95
|
|
|
96
|
-
<DropdownMenuContent
|
|
97
|
-
align="start"
|
|
98
|
-
className="w-auto min-w-40"
|
|
99
|
-
finalFocus={false}
|
|
100
|
-
portalled={false}
|
|
101
|
-
>
|
|
96
|
+
<DropdownMenuContent align="start" className="w-auto min-w-40" finalFocus={false}>
|
|
102
97
|
<DropdownMenuGroup>
|
|
103
98
|
{levels.map((level) => (
|
|
104
99
|
<HeadingDropdownMenuItem key={`heading-${level}`} editor={editor} level={level} />
|
|
@@ -83,12 +83,7 @@ export function ListDropdownMenu({
|
|
|
83
83
|
<ChevronDownIcon className="tiptap-button-dropdown-small" />
|
|
84
84
|
</DropdownMenuTrigger>
|
|
85
85
|
|
|
86
|
-
<DropdownMenuContent
|
|
87
|
-
align="start"
|
|
88
|
-
className="w-auto min-w-40"
|
|
89
|
-
finalFocus={false}
|
|
90
|
-
portalled={false}
|
|
91
|
-
>
|
|
86
|
+
<DropdownMenuContent align="start" className="w-auto min-w-40" finalFocus={false}>
|
|
92
87
|
<DropdownMenuGroup>
|
|
93
88
|
{filteredLists.map((option) => (
|
|
94
89
|
<ListDropdownMenuItem
|
|
@@ -132,14 +132,21 @@ export function DateRangePicker({
|
|
|
132
132
|
>
|
|
133
133
|
<PopoverTrigger
|
|
134
134
|
render={
|
|
135
|
-
<Button
|
|
135
|
+
<Button
|
|
136
|
+
variant="outline"
|
|
137
|
+
className={cn('w-date-range-trigger', className)}
|
|
138
|
+
disabled={disabled}
|
|
139
|
+
/>
|
|
136
140
|
}
|
|
137
141
|
>
|
|
138
142
|
<CalendarIcon />
|
|
139
143
|
<span className="min-w-0 flex-1 truncate text-left tabular-nums">{triggerLabel}</span>
|
|
140
144
|
<ChevronDown />
|
|
141
145
|
</PopoverTrigger>
|
|
142
|
-
<PopoverContent
|
|
146
|
+
<PopoverContent
|
|
147
|
+
className="w-date-range-popover gap-0 overflow-hidden rounded-sm p-0"
|
|
148
|
+
align="start"
|
|
149
|
+
>
|
|
143
150
|
<Calendar
|
|
144
151
|
mode="range"
|
|
145
152
|
month={calendarMonth}
|
|
@@ -189,7 +189,7 @@ export function GalleryField({
|
|
|
189
189
|
>
|
|
190
190
|
<CarouselContent className="-ml-3">
|
|
191
191
|
{canAdd && !disabled ? (
|
|
192
|
-
<CarouselItem className="basis-
|
|
192
|
+
<CarouselItem className="basis-gallery-item pl-3">
|
|
193
193
|
<Card className="h-full" onClick={() => setOpen(true)}>
|
|
194
194
|
<CardContent className="flex cursor-pointer flex-col p-2">
|
|
195
195
|
<div className="flex aspect-square size-full flex-col items-center justify-center gap-1 overflow-hidden rounded-sm border border-border bg-background text-muted-foreground transition-colors hover:text-foreground">
|
|
@@ -208,7 +208,7 @@ export function GalleryField({
|
|
|
208
208
|
{value.map((id) => {
|
|
209
209
|
const item = mediaMap.get(id)
|
|
210
210
|
return (
|
|
211
|
-
<CarouselItem key={id} className="basis-
|
|
211
|
+
<CarouselItem key={id} className="basis-gallery-item pl-3">
|
|
212
212
|
<SortableGalleryItem id={id} disabled={disabled}>
|
|
213
213
|
{item ? (
|
|
214
214
|
<MediaField
|
|
@@ -243,7 +243,7 @@ export function GalleryField({
|
|
|
243
243
|
</div>
|
|
244
244
|
<DragOverlay>
|
|
245
245
|
{activeId ? (
|
|
246
|
-
<div className="w-
|
|
246
|
+
<div className="w-gallery-item scale-[0.98] cursor-grabbing opacity-95">
|
|
247
247
|
{activeItem ? (
|
|
248
248
|
<MediaField
|
|
249
249
|
value={activeId}
|
|
@@ -102,7 +102,7 @@ export function MediaField({
|
|
|
102
102
|
data-media-field-action="true"
|
|
103
103
|
variant="outline"
|
|
104
104
|
onClick={handleChangeImage}
|
|
105
|
-
className="w-
|
|
105
|
+
className="w-media-thumb border-primary/10"
|
|
106
106
|
>
|
|
107
107
|
Change
|
|
108
108
|
</Button>
|
|
@@ -111,7 +111,7 @@ export function MediaField({
|
|
|
111
111
|
data-media-field-action="true"
|
|
112
112
|
variant="default"
|
|
113
113
|
onClick={handleRemove}
|
|
114
|
-
className="w-
|
|
114
|
+
className="w-media-thumb"
|
|
115
115
|
>
|
|
116
116
|
Remove
|
|
117
117
|
</Button>
|
|
@@ -13,6 +13,7 @@ import { FormDescription, FormField, FormItem, FormLabel } from '@admin/componen
|
|
|
13
13
|
import { cloneDefaultValue } from '@admin/utils/form/clone-default-value'
|
|
14
14
|
import { createListItemKey } from '@admin/utils/form/create-list-item-key'
|
|
15
15
|
import { cn } from '@admin/utils/shared/cn'
|
|
16
|
+
import { isRecord } from '@admin/utils/shared/is-record'
|
|
16
17
|
import { Plus, X } from 'lucide-react'
|
|
17
18
|
import { useFormContext, useWatch } from 'react-hook-form'
|
|
18
19
|
|
|
@@ -75,7 +76,8 @@ export function NestedObjectListField({
|
|
|
75
76
|
if (!isExpandedItemValid) return
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
const
|
|
79
|
+
const clonedDefaultValue = cloneDefaultValue(defaultValue)
|
|
80
|
+
const nextValue = isRecord(clonedDefaultValue) ? clonedDefaultValue : {}
|
|
79
81
|
const nextItems = [...items, nextValue]
|
|
80
82
|
setValue(name, nextItems, {
|
|
81
83
|
shouldDirty: true,
|
|
@@ -5,6 +5,8 @@ import { usePageBoundaryBlurVisibility } from '@admin/hooks/use-page-boundary-bl
|
|
|
5
5
|
import { cn } from '@admin/utils/shared/cn'
|
|
6
6
|
import { motion } from 'motion/react'
|
|
7
7
|
|
|
8
|
+
const DEFAULT_PROGRESSIVE_BLUR_HEIGHT = '150px'
|
|
9
|
+
|
|
8
10
|
type ProgressiveBlurProps = React.ComponentProps<typeof motion.div> & {
|
|
9
11
|
backgroundColor?: string
|
|
10
12
|
position?: 'top' | 'bottom'
|
|
@@ -18,7 +20,7 @@ function ProgressiveBlur({
|
|
|
18
20
|
style,
|
|
19
21
|
backgroundColor = 'var(--background)',
|
|
20
22
|
position = 'top',
|
|
21
|
-
height =
|
|
23
|
+
height = DEFAULT_PROGRESSIVE_BLUR_HEIGHT,
|
|
22
24
|
blurAmount = '0',
|
|
23
25
|
scrollAware = true,
|
|
24
26
|
...props
|
|
@@ -13,8 +13,7 @@ const badgeVariants = cva(
|
|
|
13
13
|
secondary: 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
|
|
14
14
|
destructive:
|
|
15
15
|
'bg-destructive/10 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/20',
|
|
16
|
-
success:
|
|
17
|
-
'bg-emerald-500/10 text-emerald-700 focus-visible:ring-emerald-500/20 [a]:hover:bg-emerald-500/20',
|
|
16
|
+
success: 'bg-success/10 text-success focus-visible:ring-success/20 [a]:hover:bg-success/20',
|
|
18
17
|
outline:
|
|
19
18
|
'border-border bg-input/30 text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
|
|
20
19
|
ghost: 'hover:bg-muted hover:text-muted-foreground',
|
|
@@ -22,33 +22,30 @@ function DropdownMenuContent({
|
|
|
22
22
|
alignOffset = 0,
|
|
23
23
|
side = 'bottom',
|
|
24
24
|
sideOffset = 4,
|
|
25
|
-
portalled = true,
|
|
26
25
|
className,
|
|
27
26
|
...props
|
|
28
27
|
}: MenuPrimitive.Popup.Props &
|
|
29
|
-
Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
</MenuPrimitive.
|
|
28
|
+
Pick<MenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
|
|
29
|
+
return (
|
|
30
|
+
<MenuPrimitive.Portal>
|
|
31
|
+
<MenuPrimitive.Positioner
|
|
32
|
+
className="isolate z-50 outline-none"
|
|
33
|
+
align={align}
|
|
34
|
+
alignOffset={alignOffset}
|
|
35
|
+
side={side}
|
|
36
|
+
sideOffset={sideOffset}
|
|
37
|
+
>
|
|
38
|
+
<MenuPrimitive.Popup
|
|
39
|
+
data-slot="dropdown-menu-content"
|
|
40
|
+
className={cn(
|
|
41
|
+
'cn-menu-target cn-menu-translucent z-50 max-h-(--available-height) w-(--anchor-width) min-w-48 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-2xl bg-popover p-1 text-popover-foreground shadow-2xl ring-1 ring-foreground/5 duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95',
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
</MenuPrimitive.Positioner>
|
|
47
|
+
</MenuPrimitive.Portal>
|
|
49
48
|
)
|
|
50
|
-
|
|
51
|
-
return portalled ? <MenuPrimitive.Portal>{content}</MenuPrimitive.Portal> : content
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form'
|
|
5
5
|
import { Label } from '@admin/components/ui/label'
|
|
6
|
+
import { useFieldErrorVisible } from '@admin/hooks/use-field-error-visible'
|
|
6
7
|
import { cn } from '@admin/utils/shared/cn'
|
|
7
8
|
import { Controller, FormProvider, useFormContext } from 'react-hook-form'
|
|
8
9
|
|
|
@@ -33,7 +34,8 @@ const FormField = <
|
|
|
33
34
|
const useFormField = () => {
|
|
34
35
|
const fieldContext = React.useContext(FormFieldContext)
|
|
35
36
|
const itemContext = React.useContext(FormItemContext)
|
|
36
|
-
const
|
|
37
|
+
const form = useFormContext()
|
|
38
|
+
const isErrorVisible = useFieldErrorVisible(form, fieldContext?.name ?? '')
|
|
37
39
|
|
|
38
40
|
if (!fieldContext) {
|
|
39
41
|
throw new Error('useFormField should be used within <FormField>')
|
|
@@ -43,7 +45,7 @@ const useFormField = () => {
|
|
|
43
45
|
throw new Error('useFormField should be used within <FormItem>')
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
const fieldState = getFieldState(fieldContext.name, formState)
|
|
48
|
+
const fieldState = form.getFieldState(fieldContext.name, form.formState)
|
|
47
49
|
|
|
48
50
|
const { id } = itemContext
|
|
49
51
|
|
|
@@ -53,7 +55,8 @@ const useFormField = () => {
|
|
|
53
55
|
formItemId: `${id}-form-item`,
|
|
54
56
|
formDescriptionId: `${id}-form-item-description`,
|
|
55
57
|
formMessageId: `${id}-form-item-message`,
|
|
56
|
-
...fieldState
|
|
58
|
+
...fieldState,
|
|
59
|
+
error: isErrorVisible ? fieldState.error : undefined
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
|
|
|
8
8
|
type={type}
|
|
9
9
|
data-slot="input"
|
|
10
10
|
className={cn(
|
|
11
|
-
'h-9 w-full min-w-0 rounded-4xl border border-input bg-input/30 px-3 py-1 text-sm transition-colors outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-
|
|
11
|
+
'h-9 w-full min-w-0 rounded-4xl border border-input bg-input/30 px-3 py-1 text-sm transition-colors outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-placeholder focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20',
|
|
12
12
|
className
|
|
13
13
|
)}
|
|
14
14
|
{...props}
|
|
@@ -19,7 +19,7 @@ function NativeSelect({ className, size = 'default', ...props }: NativeSelectPro
|
|
|
19
19
|
<select
|
|
20
20
|
data-slot="native-select"
|
|
21
21
|
data-size={size}
|
|
22
|
-
className="h-9 w-full min-w-0 appearance-none rounded-4xl border border-input bg-input/30 py-1 pr-8 pl-3 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-
|
|
22
|
+
className="h-9 w-full min-w-0 appearance-none rounded-4xl border border-input bg-input/30 py-1 pr-8 pl-3 text-sm transition-colors outline-none select-none selection:bg-primary selection:text-primary-foreground placeholder:text-placeholder focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 data-[size=sm]:h-8"
|
|
23
23
|
{...props}
|
|
24
24
|
/>
|
|
25
25
|
<ChevronDownIcon
|
|
@@ -108,7 +108,7 @@ function NavigationMenuPositioner({
|
|
|
108
108
|
)}
|
|
109
109
|
{...props}
|
|
110
110
|
>
|
|
111
|
-
<NavigationMenuPrimitive.Popup className="data-[ending-style]:easing-[ease]
|
|
111
|
+
<NavigationMenuPrimitive.Popup className="data-[ending-style]:easing-[ease] relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) rounded-2xl bg-popover text-popover-foreground shadow ring-1 ring-foreground/5 transition-[opacity,transform,width,height,scale,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0 xs:w-(--popup-width)">
|
|
112
112
|
<NavigationMenuPrimitive.Viewport className="relative size-full overflow-hidden" />
|
|
113
113
|
</NavigationMenuPrimitive.Popup>
|
|
114
114
|
</NavigationMenuPrimitive.Positioner>
|
|
@@ -40,7 +40,7 @@ function SelectTrigger({
|
|
|
40
40
|
data-slot="select-trigger"
|
|
41
41
|
data-size={size}
|
|
42
42
|
className={cn(
|
|
43
|
-
"flex w-fit items-center justify-between gap-1.5 rounded-4xl border border-input bg-input/30 px-3 py-2 text-sm whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 data-placeholder:text-
|
|
43
|
+
"flex w-fit items-center justify-between gap-1.5 rounded-4xl border border-input bg-input/30 px-3 py-2 text-sm whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 data-placeholder:text-placeholder data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
44
44
|
className
|
|
45
45
|
)}
|
|
46
46
|
{...props}
|
|
@@ -6,7 +6,7 @@ function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
|
|
|
6
6
|
<textarea
|
|
7
7
|
data-slot="textarea"
|
|
8
8
|
className={cn(
|
|
9
|
-
'flex field-sizing-content min-h-16 w-full resize-none rounded-xl border border-input bg-input/30 px-3 py-3 text-sm transition-colors outline-none placeholder:text-
|
|
9
|
+
'flex field-sizing-content min-h-16 w-full resize-none rounded-xl border border-input bg-input/30 px-3 py-3 text-sm transition-colors outline-none placeholder:text-placeholder focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20',
|
|
10
10
|
className
|
|
11
11
|
)}
|
|
12
12
|
{...props}
|
|
@@ -182,6 +182,14 @@ function safeWriteFile(filePath, content, force = false) {
|
|
|
182
182
|
fs.writeFileSync(filePath, content, "utf-8");
|
|
183
183
|
return true;
|
|
184
184
|
}
|
|
185
|
+
function safeCopyFile(src, dest, force = false) {
|
|
186
|
+
if (!force && fs.existsSync(dest)) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
ensureDir(path.dirname(dest));
|
|
190
|
+
fs.copyFileSync(src, dest);
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
185
193
|
function createGeneratedFile(filePath, content) {
|
|
186
194
|
return {
|
|
187
195
|
path: filePath.split(path.sep).join("/"),
|
|
@@ -499,6 +507,7 @@ var R2_ENV_KEYS = [
|
|
|
499
507
|
"BETTERSTART_R2_BUCKET_NAME",
|
|
500
508
|
"BETTERSTART_R2_PUBLIC_URL"
|
|
501
509
|
];
|
|
510
|
+
var PUBLIC_ASSET_FILE_NAMES = ["placeholder.png"];
|
|
502
511
|
var PROXY_FILE_NAME = "proxy.ts";
|
|
503
512
|
var PROXY_CONVENTION_FILE_NAMES = [
|
|
504
513
|
"proxy.ts",
|
|
@@ -730,6 +739,7 @@ export {
|
|
|
730
739
|
hashContent,
|
|
731
740
|
ensureDir,
|
|
732
741
|
safeWriteFile,
|
|
742
|
+
safeCopyFile,
|
|
733
743
|
createGeneratedFile,
|
|
734
744
|
toStrictJson,
|
|
735
745
|
parseDotenvFile,
|
|
@@ -763,6 +773,7 @@ export {
|
|
|
763
773
|
TIPTAP_CONTENT_EDITOR_DIRECTORIES,
|
|
764
774
|
RAILWAY_BUCKET_ENV_KEYS,
|
|
765
775
|
R2_ENV_KEYS,
|
|
776
|
+
PUBLIC_ASSET_FILE_NAMES,
|
|
766
777
|
PROXY_FILE_NAME,
|
|
767
778
|
PROXY_CONVENTION_FILE_NAMES,
|
|
768
779
|
REMOVABLE_NAMESPACE_PATTERN,
|
|
@@ -781,4 +792,4 @@ export {
|
|
|
781
792
|
replaceAdminDashToken,
|
|
782
793
|
applyAdminNamespaceToContent
|
|
783
794
|
};
|
|
784
|
-
//# sourceMappingURL=chunk-
|
|
795
|
+
//# sourceMappingURL=chunk-BNHFSHPE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../adapters/next/template-reader/read-template.ts","../utils/paths.ts","../constants/cli.ts","../constants/paths.ts","../utils/files.ts","../utils/text.ts","../adapters/next/config/namespace/protect-admin-role-literals.ts","../constants/scaffolding.ts","../adapters/next/config/namespace/protect-existing-namespace-literals.ts","../constants/patterns.ts","../adapters/next/config/namespace/is-external-module-specifier.ts","../adapters/next/config/namespace/protect-external-module-specifiers.ts","../adapters/next/config/namespace/replace-admin-camel-token.ts","../adapters/next/config/namespace/replace-admin-dash-token.ts","../adapters/next/config/namespace/replace-admin-pascal-token.ts","../adapters/next/config/namespace/replace-admin-screaming-token.ts","../adapters/next/config/namespace/validate-admin-namespace.ts","../adapters/next/config/namespace/resolve-admin-namespace.ts","../adapters/next/config/namespace/apply-admin-namespace-to-content.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport { resolveCliAssetPath } from '@cli-utils/paths.js'\n\nexport function readTemplate(relativePath: string): string {\n return fs.readFileSync(\n path.join(resolveCliAssetPath('adapters', 'next', 'templates', 'init'), relativePath),\n 'utf-8'\n )\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { CommandOptions } from '@cli-types/core-engine/commands.js'\nimport type { CliPackageJson } from '@cli-types/core-engine/utils.js'\nimport type { Command } from 'commander'\nimport { CLI_PACKAGE_NAME } from '@cli-constants/cli.js'\nimport { BETTERSTART_DIR } from '@cli-constants/paths.js'\nimport { findUpwards } from '@cli-utils/files.js'\n\nexport function betterstartDir(cwd: string, ...segments: string[]): string {\n return path.join(cwd, BETTERSTART_DIR, ...segments)\n}\n\nexport function toPosixPath(value: string): string {\n return value.replace(/\\\\/g, '/')\n}\n\nexport function trimDotSlash(value: string): string {\n return value.replace(/^[.][/\\\\]/, '')\n}\n\nexport function normalizePosixDir(value: string): string {\n return trimDotSlash(toPosixPath(value)).replace(/\\/+$/, '')\n}\n\nexport function toProjectAbsolutePath(cwd: string, filePath: string): string {\n return path.isAbsolute(filePath) ? filePath : path.join(cwd, ...filePath.split('/'))\n}\n\nexport function readLocalProjectFile(cwd: string, filePath: string): string | null {\n const fullPath = toProjectAbsolutePath(cwd, filePath)\n return fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf-8') : null\n}\n\nexport function isInsideDir(child: string, parent: string): boolean {\n const relative = path.relative(parent, child)\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))\n}\n\nexport function removePath(cwd: string, filePath: string): boolean {\n const fullPath = toProjectAbsolutePath(cwd, filePath)\n const existed = fs.existsSync(fullPath)\n fs.rmSync(fullPath, { recursive: true, force: true })\n return existed\n}\n\nexport function cleanupEmptyDirs(\n cwd: string,\n deletedPaths: string[],\n stopRoots: Iterable<string>\n): void {\n const projectRoot = path.resolve(cwd)\n const stops = new Set<string>([projectRoot, ...stopRoots])\n\n for (const deletedPath of deletedPaths) {\n let currentDir = path.dirname(toProjectAbsolutePath(cwd, deletedPath))\n\n while (isInsideDir(currentDir, projectRoot) && !stops.has(currentDir)) {\n if (!fs.existsSync(currentDir)) {\n currentDir = path.dirname(currentDir)\n continue\n }\n\n if (fs.readdirSync(currentDir).length > 0) {\n break\n }\n\n fs.rmdirSync(currentDir)\n currentDir = path.dirname(currentDir)\n }\n }\n}\n\nfunction findCliPackage(): { dir: string; pkg: CliPackageJson } | null {\n const start = path.dirname(fileURLToPath(import.meta.url))\n\n return (\n findUpwards(start, (dir) => {\n const pkgPath = path.join(dir, 'package.json')\n if (!fs.existsSync(pkgPath)) return undefined\n\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as CliPackageJson\n return pkg.name === CLI_PACKAGE_NAME ? { dir, pkg } : undefined\n } catch {\n return undefined\n }\n }) ?? null\n )\n}\n\nexport function findCliRoot(): string {\n const found = findCliPackage()\n if (found) {\n return found.dir\n }\n\n // Fallback: assume 2 levels up from dist/\n return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..')\n}\n\nexport function getCurrentCliVersion(): string {\n return findCliPackage()?.pkg.version ?? '0.0.0'\n}\n\nexport function resolveCliAssetPath(...segments: string[]): string {\n const root = findCliRoot()\n const builtPath = path.join(root, 'dist', 'assets', ...segments)\n if (fs.existsSync(builtPath)) {\n return builtPath\n }\n\n return path.join(root, ...segments)\n}\n\nexport function resolveCommandCwd(command: Command): string {\n const options = command.opts<CommandOptions>()\n return typeof options.cwd === 'string' ? path.resolve(options.cwd) : process.cwd()\n}\n","export const CLI_PACKAGE_NAME = 'betterstart-cli'\nexport const REDACTED = '[redacted]'\n","import type { PackageManager } from '@cli-types/core-engine/utils.js'\n\nexport const ADMIN_CONTAINER_ROUTE_GROUP = '(container)'\nexport const BETTERSTART_DIR = '.betterstart'\nexport const CONFIG_FILE_NAME = 'betterstart.config.ts'\nexport const DEVELOPMENT_ENV_FILES = [\n '.env.development.local',\n '.env.local',\n '.env.development',\n '.env'\n] as const\nexport const LOCKFILE_MAP: Record<string, PackageManager> = {\n 'pnpm-lock.yaml': 'pnpm',\n 'package-lock.json': 'npm',\n 'yarn.lock': 'yarn',\n 'bun.lockb': 'bun',\n 'bun.lock': 'bun'\n}\n","import crypto from 'node:crypto'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { parseEnv } from 'node:util'\nimport type { EnvSection, ProjectEnvValue } from '@cli-types/core-engine/env.js'\nimport type { GeneratedFile } from '@cli-types/core-engine/schema.js'\nimport type { FileSnapshot } from '@cli-types/core-engine/utils.js'\nimport { DEVELOPMENT_ENV_FILES } from '@cli-constants/paths.js'\nimport { normalizeLineEndings } from '@cli-utils/text.js'\nimport fse from 'fs-extra'\n\n/**\n * Walks from `startDir` to the filesystem root inclusive, returning the first\n * defined `visit` result. Inclusive matters: a walk that stops one level early\n * silently ignores a `package.json` or lockfile sitting at the root.\n */\nexport function findUpwards<T>(\n startDir: string,\n visit: (dir: string) => T | undefined\n): T | undefined {\n let dir = path.resolve(startDir)\n\n for (;;) {\n const found = visit(dir)\n if (found !== undefined) return found\n\n const parent = path.dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\nexport function hashContent(content: string): string {\n return `sha256-${crypto.createHash('sha256').update(normalizeLineEndings(content)).digest('hex')}`\n}\n\nexport function ensureDir(dirPath: string): void {\n fse.ensureDirSync(dirPath)\n}\n\nexport function safeWriteFile(filePath: string, content: string, force = false): boolean {\n if (!force && fs.existsSync(filePath)) {\n return false\n }\n ensureDir(path.dirname(filePath))\n fs.writeFileSync(filePath, content, 'utf-8')\n return true\n}\n\nexport function safeCopyFile(src: string, dest: string, force = false): boolean {\n if (!force && fs.existsSync(dest)) {\n return false\n }\n ensureDir(path.dirname(dest))\n fs.copyFileSync(src, dest)\n return true\n}\n\nexport function copyTemplateDir(\n srcDir: string,\n destDir: string,\n force = false\n): { written: string[]; skipped: string[] } {\n const written: string[] = []\n const skipped: string[] = []\n\n function walk(currentSrc: string, currentDest: string): void {\n const entries = fs.readdirSync(currentSrc, { withFileTypes: true })\n for (const entry of entries) {\n const srcPath = path.join(currentSrc, entry.name)\n const destPath = path.join(currentDest, entry.name)\n\n if (entry.isDirectory()) {\n walk(srcPath, destPath)\n } else {\n if (safeCopyFile(srcPath, destPath, force)) {\n written.push(destPath)\n } else {\n skipped.push(destPath)\n }\n }\n }\n }\n\n walk(srcDir, destDir)\n return { written, skipped }\n}\n\nexport function appendToFile(filePath: string, content: string, marker: string): boolean {\n if (fs.existsSync(filePath)) {\n const existing = fs.readFileSync(filePath, 'utf-8')\n if (existing.includes(marker)) {\n return false\n }\n fs.writeFileSync(filePath, `${existing.trimEnd()}\\n${content}\\n`, 'utf-8')\n } else {\n ensureDir(path.dirname(filePath))\n fs.writeFileSync(filePath, `${content}\\n`, 'utf-8')\n }\n return true\n}\n\n/**\n * Snapshot manifests, skip lists, and conflict paths are all keyed by these\n * strings, so a Windows `\\` here would make a project's snapshots unreadable on\n * any other machine.\n */\nexport function createGeneratedFile(filePath: string, content: string): GeneratedFile {\n return {\n path: filePath.split(path.sep).join('/'),\n content\n }\n}\n\n// Next.js and TypeScript both emit `tsconfig.json` with comments and trailing commas.\nexport function stripJsonComments(input: string): string {\n let result = ''\n let i = 0\n while (i < input.length) {\n if (input[i] === '\"') {\n let j = i + 1\n while (j < input.length) {\n if (input[j] === '\\\\') {\n j += 2\n continue\n }\n if (input[j] === '\"') {\n j++\n break\n }\n j++\n }\n result += input.slice(i, j)\n i = j\n } else if (input[i] === '/' && input[i + 1] === '/') {\n const nl = input.indexOf('\\n', i)\n i = nl === -1 ? input.length : nl\n } else if (input[i] === '/' && input[i + 1] === '*') {\n const end = input.indexOf('*/', i + 2)\n i = end === -1 ? input.length : end + 2\n } else {\n result += input[i]\n i++\n }\n }\n return result\n}\n\nexport function toStrictJson(input: string): string {\n return stripJsonComments(input).replace(/,\\s*([\\]}])/g, '$1')\n}\n\n/**\n * `node:util`'s parseEnv is the single owner of .env syntax here. A hand-rolled\n * splitter previously read `KEY=\"value\" # comment` back as `value\" # comment`\n * and understood neither `export` prefixes nor multi-line values.\n */\nexport function parseDotenvFile(filePath: string): Map<string, string> {\n if (!fs.existsSync(filePath)) return new Map()\n\n try {\n const parsed = Object.entries(parseEnv(fs.readFileSync(filePath, 'utf-8')))\n return new Map(\n parsed.filter((entry): entry is [string, string] => typeof entry[1] === 'string')\n )\n } catch {\n return new Map()\n }\n}\n\nexport function readEnvVar(cwd: string, key: string): string | undefined {\n return parseDotenvFile(path.join(cwd, '.env.local')).get(key)\n}\n\n/** Reads DEVELOPMENT_ENV_FILES in Next.js's development-file precedence order. */\nexport function resolveProjectEnvVar(cwd: string, key: string): ProjectEnvValue | undefined {\n for (const envFile of DEVELOPMENT_ENV_FILES) {\n const value = parseDotenvFile(path.join(cwd, envFile)).get(key)?.trim()\n if (value) return { source: envFile, value }\n }\n\n return undefined\n}\n\nexport function readProjectEnvVar(cwd: string, key: string): string | undefined {\n return resolveProjectEnvVar(cwd, key)?.value\n}\n\nexport function appendEnvVars(\n cwd: string,\n sections: EnvSection[],\n overwrite?: Set<string>\n): { added: string[]; skipped: string[]; updated: string[] } {\n const envPath = path.join(cwd, '.env.local')\n let existing = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf-8') : ''\n\n const existingKeys = new Set(\n existing\n .split('\\n')\n .filter((line) => line.trim() && !line.trim().startsWith('#'))\n .map((line) => line.split('=')[0]?.trim())\n .filter(Boolean)\n )\n\n const added: string[] = []\n const skipped: string[] = []\n const updated: string[] = []\n const lines: string[] = []\n\n if (overwrite) {\n for (const section of sections) {\n for (const v of section.vars) {\n if (overwrite.has(v.key) && existingKeys.has(v.key)) {\n const pattern = new RegExp(`^${v.key}=.*$`, 'm')\n const replacement = v.comment\n ? `${v.key}=\"${v.value}\" # ${v.comment}`\n : `${v.key}=\"${v.value}\"`\n existing = existing.replace(pattern, replacement)\n updated.push(v.key)\n }\n }\n }\n }\n\n if (existing.trim()) {\n lines.push('')\n }\n\n for (const section of sections) {\n const sectionVars = section.vars.filter((v) => {\n if (existingKeys.has(v.key)) {\n if (!updated.includes(v.key)) skipped.push(v.key)\n return false\n }\n added.push(v.key)\n return true\n })\n\n if (sectionVars.length === 0) continue\n\n lines.push(`# ${section.header}`)\n for (const v of sectionVars) {\n const line = v.comment ? `${v.key}=\"${v.value}\" # ${v.comment}` : `${v.key}=\"${v.value}\"`\n lines.push(line)\n }\n lines.push('')\n }\n\n if (added.length > 0 || updated.length > 0) {\n const header = existing.trim()\n ? ''\n : '# ============================================\\n# BetterStart Admin\\n# ============================================\\n'\n const content = existing.trim()\n ? `${existing.trimEnd()}\\n${lines.join('\\n')}`\n : header + lines.join('\\n')\n fs.writeFileSync(envPath, content)\n }\n\n return { added, skipped, updated }\n}\n\nexport function removeEnvVars(cwd: string, keys: string[]): string[] {\n const envPath = path.join(cwd, '.env.local')\n if (!fs.existsSync(envPath) || keys.length === 0) {\n return []\n }\n\n const keySet = new Set(keys)\n const removed: string[] = []\n const filteredLines = fs\n .readFileSync(envPath, 'utf-8')\n .split('\\n')\n .filter((line) => {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) {\n return true\n }\n\n const [key] = trimmed.split('=')\n const normalizedKey = key?.trim()\n if (normalizedKey && keySet.has(normalizedKey)) {\n removed.push(normalizedKey)\n return false\n }\n\n return true\n })\n\n fs.writeFileSync(envPath, `${filteredLines.join('\\n').trimEnd()}\\n`, 'utf-8')\n return removed\n}\n\nexport function captureFile(filePath: string): FileSnapshot {\n if (!fs.existsSync(filePath)) {\n return { existed: false }\n }\n\n return { existed: true, content: fs.readFileSync(filePath, 'utf-8') }\n}\n\nexport function restoreFile(filePath: string, snapshot: FileSnapshot): void {\n if (snapshot.existed) {\n fs.writeFileSync(filePath, snapshot.content ?? '', 'utf-8')\n return\n }\n\n if (fs.existsSync(filePath)) {\n fs.rmSync(filePath, { force: true })\n }\n}\n\nexport function readNonEmptyEnvVar(cwd: string, key: string): string | undefined {\n const value = readProjectEnvVar(cwd, key)?.trim()\n return value ? value : undefined\n}\n","import { stripVTControlCharacters } from 'node:util'\n/**\n * `stripVTControlCharacters` also removes OSC and other C1 sequences, which a\n * CSI-only regex leaves behind on CLIs that emit terminal hyperlinks.\n * `stripCarriageReturns` additionally flattens the `\\r` a progress-spinner child\n * process uses to repaint one line, so line-based filters see a single line.\n */\nexport function stripAnsi(text: string, options: { stripCarriageReturns?: boolean } = {}): string {\n const stripped = stripVTControlCharacters(text)\n return options.stripCarriageReturns ? stripped.replaceAll('\\r', '') : stripped\n}\n\nexport function toPascalCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .split(/[-_\\s]+/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join('')\n}\n\nexport function toCamelCase(str: string): string {\n const p = toPascalCase(str)\n return p.charAt(0).toLowerCase() + p.slice(1)\n}\n\nexport function singularize(str: string): string {\n if (str.endsWith('ies')) return `${str.slice(0, -3)}y`\n if (str.endsWith('ves')) return `${str.slice(0, -3)}f`\n if (\n str.endsWith('sses') ||\n str.endsWith('xes') ||\n str.endsWith('ches') ||\n str.endsWith('shes') ||\n str.endsWith('zes')\n )\n return str.slice(0, -2)\n if (str.endsWith('s') && !str.endsWith('ss')) return str.slice(0, -1)\n return str\n}\n\nexport function pluralize(str: string): string {\n if (str.endsWith('s') && !str.endsWith('ss')) return str\n if (str.endsWith('y') && !['ay', 'ey', 'iy', 'oy', 'uy'].some((v) => str.endsWith(v)))\n return `${str.slice(0, -1)}ies`\n if (str.endsWith('s') || str.endsWith('x') || str.endsWith('ch') || str.endsWith('sh'))\n return `${str}es`\n return `${str}s`\n}\n\nexport function toKebabCase(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1-$2')\n .replace(/[\\s_]+/g, '-')\n .toLowerCase()\n}\n\nexport function toScreamingSnake(str: string): string {\n return str\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s-]+/g, '_')\n .toUpperCase()\n}\n\nexport function quotePropertyName(name: string): string {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name) ? name : `'${name}'`\n}\n\nexport function humanizeName(name: string): string {\n return name\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n}\n\nexport function singularizeLabel(label: string): string {\n const words = label.split(' ')\n const lastWord = words[words.length - 1]\n words[words.length - 1] = singularize(lastWord.toLowerCase())\n words[words.length - 1] =\n words[words.length - 1].charAt(0).toUpperCase() + words[words.length - 1].slice(1)\n return words.join(' ')\n}\n\n/**\n * Escapes `\\r` and `\\n` as well as the quote character: a raw newline inside an\n * emitted single- or double-quoted literal is a syntax error, so a schema label\n * containing one would otherwise emit a file that does not parse.\n */\nexport function quoteLiteral(value: string, quote = \"'\"): string {\n const escaped = value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(new RegExp(escapeRegExp(quote), 'g'), `\\\\${quote}`)\n .replace(/\\r/g, '\\\\r')\n .replace(/\\n/g, '\\\\n')\n\n return `${quote}${escaped}${quote}`\n}\n\nexport function escapeTemplateText(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/`/g, '\\\\`').replace(/\\$\\{/g, '\\\\${')\n}\n\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n')\n}\n\nexport function escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nexport function hasConflictMarkers(content: string): boolean {\n return /^(<{7}|={7}|>{7})( |$)/m.test(content)\n}\n\nexport function splitLines(content: string): string[] {\n return normalizeLineEndings(content).split('\\n')\n}\n\nexport function normalizeWhitespace(value: string): string {\n return value.trim().replace(/\\s+/g, ' ')\n}\n\nexport function escapeJsx(str: string): string {\n return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')\n}\n\nexport function escapeAttribute(str: string): string {\n return escapeJsx(str).replace(/\"/g, '"')\n}\n\nexport function findNextNonEmptyLine(lines: string[], startIndex: number): string | null {\n for (let i = startIndex; i < lines.length; i++) {\n const trimmed = lines[i]!.trim()\n if (trimmed !== '') return trimmed\n }\n return null\n}\n\nexport function levenshtein(a: string, b: string): number {\n const matrix = Array.from({ length: a.length + 1 }, () => new Array<number>(b.length + 1).fill(0))\n\n for (let i = 0; i <= a.length; i++) matrix[i]![0] = i\n for (let j = 0; j <= b.length; j++) matrix[0]![j] = j\n\n for (let i = 1; i <= a.length; i++) {\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n matrix[i]![j] = Math.min(\n matrix[i - 1]![j]! + 1,\n matrix[i]![j - 1]! + 1,\n matrix[i - 1]![j - 1]! + cost\n )\n }\n }\n\n return matrix[a.length]![b.length]!\n}\n\nexport function toTitleCase(value: string): string {\n return normalizeWhitespace(value)\n .split(' ')\n .map((word) => (word ? `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}` : word))\n .join(' ')\n}\n\nexport function slugify(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/['\"]/g, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/-+/g, '-')\n}\n\nexport function usesIdentifier(source: string, identifier: string): boolean {\n return new RegExp(`\\\\b${escapeRegExp(identifier)}\\\\b`).test(source)\n}\n\nexport function detectIndent(raw: string): string | number {\n const indentMatch = raw.match(/^[ \\t]+(?=\")/m)\n return indentMatch?.[0] ?? 2\n}\n\nexport function jsString(value: string): string {\n return JSON.stringify(value)\n}\n\nexport function safeIdentifier(value: string, fallback: string): string {\n const pascal = toPascalCase(value).replace(/[^A-Za-z0-9_$]/g, '')\n const base = pascal ? `${pascal.charAt(0).toLowerCase()}${pascal.slice(1)}` : fallback\n return /^[A-Za-z_$]/.test(base) ? base : fallback\n}\n","export function protectAdminRoleLiterals(content: string): {\n content: string\n restore: (value: string) => string\n} {\n const protectedValues = [\n 'UserRole.ADMIN',\n \"'admin'\",\n '\"admin\"',\n '`admin`',\n '>Admin</SelectItem>',\n 'Manage admin users and roles'\n ]\n\n const replacements: Array<[string, string]> = []\n let protectedContent = content\n\n for (const [index, value] of protectedValues.entries()) {\n if (!protectedContent.includes(value)) {\n continue\n }\n\n const token = `__BETTERSTART_NAMESPACE_PROTECTED_${index}__`\n protectedContent = protectedContent.replaceAll(value, token)\n replacements.push([token, value])\n }\n\n return {\n content: protectedContent,\n restore(value: string): string {\n let restored = value\n for (const [token, original] of replacements) {\n restored = restored.replaceAll(token, original)\n }\n return restored\n }\n }\n}\n","export const DEFAULT_ADMIN_NAMESPACE = 'admin'\nexport const DEPRECATED_ADMIN_PATH_ALIAS_SUFFIXES = ['/data/*', '/auth', '/auth/middleware']\nexport const BETTERSTART_ASSET_HOST = 'assets.betterstart.dev'\nexport const LEGACY_DEFAULT_AUTH_URL = 'http://localhost:3000'\nexport const DATABASE_URL_PLACEHOLDER = 'postgresql://...'\nexport const DEFAULT_DEV_PORT = 4242\nexport const MAIN_CSS_CANDIDATES = [\n 'src/app/globals.css',\n 'app/globals.css',\n 'src/app/global.css',\n 'app/global.css',\n 'src/app/app.css',\n 'app/app.css',\n 'src/globals.css',\n 'globals.css'\n]\nexport const CONFIG_IMPORT_SHIM = 'const defineConfig = <T>(config: T): T => config'\nexport const TIPTAP_CONTENT_EDITOR_DIRECTORIES = ['tiptap-extension', 'tiptap-node', 'tiptap-ui']\nexport const RAILWAY_BUCKET_ENV_KEYS = [\n 'BETTERSTART_RAILWAY_BUCKET_ENDPOINT',\n 'BETTERSTART_RAILWAY_BUCKET_ACCESS_KEY_ID',\n 'BETTERSTART_RAILWAY_BUCKET_SECRET_ACCESS_KEY',\n 'BETTERSTART_RAILWAY_BUCKET_NAME',\n 'BETTERSTART_RAILWAY_BUCKET_REGION',\n 'BETTERSTART_RAILWAY_BUCKET_URL_STYLE'\n] as const\nexport const R2_ENV_KEYS = [\n 'BETTERSTART_R2_ACCOUNT_ID',\n 'BETTERSTART_R2_ACCESS_KEY_ID',\n 'BETTERSTART_R2_SECRET_ACCESS_KEY',\n 'BETTERSTART_R2_BUCKET_NAME',\n 'BETTERSTART_R2_PUBLIC_URL'\n] as const\nexport const PUBLIC_ASSET_FILE_NAMES = ['placeholder.png'] as const\nexport const PROXY_FILE_NAME = 'proxy.ts'\nexport const PROXY_CONVENTION_FILE_NAMES = [\n 'proxy.ts',\n 'proxy.tsx',\n 'proxy.js',\n 'proxy.jsx',\n 'middleware.ts',\n 'middleware.tsx',\n 'middleware.js',\n 'middleware.jsx'\n] as const\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\nimport { DEFAULT_ADMIN_NAMESPACE } from '@cli-constants/scaffolding.js'\n\nexport function protectExistingNamespaceLiterals(\n value: string,\n namespace: AdminNamespace\n): {\n value: string\n restore: (output: string) => string\n} {\n if (namespace.segment === DEFAULT_ADMIN_NAMESPACE) {\n return {\n value,\n restore(output: string): string {\n return output\n }\n }\n }\n\n const literals = Array.from(\n new Set([\n namespace.alias,\n namespace.apiPath,\n namespace.routePath,\n namespace.routeGroup,\n namespace.cssRootClass,\n namespace.globalsFile,\n `${namespace.segment}/`,\n `${namespace.segment}-`,\n namespace.screaming,\n namespace.pascal,\n namespace.camel\n ])\n ).sort((a, b) => b.length - a.length)\n\n const replacements: Array<[string, string]> = []\n let protectedValue = value\n\n for (const [index, literal] of literals.entries()) {\n if (!protectedValue.includes(literal)) {\n continue\n }\n\n const token = `__BSTART_NS_${index}__`\n protectedValue = protectedValue.replaceAll(literal, token)\n replacements.push([token, literal])\n }\n\n return {\n value: protectedValue,\n restore(output: string): string {\n let restored = output\n for (const [token, literal] of replacements) {\n restored = restored.replaceAll(token, literal)\n }\n return restored\n }\n }\n}\n","export const REMOVABLE_NAMESPACE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\nexport const SCHEMA_NAME_PATTERN = /^[a-z][a-zA-Z0-9-]*$/\nexport const NAMESPACE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/\nexport const MODULE_SPECIFIER_PATTERN =\n /(\\bfrom\\s*|\\bimport\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s*\\(\\s*)(['\"])([^'\"\\n]+)\\2/g\nexport const EXTERNAL_PACKAGE_PATTERN =\n /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*(?:\\/[^'\"]*)?$/\nexport const DEV_PORT_FLAG_PATTERN = /(?:^|\\s)(?:--port(?:=|\\s+)|-p(?:=|\\s+)?)(\\d+)(?=\\s|$)/\nexport const DEV_PORT_ENV_PATTERN = /(?:^|\\s)PORT=(\\d+)(?=\\s|$)/\nexport const LOCAL_PROTOCOL_PATTERN = /^(workspace|link|file|portal):/\nexport const CONFIG_IMPORT_PATTERN =\n /^import\\s+\\{[^}]*\\bdefineConfig\\b[^}]*\\}\\s+from\\s+['\"]betterstart-cli['\"];?[^\\S\\n]*$/m\nexport const CONFIG_OBJECT_PATTERNS = [\n /\\b(?:const|let|var)\\s+\\w+\\s*:\\s*NextConfig\\s*=\\s*\\{/g,\n /\\b(?:const|let|var)\\s+nextConfig\\s*=\\s*\\{/g,\n /\\b(?:const|let|var)\\s+\\w+\\s*:\\s*NextConfig\\s*=\\s*(?:[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*\\(\\s*)+\\{/g,\n /\\b(?:const|let|var)\\s+nextConfig\\s*=\\s*(?:[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*\\(\\s*)+\\{/g,\n /export\\s+default\\s+\\{/g,\n /export\\s+default\\s+(?:[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*\\(\\s*)+\\{/g,\n /module\\.exports\\s*=\\s*\\{/g,\n /module\\.exports\\s*=\\s*(?:[A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*\\(\\s*)+\\{/g\n]\n/**\n * On accounts without the Neon integration installed, the piped (non-TTY) `integration add` opens\n * the accept-terms page in a browser and polls until the user accepts, printing the URL in a\n * \"Visit this URL if the browser does not open\" line — the only signal that it is waiting.\n */\nexport const ACCEPT_TERMS_URL_PATTERN =\n /https:\\/\\/vercel\\.com\\/\\S+\\/integrations\\/accept-terms\\/\\S+/i\n/** Printed by the Vercel CLI once its accept-terms polling succeeds. */\nexport const TERMS_ACCEPTED_PATTERN = /terms accepted/i\n","import { EXTERNAL_PACKAGE_PATTERN } from '@cli-constants/patterns.js'\nimport { DEFAULT_ADMIN_NAMESPACE } from '@cli-constants/scaffolding.js'\n\nexport function isExternalModuleSpecifier(specifier: string): boolean {\n if (specifier.startsWith('.') || specifier.startsWith('/')) {\n return false\n }\n\n if (new RegExp(`^@${DEFAULT_ADMIN_NAMESPACE}(?:/|$)`).test(specifier)) {\n return false\n }\n\n return EXTERNAL_PACKAGE_PATTERN.test(specifier)\n}\n","import { MODULE_SPECIFIER_PATTERN } from '@cli-constants/patterns.js'\nimport { isExternalModuleSpecifier } from './is-external-module-specifier.js'\n\nexport function protectExternalModuleSpecifiers(content: string): {\n content: string\n restore: (value: string) => string\n} {\n const replacements: Array<[string, string]> = []\n\n const protectedContent = content.replace(\n MODULE_SPECIFIER_PATTERN,\n (match, prefix: string, quote: string, specifier: string) => {\n if (!isExternalModuleSpecifier(specifier)) {\n return match\n }\n\n const token = `__BETTERSTART_EXTERNAL_MODULE_${replacements.length}__`\n replacements.push([token, specifier])\n return `${prefix}${quote}${token}${quote}`\n }\n )\n\n return {\n content: protectedContent,\n restore(value: string): string {\n let restored = value\n for (const [token, specifier] of replacements) {\n restored = restored.replaceAll(token, specifier)\n }\n return restored\n }\n }\n}\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\n\nexport function replaceAdminCamelToken(value: string, namespace: AdminNamespace): string {\n return value.replace(/\\badmin(?=[A-Z])/g, namespace.camel)\n}\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\n\nexport function replaceAdminDashToken(value: string, namespace: AdminNamespace): string {\n return value.replaceAll('admin-', `${namespace.segment}-`)\n}\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\n\nexport function replaceAdminPascalToken(value: string, namespace: AdminNamespace): string {\n return value.replaceAll('Admin', namespace.pascal)\n}\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\n\nexport function replaceAdminScreamingToken(value: string, namespace: AdminNamespace): string {\n return value.replaceAll('ADMIN_', `${namespace.screaming}_`)\n}\n","import { NAMESPACE_PATTERN } from '@cli-constants/patterns.js'\n\nexport function validateAdminNamespace(value: string): string {\n const segment = value.trim()\n\n if (!NAMESPACE_PATTERN.test(segment)) {\n throw new Error(\n 'Namespace must be one lowercase kebab-case segment starting with a letter, for example \"admin\" or \"admin-panel\".'\n )\n }\n\n return segment\n}\n","import type { AdminNamespace } from '@cli-types/next-adapter/config.js'\nimport { DEFAULT_ADMIN_NAMESPACE } from '@cli-constants/scaffolding.js'\nimport { toCamelCase, toPascalCase, toScreamingSnake } from '@cli-utils/text.js'\nimport { validateAdminNamespace } from './validate-admin-namespace.js'\n\nexport function resolveAdminNamespace(value = DEFAULT_ADMIN_NAMESPACE): AdminNamespace {\n const segment = validateAdminNamespace(value)\n const pascal = toPascalCase(segment)\n\n return {\n segment,\n alias: `@${segment}`,\n camel: toCamelCase(segment),\n pascal,\n screaming: toScreamingSnake(segment),\n routePath: `/${segment}`,\n apiPath: `/api/${segment}`,\n cssRootClass: `${segment}-root`,\n globalsFile: `${segment}-globals.css`,\n routeGroup: `(${segment})`\n }\n}\n","import { protectAdminRoleLiterals } from './protect-admin-role-literals.js'\nimport { protectExistingNamespaceLiterals } from './protect-existing-namespace-literals.js'\nimport { protectExternalModuleSpecifiers } from './protect-external-module-specifiers.js'\nimport { replaceAdminCamelToken } from './replace-admin-camel-token.js'\nimport { replaceAdminDashToken } from './replace-admin-dash-token.js'\nimport { replaceAdminPascalToken } from './replace-admin-pascal-token.js'\nimport { replaceAdminScreamingToken } from './replace-admin-screaming-token.js'\nimport { resolveAdminNamespace } from './resolve-admin-namespace.js'\n\nexport function applyAdminNamespaceToContent(content: string, namespaceValue: string): string {\n const namespace = resolveAdminNamespace(namespaceValue)\n const { content: externalSafeContent, restore: restoreExternalModules } =\n protectExternalModuleSpecifiers(content)\n const { content: protectedContent, restore } = protectAdminRoleLiterals(externalSafeContent)\n\n const canonicalContent = protectedContent\n .replaceAll('MediaListParams', `${namespace.pascal}MediaQuery`)\n .replaceAll('MediaListResult', `${namespace.pascal}MediaPage`)\n .replaceAll(\n `${namespace.pascal}MediaQuery, ${namespace.pascal}MediaPage`,\n `${namespace.pascal}MediaPage, ${namespace.pascal}MediaQuery`\n )\n .replaceAll('UserData', 'User')\n .replaceAll('UsersResponse', 'UsersPage')\n .replaceAll('SettingData', 'Setting')\n .replaceAll('UpsertSettingInput', 'SettingUpsertInput')\n .replaceAll('UpsertSettingResult', 'SettingUpsertResult')\n .replace(\n /import\\s+\\{\\s*admin\\s*\\}\\s+from\\s+(['\"])@admin\\/utils\\/app\\/admin\\1/g,\n (_match, quote: string) =>\n `import { ${namespace.camel} } from ${quote}${namespace.alias}/utils/app/${namespace.camel}${quote}`\n )\n .replace(/\\badmin(?=\\.name\\b)/g, namespace.camel)\n .replaceAll('@admin/auth/middleware', `${namespace.alias}/auth/session`)\n .replaceAll('@admin/auth/auth', `${namespace.alias}/auth/server`)\n .replaceAll('@admin/auth/client', `${namespace.alias}/auth/client`)\n .replace(/@admin\\/auth(?=['\"`\\s)]|$)/g, `${namespace.alias}/auth/server`)\n .replace(/(\\bimport\\b[^\\n]*\\bfrom\\s+)'\\.\\/auth'/g, \"$1'./server'\")\n .replace(/@admin(?=\\/|$)/g, namespace.alias)\n .replace(/\\/api\\/admin(?=\\/|['\"`]|$)/g, namespace.apiPath)\n .replace(/(^|\\/)admin(?=\\/|['\"`]|$)/g, `$1${namespace.segment}`)\n .replaceAll('(admin)', namespace.routeGroup)\n\n const protectedNamespace = protectExistingNamespaceLiterals(canonicalContent, namespace)\n const namespacedContent = replaceAdminCamelToken(\n replaceAdminPascalToken(\n replaceAdminScreamingToken(\n replaceAdminDashToken(protectedNamespace.value, namespace),\n namespace\n ),\n namespace\n ),\n namespace\n )\n\n return restoreExternalModules(restore(protectedNamespace.restore(namespacedContent)))\n}\n"],"mappings":";AAAA,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;;;ACFvB,IAAM,mBAAmB;AACzB,IAAM,WAAW;;;ACCjB,IAAM,8BAA8B;AACpC,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,eAA+C;AAAA,EAC1D,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,YAAY;AACd;;;ACjBA,OAAO,YAAY;AACnB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,gBAAgB;;;ACHzB,SAAS,gCAAgC;AAOlC,SAAS,UAAU,MAAc,UAA8C,CAAC,GAAW;AAChG,QAAM,WAAW,yBAAyB,IAAI;AAC9C,SAAO,QAAQ,uBAAuB,SAAS,WAAW,MAAM,EAAE,IAAI;AACxE;AAEO,SAAS,aAAa,KAAqB;AAChD,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,MAAM,SAAS,EACf,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,EAC/D,KAAK,EAAE;AACZ;AAEO,SAAS,YAAY,KAAqB;AAC/C,QAAM,IAAI,aAAa,GAAG;AAC1B,SAAO,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC;AAC9C;AAEO,SAAS,YAAY,KAAqB;AAC/C,MAAI,IAAI,SAAS,KAAK,EAAG,QAAO,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC;AACnD,MAAI,IAAI,SAAS,KAAK,EAAG,QAAO,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC;AACnD,MACE,IAAI,SAAS,MAAM,KACnB,IAAI,SAAS,KAAK,KAClB,IAAI,SAAS,MAAM,KACnB,IAAI,SAAS,MAAM,KACnB,IAAI,SAAS,KAAK;AAElB,WAAO,IAAI,MAAM,GAAG,EAAE;AACxB,MAAI,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,SAAS,IAAI,EAAG,QAAO,IAAI,MAAM,GAAG,EAAE;AACpE,SAAO;AACT;AAEO,SAAS,UAAU,KAAqB;AAC7C,MAAI,IAAI,SAAS,GAAG,KAAK,CAAC,IAAI,SAAS,IAAI,EAAG,QAAO;AACrD,MAAI,IAAI,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,MAAM,MAAM,MAAM,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;AAClF,WAAO,GAAG,IAAI,MAAM,GAAG,EAAE,CAAC;AAC5B,MAAI,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,GAAG,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,SAAS,IAAI;AACnF,WAAO,GAAG,GAAG;AACf,SAAO,GAAG,GAAG;AACf;AAEO,SAAS,YAAY,KAAqB;AAC/C,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,WAAW,GAAG,EACtB,YAAY;AACjB;AAEO,SAAS,iBAAiB,KAAqB;AACpD,SAAO,IACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,WAAW,GAAG,EACtB,YAAY;AACjB;AAEO,SAAS,kBAAkB,MAAsB;AACtD,SAAO,6BAA6B,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI;AAClE;AAEO,SAAS,aAAa,MAAsB;AACjD,SAAO,KACJ,QAAQ,mBAAmB,OAAO,EAClC,QAAQ,UAAU,GAAG,EACrB,KAAK,EACL,MAAM,KAAK,EACX,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,GAAG;AACb;AAEO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,QAAM,MAAM,SAAS,CAAC,IAAI,YAAY,SAAS,YAAY,CAAC;AAC5D,QAAM,MAAM,SAAS,CAAC,IACpB,MAAM,MAAM,SAAS,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,SAAS,CAAC,EAAE,MAAM,CAAC;AACnF,SAAO,MAAM,KAAK,GAAG;AACvB;AAOO,SAAS,aAAa,OAAe,QAAQ,KAAa;AAC/D,QAAM,UAAU,MACb,QAAQ,OAAO,MAAM,EACrB,QAAQ,IAAI,OAAO,aAAa,KAAK,GAAG,GAAG,GAAG,KAAK,KAAK,EAAE,EAC1D,QAAQ,OAAO,KAAK,EACpB,QAAQ,OAAO,KAAK;AAEvB,SAAO,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK;AACnC;AAEO,SAAS,mBAAmB,OAAuB;AACxD,SAAO,MAAM,QAAQ,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAK,EAAE,QAAQ,SAAS,MAAM;AAClF;AAEO,SAAS,qBAAqB,SAAyB;AAC5D,SAAO,QAAQ,QAAQ,SAAS,IAAI;AACtC;AAEO,SAAS,aAAa,OAAuB;AAClD,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAEO,SAAS,mBAAmB,SAA0B;AAC3D,SAAO,0BAA0B,KAAK,OAAO;AAC/C;AAEO,SAAS,WAAW,SAA2B;AACpD,SAAO,qBAAqB,OAAO,EAAE,MAAM,IAAI;AACjD;AAEO,SAAS,oBAAoB,OAAuB;AACzD,SAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG;AACzC;AAEO,SAAS,UAAU,KAAqB;AAC7C,SAAO,IAAI,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAC9E;AAEO,SAAS,gBAAgB,KAAqB;AACnD,SAAO,UAAU,GAAG,EAAE,QAAQ,MAAM,QAAQ;AAC9C;AAEO,SAAS,qBAAqB,OAAiB,YAAmC;AACvF,WAAS,IAAI,YAAY,IAAI,MAAM,QAAQ,KAAK;AAC9C,UAAM,UAAU,MAAM,CAAC,EAAG,KAAK;AAC/B,QAAI,YAAY,GAAI,QAAO;AAAA,EAC7B;AACA,SAAO;AACT;AAEO,SAAS,YAAY,GAAW,GAAmB;AACxD,QAAM,SAAS,MAAM,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,MAAc,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;AAEjG,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,IAAK,QAAO,CAAC,EAAG,CAAC,IAAI;AACpD,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,IAAK,QAAO,CAAC,EAAG,CAAC,IAAI;AAEpD,WAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,aAAS,IAAI,GAAG,KAAK,EAAE,QAAQ,KAAK;AAClC,YAAM,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AACzC,aAAO,CAAC,EAAG,CAAC,IAAI,KAAK;AAAA,QACnB,OAAO,IAAI,CAAC,EAAG,CAAC,IAAK;AAAA,QACrB,OAAO,CAAC,EAAG,IAAI,CAAC,IAAK;AAAA,QACrB,OAAO,IAAI,CAAC,EAAG,IAAI,CAAC,IAAK;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,SAAO,OAAO,EAAE,MAAM,EAAG,EAAE,MAAM;AACnC;AAEO,SAAS,YAAY,OAAuB;AACjD,SAAO,oBAAoB,KAAK,EAC7B,MAAM,GAAG,EACT,IAAI,CAAC,SAAU,OAAO,GAAG,KAAK,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,KAAK,IAAK,EAC7F,KAAK,GAAG;AACb;AAEO,SAAS,QAAQ,OAAuB;AAC7C,SAAO,MACJ,KAAK,EACL,YAAY,EACZ,QAAQ,SAAS,EAAE,EACnB,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE,EACtB,QAAQ,OAAO,GAAG;AACvB;AAEO,SAAS,eAAe,QAAgB,YAA6B;AAC1E,SAAO,IAAI,OAAO,MAAM,aAAa,UAAU,CAAC,KAAK,EAAE,KAAK,MAAM;AACpE;AAEO,SAAS,aAAa,KAA8B;AACzD,QAAM,cAAc,IAAI,MAAM,eAAe;AAC7C,SAAO,cAAc,CAAC,KAAK;AAC7B;AAEO,SAAS,SAAS,OAAuB;AAC9C,SAAO,KAAK,UAAU,KAAK;AAC7B;AAEO,SAAS,eAAe,OAAe,UAA0B;AACtE,QAAM,SAAS,aAAa,KAAK,EAAE,QAAQ,mBAAmB,EAAE;AAChE,QAAM,OAAO,SAAS,GAAG,OAAO,OAAO,CAAC,EAAE,YAAY,CAAC,GAAG,OAAO,MAAM,CAAC,CAAC,KAAK;AAC9E,SAAO,cAAc,KAAK,IAAI,IAAI,OAAO;AAC3C;;;AD3LA,OAAO,SAAS;AAOT,SAAS,YACd,UACA,OACe;AACf,MAAI,MAAM,KAAK,QAAQ,QAAQ;AAE/B,aAAS;AACP,UAAM,QAAQ,MAAM,GAAG;AACvB,QAAI,UAAU,OAAW,QAAO;AAEhC,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAEO,SAAS,YAAY,SAAyB;AACnD,SAAO,UAAU,OAAO,WAAW,QAAQ,EAAE,OAAO,qBAAqB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;AAClG;AAEO,SAAS,UAAU,SAAuB;AAC/C,MAAI,cAAc,OAAO;AAC3B;AAEO,SAAS,cAAc,UAAkB,SAAiB,QAAQ,OAAgB;AACvF,MAAI,CAAC,SAAS,GAAG,WAAW,QAAQ,GAAG;AACrC,WAAO;AAAA,EACT;AACA,YAAU,KAAK,QAAQ,QAAQ,CAAC;AAChC,KAAG,cAAc,UAAU,SAAS,OAAO;AAC3C,SAAO;AACT;AAEO,SAAS,aAAa,KAAa,MAAc,QAAQ,OAAgB;AAC9E,MAAI,CAAC,SAAS,GAAG,WAAW,IAAI,GAAG;AACjC,WAAO;AAAA,EACT;AACA,YAAU,KAAK,QAAQ,IAAI,CAAC;AAC5B,KAAG,aAAa,KAAK,IAAI;AACzB,SAAO;AACT;AAmDO,SAAS,oBAAoB,UAAkB,SAAgC;AACpF,SAAO;AAAA,IACL,MAAM,SAAS,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AAAA,IACvC;AAAA,EACF;AACF;AAGO,SAAS,kBAAkB,OAAuB;AACvD,MAAI,SAAS;AACb,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,QAAQ;AACvB,QAAI,MAAM,CAAC,MAAM,KAAK;AACpB,UAAI,IAAI,IAAI;AACZ,aAAO,IAAI,MAAM,QAAQ;AACvB,YAAI,MAAM,CAAC,MAAM,MAAM;AACrB,eAAK;AACL;AAAA,QACF;AACA,YAAI,MAAM,CAAC,MAAM,KAAK;AACpB;AACA;AAAA,QACF;AACA;AAAA,MACF;AACA,gBAAU,MAAM,MAAM,GAAG,CAAC;AAC1B,UAAI;AAAA,IACN,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,IAAI,CAAC,MAAM,KAAK;AACnD,YAAM,KAAK,MAAM,QAAQ,MAAM,CAAC;AAChC,UAAI,OAAO,KAAK,MAAM,SAAS;AAAA,IACjC,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,IAAI,CAAC,MAAM,KAAK;AACnD,YAAM,MAAM,MAAM,QAAQ,MAAM,IAAI,CAAC;AACrC,UAAI,QAAQ,KAAK,MAAM,SAAS,MAAM;AAAA,IACxC,OAAO;AACL,gBAAU,MAAM,CAAC;AACjB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,aAAa,OAAuB;AAClD,SAAO,kBAAkB,KAAK,EAAE,QAAQ,gBAAgB,IAAI;AAC9D;AAOO,SAAS,gBAAgB,UAAuC;AACrE,MAAI,CAAC,GAAG,WAAW,QAAQ,EAAG,QAAO,oBAAI,IAAI;AAE7C,MAAI;AACF,UAAM,SAAS,OAAO,QAAQ,SAAS,GAAG,aAAa,UAAU,OAAO,CAAC,CAAC;AAC1E,WAAO,IAAI;AAAA,MACT,OAAO,OAAO,CAAC,UAAqC,OAAO,MAAM,CAAC,MAAM,QAAQ;AAAA,IAClF;AAAA,EACF,QAAQ;AACN,WAAO,oBAAI,IAAI;AAAA,EACjB;AACF;AAEO,SAAS,WAAW,KAAa,KAAiC;AACvE,SAAO,gBAAgB,KAAK,KAAK,KAAK,YAAY,CAAC,EAAE,IAAI,GAAG;AAC9D;AAGO,SAAS,qBAAqB,KAAa,KAA0C;AAC1F,aAAW,WAAW,uBAAuB;AAC3C,UAAM,QAAQ,gBAAgB,KAAK,KAAK,KAAK,OAAO,CAAC,EAAE,IAAI,GAAG,GAAG,KAAK;AACtE,QAAI,MAAO,QAAO,EAAE,QAAQ,SAAS,MAAM;AAAA,EAC7C;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,KAAa,KAAiC;AAC9E,SAAO,qBAAqB,KAAK,GAAG,GAAG;AACzC;AAEO,SAAS,cACd,KACA,UACA,WAC2D;AAC3D,QAAM,UAAU,KAAK,KAAK,KAAK,YAAY;AAC3C,MAAI,WAAW,GAAG,WAAW,OAAO,IAAI,GAAG,aAAa,SAAS,OAAO,IAAI;AAE5E,QAAM,eAAe,IAAI;AAAA,IACvB,SACG,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,KAAK,KAAK,KAAK,CAAC,KAAK,KAAK,EAAE,WAAW,GAAG,CAAC,EAC5D,IAAI,CAAC,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,EACxC,OAAO,OAAO;AAAA,EACnB;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAC3B,QAAM,QAAkB,CAAC;AAEzB,MAAI,WAAW;AACb,eAAW,WAAW,UAAU;AAC9B,iBAAW,KAAK,QAAQ,MAAM;AAC5B,YAAI,UAAU,IAAI,EAAE,GAAG,KAAK,aAAa,IAAI,EAAE,GAAG,GAAG;AACnD,gBAAM,UAAU,IAAI,OAAO,IAAI,EAAE,GAAG,QAAQ,GAAG;AAC/C,gBAAM,cAAc,EAAE,UAClB,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,QAAQ,EAAE,OAAO,KACrC,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK;AACxB,qBAAW,SAAS,QAAQ,SAAS,WAAW;AAChD,kBAAQ,KAAK,EAAE,GAAG;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,KAAK,GAAG;AACnB,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,cAAc,QAAQ,KAAK,OAAO,CAAC,MAAM;AAC7C,UAAI,aAAa,IAAI,EAAE,GAAG,GAAG;AAC3B,YAAI,CAAC,QAAQ,SAAS,EAAE,GAAG,EAAG,SAAQ,KAAK,EAAE,GAAG;AAChD,eAAO;AAAA,MACT;AACA,YAAM,KAAK,EAAE,GAAG;AAChB,aAAO;AAAA,IACT,CAAC;AAED,QAAI,YAAY,WAAW,EAAG;AAE9B,UAAM,KAAK,KAAK,QAAQ,MAAM,EAAE;AAChC,eAAW,KAAK,aAAa;AAC3B,YAAM,OAAO,EAAE,UAAU,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,QAAQ,EAAE,OAAO,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK;AACvF,YAAM,KAAK,IAAI;AAAA,IACjB;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,MAAI,MAAM,SAAS,KAAK,QAAQ,SAAS,GAAG;AAC1C,UAAM,SAAS,SAAS,KAAK,IACzB,KACA;AACJ,UAAM,UAAU,SAAS,KAAK,IAC1B,GAAG,SAAS,QAAQ,CAAC;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC,KAC1C,SAAS,MAAM,KAAK,IAAI;AAC5B,OAAG,cAAc,SAAS,OAAO;AAAA,EACnC;AAEA,SAAO,EAAE,OAAO,SAAS,QAAQ;AACnC;AAEO,SAAS,cAAc,KAAa,MAA0B;AACnE,QAAM,UAAU,KAAK,KAAK,KAAK,YAAY;AAC3C,MAAI,CAAC,GAAG,WAAW,OAAO,KAAK,KAAK,WAAW,GAAG;AAChD,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAAS,IAAI,IAAI,IAAI;AAC3B,QAAM,UAAoB,CAAC;AAC3B,QAAM,gBAAgB,GACnB,aAAa,SAAS,OAAO,EAC7B,MAAM,IAAI,EACV,OAAO,CAAC,SAAS;AAChB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,SAAS,GAAG,GAAG;AACjE,aAAO;AAAA,IACT;AAEA,UAAM,CAAC,GAAG,IAAI,QAAQ,MAAM,GAAG;AAC/B,UAAM,gBAAgB,KAAK,KAAK;AAChC,QAAI,iBAAiB,OAAO,IAAI,aAAa,GAAG;AAC9C,cAAQ,KAAK,aAAa;AAC1B,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,CAAC;AAEH,KAAG,cAAc,SAAS,GAAG,cAAc,KAAK,IAAI,EAAE,QAAQ,CAAC;AAAA,GAAM,OAAO;AAC5E,SAAO;AACT;AAEO,SAAS,YAAY,UAAgC;AAC1D,MAAI,CAAC,GAAG,WAAW,QAAQ,GAAG;AAC5B,WAAO,EAAE,SAAS,MAAM;AAAA,EAC1B;AAEA,SAAO,EAAE,SAAS,MAAM,SAAS,GAAG,aAAa,UAAU,OAAO,EAAE;AACtE;AAEO,SAAS,YAAY,UAAkB,UAA8B;AAC1E,MAAI,SAAS,SAAS;AACpB,OAAG,cAAc,UAAU,SAAS,WAAW,IAAI,OAAO;AAC1D;AAAA,EACF;AAEA,MAAI,GAAG,WAAW,QAAQ,GAAG;AAC3B,OAAG,OAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,EACrC;AACF;AAEO,SAAS,mBAAmB,KAAa,KAAiC;AAC/E,QAAM,QAAQ,kBAAkB,KAAK,GAAG,GAAG,KAAK;AAChD,SAAO,QAAQ,QAAQ;AACzB;;;AHhTO,SAAS,eAAe,QAAgB,UAA4B;AACzE,SAAOC,MAAK,KAAK,KAAK,iBAAiB,GAAG,QAAQ;AACpD;AAEO,SAAS,YAAY,OAAuB;AACjD,SAAO,MAAM,QAAQ,OAAO,GAAG;AACjC;AAEO,SAAS,aAAa,OAAuB;AAClD,SAAO,MAAM,QAAQ,aAAa,EAAE;AACtC;AAEO,SAAS,kBAAkB,OAAuB;AACvD,SAAO,aAAa,YAAY,KAAK,CAAC,EAAE,QAAQ,QAAQ,EAAE;AAC5D;AAEO,SAAS,sBAAsB,KAAa,UAA0B;AAC3E,SAAOA,MAAK,WAAW,QAAQ,IAAI,WAAWA,MAAK,KAAK,KAAK,GAAG,SAAS,MAAM,GAAG,CAAC;AACrF;AAEO,SAAS,qBAAqB,KAAa,UAAiC;AACjF,QAAM,WAAW,sBAAsB,KAAK,QAAQ;AACpD,SAAOC,IAAG,WAAW,QAAQ,IAAIA,IAAG,aAAa,UAAU,OAAO,IAAI;AACxE;AAEO,SAAS,YAAY,OAAe,QAAyB;AAClE,QAAM,WAAWD,MAAK,SAAS,QAAQ,KAAK;AAC5C,SAAO,aAAa,MAAO,CAAC,SAAS,WAAW,IAAI,KAAK,CAACA,MAAK,WAAW,QAAQ;AACpF;AAEO,SAAS,WAAW,KAAa,UAA2B;AACjE,QAAM,WAAW,sBAAsB,KAAK,QAAQ;AACpD,QAAM,UAAUC,IAAG,WAAW,QAAQ;AACtC,EAAAA,IAAG,OAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACpD,SAAO;AACT;AAEO,SAAS,iBACd,KACA,cACA,WACM;AACN,QAAM,cAAcD,MAAK,QAAQ,GAAG;AACpC,QAAM,QAAQ,oBAAI,IAAY,CAAC,aAAa,GAAG,SAAS,CAAC;AAEzD,aAAW,eAAe,cAAc;AACtC,QAAI,aAAaA,MAAK,QAAQ,sBAAsB,KAAK,WAAW,CAAC;AAErE,WAAO,YAAY,YAAY,WAAW,KAAK,CAAC,MAAM,IAAI,UAAU,GAAG;AACrE,UAAI,CAACC,IAAG,WAAW,UAAU,GAAG;AAC9B,qBAAaD,MAAK,QAAQ,UAAU;AACpC;AAAA,MACF;AAEA,UAAIC,IAAG,YAAY,UAAU,EAAE,SAAS,GAAG;AACzC;AAAA,MACF;AAEA,MAAAA,IAAG,UAAU,UAAU;AACvB,mBAAaD,MAAK,QAAQ,UAAU;AAAA,IACtC;AAAA,EACF;AACF;AAEA,SAAS,iBAA8D;AACrE,QAAM,QAAQA,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAEzD,SACE,YAAY,OAAO,CAAC,QAAQ;AAC1B,UAAM,UAAUA,MAAK,KAAK,KAAK,cAAc;AAC7C,QAAI,CAACC,IAAG,WAAW,OAAO,EAAG,QAAO;AAEpC,QAAI;AACF,YAAM,MAAM,KAAK,MAAMA,IAAG,aAAa,SAAS,OAAO,CAAC;AACxD,aAAO,IAAI,SAAS,mBAAmB,EAAE,KAAK,IAAI,IAAI;AAAA,IACxD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC,KAAK;AAEV;AAEO,SAAS,cAAsB;AACpC,QAAM,QAAQ,eAAe;AAC7B,MAAI,OAAO;AACT,WAAO,MAAM;AAAA,EACf;AAGA,SAAOD,MAAK,QAAQA,MAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,IAAI;AAC9E;AAEO,SAAS,uBAA+B;AAC7C,SAAO,eAAe,GAAG,IAAI,WAAW;AAC1C;AAEO,SAAS,uBAAuB,UAA4B;AACjE,QAAM,OAAO,YAAY;AACzB,QAAM,YAAYA,MAAK,KAAK,MAAM,QAAQ,UAAU,GAAG,QAAQ;AAC/D,MAAIC,IAAG,WAAW,SAAS,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,SAAOD,MAAK,KAAK,MAAM,GAAG,QAAQ;AACpC;AAEO,SAAS,kBAAkB,SAA0B;AAC1D,QAAM,UAAU,QAAQ,KAAqB;AAC7C,SAAO,OAAO,QAAQ,QAAQ,WAAWA,MAAK,QAAQ,QAAQ,GAAG,IAAI,QAAQ,IAAI;AACnF;;;ADnHO,SAAS,aAAa,cAA8B;AACzD,SAAOE,IAAG;AAAA,IACRC,MAAK,KAAK,oBAAoB,YAAY,QAAQ,aAAa,MAAM,GAAG,YAAY;AAAA,IACpF;AAAA,EACF;AACF;;;AMTO,SAAS,yBAAyB,SAGvC;AACA,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,eAAwC,CAAC;AAC/C,MAAI,mBAAmB;AAEvB,aAAW,CAAC,OAAO,KAAK,KAAK,gBAAgB,QAAQ,GAAG;AACtD,QAAI,CAAC,iBAAiB,SAAS,KAAK,GAAG;AACrC;AAAA,IACF;AAEA,UAAM,QAAQ,qCAAqC,KAAK;AACxD,uBAAmB,iBAAiB,WAAW,OAAO,KAAK;AAC3D,iBAAa,KAAK,CAAC,OAAO,KAAK,CAAC;AAAA,EAClC;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ,OAAuB;AAC7B,UAAI,WAAW;AACf,iBAAW,CAAC,OAAO,QAAQ,KAAK,cAAc;AAC5C,mBAAW,SAAS,WAAW,OAAO,QAAQ;AAAA,MAChD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACpCO,IAAM,0BAA0B;AAChC,IAAM,uCAAuC,CAAC,WAAW,SAAS,kBAAkB;AACpF,IAAM,yBAAyB;AAC/B,IAAM,0BAA0B;AAChC,IAAM,2BAA2B;AACjC,IAAM,mBAAmB;AACzB,IAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,qBAAqB;AAC3B,IAAM,oCAAoC,CAAC,oBAAoB,eAAe,WAAW;AACzF,IAAM,0BAA0B;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,0BAA0B,CAAC,iBAAiB;AAClD,IAAM,kBAAkB;AACxB,IAAM,8BAA8B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACzCO,SAAS,iCACd,OACA,WAIA;AACA,MAAI,UAAU,YAAY,yBAAyB;AACjD,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,QAAwB;AAC9B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,MAAM;AAAA,IACrB,oBAAI,IAAI;AAAA,MACN,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,GAAG,UAAU,OAAO;AAAA,MACpB,GAAG,UAAU,OAAO;AAAA,MACpB,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAEpC,QAAM,eAAwC,CAAC;AAC/C,MAAI,iBAAiB;AAErB,aAAW,CAAC,OAAO,OAAO,KAAK,SAAS,QAAQ,GAAG;AACjD,QAAI,CAAC,eAAe,SAAS,OAAO,GAAG;AACrC;AAAA,IACF;AAEA,UAAM,QAAQ,eAAe,KAAK;AAClC,qBAAiB,eAAe,WAAW,SAAS,KAAK;AACzD,iBAAa,KAAK,CAAC,OAAO,OAAO,CAAC;AAAA,EACpC;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,QAAQ,QAAwB;AAC9B,UAAI,WAAW;AACf,iBAAW,CAAC,OAAO,OAAO,KAAK,cAAc;AAC3C,mBAAW,SAAS,WAAW,OAAO,OAAO;AAAA,MAC/C;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC1DO,IAAM,8BAA8B;AACpC,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,2BACX;AACK,IAAM,2BACX;AACK,IAAM,wBAAwB;AAC9B,IAAM,uBAAuB;AAC7B,IAAM,yBAAyB;AAC/B,IAAM,wBACX;AACK,IAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,2BACX;AAEK,IAAM,yBAAyB;;;AC3B/B,SAAS,0BAA0B,WAA4B;AACpE,MAAI,UAAU,WAAW,GAAG,KAAK,UAAU,WAAW,GAAG,GAAG;AAC1D,WAAO;AAAA,EACT;AAEA,MAAI,IAAI,OAAO,KAAK,uBAAuB,SAAS,EAAE,KAAK,SAAS,GAAG;AACrE,WAAO;AAAA,EACT;AAEA,SAAO,yBAAyB,KAAK,SAAS;AAChD;;;ACVO,SAAS,gCAAgC,SAG9C;AACA,QAAM,eAAwC,CAAC;AAE/C,QAAM,mBAAmB,QAAQ;AAAA,IAC/B;AAAA,IACA,CAAC,OAAO,QAAgB,OAAe,cAAsB;AAC3D,UAAI,CAAC,0BAA0B,SAAS,GAAG;AACzC,eAAO;AAAA,MACT;AAEA,YAAM,QAAQ,iCAAiC,aAAa,MAAM;AAClE,mBAAa,KAAK,CAAC,OAAO,SAAS,CAAC;AACpC,aAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ,OAAuB;AAC7B,UAAI,WAAW;AACf,iBAAW,CAAC,OAAO,SAAS,KAAK,cAAc;AAC7C,mBAAW,SAAS,WAAW,OAAO,SAAS;AAAA,MACjD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC9BO,SAAS,uBAAuB,OAAe,WAAmC;AACvF,SAAO,MAAM,QAAQ,qBAAqB,UAAU,KAAK;AAC3D;;;ACFO,SAAS,sBAAsB,OAAe,WAAmC;AACtF,SAAO,MAAM,WAAW,UAAU,GAAG,UAAU,OAAO,GAAG;AAC3D;;;ACFO,SAAS,wBAAwB,OAAe,WAAmC;AACxF,SAAO,MAAM,WAAW,SAAS,UAAU,MAAM;AACnD;;;ACFO,SAAS,2BAA2B,OAAe,WAAmC;AAC3F,SAAO,MAAM,WAAW,UAAU,GAAG,UAAU,SAAS,GAAG;AAC7D;;;ACFO,SAAS,uBAAuB,OAAuB;AAC5D,QAAM,UAAU,MAAM,KAAK;AAE3B,MAAI,CAAC,kBAAkB,KAAK,OAAO,GAAG;AACpC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACPO,SAAS,sBAAsB,QAAQ,yBAAyC;AACrF,QAAM,UAAU,uBAAuB,KAAK;AAC5C,QAAM,SAAS,aAAa,OAAO;AAEnC,SAAO;AAAA,IACL;AAAA,IACA,OAAO,IAAI,OAAO;AAAA,IAClB,OAAO,YAAY,OAAO;AAAA,IAC1B;AAAA,IACA,WAAW,iBAAiB,OAAO;AAAA,IACnC,WAAW,IAAI,OAAO;AAAA,IACtB,SAAS,QAAQ,OAAO;AAAA,IACxB,cAAc,GAAG,OAAO;AAAA,IACxB,aAAa,GAAG,OAAO;AAAA,IACvB,YAAY,IAAI,OAAO;AAAA,EACzB;AACF;;;ACZO,SAAS,6BAA6B,SAAiB,gBAAgC;AAC5F,QAAM,YAAY,sBAAsB,cAAc;AACtD,QAAM,EAAE,SAAS,qBAAqB,SAAS,uBAAuB,IACpE,gCAAgC,OAAO;AACzC,QAAM,EAAE,SAAS,kBAAkB,QAAQ,IAAI,yBAAyB,mBAAmB;AAE3F,QAAM,mBAAmB,iBACtB,WAAW,mBAAmB,GAAG,UAAU,MAAM,YAAY,EAC7D,WAAW,mBAAmB,GAAG,UAAU,MAAM,WAAW,EAC5D;AAAA,IACC,GAAG,UAAU,MAAM,eAAe,UAAU,MAAM;AAAA,IAClD,GAAG,UAAU,MAAM,cAAc,UAAU,MAAM;AAAA,EACnD,EACC,WAAW,YAAY,MAAM,EAC7B,WAAW,iBAAiB,WAAW,EACvC,WAAW,eAAe,SAAS,EACnC,WAAW,sBAAsB,oBAAoB,EACrD,WAAW,uBAAuB,qBAAqB,EACvD;AAAA,IACC;AAAA,IACA,CAAC,QAAQ,UACP,YAAY,UAAU,KAAK,WAAW,KAAK,GAAG,UAAU,KAAK,cAAc,UAAU,KAAK,GAAG,KAAK;AAAA,EACtG,EACC,QAAQ,wBAAwB,UAAU,KAAK,EAC/C,WAAW,0BAA0B,GAAG,UAAU,KAAK,eAAe,EACtE,WAAW,oBAAoB,GAAG,UAAU,KAAK,cAAc,EAC/D,WAAW,sBAAsB,GAAG,UAAU,KAAK,cAAc,EACjE,QAAQ,+BAA+B,GAAG,UAAU,KAAK,cAAc,EACvE,QAAQ,0CAA0C,cAAc,EAChE,QAAQ,mBAAmB,UAAU,KAAK,EAC1C,QAAQ,+BAA+B,UAAU,OAAO,EACxD,QAAQ,8BAA8B,KAAK,UAAU,OAAO,EAAE,EAC9D,WAAW,WAAW,UAAU,UAAU;AAE7C,QAAM,qBAAqB,iCAAiC,kBAAkB,SAAS;AACvF,QAAM,oBAAoB;AAAA,IACxB;AAAA,MACE;AAAA,QACE,sBAAsB,mBAAmB,OAAO,SAAS;AAAA,QACzD;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,EACF;AAEA,SAAO,uBAAuB,QAAQ,mBAAmB,QAAQ,iBAAiB,CAAC,CAAC;AACtF;","names":["fs","path","fs","path","path","fs","fs","path"]}
|