@stacksjs/defaults 0.70.161 → 0.70.163
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/app/Actions/Auth/LoginAction.ts +4 -1
- package/app/Actions/Auth/RegisterAction.ts +5 -1
- package/package.json +1 -1
- package/resources/components/Audio.stx +92 -0
- package/resources/components/Docs/Demo/StepperCode.md +1 -1
- package/resources/components/Image.stx +59 -0
- package/resources/components/Video.stx +108 -0
- package/resources/components/index.ts +10 -2
- package/resources/plugins/preloader.ts +16 -10
- package/resources/views/index.stx +2 -2
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { Auth, createTwoFactorChallenge, getTwoFactorState } from '@stacksjs/auth'
|
|
2
3
|
import { User } from '@stacksjs/orm'
|
|
4
|
+
import { response } from '@stacksjs/router'
|
|
5
|
+
import { schema } from '@stacksjs/validation'
|
|
3
6
|
|
|
4
7
|
export default new Action({
|
|
5
8
|
name: 'LoginAction',
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { Auth, register } from '@stacksjs/auth'
|
|
3
|
+
import { dispatch } from '@stacksjs/events'
|
|
4
|
+
import { response } from '@stacksjs/router'
|
|
5
|
+
import { schema } from '@stacksjs/validation'
|
|
2
6
|
|
|
3
7
|
export default new Action({
|
|
4
8
|
name: 'RegisterAction',
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.163",
|
|
6
6
|
"description": "Default Stacks scaffold resources (views, layouts, components, preloader) — shipped so apps consuming the framework from node_modules get the same fallback resources a vendored checkout provides. Source of truth: storage/framework/defaults.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"license": "MIT",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface AudioSource { src: string, type?: string }
|
|
3
|
+
interface AudioDrm {
|
|
4
|
+
widevine?: { url: string, headers?: Record<string, string> }
|
|
5
|
+
playready?: { url: string, headers?: Record<string, string> }
|
|
6
|
+
fairplay?: { url: string, certificateUrl: string, headers?: Record<string, string> }
|
|
7
|
+
}
|
|
8
|
+
interface AudioTrack { src: string, kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata', srclang?: string, label?: string, default?: boolean }
|
|
9
|
+
interface AudioProps {
|
|
10
|
+
src: string
|
|
11
|
+
sources?: AudioSource[]
|
|
12
|
+
drm?: AudioDrm
|
|
13
|
+
tracks?: AudioTrack[]
|
|
14
|
+
title?: string
|
|
15
|
+
artist?: string
|
|
16
|
+
artwork?: string
|
|
17
|
+
waveform?: string
|
|
18
|
+
controls?: boolean
|
|
19
|
+
autoplay?: boolean
|
|
20
|
+
loop?: boolean
|
|
21
|
+
muted?: boolean
|
|
22
|
+
preload?: 'none' | 'metadata' | 'auto'
|
|
23
|
+
crossorigin?: 'anonymous' | 'use-credentials'
|
|
24
|
+
class?: string
|
|
25
|
+
}
|
|
26
|
+
const props = defineProps<AudioProps>()
|
|
27
|
+
const src = props.src || ''
|
|
28
|
+
const sources = props.sources || []
|
|
29
|
+
const tracks = props.tracks || []
|
|
30
|
+
const title = props.title || 'Audio player'
|
|
31
|
+
const artist = props.artist || ''
|
|
32
|
+
const artwork = props.artwork || ''
|
|
33
|
+
const waveform = props.waveform || ''
|
|
34
|
+
const controls = props.controls !== false
|
|
35
|
+
const preload = props.preload || 'metadata'
|
|
36
|
+
const crossorigin = props.crossorigin || ''
|
|
37
|
+
const className = props.class || ''
|
|
38
|
+
const playerSources = (sources.length ? sources : src ? [{ src }] : []).map(source => props.drm && (source.type === 'application/dash+xml' || source.src.split(/[?#]/, 1)[0].toLowerCase().endsWith('.mpd')) ? { ...source, type: 'application/dash+xml', drm: props.drm } : source)
|
|
39
|
+
const playerTracks = tracks.map(track => ({ ...track, language: track.srclang }))
|
|
40
|
+
const playerConfig = JSON.stringify({ sources: playerSources, tracks: playerTracks, ...(props.drm ? { drm: props.drm } : {}) }).replaceAll('<', '\\u003c').replaceAll('>', '\\u003e').replaceAll('&', '\\u0026')
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<script client>
|
|
44
|
+
import { registerElements } from 'ts-video-player/elements'
|
|
45
|
+
registerElements()
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<figure class="m-0 overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-stone-200 dark:bg-stone-950 dark:ring-stone-800 {{ className }}">
|
|
49
|
+
<div class="flex gap-4 items-center p-4 sm:p-5">
|
|
50
|
+
@if(artwork)
|
|
51
|
+
<img src="{{ artwork }}" alt="" width="72" height="72" loading="lazy" decoding="async" class="object-cover shrink-0 h-18 w-18 ring-1 ring-black/5 rounded-xl dark:ring-white/10">
|
|
52
|
+
@else
|
|
53
|
+
<div class="flex items-center justify-center shrink-0 h-18 w-18 text-stone-500 dark:text-stone-400 bg-stone-100 dark:bg-stone-900 rounded-xl" aria-hidden="true"><span class="h-7 w-7 i-hugeicons-music-note-01"></span></div>
|
|
54
|
+
@endif
|
|
55
|
+
<div class="flex-1 min-w-0">
|
|
56
|
+
<figcaption class="font-semibold text-sm text-stone-950 truncate dark:text-white">{{ title }}</figcaption>
|
|
57
|
+
@if(artist)<p class="mt-0.5 text-sm text-stone-500 truncate dark:text-stone-400">{{ artist }}</p>@endif
|
|
58
|
+
@if(waveform)<img src="{{ waveform }}" alt="" loading="lazy" decoding="async" class="object-cover mt-3 h-10 w-full opacity-70 dark:opacity-80">@endif
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="p-3 bg-stone-950 border-stone-100 border-t dark:border-stone-800">
|
|
62
|
+
<video-player src="{{ src }}" title="{{ title }}" data-media-config="{{ playerConfig }}" @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" keep-alive aria-label="{{ title }}" class="block overflow-hidden relative h-16 w-full text-white rounded-xl focus-within:ring-2 focus-within:ring-sky-500">
|
|
63
|
+
<media-error-display></media-error-display>
|
|
64
|
+
<audio data-native-fallback src="{{ src }}" @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" @endif aria-label="{{ title }}" class="block h-16 w-full accent-sky-500">
|
|
65
|
+
@foreach (sources as source)<source src="{{ source.src }}" @if(source.type) type="{{ source.type }}" @endif>@endforeach
|
|
66
|
+
@foreach (tracks as track)<track src="{{ track.src }}" kind="{{ track.kind }}" @if(track.srclang) srclang="{{ track.srclang }}" @endif @if(track.label) label="{{ track.label }}" @endif @if(track.default) default @endif>@endforeach
|
|
67
|
+
Your browser does not support audio playback.
|
|
68
|
+
</audio>
|
|
69
|
+
@if(controls)
|
|
70
|
+
<video-skin>
|
|
71
|
+
<media-seek-button slot="left" seconds="-10" aria-label="Back 10 seconds"></media-seek-button>
|
|
72
|
+
<media-play-button slot="left" aria-label="Play or pause"></media-play-button>
|
|
73
|
+
<media-seek-button slot="left" seconds="10" aria-label="Forward 10 seconds"></media-seek-button>
|
|
74
|
+
<media-time-group slot="center" class="font-mono tabular-nums text-xs"></media-time-group>
|
|
75
|
+
<media-progress-bar slot="center" @if(waveform) waveform="{{ waveform }}" @endif aria-label="Audio progress"></media-progress-bar>
|
|
76
|
+
<media-mute-button slot="right" aria-label="Mute or unmute"></media-mute-button>
|
|
77
|
+
<media-volume-slider slot="right" aria-label="Volume"></media-volume-slider>
|
|
78
|
+
<media-playback-rate-button slot="right" rates="0.5,0.75,1,1.25,1.5,2" aria-label="Playback speed"></media-playback-rate-button>
|
|
79
|
+
<media-settings-menu slot="right" aria-label="Audio settings"></media-settings-menu>
|
|
80
|
+
<media-airplay-button slot="right" aria-label="Play on AirPlay"></media-airplay-button>
|
|
81
|
+
<media-remote-playback-button slot="right" aria-label="Play on another device"></media-remote-playback-button>
|
|
82
|
+
</video-skin>
|
|
83
|
+
@endif
|
|
84
|
+
</video-player>
|
|
85
|
+
</div>
|
|
86
|
+
</figure>
|
|
87
|
+
|
|
88
|
+
<style>
|
|
89
|
+
video-player:not(:defined) video-skin { display: none; }
|
|
90
|
+
video-player:defined > [data-native-fallback] { display: none; }
|
|
91
|
+
@media (prefers-reduced-motion: reduce) { video-player, video-player * { transition-duration: 0.01ms !important; } }
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface ImageSource { type: string, srcset: string, media?: string }
|
|
3
|
+
interface ImageProps {
|
|
4
|
+
src: string
|
|
5
|
+
alt: string
|
|
6
|
+
width?: number
|
|
7
|
+
height?: number
|
|
8
|
+
aspectRatio?: string
|
|
9
|
+
srcset?: string
|
|
10
|
+
sizes?: string
|
|
11
|
+
sources?: ImageSource[]
|
|
12
|
+
loading?: 'lazy' | 'eager'
|
|
13
|
+
decoding?: 'async' | 'sync' | 'auto'
|
|
14
|
+
fetchpriority?: 'high' | 'low' | 'auto'
|
|
15
|
+
priority?: boolean
|
|
16
|
+
decorative?: boolean
|
|
17
|
+
fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
|
|
18
|
+
position?: string
|
|
19
|
+
placeholder?: string
|
|
20
|
+
class?: string
|
|
21
|
+
}
|
|
22
|
+
const props = defineProps<ImageProps>()
|
|
23
|
+
if (!props.decorative && !props.alt?.trim()) throw new TypeError('Image alt text is required unless decorative is true')
|
|
24
|
+
const src = props.src || ''
|
|
25
|
+
const alt = props.decorative ? '' : props.alt || ''
|
|
26
|
+
const width = props.width || ''
|
|
27
|
+
const height = props.height || ''
|
|
28
|
+
const ratio = props.aspectRatio || (width && height ? `${width} / ${height}` : '')
|
|
29
|
+
const srcset = props.srcset || ''
|
|
30
|
+
const sizes = props.sizes || (srcset ? '100vw' : '')
|
|
31
|
+
const sources = props.sources || []
|
|
32
|
+
const loading = props.priority ? 'eager' : props.loading || 'lazy'
|
|
33
|
+
const decoding = props.decoding || 'async'
|
|
34
|
+
const priority = props.priority ? 'high' : props.fetchpriority || 'auto'
|
|
35
|
+
const fit = props.fit || 'cover'
|
|
36
|
+
const position = props.position || 'center'
|
|
37
|
+
const placeholder = props.placeholder || ''
|
|
38
|
+
const className = props.class || ''
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<picture class="relative block overflow-hidden bg-stone-100 dark:bg-stone-900 {{ className }}" @if(ratio) style="aspect-ratio: {{ ratio }};" @endif>
|
|
42
|
+
@foreach (sources as source)
|
|
43
|
+
<source type="{{ source.type }}" srcset="{{ source.srcset }}" @if(source.media) media="{{ source.media }}" @endif @if(sizes) sizes="{{ sizes }}" @endif>
|
|
44
|
+
@endforeach
|
|
45
|
+
<img
|
|
46
|
+
src="{{ src }}"
|
|
47
|
+
alt="{{ alt }}"
|
|
48
|
+
@if(width) width="{{ width }}" @endif
|
|
49
|
+
@if(height) height="{{ height }}" @endif
|
|
50
|
+
@if(srcset) srcset="{{ srcset }}" @endif
|
|
51
|
+
@if(sizes) sizes="{{ sizes }}" @endif
|
|
52
|
+
loading="{{ loading }}"
|
|
53
|
+
decoding="{{ decoding }}"
|
|
54
|
+
fetchpriority="{{ priority }}"
|
|
55
|
+
@if(props.decorative) aria-hidden="true" @endif
|
|
56
|
+
class="h-full w-full"
|
|
57
|
+
style="object-fit: {{ fit }}; object-position: {{ position }}; @if(placeholder) background: {{ placeholder }} center / cover no-repeat; @endif"
|
|
58
|
+
>
|
|
59
|
+
</picture>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script server>
|
|
2
|
+
interface VideoSource { src: string, type?: string }
|
|
3
|
+
interface VideoDrm {
|
|
4
|
+
widevine?: { url: string, headers?: Record<string, string> }
|
|
5
|
+
playready?: { url: string, headers?: Record<string, string> }
|
|
6
|
+
fairplay?: { url: string, certificateUrl: string, headers?: Record<string, string> }
|
|
7
|
+
}
|
|
8
|
+
interface VideoTrack { src: string, kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata', srclang?: string, label?: string, default?: boolean }
|
|
9
|
+
interface VideoProps {
|
|
10
|
+
src: string
|
|
11
|
+
sources?: VideoSource[]
|
|
12
|
+
drm?: VideoDrm
|
|
13
|
+
tracks?: VideoTrack[]
|
|
14
|
+
poster?: string
|
|
15
|
+
title?: string
|
|
16
|
+
width?: number
|
|
17
|
+
height?: number
|
|
18
|
+
aspectRatio?: string
|
|
19
|
+
controls?: boolean
|
|
20
|
+
autoplay?: boolean
|
|
21
|
+
loop?: boolean
|
|
22
|
+
muted?: boolean
|
|
23
|
+
playsinline?: boolean
|
|
24
|
+
preload?: 'none' | 'metadata' | 'auto'
|
|
25
|
+
crossorigin?: 'anonymous' | 'use-credentials'
|
|
26
|
+
controlslist?: string
|
|
27
|
+
disablePictureInPicture?: boolean
|
|
28
|
+
class?: string
|
|
29
|
+
}
|
|
30
|
+
const props = defineProps<VideoProps>()
|
|
31
|
+
const src = props.src || ''
|
|
32
|
+
const sources = props.sources || []
|
|
33
|
+
const tracks = props.tracks || []
|
|
34
|
+
const title = props.title || 'Video player'
|
|
35
|
+
const poster = props.poster || ''
|
|
36
|
+
const width = props.width || ''
|
|
37
|
+
const height = props.height || ''
|
|
38
|
+
const ratio = props.aspectRatio || (width && height ? `${width} / ${height}` : '16 / 9')
|
|
39
|
+
const controls = props.controls !== false
|
|
40
|
+
const inline = props.playsinline !== false
|
|
41
|
+
const preload = props.preload || 'metadata'
|
|
42
|
+
const crossorigin = props.crossorigin || ''
|
|
43
|
+
const controlslist = props.controlslist || 'nodownload'
|
|
44
|
+
const className = props.class || ''
|
|
45
|
+
const playerSources = (sources.length ? sources : src ? [{ src }] : []).map(source => props.drm && (source.type === 'application/dash+xml' || source.src.split(/[?#]/, 1)[0].toLowerCase().endsWith('.mpd')) ? { ...source, type: 'application/dash+xml', drm: props.drm } : source)
|
|
46
|
+
const playerTracks = tracks.map(track => ({ ...track, language: track.srclang }))
|
|
47
|
+
const playerConfig = JSON.stringify({ sources: playerSources, tracks: playerTracks, ...(props.drm ? { drm: props.drm } : {}) }).replaceAll('<', '\\u003c').replaceAll('>', '\\u003e').replaceAll('&', '\\u0026')
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<script client>
|
|
51
|
+
import { registerElements } from 'ts-video-player/elements'
|
|
52
|
+
registerElements()
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<figure class="m-0 {{ className }}">
|
|
56
|
+
<video-player
|
|
57
|
+
src="{{ src }}"
|
|
58
|
+
data-media-config="{{ playerConfig }}"
|
|
59
|
+
@if(poster) poster="{{ poster }}" @endif
|
|
60
|
+
@if(controls) controls @endif
|
|
61
|
+
@if(props.autoplay) autoplay @endif
|
|
62
|
+
@if(props.loop) loop @endif
|
|
63
|
+
@if(props.muted) muted @endif
|
|
64
|
+
@if(inline) playsinline @endif
|
|
65
|
+
preload="{{ preload }}"
|
|
66
|
+
@if(crossorigin) crossorigin="{{ crossorigin }}" @endif
|
|
67
|
+
controlslist="{{ controlslist }}"
|
|
68
|
+
@if(props.disablePictureInPicture) disable-picture-in-picture @endif
|
|
69
|
+
keep-alive
|
|
70
|
+
aria-label="{{ title }}"
|
|
71
|
+
class="block overflow-hidden relative w-full bg-black ring-1 ring-black/10 rounded-2xl dark:ring-white/10 focus-within:ring-2 focus-within:ring-sky-500 shadow-sm group"
|
|
72
|
+
style="aspect-ratio: {{ ratio }};"
|
|
73
|
+
>
|
|
74
|
+
<media-error-display></media-error-display>
|
|
75
|
+
<video data-native-fallback src="{{ src }}" @if(poster) poster="{{ poster }}" @endif @if(width) width="{{ width }}" @endif @if(height) height="{{ height }}" @endif @if(controls) controls @endif @if(props.autoplay) autoplay @endif @if(props.loop) loop @endif @if(props.muted) muted @endif @if(inline) playsinline @endif preload="{{ preload }}" @if(crossorigin) crossorigin="{{ crossorigin }}" @endif controlslist="{{ controlslist }}" @if(props.disablePictureInPicture) disablepictureinpicture @endif aria-label="{{ title }}" class="object-contain h-full w-full">
|
|
76
|
+
@foreach (sources as source)
|
|
77
|
+
<source src="{{ source.src }}" @if(source.type) type="{{ source.type }}" @endif>
|
|
78
|
+
@endforeach
|
|
79
|
+
@foreach (tracks as track)
|
|
80
|
+
<track src="{{ track.src }}" kind="{{ track.kind }}" @if(track.srclang) srclang="{{ track.srclang }}" @endif @if(track.label) label="{{ track.label }}" @endif @if(track.default) default @endif>
|
|
81
|
+
@endforeach
|
|
82
|
+
Your browser does not support video playback.
|
|
83
|
+
</video>
|
|
84
|
+
<video-skin>
|
|
85
|
+
<media-seek-button slot="left" seconds="-10" aria-label="Back 10 seconds"></media-seek-button>
|
|
86
|
+
<media-play-button slot="left" aria-label="Play or pause"></media-play-button>
|
|
87
|
+
<media-seek-button slot="left" seconds="10" aria-label="Forward 10 seconds"></media-seek-button>
|
|
88
|
+
<media-live-button slot="left" aria-label="Go to live edge"></media-live-button>
|
|
89
|
+
<media-time-group slot="center" class="font-mono tabular-nums text-xs"></media-time-group>
|
|
90
|
+
<media-progress-bar slot="center" previews="metadata" aria-label="Video progress"></media-progress-bar>
|
|
91
|
+
<media-mute-button slot="right" aria-label="Mute or unmute"></media-mute-button>
|
|
92
|
+
<media-volume-slider slot="right" aria-label="Volume"></media-volume-slider>
|
|
93
|
+
<media-playback-rate-button slot="right" rates="0.5,0.75,1,1.25,1.5,2" aria-label="Playback speed"></media-playback-rate-button>
|
|
94
|
+
<media-settings-menu slot="right" aria-label="Video settings"></media-settings-menu>
|
|
95
|
+
<media-airplay-button slot="right" aria-label="Play on AirPlay"></media-airplay-button>
|
|
96
|
+
<media-remote-playback-button slot="right" aria-label="Play on another device"></media-remote-playback-button>
|
|
97
|
+
<media-pip-button slot="right" aria-label="Picture in Picture"></media-pip-button>
|
|
98
|
+
<media-fullscreen-button slot="right" aria-label="Fullscreen"></media-fullscreen-button>
|
|
99
|
+
</video-skin>
|
|
100
|
+
</video-player>
|
|
101
|
+
<figcaption class="sr-only">{{ title }}</figcaption>
|
|
102
|
+
</figure>
|
|
103
|
+
|
|
104
|
+
<style>
|
|
105
|
+
video-player:not(:defined) video-skin { display: none; }
|
|
106
|
+
video-player:defined > [data-native-fallback] { display: none; }
|
|
107
|
+
@media (prefers-reduced-motion: reduce) { video-player, video-player * { transition-duration: 0.01ms !important; } }
|
|
108
|
+
</style>
|
|
@@ -4,5 +4,13 @@
|
|
|
4
4
|
* Complete dashboard components for building modern admin interfaces.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
//
|
|
8
|
-
export
|
|
7
|
+
// Layout components
|
|
8
|
+
export { default as DashboardLayout } from './Dashboard/DashboardLayout.stx'
|
|
9
|
+
export { default as NavbarModern } from './Dashboard/NavbarModern.stx'
|
|
10
|
+
export { default as SidebarModern } from './Dashboard/SidebarModern.stx'
|
|
11
|
+
|
|
12
|
+
// Dashboard and UI components
|
|
13
|
+
export * from './Dashboard'
|
|
14
|
+
export { default as Audio } from './Audio.stx'
|
|
15
|
+
export { default as Image } from './Image.stx'
|
|
16
|
+
export { default as Video } from './Video.stx'
|
|
@@ -71,24 +71,30 @@ if (!skipPreloader) {
|
|
|
71
71
|
process.env.APP_ENV = 'production'
|
|
72
72
|
process.env.NODE_ENV = 'production'
|
|
73
73
|
}
|
|
74
|
+
}
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
// Decrypt and load .env files for real command invocations. This is gated on
|
|
77
|
+
// isRepl / isPostinstall ONLY, not on the fast-command `skipPreloader`: fast
|
|
78
|
+
// commands (migrate, build, seed, ...) DO need decrypted config, which the old
|
|
79
|
+
// `skipPreloader` gate wrongly denied them (an encrypted `.env.<env>` never
|
|
80
|
+
// decrypted for those commands even with the key present). See stacksjs/stacks#2048.
|
|
81
|
+
//
|
|
82
|
+
// Postinstall still skips: @stacksjs/env may not be linked yet mid-install, so
|
|
83
|
+
// importing it there can fail (see the isPostinstall note above). The REPL keeps
|
|
84
|
+
// its original skip. The heavy auto-import graph below stays gated separately via
|
|
85
|
+
// `skipAutoImports`.
|
|
86
|
+
if (!isRepl && !isPostinstall) {
|
|
87
|
+
// Resolve the vendored source first; the package fallback covers non-standard
|
|
88
|
+
// layouts where defaults is consumed outside the framework layout.
|
|
81
89
|
const envPackage = '@stacksjs/' + 'env'
|
|
82
90
|
const { autoLoadEnv } = await import('../../../core/env/src/plugin.ts')
|
|
83
91
|
.catch(() => import(envPackage))
|
|
84
92
|
|
|
85
|
-
// Auto-load .env files based on environment
|
|
86
|
-
// Set quiet: true to prevent duplicate logging across multiple processes
|
|
87
|
-
//
|
|
88
93
|
// Pass the resolved env so deploy commands deterministically select their
|
|
89
94
|
// matching `.env.<env>` file. autoLoadEnv discovers `.env.keys` by default,
|
|
90
95
|
// replaces ciphertext that Bun preloaded, and preserves genuine shell/CI
|
|
91
|
-
// overrides while applying environment-specific file precedence.
|
|
96
|
+
// overrides while applying environment-specific file precedence. quiet: true
|
|
97
|
+
// prevents duplicate logging across multiple processes.
|
|
92
98
|
autoLoadEnv({ quiet: true, env: process.env.APP_ENV })
|
|
93
99
|
}
|
|
94
100
|
|
|
@@ -1642,12 +1642,12 @@ export default {
|
|
|
1642
1642
|
<td style="padding: 8px; font-size: 11px; color: #666; text-align: right;">09/29/2025</td>
|
|
1643
1643
|
</tr>
|
|
1644
1644
|
<tr style="border-bottom: 1px solid #e0e0e0;">
|
|
1645
|
-
<td style="padding: 8px; font-size: 11px;">📖
|
|
1645
|
+
<td style="padding: 8px; font-size: 11px;">📖 BunPress</td>
|
|
1646
1646
|
<td style="padding: 8px; font-size: 11px; color: #666;">Static Site Generator</td>
|
|
1647
1647
|
<td style="padding: 8px; font-size: 11px; color: #666; text-align: right;">09/28/2025</td>
|
|
1648
1648
|
</tr>
|
|
1649
1649
|
<tr style="border-bottom: 1px solid #e0e0e0;">
|
|
1650
|
-
<td style="padding: 8px; font-size: 11px;">📚
|
|
1650
|
+
<td style="padding: 8px; font-size: 11px;">📚 STX Docs</td>
|
|
1651
1651
|
<td style="padding: 8px; font-size: 11px; color: #666;">Static Site Generator</td>
|
|
1652
1652
|
<td style="padding: 8px; font-size: 11px; color: #666; text-align: right;">09/27/2025</td>
|
|
1653
1653
|
</tr>
|