@stacksjs/stx 0.2.151 → 0.2.153
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/app-shell.js +28 -1
- package/dist/browser-composables.d.ts +24 -9
- package/dist/build-id.d.ts +49 -0
- package/dist/build-id.js +20 -0
- package/dist/cli.js +897 -659
- package/dist/client-script.js +2 -2
- package/dist/color-mode-boot.d.ts +15 -10
- package/dist/color-mode-boot.js +12 -8
- package/dist/component-client-factories.js +3 -2
- package/dist/component-processing.d.ts +16 -0
- package/dist/component-processing.js +4 -1
- package/dist/component-renderer.js +2 -2
- package/dist/composables/index.d.ts +6 -1
- package/dist/composables/use-color-mode.d.ts +19 -4
- package/dist/composables/use-color-mode.js +37 -24
- package/dist/composables/use-device-orientation.d.ts +8 -1
- package/dist/composables/use-event-source.d.ts +14 -1
- package/dist/composables/use-eye-dropper.d.ts +10 -1
- package/dist/composables/use-idle.d.ts +21 -3
- package/dist/composables/use-storage.d.ts +15 -10
- package/dist/composables/use-storage.js +63 -2
- package/dist/composables/use-text-selection.d.ts +27 -3
- package/dist/composables/use-wake-lock.d.ts +2 -2
- package/dist/craft.js +625 -387
- package/dist/dev-server/serve-app.js +9 -5
- package/dist/dev-server/types.d.ts +8 -1
- package/dist/document-shell.d.ts +55 -0
- package/dist/document-shell.js +103 -3
- package/dist/edge-runtime.d.ts +1 -1
- package/dist/head.js +5 -1
- package/dist/includes.js +4 -2
- package/dist/index.d.ts +17 -0
- package/dist/index.js +9 -0
- package/dist/process.js +7 -3
- package/dist/production-builder.js +3 -1
- package/dist/pwa.js +591 -353
- package/dist/render.d.ts +1 -1
- package/dist/render.js +2 -2
- package/dist/signals.js +280 -44
- package/dist/ssg.js +603 -365
- package/dist/ssr.d.ts +17 -1
- package/dist/stx.d.ts +14 -6
- package/dist/types/config-types.d.ts +1 -0
- package/dist/utils.js +1 -8
- package/dist/variable-extractor.d.ts +8 -0
- package/dist/variable-extractor.js +24 -9
- package/dist/visual-testing.d.ts +26 -3
- package/package.json +5 -5
- package/stx.d.ts +14 -6
package/dist/ssr.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare function render(template: string, data?: Record<string, unknown>,
|
|
|
16
16
|
/**
|
|
17
17
|
* Create a STX server application
|
|
18
18
|
*/
|
|
19
|
-
export declare function createApp(config?: AppConfig):
|
|
19
|
+
export declare function createApp(config?: AppConfig): StxServerApp;
|
|
20
20
|
/** Session data store */
|
|
21
21
|
export declare interface SessionData {
|
|
22
22
|
[key: string]: unknown
|
|
@@ -87,6 +87,22 @@ export declare interface AppConfig {
|
|
|
87
87
|
csrfEnabled?: boolean
|
|
88
88
|
sessionStore?: SessionStore
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Handle returned by {@link createApp} — the server application surface.
|
|
92
|
+
*/
|
|
93
|
+
export declare interface StxServerApp {
|
|
94
|
+
fetch: (request: Request) => Promise<Response>
|
|
95
|
+
get: (pattern: string, handler: RouteHandler, middleware?: Middleware[]) => StxServerApp
|
|
96
|
+
post: (pattern: string, handler: RouteHandler, middleware?: Middleware[]) => StxServerApp
|
|
97
|
+
put: (pattern: string, handler: RouteHandler, middleware?: Middleware[]) => StxServerApp
|
|
98
|
+
delete: (pattern: string, handler: RouteHandler, middleware?: Middleware[]) => StxServerApp
|
|
99
|
+
patch: (pattern: string, handler: RouteHandler, middleware?: Middleware[]) => StxServerApp
|
|
100
|
+
use: (middleware: Middleware) => StxServerApp
|
|
101
|
+
render: (template: string, data?: Record<string, unknown>, ctx?: RequestContext) => Promise<Response>
|
|
102
|
+
redirect: (url: string, status?: 302 | 301 | 303 | 307 | 308) => Response
|
|
103
|
+
back: (ctx: RequestContext, errors?: ValidationErrors, oldInput?: Record<string, string>) => Response
|
|
104
|
+
listen: (port?: number) => ReturnType<typeof Bun.serve>
|
|
105
|
+
}
|
|
90
106
|
/** Route handler */
|
|
91
107
|
// eslint-disable-next-line pickier/no-unused-vars
|
|
92
108
|
export type RouteHandler = (ctx: RequestContext) => Response | Promise<Response>;
|
package/dist/stx.d.ts
CHANGED
|
@@ -237,11 +237,19 @@ interface StxColorModeOptions {
|
|
|
237
237
|
/** localStorage key holding the preference. @default 'stx-color-mode' */
|
|
238
238
|
storageKey?: string
|
|
239
239
|
/** Mode used when nothing valid is stored. @default 'auto' */
|
|
240
|
-
initialMode?: 'light' | 'dark' | 'auto'
|
|
241
|
-
/**
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
240
|
+
initialMode?: 'light' | 'dark' | 'auto' | 'system'
|
|
241
|
+
/**
|
|
242
|
+
* Class applied to `<html>` when dark. @default 'dark'
|
|
243
|
+
* Applied alongside `attribute`; pass `null` to opt out of the class.
|
|
244
|
+
*/
|
|
245
|
+
darkClass?: string | null
|
|
246
|
+
/** Attribute set to the resolved mode on `<html>`, e.g. 'data-theme'. */
|
|
247
|
+
attribute?: string | null
|
|
248
|
+
/**
|
|
249
|
+
* Spelling written to storage for "follow the system".
|
|
250
|
+
* @default whatever is already stored, else 'auto'
|
|
251
|
+
*/
|
|
252
|
+
autoValue?: 'auto' | 'system'
|
|
245
253
|
/** Suppress CSS transitions across a mode switch. @default true */
|
|
246
254
|
disableTransitions?: boolean
|
|
247
255
|
}
|
|
@@ -257,7 +265,7 @@ declare function useColorMode(_options?: StxColorModeOptions): {
|
|
|
257
265
|
/** User preference, which may be 'auto'. */
|
|
258
266
|
readonly preference: 'light' | 'dark' | 'auto'
|
|
259
267
|
readonly isDark: boolean
|
|
260
|
-
set: (mode: 'light' | 'dark' | 'auto') => void
|
|
268
|
+
set: (mode: 'light' | 'dark' | 'auto' | 'system') => void
|
|
261
269
|
toggle: () => void
|
|
262
270
|
subscribe: (fn: (mode: 'light' | 'dark', preference: 'light' | 'dark' | 'auto') => void) => () => void
|
|
263
271
|
}
|
|
@@ -242,6 +242,7 @@ export declare interface AppHeadConfig {
|
|
|
242
242
|
link?: Array<Record<string, string>>
|
|
243
243
|
script?: Array<{ src?: string, content?: string, [key: string]: any }>
|
|
244
244
|
headRaw?: string
|
|
245
|
+
htmlAttrs?: Record<string, string>
|
|
245
246
|
bodyClass?: string
|
|
246
247
|
bodyAttrs?: Record<string, string>
|
|
247
248
|
}
|
package/dist/utils.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { extractAndStripCssImports, extractBridgeData, injectBrowserCoreAutoImports, processClientScript, renderVendorStyleTags } from "./client-script.js";
|
|
4
4
|
import { COMPONENT_CLIENT_FACTORIES_CONTEXT_KEY, registerComponentClientFactory } from "./component-client-factories.js";
|
|
5
|
-
import { interpolateScriptExpressions, processExpressions
|
|
5
|
+
import { interpolateScriptExpressions, processExpressions } from "./expressions.js";
|
|
6
6
|
import { COMPONENT_SCOPE_LOCAL_GLOBALS, buildRuntimeGlobalsDestructure } from "./runtime-globals.js";
|
|
7
7
|
import { transformStoreImports } from "./store-imports.js";
|
|
8
8
|
import { LRUCache } from "./performance-utils.js";
|
|
@@ -648,13 +648,6 @@ ${triedPaths.map((p) => ` - ${p}`).join(`
|
|
|
648
648
|
templateContent = templateContent.replace(/\{\{\s*text\s*\|\|\s*slot\s*\}\}/g, () => slotContent);
|
|
649
649
|
const { applySlots } = await importOnce("stx/slots", () => import("./slots.js")), { defaultSlot, namedSlots } = parsedSlotContent;
|
|
650
650
|
templateContent = await applySlots(templateContent, defaultSlot, namedSlots, componentContext);
|
|
651
|
-
for (const [key, value] of Object.entries(componentContext))
|
|
652
|
-
if (typeof value === "string") {
|
|
653
|
-
if (value.includes("<") && value.includes(">") || value.includes("<") || value.includes(""")) {
|
|
654
|
-
const unescaped = unescapeHtml(value);
|
|
655
|
-
componentContext[key] = unescaped;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
651
|
const hasSignalScripts = clientScripts.some((s) => /\b(?:state|derived|effect|ref|reactive|computed|watch|watchEffect|useReactiveProp|defineProps|withDefaults|defineEmits|defineExpose|defineSlots)\s*(?:<[^<>()]*>)?\s*\(/.test(s)), clientSignalNames = componentClientSignalNames(clientScripts);
|
|
659
652
|
if (clientSignalNames.length > 0)
|
|
660
653
|
componentContext.__stx_client_signal_names = clientSignalNames;
|
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* @returns JavaScript code with TypeScript syntax stripped
|
|
6
6
|
*/
|
|
7
7
|
export declare function stripTypeScript(scriptContent: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Whether a script failure was a module that could not be found.
|
|
10
|
+
*
|
|
11
|
+
* Matched on the message because the failure arrives as a plain Error from the
|
|
12
|
+
* runtime's loader rather than a typed one, and the wording differs between
|
|
13
|
+
* Bun and Node.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isModuleResolutionFailure(message: string): boolean;
|
|
8
16
|
export declare function extractVariables(scriptContent: string, context: Record<string, unknown>, filePath: string, options?: ExtractVariablesOptions): Promise<void>;
|
|
9
17
|
/**
|
|
10
18
|
* Convert ES module syntax to CommonJS
|
|
@@ -210,6 +210,9 @@ export function stripTypeScript(scriptContent) {
|
|
|
210
210
|
`);
|
|
211
211
|
return result;
|
|
212
212
|
}
|
|
213
|
+
export function isModuleResolutionFailure(message) {
|
|
214
|
+
return /cannot find module|could not resolve|module not found|failed to resolve/i.test(message);
|
|
215
|
+
}
|
|
213
216
|
export async function extractVariables(scriptContent, context, filePath, options = {}) {
|
|
214
217
|
if (!scriptContent.trim())
|
|
215
218
|
return;
|
|
@@ -470,10 +473,11 @@ export async function extractVariables(scriptContent, context, filePath, options
|
|
|
470
473
|
if (!(key in context))
|
|
471
474
|
context[key] = value;
|
|
472
475
|
} catch (primaryError) {
|
|
473
|
-
|
|
474
|
-
|
|
476
|
+
const msg = primaryError instanceof Error ? primaryError.message : String(primaryError);
|
|
477
|
+
if (isModuleResolutionFailure(msg))
|
|
478
|
+
console.warn(`[stx] server <script> in ${filePath ?? "<unknown>"} imports a module that does not resolve, so every variable in that script is undefined. Cause: ${msg}`);
|
|
479
|
+
else if (process.env.STX_DEBUG)
|
|
475
480
|
console.warn(`[stx] server <script> did not execute in ${filePath ?? "<unknown>"} \u2014 falling back to static extraction. Cause: ${msg}`);
|
|
476
|
-
}
|
|
477
481
|
try {
|
|
478
482
|
await fallbackVariableExtraction(jsContent, context, filePath);
|
|
479
483
|
} catch (fallbackError) {
|
|
@@ -590,13 +594,24 @@ export function convertToCommonJS(scriptContent, filePath) {
|
|
|
590
594
|
convertedLines.push(`const ${name} = await import('${resolved}')`);
|
|
591
595
|
convertedLines.push(`module.exports.${name} = ${name};`);
|
|
592
596
|
} else if (namedImportMatch) {
|
|
593
|
-
const [, names, source] = namedImportMatch,
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
597
|
+
const [, names, source] = namedImportMatch, resolved = resolveSource(source), specifiers = [], exported = [];
|
|
598
|
+
for (const raw of names.split(",")) {
|
|
599
|
+
const specifier = raw.trim();
|
|
600
|
+
if (!specifier)
|
|
601
|
+
continue;
|
|
602
|
+
const aliased = specifier.split(/\s+as\s+/);
|
|
603
|
+
if (aliased.length === 2) {
|
|
604
|
+
const [imported, local] = [aliased[0].trim(), aliased[1].trim()];
|
|
605
|
+
specifiers.push(`${imported}: ${local}`);
|
|
606
|
+
exported.push(local);
|
|
607
|
+
} else {
|
|
608
|
+
specifiers.push(specifier);
|
|
609
|
+
exported.push(specifier);
|
|
610
|
+
}
|
|
599
611
|
}
|
|
612
|
+
convertedLines.push(`const { ${specifiers.join(", ")} } = await import('${resolved}')`);
|
|
613
|
+
for (const local of exported)
|
|
614
|
+
convertedLines.push(`module.exports.${local} = ${local};`);
|
|
600
615
|
} else if (sideEffectMatch) {
|
|
601
616
|
const resolved = resolveSource(sideEffectMatch[1]);
|
|
602
617
|
convertedLines.push(`await import('${resolved}')`);
|
package/dist/visual-testing.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Create a snapshot tester
|
|
3
3
|
*/
|
|
4
|
-
export declare function createSnapshotTester(config?: VisualTestConfig):
|
|
4
|
+
export declare function createSnapshotTester(config?: VisualTestConfig): SnapshotTester;
|
|
5
5
|
/**
|
|
6
6
|
* Create a visual regression tester
|
|
7
7
|
*/
|
|
8
|
-
export declare function createVisualRegressionTester(config?: VisualTestConfig):
|
|
8
|
+
export declare function createVisualRegressionTester(config?: VisualTestConfig): VisualRegressionTester;
|
|
9
9
|
/**
|
|
10
10
|
* Create a story-based visual tester
|
|
11
11
|
*/
|
|
12
|
-
export declare function createStoryTester(config?: VisualTestConfig):
|
|
12
|
+
export declare function createStoryTester(config?: VisualTestConfig): StoryTester;
|
|
13
13
|
/**
|
|
14
14
|
* Generate visual test report
|
|
15
15
|
*/
|
|
@@ -89,6 +89,29 @@ export declare interface Story {
|
|
|
89
89
|
args?: Record<string, unknown>
|
|
90
90
|
viewports?: Viewport[]
|
|
91
91
|
}
|
|
92
|
+
/** Handle returned by {@link createSnapshotTester}. */
|
|
93
|
+
export declare interface SnapshotTester {
|
|
94
|
+
snapshot: (html: string, name: string) => Promise<SnapshotResult>
|
|
95
|
+
snapshotJson: (data: unknown, name: string) => Promise<SnapshotResult>
|
|
96
|
+
matchInlineSnapshot: (actual: string, expected?: string) => { passed: boolean, expected: string }
|
|
97
|
+
getConfig: () => Required<VisualTestConfig>
|
|
98
|
+
}
|
|
99
|
+
/** Handle returned by {@link createVisualRegressionTester}. */
|
|
100
|
+
export declare interface VisualRegressionTester {
|
|
101
|
+
compareScreenshots: (name: string, actual: Buffer, viewport?: string) => Promise<ScreenshotResult>
|
|
102
|
+
testViewports: (name: string, captureScreenshot: (viewport: Viewport) => Promise<Buffer>, viewports?: Viewport[]) => Promise<ScreenshotResult[]>
|
|
103
|
+
getSnapshotTester: () => SnapshotTester
|
|
104
|
+
}
|
|
105
|
+
/** Handle returned by {@link createStoryTester}. */
|
|
106
|
+
export declare interface StoryTester {
|
|
107
|
+
addStory: (story: Story) => void
|
|
108
|
+
addStories: (storyList: Story[]) => void
|
|
109
|
+
getStories: () => Story[]
|
|
110
|
+
getStoriesForComponent: (component: string) => Story[]
|
|
111
|
+
testStory: (storyId: string) => Promise<VisualTestResult>
|
|
112
|
+
testAllStories: () => Promise<VisualTestResult[]>
|
|
113
|
+
generateStoryIndex: () => Promise<string>
|
|
114
|
+
}
|
|
92
115
|
// =============================================================================
|
|
93
116
|
// Test Reporter
|
|
94
117
|
// =============================================================================
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/stx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.153",
|
|
5
5
|
"description": "A performant UI Framework. Powered by Bun.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -117,12 +117,12 @@
|
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"@cwcss/crosswind": "^0.2.14",
|
|
119
119
|
"@stacksjs/clapp": "^0.2.0",
|
|
120
|
-
"@stacksjs/desktop": "0.2.
|
|
121
|
-
"@stacksjs/sanitizer": "0.2.
|
|
120
|
+
"@stacksjs/desktop": "0.2.153",
|
|
121
|
+
"@stacksjs/sanitizer": "0.2.153",
|
|
122
122
|
"@stacksjs/ts-i18n": "^0.1.11",
|
|
123
|
-
"bun-plugin-stx": "0.2.
|
|
123
|
+
"bun-plugin-stx": "0.2.153",
|
|
124
124
|
"bunfig": "^0.15.17",
|
|
125
|
-
"stx-router": "0.2.
|
|
125
|
+
"stx-router": "0.2.153",
|
|
126
126
|
"ts-broadcasting": "^0.0.9",
|
|
127
127
|
"ts-images": "^0.1.9",
|
|
128
128
|
"ts-syntax-highlighter": "^0.2.1"
|
package/stx.d.ts
CHANGED
|
@@ -237,11 +237,19 @@ interface StxColorModeOptions {
|
|
|
237
237
|
/** localStorage key holding the preference. @default 'stx-color-mode' */
|
|
238
238
|
storageKey?: string
|
|
239
239
|
/** Mode used when nothing valid is stored. @default 'auto' */
|
|
240
|
-
initialMode?: 'light' | 'dark' | 'auto'
|
|
241
|
-
/**
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
240
|
+
initialMode?: 'light' | 'dark' | 'auto' | 'system'
|
|
241
|
+
/**
|
|
242
|
+
* Class applied to `<html>` when dark. @default 'dark'
|
|
243
|
+
* Applied alongside `attribute`; pass `null` to opt out of the class.
|
|
244
|
+
*/
|
|
245
|
+
darkClass?: string | null
|
|
246
|
+
/** Attribute set to the resolved mode on `<html>`, e.g. 'data-theme'. */
|
|
247
|
+
attribute?: string | null
|
|
248
|
+
/**
|
|
249
|
+
* Spelling written to storage for "follow the system".
|
|
250
|
+
* @default whatever is already stored, else 'auto'
|
|
251
|
+
*/
|
|
252
|
+
autoValue?: 'auto' | 'system'
|
|
245
253
|
/** Suppress CSS transitions across a mode switch. @default true */
|
|
246
254
|
disableTransitions?: boolean
|
|
247
255
|
}
|
|
@@ -257,7 +265,7 @@ declare function useColorMode(_options?: StxColorModeOptions): {
|
|
|
257
265
|
/** User preference, which may be 'auto'. */
|
|
258
266
|
readonly preference: 'light' | 'dark' | 'auto'
|
|
259
267
|
readonly isDark: boolean
|
|
260
|
-
set: (mode: 'light' | 'dark' | 'auto') => void
|
|
268
|
+
set: (mode: 'light' | 'dark' | 'auto' | 'system') => void
|
|
261
269
|
toggle: () => void
|
|
262
270
|
subscribe: (fn: (mode: 'light' | 'dark', preference: 'light' | 'dark' | 'auto') => void) => () => void
|
|
263
271
|
}
|