@askrjs/askr 0.0.41 → 0.0.43

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.
Files changed (55) hide show
  1. package/dist/benchmark.js +2 -2
  2. package/dist/boot/index.d.ts.map +1 -1
  3. package/dist/boot/index.js +2 -0
  4. package/dist/boot/index.js.map +1 -1
  5. package/dist/common/route-activity.js +30 -0
  6. package/dist/common/route-activity.js.map +1 -0
  7. package/dist/common/router.d.ts +4 -2
  8. package/dist/common/router.d.ts.map +1 -1
  9. package/dist/data/index.d.ts +21 -2
  10. package/dist/data/index.d.ts.map +1 -1
  11. package/dist/data/index.js +56 -3
  12. package/dist/data/index.js.map +1 -1
  13. package/dist/data/invalidation-listeners.js +15 -0
  14. package/dist/data/invalidation-listeners.js.map +1 -0
  15. package/dist/renderer/dom.js +35 -20
  16. package/dist/renderer/dom.js.map +1 -1
  17. package/dist/renderer/evaluate.js +27 -17
  18. package/dist/renderer/evaluate.js.map +1 -1
  19. package/dist/renderer/for-commit.js +9 -0
  20. package/dist/renderer/for-commit.js.map +1 -1
  21. package/dist/resources/index.d.ts +2 -2
  22. package/dist/resources/index.js +2 -2
  23. package/dist/router/match.js +31 -6
  24. package/dist/router/match.js.map +1 -1
  25. package/dist/router/navigate.d.ts.map +1 -1
  26. package/dist/router/navigate.js +30 -4
  27. package/dist/router/navigate.js.map +1 -1
  28. package/dist/router/route.d.ts +6 -1
  29. package/dist/router/route.d.ts.map +1 -1
  30. package/dist/router/route.js +35 -8
  31. package/dist/router/route.js.map +1 -1
  32. package/dist/runtime/child-scope.js +1 -0
  33. package/dist/runtime/child-scope.js.map +1 -1
  34. package/dist/runtime/component.d.ts +8 -1
  35. package/dist/runtime/component.d.ts.map +1 -1
  36. package/dist/runtime/component.js +207 -44
  37. package/dist/runtime/component.js.map +1 -1
  38. package/dist/runtime/fastlane.js +6 -0
  39. package/dist/runtime/fastlane.js.map +1 -1
  40. package/dist/runtime/for.d.ts.map +1 -1
  41. package/dist/runtime/for.js +18 -1
  42. package/dist/runtime/for.js.map +1 -1
  43. package/dist/runtime/operations.d.ts +11 -3
  44. package/dist/runtime/operations.d.ts.map +1 -1
  45. package/dist/runtime/operations.js +161 -22
  46. package/dist/runtime/operations.js.map +1 -1
  47. package/dist/runtime/readable.d.ts +1 -0
  48. package/dist/runtime/readable.d.ts.map +1 -1
  49. package/dist/runtime/readable.js +7 -4
  50. package/dist/runtime/readable.js.map +1 -1
  51. package/dist/testing/index.d.ts +53 -0
  52. package/dist/testing/index.d.ts.map +1 -0
  53. package/dist/testing/index.js +172 -0
  54. package/dist/testing/index.js.map +1 -0
  55. package/package.json +11 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/testing/index.ts"],"sourcesContent":["import type { Query, QueryStaleReason } from '../data';\nimport { parseSegments } from '../router/match';\nimport { computeRouteActivityMatches } from '../router/route';\nimport type {\n ParsedSegment,\n Route,\n RouteManifest,\n RouteMatch,\n RouteRecord,\n} from '../common/router';\nimport {\n addInvalidationListener,\n type InvalidationEvent,\n} from '../data/invalidation-listeners';\n\nexport type MockRefresh = () => void | Promise<void>;\n\nexport interface MockQueryOptions {\n refresh?: MockRefresh;\n}\n\nexport interface InvalidationRecord {\n prefix: string;\n markPendingWrite: boolean;\n}\n\nexport interface InvalidationRecorder {\n readonly calls: readonly InvalidationRecord[];\n readonly prefixes: readonly string[];\n clear(): void;\n stop(): void;\n}\n\ninterface MatchRouteOptions {\n manifest?: RouteManifest;\n routes?: readonly Route[];\n}\n\nexport interface RoutePatternWarning {\n kind: 'route-collision';\n path: string;\n conflictingPath: string;\n segment: string;\n namespace: string | undefined;\n message: string;\n}\n\ntype StaleValueReason = Exclude<QueryStaleReason, 'error'>;\n\nfunction normalizeRefresh(options?: MockQueryOptions): () => Promise<void> {\n return async () => {\n await options?.refresh?.();\n };\n}\n\nfunction makeQuery<T extends {}>(\n state: Omit<Query<T>, 'refresh'>,\n options?: MockQueryOptions\n): Query<T> {\n return {\n ...state,\n refresh: normalizeRefresh(options),\n } as Query<T>;\n}\n\nfunction createFreshQuery<T extends {}>(\n data: T,\n options?: MockQueryOptions\n): Query<T> {\n return makeQuery(\n {\n data,\n error: null,\n loading: false,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n },\n options\n );\n}\n\nexport const mockQuery = Object.assign(createFreshQuery, {\n loading<T extends {} = {}>(options?: MockQueryOptions): Query<T> {\n return makeQuery(\n {\n data: null,\n error: null,\n loading: true,\n refreshing: false,\n stale: false,\n consistency: 'fresh',\n staleReason: null,\n },\n options\n );\n },\n\n error<T extends {} = {}>(\n error: {},\n previousData?: T,\n options?: MockQueryOptions\n ): Query<T> {\n return makeQuery(\n {\n data: previousData ?? null,\n error,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: 'error',\n } as Omit<Query<T>, 'refresh'>,\n options\n );\n },\n\n refreshing<T extends {}>(data: T, options?: MockQueryOptions): Query<T> {\n return makeQuery(\n {\n data,\n error: null,\n loading: false,\n refreshing: true,\n stale: true,\n consistency: 'refreshing',\n staleReason: null,\n },\n options\n );\n },\n\n stale<T extends {}>(\n data: T,\n reason: StaleValueReason = 'inconsistent',\n options?: MockQueryOptions\n ): Query<T> {\n return makeQuery(\n {\n data,\n error: null,\n loading: false,\n refreshing: false,\n stale: true,\n consistency: 'stale',\n staleReason: reason,\n },\n options\n );\n },\n\n pendingWrite<T extends {}>(data: T, options?: MockQueryOptions): Query<T> {\n return makeQuery(\n {\n data,\n error: null,\n loading: false,\n refreshing: true,\n stale: true,\n consistency: 'pending-write',\n staleReason: null,\n },\n options\n );\n },\n});\n\nexport const queryState = {\n fresh: createFreshQuery,\n loading: mockQuery.loading,\n error: mockQuery.error,\n refreshing: mockQuery.refreshing,\n stale: mockQuery.stale,\n pendingWrite: mockQuery.pendingWrite,\n};\n\nexport function createInvalidationRecorder(): InvalidationRecorder {\n const records: InvalidationRecord[] = [];\n let active = true;\n\n const unsubscribe = addInvalidationListener((event: InvalidationEvent) => {\n records.push({\n prefix: event.prefix,\n markPendingWrite: event.markPendingWrite,\n });\n });\n\n return {\n get calls() {\n return records.slice();\n },\n\n get prefixes() {\n return records.map((record) => record.prefix);\n },\n\n clear() {\n records.length = 0;\n },\n\n stop() {\n if (!active) {\n return;\n }\n\n active = false;\n unsubscribe();\n },\n };\n}\n\nexport function matchRoute(\n path: string,\n options: MatchRouteOptions = {}\n): RouteMatch | null {\n return computeRouteActivityMatches(path, options)[0] ?? null;\n}\n\ntype RoutePatternRecord = {\n path: string;\n segments: ParsedSegment[];\n namespace: string | undefined;\n};\n\nfunction getRoutePatternRecords(\n options: MatchRouteOptions\n): RoutePatternRecord[] {\n if (options.manifest) {\n return options.manifest.records.map((record: RouteRecord) => ({\n path: record.path,\n segments: record.segments,\n namespace: record.options.namespace,\n }));\n }\n\n return (options.routes ?? []).map((route) => ({\n path: route.path,\n segments: parseSegments(route.path),\n namespace: route.namespace,\n }));\n}\n\nfunction routePrefixMatches(\n splatPrefix: readonly ParsedSegment[],\n routeSegments: readonly ParsedSegment[]\n): boolean {\n if (routeSegments.length <= splatPrefix.length) {\n return false;\n }\n\n for (let index = 0; index < splatPrefix.length; index++) {\n const splatSegment = splatPrefix[index];\n const routeSegment = routeSegments[index];\n\n if (\n splatSegment.kind === 'static' &&\n routeSegment.kind === 'static' &&\n splatSegment.value !== routeSegment.value\n ) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function getRouteWarnings(\n options: MatchRouteOptions = {}\n): RoutePatternWarning[] {\n const records = getRoutePatternRecords(options);\n const warnings: RoutePatternWarning[] = [];\n\n for (const record of records) {\n const splatIndex = record.segments.findIndex(\n (segment) => segment.kind === 'splat'\n );\n if (splatIndex === -1) {\n continue;\n }\n\n const splatPrefix = record.segments.slice(0, splatIndex);\n for (const candidate of records) {\n if (\n candidate === record ||\n candidate.namespace !== record.namespace ||\n !routePrefixMatches(splatPrefix, candidate.segments)\n ) {\n continue;\n }\n\n const reservedSegment = candidate.segments[splatIndex];\n if (reservedSegment?.kind !== 'static') {\n continue;\n }\n\n warnings.push({\n kind: 'route-collision',\n path: record.path,\n conflictingPath: candidate.path,\n segment: reservedSegment.value,\n namespace: record.namespace,\n message: `Route \"${candidate.path}\" reserves segment \"${reservedSegment.value}\" under named splat route \"${record.path}\".`,\n });\n }\n }\n\n return warnings.sort((left, right) => {\n const pathOrder = left.path.localeCompare(right.path);\n if (pathOrder !== 0) {\n return pathOrder;\n }\n return left.conflictingPath.localeCompare(right.conflictingPath);\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askrjs/askr",
3
- "version": "0.0.41",
3
+ "version": "0.0.43",
4
4
  "description": "Actor-backed deterministic UI framework",
5
5
  "keywords": [
6
6
  "askr",
@@ -80,6 +80,10 @@
80
80
  "import": "./dist/data/index.js",
81
81
  "types": "./dist/data/index.d.ts"
82
82
  },
83
+ "./testing": {
84
+ "import": "./dist/testing/index.js",
85
+ "types": "./dist/testing/index.d.ts"
86
+ },
83
87
  "./fx": {
84
88
  "import": "./dist/fx/index.js",
85
89
  "types": "./dist/fx/index.d.ts"
@@ -127,7 +131,7 @@
127
131
  "bench:tier4": "cross-env NODE_ENV=production vp test bench --run --reporter=default --config vitest.bench.tier4.config.ts"
128
132
  },
129
133
  "devDependencies": {
130
- "@types/node": "^25.9.2",
134
+ "@types/node": "^25.9.3",
131
135
  "cross-env": "^10.1.0",
132
136
  "jsdom": "^29.1.1",
133
137
  "playwright": "^1.60.0",
@@ -145,5 +149,9 @@
145
149
  "engines": {
146
150
  "node": ">=18"
147
151
  },
148
- "packageManager": "npm@11.16.0"
152
+ "packageManager": "npm@11.17.0",
153
+ "allowScripts": {
154
+ "fsevents@2.3.3": true,
155
+ "fsevents@2.3.2": true
156
+ }
149
157
  }