@stacksjs/stx 0.1.16 → 0.2.3
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/a11y.d.ts +109 -5
- package/dist/analytics.d.ts +40 -0
- package/dist/animation.d.ts +91 -1
- package/dist/app.d.ts +51 -0
- package/dist/ast.d.ts +286 -0
- package/dist/async-components.d.ts +101 -0
- package/dist/auth.d.ts +1 -3
- package/dist/browser-composables.d.ts +314 -0
- package/dist/build-optimizer.d.ts +126 -0
- package/dist/build-views.d.ts +37 -0
- package/dist/bundle-analyzer/collector.d.ts +66 -0
- package/dist/bundle-analyzer/index.d.ts +60 -0
- package/dist/bundle-analyzer/report.d.ts +39 -0
- package/dist/bundle-analyzer/treemap.d.ts +19 -0
- package/dist/bundle-analyzer.js +499 -0
- package/dist/caching.d.ts +7 -0
- package/dist/cli.js +10885 -1203
- package/dist/client/directive.d.ts +10 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/router.d.ts +36 -0
- package/dist/client/stx-router.browser.d.ts +0 -0
- package/dist/client-script.d.ts +22 -0
- package/dist/component-hmr.d.ts +120 -0
- package/dist/components.d.ts +23 -1
- package/dist/composables/index.d.ts +277 -0
- package/dist/composables/use-battery.d.ts +46 -0
- package/dist/composables/use-broadcast-channel.d.ts +58 -0
- package/dist/composables/use-clipboard.d.ts +34 -0
- package/dist/composables/use-cookie.d.ts +70 -0
- package/dist/composables/use-device-orientation.d.ts +109 -0
- package/dist/composables/use-event-source.d.ts +77 -0
- package/dist/composables/use-eye-dropper.d.ts +107 -0
- package/dist/composables/use-fetch.d.ts +84 -0
- package/dist/composables/use-fullscreen.d.ts +47 -0
- package/dist/composables/use-geolocation.d.ts +62 -0
- package/dist/composables/use-idle.d.ts +84 -0
- package/dist/composables/use-intersection-observer.d.ts +81 -0
- package/dist/composables/use-keyboard.d.ts +100 -0
- package/dist/composables/use-media-query.d.ts +56 -0
- package/dist/composables/use-mouse.d.ts +64 -0
- package/dist/composables/use-mutation-observer.d.ts +101 -0
- package/dist/composables/use-network.d.ts +40 -0
- package/dist/composables/use-notification.d.ts +89 -0
- package/dist/composables/use-permissions.d.ts +109 -0
- package/dist/composables/use-resize-observer.d.ts +60 -0
- package/dist/composables/use-share.d.ts +70 -0
- package/dist/composables/use-speech.d.ts +117 -0
- package/dist/composables/use-storage.d.ts +64 -0
- package/dist/composables/use-text-selection.d.ts +97 -0
- package/dist/composables/use-wake-lock.d.ts +85 -0
- package/dist/composables/use-websocket.d.ts +69 -0
- package/dist/composables/use-window.d.ts +84 -0
- package/dist/composables.d.ts +268 -0
- package/dist/composition-api.d.ts +190 -0
- package/dist/computed.d.ts +137 -0
- package/dist/conditionals.d.ts +14 -2
- package/dist/config.d.ts +36 -3
- package/dist/craft-bridge.d.ts +319 -0
- package/dist/craft-compiler.d.ts +229 -0
- package/dist/craft-components.d.ts +411 -0
- package/dist/craft-entry.d.ts +5 -0
- package/dist/craft-ssr.d.ts +134 -0
- package/dist/craft.js +1553 -0
- package/dist/csp.d.ts +229 -0
- package/dist/database.d.ts +407 -0
- package/dist/database.js +5 -0
- package/dist/defer.d.ts +4 -0
- package/dist/deploy/config-generators.d.ts +75 -0
- package/dist/deploy/index.d.ts +84 -0
- package/dist/deploy/netlify.d.ts +109 -0
- package/dist/dev-server/crosswind.d.ts +54 -0
- package/dist/dev-server/index.d.ts +7 -0
- package/dist/dev-server/keyboard-shortcuts.d.ts +34 -0
- package/dist/dev-server/native-window.d.ts +40 -0
- package/dist/dev-server/port-utils.d.ts +27 -0
- package/dist/dev-server/terminal-colors.d.ts +60 -0
- package/dist/dev-server/theme-selector.d.ts +32 -0
- package/dist/dev-server/types.d.ts +92 -0
- package/dist/dev-server.d.ts +21 -0
- package/dist/devtools.d.ts +142 -0
- package/dist/directive-api.d.ts +111 -0
- package/dist/dynamic-components.d.ts +14 -0
- package/dist/edge-runtime.d.ts +200 -0
- package/dist/env.d.ts +9 -0
- package/dist/error-boundaries.d.ts +71 -0
- package/dist/error-handling.d.ts +1 -101
- package/dist/errors/codes.d.ts +99 -0
- package/dist/errors/formatter.d.ts +64 -0
- package/dist/errors/index.d.ts +56 -0
- package/dist/errors/logger.d.ts +74 -0
- package/dist/errors/sanitizer.d.ts +43 -0
- package/dist/errors/types.d.ts +79 -0
- package/dist/events.d.ts +106 -0
- package/dist/expressions.d.ts +86 -11
- package/dist/formatter.d.ts +4 -0
- package/dist/forms-validation.d.ts +173 -0
- package/dist/forms.d.ts +157 -8
- package/dist/head.d.ts +225 -0
- package/dist/heatmap.d.ts +125 -0
- package/dist/hot-reload.d.ts +87 -0
- package/dist/hydration-runtime.d.ts +47 -0
- package/dist/hydration.d.ts +161 -0
- package/dist/i18n.d.ts +240 -4
- package/dist/image-optimization/build-plugin.d.ts +53 -0
- package/dist/image-optimization/component.d.ts +46 -0
- package/dist/image-optimization/directive.d.ts +30 -0
- package/dist/image-optimization/index.d.ts +86 -0
- package/dist/image-optimization/processor.d.ts +112 -0
- package/dist/includes.d.ts +94 -9
- package/dist/index.d.ts +63 -3
- package/dist/index.js +11604 -1318
- package/dist/init.d.ts +32 -2
- package/dist/interactive.d.ts +14 -0
- package/dist/internal-markdown.d.ts +22 -0
- package/dist/jsx-runtime.d.ts +110 -0
- package/dist/keep-alive.d.ts +87 -0
- package/dist/lazy-loader.d.ts +122 -0
- package/dist/loading-indicator.d.ts +40 -0
- package/dist/loops.d.ts +22 -1
- package/dist/media/client/blur-up.d.ts +65 -0
- package/dist/media/client/index.d.ts +77 -0
- package/dist/media/client/lazy-load.d.ts +73 -0
- package/dist/media/client/upload-handler.d.ts +79 -0
- package/dist/media/image/component.d.ts +46 -0
- package/dist/media/image/directive.d.ts +9 -0
- package/dist/media/image/editing.d.ts +212 -0
- package/dist/media/image/index.d.ts +118 -0
- package/dist/media/image/placeholder.d.ts +78 -0
- package/dist/media/image/processor/cache.d.ts +32 -0
- package/dist/media/image/processor/index.d.ts +12 -0
- package/dist/media/image/processor/optimizer.d.ts +13 -0
- package/dist/media/image/processor/responsive.d.ts +17 -0
- package/dist/media/image/srcset.d.ts +158 -0
- package/dist/media/index.d.ts +295 -0
- package/dist/media/manager/embed.d.ts +25 -0
- package/dist/media/protected/component.d.ts +34 -0
- package/dist/media/protected/index.d.ts +34 -0
- package/dist/media/protected/signature.d.ts +72 -0
- package/dist/media/shared/cache.d.ts +54 -0
- package/dist/media/shared/hash.d.ts +24 -0
- package/dist/media/shared/index.d.ts +2 -0
- package/dist/media/types.d.ts +1051 -0
- package/dist/media/upload/component.d.ts +23 -0
- package/dist/media/upload/index.d.ts +1 -0
- package/dist/media/video/directive.d.ts +9 -0
- package/dist/media/video/index.d.ts +47 -0
- package/dist/media/video/processor/cache.d.ts +33 -0
- package/dist/media/video/processor/index.d.ts +21 -0
- package/dist/media/video/processor/streaming.d.ts +19 -0
- package/dist/media/video/processor/thumbnail.d.ts +28 -0
- package/dist/media/video/processor/transcoder.d.ts +9 -0
- package/dist/middleware.d.ts +42 -3
- package/dist/native-build.d.ts +74 -0
- package/dist/parser/directive-parser.d.ts +79 -0
- package/dist/parser/expression-parser.d.ts +59 -0
- package/dist/parser/index.d.ts +35 -0
- package/dist/parser/tokenizer.d.ts +81 -0
- package/dist/partial-hydration.d.ts +88 -0
- package/dist/performance-utils.d.ts +146 -3
- package/dist/plugin-system.d.ts +128 -0
- package/dist/plugin.d.ts +1 -0
- package/dist/precompiler.d.ts +108 -0
- package/dist/production-build.d.ts +199 -0
- package/dist/props.d.ts +199 -0
- package/dist/pwa/audit.d.ts +42 -0
- package/dist/pwa/directives.d.ts +29 -0
- package/dist/pwa/icons.d.ts +39 -0
- package/dist/pwa/index.d.ts +59 -0
- package/dist/pwa/inject.d.ts +22 -0
- package/dist/pwa/manifest.d.ts +104 -0
- package/dist/pwa/offline.d.ts +8 -0
- package/dist/pwa/precache.d.ts +29 -0
- package/dist/pwa/service-worker.d.ts +21 -0
- package/dist/pwa/workbox-strategies.d.ts +100 -0
- package/dist/pwa/workbox.d.ts +52 -0
- package/dist/pwa.d.ts +51 -0
- package/dist/pwa.js +8124 -0
- package/dist/reactive-bindings.d.ts +24 -0
- package/dist/reactive.d.ts +100 -0
- package/dist/reactivity.d.ts +253 -0
- package/dist/route-middleware.d.ts +232 -0
- package/dist/router.d.ts +31 -0
- package/dist/routes.d.ts +0 -7
- package/dist/runtime.d.ts +140 -0
- package/dist/safe-evaluator.d.ts +117 -3
- package/dist/scaffolding.d.ts +113 -0
- package/dist/seo.d.ts +120 -7
- package/dist/server-components.d.ts +134 -0
- package/dist/signals.d.ts +501 -0
- package/dist/slots.d.ts +63 -0
- package/dist/source-maps.d.ts +117 -0
- package/dist/ssg.d.ts +157 -0
- package/dist/ssg.js +6831 -0
- package/dist/ssr.d.ts +107 -0
- package/dist/state-management.d.ts +324 -0
- package/dist/stores-client.d.ts +70 -0
- package/dist/story/addons.d.ts +123 -0
- package/dist/story/analytics.d.ts +92 -0
- package/dist/story/auto-stories.d.ts +38 -0
- package/dist/story/bookmarks.d.ts +53 -0
- package/dist/story/bun-test.d.ts +44 -0
- package/dist/story/cli.d.ts +34 -0
- package/dist/story/collect/analyzer.d.ts +33 -0
- package/dist/story/collect/index.d.ts +27 -0
- package/dist/story/collect/parser.d.ts +17 -0
- package/dist/story/collect/scanner.d.ts +13 -0
- package/dist/story/collect/tree.d.ts +17 -0
- package/dist/story/commands/build.d.ts +14 -0
- package/dist/story/commands/dev.d.ts +16 -0
- package/dist/story/commands/index.d.ts +6 -0
- package/dist/story/commands/preview.d.ts +15 -0
- package/dist/story/compiled-output.d.ts +26 -0
- package/dist/story/composition.d.ts +47 -0
- package/dist/story/config-watcher.d.ts +26 -0
- package/dist/story/config.d.ts +26 -0
- package/dist/story/context.d.ts +21 -0
- package/dist/story/controls/index.d.ts +54 -0
- package/dist/story/crosswind.d.ts +29 -0
- package/dist/story/desktop-preview.d.ts +34 -0
- package/dist/story/docs-generator.d.ts +30 -0
- package/dist/story/errors.d.ts +47 -0
- package/dist/story/figma-export.d.ts +169 -0
- package/dist/story/generator.d.ts +21 -0
- package/dist/story/hmr.d.ts +64 -0
- package/dist/story/hot-swap.d.ts +35 -0
- package/dist/story/index.d.ts +51 -0
- package/dist/story/interactions.d.ts +52 -0
- package/dist/story/keyboard-shortcuts.d.ts +34 -0
- package/dist/story/output.d.ts +85 -0
- package/dist/story/performance.d.ts +76 -0
- package/dist/story/presets.d.ts +62 -0
- package/dist/story/props-validation.d.ts +45 -0
- package/dist/story/renderer.d.ts +53 -0
- package/dist/story/search-index.d.ts +47 -0
- package/dist/story/search.d.ts +45 -0
- package/dist/story/server.d.ts +21 -0
- package/dist/story/setup.d.ts +47 -0
- package/dist/story/snapshots.d.ts +65 -0
- package/dist/story/testing.d.ts +58 -0
- package/dist/story/theme.d.ts +68 -0
- package/dist/story/types.d.ts +249 -0
- package/dist/story/ui/code-panel.d.ts +42 -0
- package/dist/story/ui/controls-panel.d.ts +25 -0
- package/dist/story/ui/index.d.ts +4 -0
- package/dist/story/ui/navigation.d.ts +55 -0
- package/dist/story/ui/preview.d.ts +46 -0
- package/dist/story/visual-testing.d.ts +45 -0
- package/dist/streaming.d.ts +82 -2
- package/dist/suspense.d.ts +83 -0
- package/dist/teleport.d.ts +9 -0
- package/dist/testing.d.ts +289 -0
- package/dist/transitions.d.ts +87 -0
- package/dist/type-checker.d.ts +109 -0
- package/dist/types/component-types.d.ts +129 -0
- package/dist/types/config-types.d.ts +336 -0
- package/dist/types/context-types.d.ts +99 -0
- package/dist/types/csp-types.d.ts +79 -0
- package/dist/types/directive-types.d.ts +259 -0
- package/dist/types/index.d.ts +98 -0
- package/dist/types/pwa-types.d.ts +218 -0
- package/dist/types.d.ts +1 -315
- package/dist/typescript-templates.d.ts +178 -0
- package/dist/utils.d.ts +52 -6
- package/dist/validator.d.ts +77 -0
- package/dist/variable-extractor.d.ts +39 -0
- package/dist/view-composers.d.ts +154 -9
- package/dist/virtual-scrolling.d.ts +103 -0
- package/dist/visual-editor.d.ts +209 -0
- package/dist/visual-testing.d.ts +109 -0
- package/dist/visual-testing.js +126 -0
- package/dist/vue-template.d.ts +16 -0
- package/dist/web-components/css-scoping.d.ts +54 -0
- package/dist/web-components/index.d.ts +20 -0
- package/dist/web-components/reactive-generator.d.ts +72 -0
- package/dist/web-components.d.ts +222 -2
- package/dist/x-element.d.ts +35 -0
- package/package.json +41 -10
package/dist/csp.d.ts
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import type { CspConfig, CspDirectives, CspPreset, CustomDirective, StxOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a cryptographically secure nonce for CSP
|
|
4
|
+
*
|
|
5
|
+
* @param length - Length of nonce in bytes (default 16)
|
|
6
|
+
* @returns Base64-encoded nonce string
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const nonce = generateNonce()
|
|
11
|
+
* // Returns something like: "4AiRXmSkM+XRG3E2Y1fO9Q=="
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateNonce(length?: number): string;
|
|
15
|
+
/**
|
|
16
|
+
* Get or create a nonce for the current request context
|
|
17
|
+
*
|
|
18
|
+
* Uses WeakMap to ensure nonce is request-scoped and can be garbage collected.
|
|
19
|
+
* If no context is provided, generates a new nonce each time.
|
|
20
|
+
*
|
|
21
|
+
* @param context - Request context object for nonce scoping
|
|
22
|
+
* @param config - CSP configuration (may include custom nonce generator)
|
|
23
|
+
* @returns The nonce for the current context
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* // In a request handler
|
|
28
|
+
* const ctx = { requestId: '123' }
|
|
29
|
+
* const nonce = getNonce(ctx, cspConfig)
|
|
30
|
+
* // Same nonce returned for same context object
|
|
31
|
+
* const sameNonce = getNonce(ctx, cspConfig)
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function getNonce(context?: object, config?: CspConfig): string;
|
|
35
|
+
/**
|
|
36
|
+
* Clear the nonce for a context (useful for testing or manual cleanup)
|
|
37
|
+
*
|
|
38
|
+
* @param context - Request context to clear nonce for
|
|
39
|
+
*/
|
|
40
|
+
export declare function clearNonce(context: object): void;
|
|
41
|
+
/**
|
|
42
|
+
* Generate a CSP header string from directive configuration
|
|
43
|
+
*
|
|
44
|
+
* @param directives - CSP directive configuration
|
|
45
|
+
* @param nonce - Optional nonce to inject into script-src and style-src
|
|
46
|
+
* @returns CSP header string
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const header = generateCspHeader({
|
|
51
|
+
* 'default-src': ["'self'"],
|
|
52
|
+
* 'script-src': ["'self'", 'https://cdn.example.com'],
|
|
53
|
+
* 'upgrade-insecure-requests': true,
|
|
54
|
+
* })
|
|
55
|
+
* // Returns: "default-src 'self'; script-src 'self' https://cdn.example.com; upgrade-insecure-requests"
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function generateCspHeader(directives: CspDirectives, nonce?: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Generate CSP meta tag HTML
|
|
61
|
+
*
|
|
62
|
+
* @param directives - CSP directive configuration
|
|
63
|
+
* @param nonce - Optional nonce to inject
|
|
64
|
+
* @returns HTML meta tag string
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const metaTag = generateCspMetaTag({
|
|
69
|
+
* 'default-src': ["'self'"],
|
|
70
|
+
* })
|
|
71
|
+
* // Returns: '<meta http-equiv="Content-Security-Policy" content="default-src \'self\'">'
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function generateCspMetaTag(directives: CspDirectives, nonce?: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* Get a CSP preset configuration by name
|
|
77
|
+
*
|
|
78
|
+
* @param preset - Name of the preset
|
|
79
|
+
* @returns CSP configuration object
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const config = getCspPreset('strict')
|
|
84
|
+
* // Returns full CspConfig with strict directives
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export declare function getCspPreset(preset: CspPreset): CspConfig;
|
|
88
|
+
/**
|
|
89
|
+
* Merge two CSP directive configurations
|
|
90
|
+
*
|
|
91
|
+
* Sources from the second config are added to the first.
|
|
92
|
+
* Boolean directives are OR'd together.
|
|
93
|
+
*
|
|
94
|
+
* @param base - Base CSP directives
|
|
95
|
+
* @param override - Override/additional directives
|
|
96
|
+
* @returns Merged CSP directives
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const merged = mergeCspDirectives(
|
|
101
|
+
* { 'default-src': ["'self'"], 'script-src': ["'self'"] },
|
|
102
|
+
* { 'script-src': ['https://cdn.example.com'], 'img-src': ['https:'] }
|
|
103
|
+
* )
|
|
104
|
+
* // Result: {
|
|
105
|
+
* // 'default-src': ["'self'"],
|
|
106
|
+
* // 'script-src': ["'self'", "https://cdn.example.com"],
|
|
107
|
+
* // 'img-src': ["https:"]
|
|
108
|
+
* // }
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function mergeCspDirectives(base: CspDirectives, override: CspDirectives): CspDirectives;
|
|
112
|
+
/**
|
|
113
|
+
* Inject CSP meta tag into HTML head
|
|
114
|
+
*
|
|
115
|
+
* @param html - HTML content
|
|
116
|
+
* @param config - CSP configuration
|
|
117
|
+
* @param context - Request context for nonce scoping
|
|
118
|
+
* @returns HTML with CSP meta tag injected
|
|
119
|
+
*/
|
|
120
|
+
export declare function injectCspMetaTag(html: string, config: CspConfig, context?: object): string;
|
|
121
|
+
/**
|
|
122
|
+
* Add nonce attribute to all inline script and style tags
|
|
123
|
+
*
|
|
124
|
+
* @param html - HTML content
|
|
125
|
+
* @param nonce - Nonce value to add
|
|
126
|
+
* @returns HTML with nonce attributes added
|
|
127
|
+
*/
|
|
128
|
+
export declare function addNonceToInlineContent(html: string, nonce: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* Process CSP-related directives in templates
|
|
131
|
+
*
|
|
132
|
+
* Handles:
|
|
133
|
+
* - @csp - Insert CSP meta tag
|
|
134
|
+
* - @cspNonce - Output current nonce value
|
|
135
|
+
*
|
|
136
|
+
* @param template - Template content
|
|
137
|
+
* @param context - Template context
|
|
138
|
+
* @param _filePath - Source file path
|
|
139
|
+
* @param options - STX options
|
|
140
|
+
* @returns Processed template
|
|
141
|
+
*/
|
|
142
|
+
export declare function processCspDirectives(template: string, context: Record<string, any>, _filePath: string, options: StxOptions): string;
|
|
143
|
+
/**
|
|
144
|
+
* Register CSP-related custom directives
|
|
145
|
+
*
|
|
146
|
+
* @returns Array of custom directives for CSP
|
|
147
|
+
*/
|
|
148
|
+
export declare function registerCspDirectives(): CustomDirective[];
|
|
149
|
+
/**
|
|
150
|
+
* Validate CSP directive configuration
|
|
151
|
+
*
|
|
152
|
+
* @param directives - CSP directives to validate
|
|
153
|
+
* @returns Array of validation warnings
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const warnings = validateCspDirectives({
|
|
158
|
+
* 'script-src': ["'unsafe-inline'", "'unsafe-eval'"],
|
|
159
|
+
* })
|
|
160
|
+
* // Returns warnings about unsafe usage
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export declare function validateCspDirectives(directives: CspDirectives): string[];
|
|
164
|
+
/**
|
|
165
|
+
* Get the appropriate CSP header name based on configuration
|
|
166
|
+
*
|
|
167
|
+
* @param reportOnly - Whether to use report-only mode
|
|
168
|
+
* @returns Header name string
|
|
169
|
+
*/
|
|
170
|
+
export declare function getCspHeaderName(reportOnly?: boolean): string;
|
|
171
|
+
/**
|
|
172
|
+
* Create CSP headers object for HTTP response
|
|
173
|
+
*
|
|
174
|
+
* @param config - CSP configuration
|
|
175
|
+
* @param context - Request context for nonce scoping
|
|
176
|
+
* @returns Headers object ready to spread into response
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const headers = createCspHeaders(cspConfig, requestContext)
|
|
181
|
+
* return new Response(body, { headers: { ...headers } })
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export declare function createCspHeaders(config: CspConfig, context?: object): Record<string, string>;
|
|
185
|
+
/**
|
|
186
|
+
* Strict CSP preset - Maximum security, may require nonces for inline content
|
|
187
|
+
*
|
|
188
|
+
* - No unsafe-inline or unsafe-eval
|
|
189
|
+
* - Uses strict-dynamic for scripts
|
|
190
|
+
* - Blocks object/embed
|
|
191
|
+
* - Restricts form actions to same origin
|
|
192
|
+
*/
|
|
193
|
+
export declare const strictCspPreset: CspDirectives;
|
|
194
|
+
/**
|
|
195
|
+
* Moderate CSP preset - Balanced security and compatibility
|
|
196
|
+
*
|
|
197
|
+
* - Allows unsafe-inline for styles (common requirement)
|
|
198
|
+
* - Blocks unsafe-eval
|
|
199
|
+
* - Allows data: URIs for images
|
|
200
|
+
*/
|
|
201
|
+
export declare const moderateCspPreset: CspDirectives;
|
|
202
|
+
/**
|
|
203
|
+
* Relaxed CSP preset - Basic protection, maximum compatibility
|
|
204
|
+
*
|
|
205
|
+
* - Allows unsafe-inline for both scripts and styles
|
|
206
|
+
* - Still blocks unsafe-eval and object embeds
|
|
207
|
+
*/
|
|
208
|
+
export declare const relaxedCspPreset: CspDirectives;
|
|
209
|
+
/**
|
|
210
|
+
* API-only CSP preset - For JSON API responses
|
|
211
|
+
*
|
|
212
|
+
* - Blocks all content loading (APIs shouldn't render HTML)
|
|
213
|
+
* - Prevents framing
|
|
214
|
+
*/
|
|
215
|
+
export declare const apiCspPreset: CspDirectives;
|
|
216
|
+
/**
|
|
217
|
+
* CSP meta tag directive
|
|
218
|
+
* Usage: @csp
|
|
219
|
+
*/
|
|
220
|
+
export declare const cspDirective: CustomDirective;
|
|
221
|
+
/**
|
|
222
|
+
* CSP nonce directive
|
|
223
|
+
* Usage: @cspNonce
|
|
224
|
+
*/
|
|
225
|
+
export declare const cspNonceDirective: CustomDirective;
|
|
226
|
+
/**
|
|
227
|
+
* Default CSP configuration - moderate preset
|
|
228
|
+
*/
|
|
229
|
+
export declare const defaultCspConfig: CspConfig;
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
import type { StxOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Configure database connections
|
|
4
|
+
*
|
|
5
|
+
* @param config - Database configuration
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* configureDatabase({
|
|
9
|
+
* default: 'sqlite',
|
|
10
|
+
* connections: {
|
|
11
|
+
* sqlite: { driver: 'sqlite', database: './database.db' }
|
|
12
|
+
* }
|
|
13
|
+
* })
|
|
14
|
+
*/
|
|
15
|
+
export declare function configureDatabase(config: Partial<DatabaseConfig>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Get current database configuration
|
|
18
|
+
*/
|
|
19
|
+
export declare function getDatabaseConfig(): DatabaseConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Reset database configuration to defaults
|
|
22
|
+
*/
|
|
23
|
+
export declare function resetDatabaseConfig(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Register a custom database adapter
|
|
26
|
+
*
|
|
27
|
+
* @param name - Connection name
|
|
28
|
+
* @param adapter - Database adapter instance
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerAdapter(name: string, adapter: DatabaseAdapter): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get database adapter for connection
|
|
33
|
+
*
|
|
34
|
+
* @param connection - Connection name (defaults to default connection)
|
|
35
|
+
*/
|
|
36
|
+
export declare function getAdapter(connection?: string): DatabaseAdapter;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new query builder for a table
|
|
39
|
+
*
|
|
40
|
+
* @param table - Table name
|
|
41
|
+
* @returns Query builder instance
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const users = await query('users')
|
|
45
|
+
* .where('active', true)
|
|
46
|
+
* .orderBy('name')
|
|
47
|
+
* .get()
|
|
48
|
+
*/
|
|
49
|
+
export declare function query(table: string): QueryBuilder;
|
|
50
|
+
/**
|
|
51
|
+
* Alias for query()
|
|
52
|
+
*/
|
|
53
|
+
export declare function table(name: string): QueryBuilder;
|
|
54
|
+
/**
|
|
55
|
+
* Create a raw SQL expression
|
|
56
|
+
*/
|
|
57
|
+
export declare function raw(sql: string, bindings?: unknown[]): RawExpression;
|
|
58
|
+
/**
|
|
59
|
+
* Define a model
|
|
60
|
+
*
|
|
61
|
+
* @param name - Model name
|
|
62
|
+
* @param definition - Model definition
|
|
63
|
+
* @returns Model instance
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const User = defineModel('User', {
|
|
67
|
+
* table: 'users',
|
|
68
|
+
* primaryKey: 'id',
|
|
69
|
+
* fillable: ['name', 'email'],
|
|
70
|
+
* hidden: ['password'],
|
|
71
|
+
* relationships: {
|
|
72
|
+
* posts: { type: 'hasMany', model: 'Post', foreignKey: 'user_id' }
|
|
73
|
+
* }
|
|
74
|
+
* })
|
|
75
|
+
*/
|
|
76
|
+
export declare function defineModel(name: string, definition: ModelDefinition): Model;
|
|
77
|
+
/**
|
|
78
|
+
* Get a registered model by name
|
|
79
|
+
*/
|
|
80
|
+
export declare function getModel(name: string): Model;
|
|
81
|
+
/**
|
|
82
|
+
* Check if a model is registered
|
|
83
|
+
*/
|
|
84
|
+
export declare function hasModel(name: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Run a callback within a transaction
|
|
87
|
+
*
|
|
88
|
+
* @param callback - Function to run within transaction
|
|
89
|
+
* @param connection - Optional connection name
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* await transaction(async () => {
|
|
93
|
+
* await query('users').insert({ name: 'John' })
|
|
94
|
+
* await query('profiles').insert({ user_id: 1, bio: 'Hello' })
|
|
95
|
+
* })
|
|
96
|
+
*/
|
|
97
|
+
export declare function transaction<T>(callback: () => Promise<T>, connection?: string): Promise<T>;
|
|
98
|
+
/**
|
|
99
|
+
* Clear all query cache
|
|
100
|
+
*/
|
|
101
|
+
export declare function clearQueryCache(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Get query cache statistics
|
|
104
|
+
*/
|
|
105
|
+
export declare function getQueryCacheStats(): { size: number, keys: string[] };
|
|
106
|
+
/**
|
|
107
|
+
* Get query log
|
|
108
|
+
*/
|
|
109
|
+
export declare function getQueryLog(): typeof queryLog;
|
|
110
|
+
/**
|
|
111
|
+
* Clear query log
|
|
112
|
+
*/
|
|
113
|
+
export declare function clearQueryLog(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Enable or disable query logging
|
|
116
|
+
*/
|
|
117
|
+
export declare function enableQueryLogging(enabled?: boolean): void;
|
|
118
|
+
/**
|
|
119
|
+
* Process @db directive in templates
|
|
120
|
+
*
|
|
121
|
+
* Syntax: @db('table')->method()->method()
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* @db('users')->where('active', true)->get()
|
|
125
|
+
* @db('posts')->orderBy('created_at', 'desc')->limit(5)->get()
|
|
126
|
+
*/
|
|
127
|
+
export declare function processDbDirective(template: string, context: Record<string, any>, _filePath: string, _options: StxOptions): Promise<string>;
|
|
128
|
+
/**
|
|
129
|
+
* Process @model directive in templates
|
|
130
|
+
*
|
|
131
|
+
* Syntax: @model('ModelName')->method()
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* @model('User')->find(1)
|
|
135
|
+
* @model('Post')->where('published', true)->get()
|
|
136
|
+
*/
|
|
137
|
+
export declare function processModelDirective(template: string, context: Record<string, any>, _filePath: string, _options: StxOptions): Promise<string>;
|
|
138
|
+
/**
|
|
139
|
+
* Process @query directive for inline SQL
|
|
140
|
+
*
|
|
141
|
+
* Syntax: @query('SELECT * FROM users WHERE id = ?', [1])
|
|
142
|
+
*/
|
|
143
|
+
export declare function processQueryDirective(template: string, context: Record<string, any>, _filePath: string, _options: StxOptions): Promise<string>;
|
|
144
|
+
/**
|
|
145
|
+
* Process all database-related directives in a template
|
|
146
|
+
*/
|
|
147
|
+
export declare function processDatabaseDirectives(template: string, context: Record<string, any>, filePath: string, options: StxOptions): Promise<string>;
|
|
148
|
+
/**
|
|
149
|
+
* Get schema builder
|
|
150
|
+
*/
|
|
151
|
+
export declare function schema(): SchemaBuilder;
|
|
152
|
+
/**
|
|
153
|
+
* Database connection configuration
|
|
154
|
+
*/
|
|
155
|
+
export declare interface ConnectionConfig {
|
|
156
|
+
driver: DatabaseDriver
|
|
157
|
+
database: string
|
|
158
|
+
host?: string
|
|
159
|
+
port?: number
|
|
160
|
+
username?: string
|
|
161
|
+
password?: string
|
|
162
|
+
poolSize?: number
|
|
163
|
+
timeout?: number
|
|
164
|
+
ssl?: boolean | Record<string, unknown>
|
|
165
|
+
options?: Record<string, unknown>
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Database configuration
|
|
169
|
+
*/
|
|
170
|
+
export declare interface DatabaseConfig {
|
|
171
|
+
default: string
|
|
172
|
+
connections: Record<string, ConnectionConfig>
|
|
173
|
+
logging?: boolean
|
|
174
|
+
cacheTTL?: number
|
|
175
|
+
maxCacheSize?: number
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Where clause condition
|
|
179
|
+
*/
|
|
180
|
+
export declare interface WhereCondition {
|
|
181
|
+
column: string
|
|
182
|
+
operator: QueryOperator
|
|
183
|
+
value: unknown
|
|
184
|
+
boolean: 'and' | 'or'
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Order by clause
|
|
188
|
+
*/
|
|
189
|
+
export declare interface OrderByClause {
|
|
190
|
+
column: string
|
|
191
|
+
direction: 'asc' | 'desc'
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Join clause
|
|
195
|
+
*/
|
|
196
|
+
export declare interface JoinClause {
|
|
197
|
+
type: 'inner' | 'left' | 'right' | 'cross'
|
|
198
|
+
table: string
|
|
199
|
+
first: string
|
|
200
|
+
operator: string
|
|
201
|
+
second: string
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Raw SQL expression
|
|
205
|
+
*/
|
|
206
|
+
export declare interface RawExpression {
|
|
207
|
+
__raw: true
|
|
208
|
+
sql: string
|
|
209
|
+
bindings: unknown[]
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Relationship definition
|
|
213
|
+
*/
|
|
214
|
+
export declare interface RelationshipDefinition {
|
|
215
|
+
type: 'hasOne' | 'hasMany' | 'belongsTo' | 'belongsToMany'
|
|
216
|
+
model: string
|
|
217
|
+
foreignKey?: string
|
|
218
|
+
localKey?: string
|
|
219
|
+
pivotTable?: string
|
|
220
|
+
pivotForeignKey?: string
|
|
221
|
+
pivotRelatedKey?: string
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Model definition
|
|
225
|
+
*/
|
|
226
|
+
export declare interface ModelDefinition {
|
|
227
|
+
table: string
|
|
228
|
+
primaryKey?: string
|
|
229
|
+
fillable?: string[]
|
|
230
|
+
hidden?: string[]
|
|
231
|
+
timestamps?: { createdAt?: string, updatedAt?: string } | boolean
|
|
232
|
+
softDeletes?: string | boolean
|
|
233
|
+
defaults?: Record<string, unknown>
|
|
234
|
+
casts?: Record<string, 'string' | 'number' | 'boolean' | 'date' | 'json' | 'array'>
|
|
235
|
+
relationships?: Record<string, RelationshipDefinition>
|
|
236
|
+
scopes?: Record<string, (query: QueryBuilder) => QueryBuilder>
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Model instance
|
|
240
|
+
*/
|
|
241
|
+
export declare interface ModelInstance {
|
|
242
|
+
get: (key: string) => unknown
|
|
243
|
+
set: (key: string, value: unknown) => void
|
|
244
|
+
toJSON: () => Row
|
|
245
|
+
save: () => Promise<void>
|
|
246
|
+
delete: () => Promise<void>
|
|
247
|
+
refresh: () => Promise<void>
|
|
248
|
+
exists: boolean
|
|
249
|
+
original: Row
|
|
250
|
+
attributes: Row
|
|
251
|
+
isDirty: (key?: string) => boolean
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Model class
|
|
255
|
+
*/
|
|
256
|
+
export declare interface Model {
|
|
257
|
+
name: string
|
|
258
|
+
definition: ModelDefinition
|
|
259
|
+
find: (id: unknown) => Promise<ModelInstance | null>
|
|
260
|
+
findOrFail: (id: unknown) => Promise<ModelInstance>
|
|
261
|
+
all: () => Promise<ModelInstance[]>
|
|
262
|
+
create: (attributes: Row) => Promise<ModelInstance>
|
|
263
|
+
update: (attributes: Row) => Promise<number>
|
|
264
|
+
destroy: (ids: unknown | unknown[]) => Promise<number>
|
|
265
|
+
query: () => QueryBuilder
|
|
266
|
+
where: (column: string, operatorOrValue: QueryOperator | unknown, value?: unknown) => QueryBuilder
|
|
267
|
+
first: () => Promise<ModelInstance | null>
|
|
268
|
+
get: () => Promise<ModelInstance[]>
|
|
269
|
+
count: () => Promise<number>
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Database adapter interface
|
|
273
|
+
*/
|
|
274
|
+
export declare interface DatabaseAdapter {
|
|
275
|
+
connect: () => Promise<void>
|
|
276
|
+
disconnect: () => Promise<void>
|
|
277
|
+
query: <T = Row>(sql: string, bindings?: unknown[]) => Promise<T[]>
|
|
278
|
+
insert: (sql: string, bindings?: unknown[]) => Promise<unknown>
|
|
279
|
+
execute: (sql: string, bindings?: unknown[]) => Promise<number>
|
|
280
|
+
beginTransaction: () => Promise<void>
|
|
281
|
+
commit: () => Promise<void>
|
|
282
|
+
rollback: () => Promise<void>
|
|
283
|
+
isConnected: () => boolean
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Supported database drivers
|
|
287
|
+
*/
|
|
288
|
+
export type DatabaseDriver = 'sqlite' | 'postgres' | 'mysql' | 'custom'
|
|
289
|
+
/**
|
|
290
|
+
* Query operator types
|
|
291
|
+
*/
|
|
292
|
+
export type QueryOperator = '=' | '!=' | '<' | '<=' | '>' | '>=' | 'like' | 'in' | 'not in' | 'between' | 'is null' | 'is not null'
|
|
293
|
+
/**
|
|
294
|
+
* Query result row
|
|
295
|
+
*/
|
|
296
|
+
export type Row = Record<string, unknown>
|
|
297
|
+
/**
|
|
298
|
+
* Fluent query builder class
|
|
299
|
+
*/
|
|
300
|
+
export declare class QueryBuilder {
|
|
301
|
+
private _table: string;
|
|
302
|
+
private _columns: (string | RawExpression)[];
|
|
303
|
+
private _wheres: WhereCondition[];
|
|
304
|
+
private _orders: OrderByClause[];
|
|
305
|
+
private _joins: JoinClause[];
|
|
306
|
+
private _groupBy: string[];
|
|
307
|
+
private _having: WhereCondition[];
|
|
308
|
+
private _limit?: number;
|
|
309
|
+
private _offset?: number;
|
|
310
|
+
private _distinct: boolean;
|
|
311
|
+
private _connection?: string;
|
|
312
|
+
private _bindings: unknown[];
|
|
313
|
+
private _modelDefinition?: ModelDefinition;
|
|
314
|
+
constructor(table?: string);
|
|
315
|
+
table(name: string): this;
|
|
316
|
+
from(name: string): this;
|
|
317
|
+
connection(name: string): this;
|
|
318
|
+
select(columns: (string | RawExpression)[]): this;
|
|
319
|
+
addSelect(columns: (string | RawExpression)[]): this;
|
|
320
|
+
distinct(): this;
|
|
321
|
+
where(column: string, operatorOrValue: QueryOperator | unknown, value?: unknown): this;
|
|
322
|
+
orWhere(column: string, operatorOrValue: QueryOperator | unknown, value?: unknown): this;
|
|
323
|
+
whereIn(column: string, values: unknown[]): this;
|
|
324
|
+
whereNotIn(column: string, values: unknown[]): this;
|
|
325
|
+
whereNull(column: string): this;
|
|
326
|
+
whereNotNull(column: string): this;
|
|
327
|
+
whereBetween(column: string, min: unknown, max: unknown): this;
|
|
328
|
+
whereLike(column: string, pattern: string): this;
|
|
329
|
+
join(table: string, first: string, operator: string, second: string): this;
|
|
330
|
+
leftJoin(table: string, first: string, operator: string, second: string): this;
|
|
331
|
+
rightJoin(table: string, first: string, operator: string, second: string): this;
|
|
332
|
+
orderBy(column: string, direction?: 'asc' | 'desc'): this;
|
|
333
|
+
orderByDesc(column: string): this;
|
|
334
|
+
groupBy(columns: string[]): this;
|
|
335
|
+
having(column: string, operator: QueryOperator, value: unknown): this;
|
|
336
|
+
limit(count: number): this;
|
|
337
|
+
take(count: number): this;
|
|
338
|
+
offset(count: number): this;
|
|
339
|
+
skip(count: number): this;
|
|
340
|
+
forPage(page: number, perPage?: number): this;
|
|
341
|
+
get(): Promise<Row[]>;
|
|
342
|
+
first(): Promise<Row | null>;
|
|
343
|
+
firstOrFail(): Promise<Row>;
|
|
344
|
+
find(id: unknown, primaryKey?: string): Promise<Row | null>;
|
|
345
|
+
value(column: string): Promise<unknown>;
|
|
346
|
+
pluck(column: string): Promise<unknown[]>;
|
|
347
|
+
exists(): Promise<boolean>;
|
|
348
|
+
doesntExist(): Promise<boolean>;
|
|
349
|
+
count(column?: string): Promise<number>;
|
|
350
|
+
max(column: string): Promise<number | null>;
|
|
351
|
+
min(column: string): Promise<number | null>;
|
|
352
|
+
sum(column: string): Promise<number>;
|
|
353
|
+
avg(column: string): Promise<number | null>;
|
|
354
|
+
insert(data: Row): Promise<unknown>;
|
|
355
|
+
insertAll(rows: Row[]): Promise<void>;
|
|
356
|
+
update(data: Row): Promise<number>;
|
|
357
|
+
increment(column: string, amount?: number): Promise<number>;
|
|
358
|
+
decrement(column: string, amount?: number): Promise<number>;
|
|
359
|
+
delete(): Promise<number>;
|
|
360
|
+
truncate(): Promise<void>;
|
|
361
|
+
toSql(): { sql: string, bindings: unknown[] };
|
|
362
|
+
private buildWhereClause(): string;
|
|
363
|
+
private getCacheKey(sql: string, bindings: unknown[]): string;
|
|
364
|
+
clone(): QueryBuilder;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Database error with query context
|
|
368
|
+
*/
|
|
369
|
+
export declare class DatabaseError extends Error {
|
|
370
|
+
public sql?: string;
|
|
371
|
+
public bindings?: unknown[];
|
|
372
|
+
constructor(message: string, sql?: string, bindings?: unknown[]);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Schema builder for database migrations
|
|
376
|
+
*/
|
|
377
|
+
export declare class SchemaBuilder {
|
|
378
|
+
private _connection?: string;
|
|
379
|
+
connection(name: string): this;
|
|
380
|
+
create(table: string, callback: (blueprint: Blueprint) => void): Promise<void>;
|
|
381
|
+
drop(table: string): Promise<void>;
|
|
382
|
+
rename(from: string, to: string): Promise<void>;
|
|
383
|
+
hasTable(table: string): Promise<boolean>;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Table blueprint for schema definitions
|
|
387
|
+
*/
|
|
388
|
+
export declare class Blueprint {
|
|
389
|
+
private columns: string[];
|
|
390
|
+
private indices: string[];
|
|
391
|
+
private table: string;
|
|
392
|
+
constructor(table: string);
|
|
393
|
+
id(name?: string): this;
|
|
394
|
+
string(name: string, length?: number): this;
|
|
395
|
+
text(name: string): this;
|
|
396
|
+
integer(name: string): this;
|
|
397
|
+
boolean(name: string): this;
|
|
398
|
+
datetime(name: string): this;
|
|
399
|
+
timestamps(): this;
|
|
400
|
+
softDeletes(): this;
|
|
401
|
+
json(name: string): this;
|
|
402
|
+
foreignId(name: string): this;
|
|
403
|
+
index(columns: string | string[]): this;
|
|
404
|
+
unique(columns: string | string[]): this;
|
|
405
|
+
toCreateSQL(): string;
|
|
406
|
+
getIndexSQL(): string[];
|
|
407
|
+
}
|
package/dist/database.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var Q=import.meta.require;var $={default:"sqlite",connections:{},logging:!1,cacheTTL:0,maxCacheSize:1000},V={},A={},L=new Map,S=[];function o(z){$={...$,...z}}function r(){return{...$}}function a(){$={default:"sqlite",connections:{},logging:!1,cacheTTL:0,maxCacheSize:1000};for(let z of Object.keys(V))delete V[z];L.clear(),S.length=0}function t(z,H){V[z]=H}function F(z){let H=z||$.default;if(V[H])return V[H];let U=$.connections[H];if(!U)throw Error(`Database connection "${H}" not configured`);let W=h(U);return V[H]=W,W}function h(z){switch(z.driver){case"sqlite":return q(z);case"postgres":return y(z);case"mysql":return f(z);default:throw Error(`Unsupported database driver: ${z.driver}`)}}function q(z){let H=null,U=!1;return{async connect(){if(U)return;let{Database:W}=await import("bun:sqlite");H=new W(z.database,{create:!0,readwrite:!0}),U=!0},async disconnect(){if(H)H.close(),H=null,U=!1},async query(W,J=[]){if(!U)await this.connect();let X=performance.now();try{let Y=H.prepare(W).all(...J);if($.logging)B(W,J,performance.now()-X);return Y}catch(Z){throw new O(`Query failed: ${Z}`,W,J)}},async insert(W,J=[]){if(!U)await this.connect();let X=performance.now();try{let Y=H.prepare(W).run(...J);if($.logging)B(W,J,performance.now()-X);return Y.lastInsertRowid}catch(Z){throw new O(`Insert failed: ${Z}`,W,J)}},async execute(W,J=[]){if(!U)await this.connect();let X=performance.now();try{let Y=H.prepare(W).run(...J);if($.logging)B(W,J,performance.now()-X);return Y.changes}catch(Z){throw new O(`Execute failed: ${Z}`,W,J)}},async beginTransaction(){if(!U)await this.connect();H.run("BEGIN TRANSACTION")},async commit(){H.run("COMMIT")},async rollback(){H.run("ROLLBACK")},isConnected(){return U}}}function y(z){let H=!1,U=null;return{async connect(){if(H)return;try{let{Client:W}=await import("pg");U=new W({host:z.host||"localhost",port:z.port||5432,database:z.database,user:z.username,password:z.password,ssl:z.ssl}),await U.connect(),H=!0}catch(W){throw Error(`PostgreSQL connection failed. Install 'pg' package: ${W}`)}},async disconnect(){if(U)await U.end(),U=null,H=!1},async query(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let Z=await U.query(W,J);if($.logging)B(W,J,performance.now()-X);return Z.rows}catch(Z){throw new O(`Query failed: ${Z}`,W,J)}},async insert(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let Z=await U.query(`${W} RETURNING id`,J);if($.logging)B(W,J,performance.now()-X);return Z.rows[0]?.id}catch(Z){throw new O(`Insert failed: ${Z}`,W,J)}},async execute(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let Z=await U.query(W,J);if($.logging)B(W,J,performance.now()-X);return Z.rowCount||0}catch(Z){throw new O(`Execute failed: ${Z}`,W,J)}},async beginTransaction(){if(!H)await this.connect();await U.query("BEGIN")},async commit(){await U.query("COMMIT")},async rollback(){await U.query("ROLLBACK")},isConnected(){return H}}}function f(z){let H=!1,U=null;return{async connect(){if(H)return;try{U=(await import("mysql2/promise")).createPool({host:z.host||"localhost",port:z.port||3306,database:z.database,user:z.username,password:z.password,waitForConnections:!0,connectionLimit:z.poolSize||10,queueLimit:0}),H=!0}catch(W){throw Error(`MySQL connection failed. Install 'mysql2' package: ${W}`)}},async disconnect(){if(U)await U.end(),U=null,H=!1},async query(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let[Z]=await U.execute(W,J);if($.logging)B(W,J,performance.now()-X);return Z}catch(Z){throw new O(`Query failed: ${Z}`,W,J)}},async insert(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let[Z]=await U.execute(W,J);if($.logging)B(W,J,performance.now()-X);return Z.insertId}catch(Z){throw new O(`Insert failed: ${Z}`,W,J)}},async execute(W,J=[]){if(!H)await this.connect();let X=performance.now();try{let[Z]=await U.execute(W,J);if($.logging)B(W,J,performance.now()-X);return Z.affectedRows||0}catch(Z){throw new O(`Execute failed: ${Z}`,W,J)}},async beginTransaction(){if(!H)await this.connect();let W=await U.getConnection();return await W.beginTransaction(),W},async commit(){await U.execute("COMMIT")},async rollback(){await U.execute("ROLLBACK")},isConnected(){return H}}}class D{_table="";_columns=["*"];_wheres=[];_orders=[];_joins=[];_groupBy=[];_having=[];_limit;_offset;_distinct=!1;_connection;_bindings=[];_modelDefinition;constructor(z){if(z)this._table=z}table(z){return this._table=z,this}from(z){return this.table(z)}connection(z){return this._connection=z,this}select(...z){return this._columns=z.length>0?z:["*"],this}addSelect(...z){if(this._columns[0]==="*")this._columns=z;else this._columns.push(...z);return this}distinct(){return this._distinct=!0,this}where(z,H,U){let W="=",J=H;if(U!==void 0)W=H,J=U;return this._wheres.push({column:z,operator:W,value:J,boolean:"and"}),this}orWhere(z,H,U){let W="=",J=H;if(U!==void 0)W=H,J=U;return this._wheres.push({column:z,operator:W,value:J,boolean:"or"}),this}whereIn(z,H){return this._wheres.push({column:z,operator:"in",value:H,boolean:"and"}),this}whereNotIn(z,H){return this._wheres.push({column:z,operator:"not in",value:H,boolean:"and"}),this}whereNull(z){return this._wheres.push({column:z,operator:"is null",value:null,boolean:"and"}),this}whereNotNull(z){return this._wheres.push({column:z,operator:"is not null",value:null,boolean:"and"}),this}whereBetween(z,H,U){return this._wheres.push({column:z,operator:"between",value:[H,U],boolean:"and"}),this}whereLike(z,H){return this._wheres.push({column:z,operator:"like",value:H,boolean:"and"}),this}join(z,H,U,W){return this._joins.push({type:"inner",table:z,first:H,operator:U,second:W}),this}leftJoin(z,H,U,W){return this._joins.push({type:"left",table:z,first:H,operator:U,second:W}),this}rightJoin(z,H,U,W){return this._joins.push({type:"right",table:z,first:H,operator:U,second:W}),this}orderBy(z,H="asc"){return this._orders.push({column:z,direction:H}),this}orderByDesc(z){return this.orderBy(z,"desc")}groupBy(...z){return this._groupBy.push(...z),this}having(z,H,U){return this._having.push({column:z,operator:H,value:U,boolean:"and"}),this}limit(z){return this._limit=z,this}take(z){return this.limit(z)}offset(z){return this._offset=z,this}skip(z){return this.offset(z)}forPage(z,H=15){return this.offset((z-1)*H).limit(H)}async get(){let{sql:z,bindings:H}=this.toSql();if($.cacheTTL&&$.cacheTTL>0){let J=this.getCacheKey(z,H),X=g(J);if(X!==void 0)return X}let W=await F(this._connection).query(z,H);if($.cacheTTL&&$.cacheTTL>0){let J=this.getCacheKey(z,H);m(J,W,$.cacheTTL)}return W}async first(){return(await this.limit(1).get())[0]||null}async firstOrFail(){let z=await this.first();if(!z)throw Error("No results found");return z}async find(z,H="id"){return this.where(H,z).first()}async value(z){let H=await this.select(z).first();return H?H[z]:null}async pluck(z){return(await this.select(z).get()).map((U)=>U[z])}async exists(){return(await this.select(E("1")).limit(1).get()).length>0}async doesntExist(){return!await this.exists()}async count(z="*"){let H=await this.select(E(`COUNT(${z}) as count`)).first();return Number(H?.count||0)}async max(z){return(await this.select(E(`MAX(${z}) as max`)).first())?.max}async min(z){return(await this.select(E(`MIN(${z}) as min`)).first())?.min}async sum(z){let H=await this.select(E(`SUM(${z}) as sum`)).first();return Number(H?.sum||0)}async avg(z){return(await this.select(E(`AVG(${z}) as avg`)).first())?.avg}async insert(z){let H=Object.keys(z),U=H.map(()=>"?").join(", "),W=Object.values(z),J=`INSERT INTO ${this._table} (${H.join(", ")}) VALUES (${U})`,X=F(this._connection);return P(this._table),X.insert(J,W)}async insertAll(z){if(z.length===0)return;let H=Object.keys(z[0]),U=z.map(()=>`(${H.map(()=>"?").join(", ")})`).join(", "),W=z.flatMap((Z)=>Object.values(Z)),J=`INSERT INTO ${this._table} (${H.join(", ")}) VALUES ${U}`,X=F(this._connection);P(this._table),await X.execute(J,W)}async update(z){this._bindings=[];let H=this.buildWhereClause(),U=[...this._bindings],W=Object.keys(z).map((Y)=>`${Y} = ?`).join(", "),J=[...Object.values(z),...U],X=`UPDATE ${this._table} SET ${W}${H}`,Z=F(this._connection);return P(this._table),Z.execute(X,J)}async increment(z,H=1){this._bindings=[];let U=this.buildWhereClause(),W=`UPDATE ${this._table} SET ${z} = ${z} + ?${U}`,J=F(this._connection);return P(this._table),J.execute(W,[H,...this._bindings])}async decrement(z,H=1){return this.increment(z,-H)}async delete(){this._bindings=[];let z=this.buildWhereClause(),H=`DELETE FROM ${this._table}${z}`,U=F(this._connection);return P(this._table),U.execute(H,this._bindings)}async truncate(){let z=F(this._connection);P(this._table),await z.execute(`DELETE FROM ${this._table}`)}toSql(){this._bindings=[];let z="SELECT ";if(this._distinct)z+="DISTINCT ";z+=this._columns.map((H)=>{if(typeof H==="object"&&H.__raw)return H.sql;return H}).join(", "),z+=` FROM ${this._table}`;for(let H of this._joins)z+=` ${H.type.toUpperCase()} JOIN ${H.table} ON ${H.first} ${H.operator} ${H.second}`;if(z+=this.buildWhereClause(),this._groupBy.length>0)z+=` GROUP BY ${this._groupBy.join(", ")}`;if(this._having.length>0){let H=this._having.map((U,W)=>{let J=W===0?"":` ${U.boolean.toUpperCase()} `;return this._bindings.push(U.value),`${J}${U.column} ${U.operator} ?`});z+=` HAVING ${H.join("")}`}if(this._orders.length>0)z+=` ORDER BY ${this._orders.map((H)=>`${H.column} ${H.direction.toUpperCase()}`).join(", ")}`;if(this._limit!==void 0)z+=` LIMIT ${this._limit}`;if(this._offset!==void 0)z+=` OFFSET ${this._offset}`;return{sql:z,bindings:this._bindings}}buildWhereClause(){if(this._wheres.length===0)return"";return this._wheres.map((H,U)=>{let W=U===0?" WHERE ":` ${H.boolean.toUpperCase()} `;switch(H.operator){case"in":{let J=H.value,X=J.map(()=>"?").join(", ");return this._bindings.push(...J),`${W}${H.column} IN (${X})`}case"not in":{let J=H.value,X=J.map(()=>"?").join(", ");return this._bindings.push(...J),`${W}${H.column} NOT IN (${X})`}case"between":{let[J,X]=H.value;return this._bindings.push(J,X),`${W}${H.column} BETWEEN ? AND ?`}case"is null":return`${W}${H.column} IS NULL`;case"is not null":return`${W}${H.column} IS NOT NULL`;default:return this._bindings.push(H.value),`${W}${H.column} ${H.operator} ?`}}).join("")}getCacheKey(z,H){return`${this._table}:${z}:${JSON.stringify(H)}`}clone(){let z=new D(this._table);return z._columns=[...this._columns],z._wheres=[...this._wheres],z._orders=[...this._orders],z._joins=[...this._joins],z._groupBy=[...this._groupBy],z._having=[...this._having],z._limit=this._limit,z._offset=this._offset,z._distinct=this._distinct,z._connection=this._connection,z}}function G(z){return new D(z)}function n(z){return G(z)}function E(z,H=[]){return{__raw:!0,sql:z,bindings:H}}function e(z,H){let U=H.primaryKey||"id",W={name:z,definition:H,async find(J){let X=await G(H.table).where(U,J).first();return X?N(W,X):null},async findOrFail(J){let X=await this.find(J);if(!X)throw Error(`${z} not found with ${U} = ${J}`);return X},async all(){return(await G(H.table).get()).map((X)=>N(W,X))},async create(J){let X={...H.defaults,...J},Z=H.fillable?Object.fromEntries(Object.entries(X).filter(([_])=>H.fillable.includes(_))):X;if(H.timestamps!==!1){let _=new Date().toISOString(),R=typeof H.timestamps==="object"?H.timestamps.createdAt||"created_at":"created_at",T=typeof H.timestamps==="object"?H.timestamps.updatedAt||"updated_at":"updated_at";Z[R]=_,Z[T]=_}let Y=await G(H.table).insert(Z);return this.findOrFail(Y)},async update(J){return G(H.table).update(J)},async destroy(J){let X=Array.isArray(J)?J:[J];return G(H.table).whereIn(U,X).delete()},query(){return G(H.table)},where(J,X,Z){return this.query().where(J,X,Z)},async first(){let J=await this.query().first();return J?N(W,J):null},async get(){return(await this.query().get()).map((X)=>N(W,X))},async count(){return this.query().count()}};return A[z]=W,W}function k(z){let H=A[z];if(!H)throw Error(`Model "${z}" not defined. Use defineModel() first.`);return H}function zz(z){return z in A}function N(z,H){let{definition:U}=z,W=U.primaryKey||"id",J={...H},X={...H};if(U.casts){for(let[Y,_]of Object.entries(U.casts))if(Y in X)X[Y]=p(X[Y],_)}let Z={exists:!0,original:J,attributes:X,get(Y){return X[Y]},set(Y,_){X[Y]=_},toJSON(){let Y={...X};if(U.hidden)for(let _ of U.hidden)delete Y[_];return Y},async save(){let Y={};for(let _ of Object.keys(X))if(X[_]!==J[_])Y[_]=X[_];if(Object.keys(Y).length>0){if(U.timestamps!==!1){let _=typeof U.timestamps==="object"?U.timestamps.updatedAt||"updated_at":"updated_at";Y[_]=new Date().toISOString()}await G(U.table).where(W,J[W]).update(Y),Object.assign(J,Y)}},async delete(){if(U.softDeletes){let Y=typeof U.softDeletes==="string"?U.softDeletes:"deleted_at";await G(U.table).where(W,J[W]).update({[Y]:new Date().toISOString()})}else await G(U.table).where(W,J[W]).delete();Z.exists=!1},async refresh(){let Y=await G(U.table).where(W,J[W]).first();if(Y)Object.assign(J,Y),Object.assign(X,Y)},isDirty(Y){if(Y)return X[Y]!==J[Y];return Object.keys(X).some((_)=>X[_]!==J[_])}};if(U.relationships)for(let[Y,_]of Object.entries(U.relationships))Object.defineProperty(Z,Y,{value:async()=>{return b(Z,_,z)},enumerable:!1});return new Proxy(Z,{get(Y,_){if(_ in Y)return Y[_];return X[_]},set(Y,_,R){if(_ in Y)Y[_]=R;else X[_]=R;return!0}})}async function b(z,H,U){let W=k(H.model),J=U.definition.primaryKey||"id";switch(H.type){case"hasOne":{let X=H.foreignKey||`${U.name.toLowerCase()}_id`,Z=await G(W.definition.table).where(X,z.get(J)).first();return Z?N(W,Z):null}case"hasMany":{let X=H.foreignKey||`${U.name.toLowerCase()}_id`;return(await G(W.definition.table).where(X,z.get(J)).get()).map((Y)=>N(W,Y))}case"belongsTo":{let X=H.foreignKey||`${H.model.toLowerCase()}_id`,Z=H.localKey||"id",Y=await G(W.definition.table).where(Z,z.get(X)).first();return Y?N(W,Y):null}case"belongsToMany":{let X=H.pivotTable||[U.name,H.model].sort().join("_").toLowerCase(),Z=H.pivotForeignKey||`${U.name.toLowerCase()}_id`,Y=H.pivotRelatedKey||`${H.model.toLowerCase()}_id`,_=W.definition.primaryKey||"id";return(await G(W.definition.table).join(X,`${W.definition.table}.${_}`,"=",`${X}.${Y}`).where(`${X}.${Z}`,z.get(J)).get()).map((T)=>N(W,T))}default:return null}}function p(z,H){if(z===null||z===void 0)return z;switch(H){case"string":return String(z);case"number":return Number(z);case"boolean":return Boolean(z);case"date":return new Date(z);case"json":case"array":return typeof z==="string"?JSON.parse(z):z;default:return z}}async function Hz(z,H){let U=F(H);await U.beginTransaction();try{let W=await z();return await U.commit(),W}catch(W){throw await U.rollback(),W}}function g(z){let H=L.get(z);if(!H)return;if(Date.now()-H.timestamp>H.ttl*1000){L.delete(z);return}return H.result}function m(z,H,U){if(L.size>=($.maxCacheSize||1000)){let W=L.keys().next().value;if(W)L.delete(W)}L.set(z,{result:H,timestamp:Date.now(),ttl:U})}function P(z){for(let H of L.keys())if(H.startsWith(`${z}:`))L.delete(H)}function Jz(){L.clear()}function Uz(){return{size:L.size,keys:[...L.keys()]}}function B(z,H,U){if(S.push({sql:z,bindings:H,duration:U,timestamp:new Date}),S.length>1000)S.shift()}function Wz(){return[...S]}function Xz(){S.length=0}function Yz(z=!0){$.logging=z}class O extends Error{sql;bindings;constructor(z,H,U){super(z);this.sql=H;this.bindings=U;this.name="DatabaseError"}}async function u(z,H,U,W){let J=/@db\(\s*['"]([^'"]+)['"]\s*\)((?:->\w+\([^)]*\))*)/g,X=z,Z=[...z.matchAll(J)];for(let Y of Z){let[_,R,T]=Y;try{let j=await s(R,T),I=`$${R}`;H[I]=j,X=X.replace(_,"")}catch(j){X=X.replace(_,`<!-- DB Error: ${j instanceof Error?j.message:String(j)} -->`)}}return X}async function d(z,H,U,W){let J=/@model\(\s*['"]([^'"]+)['"]\s*\)((?:->\w+\([^)]*\))*)/g,X=z,Z=[...z.matchAll(J)];for(let Y of Z){let[_,R,T]=Y;try{let j=k(R),I=await l(j,T),K=`$${R.toLowerCase()}`;H[K]=I,X=X.replace(_,"")}catch(j){X=X.replace(_,`<!-- Model Error: ${j instanceof Error?j.message:String(j)} -->`)}}return X}async function c(z,H,U,W){let J=/@query\(\s*['"]([^'"]+)['"]\s*(?:,\s*(\[[^\]]*\]))?\s*\)\s*as\s+\$(\w+)/g,X=z,Z=[...z.matchAll(J)];for(let Y of Z){let[_,R,T,j]=Y;try{let I=T?JSON.parse(T):[],v=await F().query(R,I);H[`$${j}`]=v,X=X.replace(_,"")}catch(I){X=X.replace(_,`<!-- Query Error: ${I instanceof Error?I.message:String(I)} -->`)}}return X}async function s(z,H){let U=G(z),W=/->(\w+)\(([^)]*)\)/g,J=[...H.matchAll(W)],X=U;for(let[,Z,Y]of J){let _=M(Y);if(typeof X[Z]==="function"){if(X=X[Z](..._),X instanceof Promise){X=await X;break}}}if(X instanceof D)X=await X.get();return X}async function l(z,H){let U=/->(\w+)\(([^)]*)\)/g,W=[...H.matchAll(U)],J=z;for(let[,X,Z]of W){let Y=M(Z);if(typeof J[X]==="function"){if(J=J[X](...Y),J instanceof Promise)J=await J}else if(J instanceof D){if(typeof J[X]==="function"){if(J=J[X](...Y),J instanceof Promise)J=await J}}}if(J instanceof D)J=await J.get();return J}function M(z){if(!z.trim())return[];let H=[],U="",W=0,J=!1,X="";for(let Z=0;Z<z.length;Z++){let Y=z[Z];if(!J&&(Y==='"'||Y==="'"))J=!0,X=Y,U+=Y;else if(J&&Y===X)J=!1,U+=Y;else if(!J&&(Y==="["||Y==="{"||Y==="("))W++,U+=Y;else if(!J&&(Y==="]"||Y==="}"||Y===")"))W--,U+=Y;else if(!J&&W===0&&Y===",")H.push(x(U.trim())),U="";else U+=Y}if(U.trim())H.push(x(U.trim()));return H}function x(z){if(z.startsWith('"')&&z.endsWith('"')||z.startsWith("'")&&z.endsWith("'"))return z.slice(1,-1);if(z==="true")return!0;if(z==="false")return!1;if(z==="null")return null;let H=Number(z);if(!Number.isNaN(H))return H;try{return JSON.parse(z)}catch{return z}}async function Zz(z,H,U,W){let J=z;return J=await c(J,H,U,W),J=await d(J,H,U,W),J=await u(J,H,U,W),J}class w{_connection;connection(z){return this._connection=z,this}async create(z,H){let U=new C(z);H(U);let W=U.toCreateSQL();await F(this._connection).execute(W)}async drop(z){await F(this._connection).execute(`DROP TABLE IF EXISTS ${z}`)}async rename(z,H){await F(this._connection).execute(`ALTER TABLE ${z} RENAME TO ${H}`)}async hasTable(z){let H=F(this._connection);try{return await H.query(`SELECT 1 FROM ${z} LIMIT 1`),!0}catch{return!1}}}class C{table;columns=[];indices=[];constructor(z){this.table=z}id(z="id"){return this.columns.push(`${z} INTEGER PRIMARY KEY AUTOINCREMENT`),this}string(z,H=255){return this.columns.push(`${z} VARCHAR(${H})`),this}text(z){return this.columns.push(`${z} TEXT`),this}integer(z){return this.columns.push(`${z} INTEGER`),this}boolean(z){return this.columns.push(`${z} BOOLEAN DEFAULT 0`),this}datetime(z){return this.columns.push(`${z} DATETIME`),this}timestamps(){return this.columns.push("created_at DATETIME DEFAULT CURRENT_TIMESTAMP"),this.columns.push("updated_at DATETIME DEFAULT CURRENT_TIMESTAMP"),this}softDeletes(){return this.columns.push("deleted_at DATETIME"),this}json(z){return this.columns.push(`${z} TEXT`),this}foreignId(z){return this.columns.push(`${z} INTEGER`),this}index(z){let H=Array.isArray(z)?z:[z],U=`idx_${this.table}_${H.join("_")}`;return this.indices.push(`CREATE INDEX ${U} ON ${this.table} (${H.join(", ")})`),this}unique(z){let H=Array.isArray(z)?z:[z],U=`uniq_${this.table}_${H.join("_")}`;return this.indices.push(`CREATE UNIQUE INDEX ${U} ON ${this.table} (${H.join(", ")})`),this}toCreateSQL(){return`CREATE TABLE IF NOT EXISTS ${this.table} (
|
|
3
|
+
${this.columns.join(`,
|
|
4
|
+
`)}
|
|
5
|
+
)`}getIndexSQL(){return this.indices}}function _z(){return new w}export{Hz as transaction,n as table,_z as schema,a as resetDatabaseConfig,t as registerAdapter,E as raw,G as query,c as processQueryDirective,d as processModelDirective,u as processDbDirective,Zz as processDatabaseDirectives,zz as hasModel,Wz as getQueryLog,Uz as getQueryCacheStats,k as getModel,r as getDatabaseConfig,F as getAdapter,Yz as enableQueryLogging,e as defineModel,o as configureDatabase,Xz as clearQueryLog,Jz as clearQueryCache,w as SchemaBuilder,D as QueryBuilder,O as DatabaseError,C as Blueprint};
|
package/dist/defer.d.ts
ADDED