polen 0.11.0-next.26 → 0.11.0-next.28

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 (48) hide show
  1. package/build/api/builder/ssg/generate.d.ts.map +1 -1
  2. package/build/api/builder/ssg/generate.js +76 -50
  3. package/build/api/builder/ssg/generate.js.map +1 -1
  4. package/build/api/builder/ssg/page-generator.worker.js +59 -55
  5. package/build/api/builder/ssg/page-generator.worker.js.map +1 -1
  6. package/build/api/builder/ssg/server-runner.worker.js +34 -40
  7. package/build/api/builder/ssg/server-runner.worker.js.map +1 -1
  8. package/build/api/builder/ssg/worker-messages.d.ts +10 -0
  9. package/build/api/builder/ssg/worker-messages.d.ts.map +1 -1
  10. package/build/api/builder/ssg/worker-messages.js +7 -1
  11. package/build/api/builder/ssg/worker-messages.js.map +1 -1
  12. package/build/template/components/ReferenceLink.d.ts +1 -0
  13. package/build/template/components/ReferenceLink.d.ts.map +1 -1
  14. package/build/template/components/ReferenceLink.js.map +1 -1
  15. package/build/template/components/graphql/type-link.d.ts.map +1 -1
  16. package/build/template/components/graphql/type-link.js +7 -6
  17. package/build/template/components/graphql/type-link.js.map +1 -1
  18. package/build/vite/plugins/routes-manifest.d.ts.map +1 -1
  19. package/build/vite/plugins/routes-manifest.js +5 -2
  20. package/build/vite/plugins/routes-manifest.js.map +1 -1
  21. package/package.json +38 -48
  22. package/src/api/builder/ssg/generate.ts +111 -71
  23. package/src/api/builder/ssg/page-generator.worker.ts +106 -74
  24. package/src/api/builder/ssg/server-runner.worker.ts +39 -44
  25. package/src/api/builder/ssg/worker-messages.ts +11 -1
  26. package/src/template/components/ReferenceLink.tsx +1 -0
  27. package/src/template/components/graphql/type-link.tsx +21 -9
  28. package/src/vite/plugins/routes-manifest.ts +5 -2
  29. package/build/lib/extensible-data/$.d.ts +0 -2
  30. package/build/lib/extensible-data/$.d.ts.map +0 -1
  31. package/build/lib/extensible-data/$.js +0 -2
  32. package/build/lib/extensible-data/$.js.map +0 -1
  33. package/build/lib/extensible-data/extensible-data.d.ts +0 -17
  34. package/build/lib/extensible-data/extensible-data.d.ts.map +0 -1
  35. package/build/lib/extensible-data/extensible-data.js +0 -24
  36. package/build/lib/extensible-data/extensible-data.js.map +0 -1
  37. package/build/lib/vite-plugin-reactive-data/$.d.ts +0 -2
  38. package/build/lib/vite-plugin-reactive-data/$.d.ts.map +0 -1
  39. package/build/lib/vite-plugin-reactive-data/$.js +0 -2
  40. package/build/lib/vite-plugin-reactive-data/$.js.map +0 -1
  41. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.d.ts +0 -32
  42. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.d.ts.map +0 -1
  43. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.js +0 -85
  44. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.js.map +0 -1
  45. package/src/lib/extensible-data/$.ts +0 -1
  46. package/src/lib/extensible-data/extensible-data.ts +0 -38
  47. package/src/lib/vite-plugin-reactive-data/$.ts +0 -1
  48. package/src/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.ts +0 -124
@@ -2,15 +2,11 @@
2
2
  * Worker that generates static pages by fetching from servers.
3
3
  * This is executed in a worker thread using Effect Worker API.
4
4
  */
5
- import { debugPolen } from '#singletons/debug'
6
- import { Path, WorkerRunner } from '@effect/platform'
5
+ import { FileSystem, Path, WorkerRunner } from '@effect/platform'
7
6
  import { NodeContext, NodeRuntime, NodeWorkerRunner } from '@effect/platform-node'
8
- import { Data, Effect, Layer } from 'effect'
9
- import { promises as fs } from 'node:fs'
7
+ import { Array, Data, Duration, Effect, Either, Layer } from 'effect'
10
8
  import { type GenerateResult, PageMessage } from './worker-messages.js'
11
9
 
12
- const debug = debugPolen.sub(`api:ssg:page-generator`)
13
-
14
10
  // ============================================================================
15
11
  // Error Types
16
12
  // ============================================================================
@@ -31,85 +27,118 @@ class RouteProcessingError extends Data.Error<{
31
27
  // Generate Pages Handler
32
28
  // ============================================================================
33
29
 
30
+ // Fetch HTML from server using Effect patterns
31
+ const fetchPage = (url: string) =>
32
+ Effect.gen(function*() {
33
+ const response = yield* Effect.tryPromise({
34
+ try: () => fetch(url),
35
+ catch: (error) => new Error(`Network error: ${error}`),
36
+ })
37
+
38
+ if (!response.ok) {
39
+ return yield* Effect.fail(
40
+ new Error(`HTTP ${response.status}: ${response.statusText}`),
41
+ )
42
+ }
43
+
44
+ return yield* Effect.tryPromise({
45
+ try: () => response.text(),
46
+ catch: (error) => new Error(`Failed to read response: ${error}`),
47
+ })
48
+ })
49
+
50
+ // Write HTML to file system
51
+ const writeHtmlFile = (outputPath: string, html: string) =>
52
+ Effect.gen(function*() {
53
+ const fs = yield* FileSystem.FileSystem
54
+ const path = yield* Path.Path
55
+
56
+ const dir = path.dirname(outputPath)
57
+ yield* fs.makeDirectory(dir, { recursive: true })
58
+ yield* fs.writeFileString(outputPath, html)
59
+ })
60
+
61
+ // Process a single route
62
+ const processRoute = (
63
+ route: string,
64
+ serverPort: number,
65
+ outputDir: string,
66
+ ) =>
67
+ Effect.gen(function*() {
68
+ const path = yield* Path.Path
69
+
70
+ // Fetch the page from the server
71
+ const url = `http://localhost:${serverPort}${route}`
72
+ const html = yield* fetchPage(url).pipe(
73
+ Effect.mapError(error => new RouteProcessingError({ route, cause: error })),
74
+ )
75
+
76
+ // Determine output file path
77
+ const outputPath = path.join(
78
+ outputDir,
79
+ route === '/' ? 'index.html' : `${route.slice(1)}/index.html`,
80
+ )
81
+
82
+ // Write the HTML file
83
+ yield* writeHtmlFile(outputPath, html).pipe(
84
+ Effect.mapError(error => new RouteProcessingError({ route, cause: error })),
85
+ )
86
+
87
+ return route
88
+ })
89
+
34
90
  const handlers = {
35
91
  GeneratePages: (
36
92
  { routes, serverPort, outputDir }: { routes: readonly string[]; serverPort: number; outputDir: string },
37
93
  ) =>
38
94
  Effect.gen(function*() {
39
- const path = yield* Path.Path
40
- const startTime = Date.now()
41
- let processedCount = 0
42
-
43
- debug(`Starting batch generation`, {
44
- totalRoutes: routes.length,
45
- serverPort,
46
- })
47
-
48
- // Process each route by fetching from the server
49
- for (const route of routes) {
50
- yield* Effect.tryPromise({
51
- try: async () => {
52
- // Fetch the page from the server
53
- const url = `http://localhost:${serverPort}${route}`
54
- const response = await fetch(url)
55
-
56
- if (!response.ok) {
57
- throw new Error(`Failed to fetch ${route}: ${response.status} ${response.statusText}`)
58
- }
59
-
60
- const html = await response.text()
61
-
62
- // Determine output file path
63
- const outputPath = path.join(
64
- outputDir,
65
- route === '/' ? 'index.html' : `${route.slice(1)}/index.html`,
66
- )
67
-
68
- // Ensure directory exists
69
- const dir = path.dirname(outputPath)
70
- await fs.mkdir(dir, { recursive: true })
71
-
72
- // Write the HTML file
73
- await fs.writeFile(outputPath, html, 'utf-8')
74
-
75
- processedCount++
76
-
77
- // Log progress every 5 routes or on last route
78
- if (processedCount % 5 === 0 || processedCount === routes.length) {
79
- debug(`Progress`, {
80
- processedCount,
81
- totalRoutes: routes.length,
82
- serverPort,
83
- })
84
- }
85
- },
86
- catch: (error) => {
87
- debug(`Failed to process route`, { route, error })
88
- return new RouteProcessingError({ route, cause: error })
89
- },
90
- })
91
- }
95
+ yield* Effect.logDebug(`Starting batch generation`).pipe(
96
+ Effect.annotateLogs({
97
+ totalRoutes: routes.length,
98
+ serverPort,
99
+ }),
100
+ )
101
+
102
+ // Process all routes with timing, collecting both successes and failures
103
+ const [duration, results] = yield* Effect.forEach(
104
+ routes,
105
+ (route, index) =>
106
+ processRoute(route, serverPort, outputDir).pipe(
107
+ Effect.tap(() =>
108
+ // Log progress every 5 routes
109
+ (index + 1) % 5 === 0 || index === routes.length - 1
110
+ ? Effect.logDebug(`Progress: ${index + 1}/${routes.length} routes processed`)
111
+ : Effect.void
112
+ ),
113
+ Effect.either, // Convert to Either to capture both success and failure
114
+ ),
115
+ { concurrency: 1 }, // Process sequentially to avoid overwhelming the server
116
+ ).pipe(Effect.timed)
117
+
118
+ // Partition results into successes and failures
119
+ const [failures, successes] = Array.partition(results, Either.isRight)
120
+ const processedCount = successes.length
92
121
 
93
122
  const result: GenerateResult = {
94
- success: true,
123
+ success: failures.length === 0,
95
124
  processedCount,
96
- duration: Date.now() - startTime,
125
+ duration: Duration.toMillis(duration),
97
126
  memoryUsed: process.memoryUsage().heapUsed,
127
+ ...(failures.length > 0 && {
128
+ error: `Failed to generate ${failures.length} out of ${routes.length} routes`,
129
+ failures: failures.map((f) => ({
130
+ route: f.left.route,
131
+ error: f.left.cause instanceof Error ? f.left.cause.message : String(f.left.cause),
132
+ })),
133
+ }),
98
134
  }
99
135
 
100
- debug(`Batch generation complete`, result)
136
+ yield* Effect.logDebug(`Batch generation complete`).pipe(
137
+ Effect.annotateLogs(result),
138
+ )
139
+
101
140
  return result
102
- }).pipe(
103
- Effect.catchAll((error) =>
104
- Effect.succeed({
105
- success: false,
106
- processedCount: 0,
107
- duration: Date.now() - Date.now(),
108
- memoryUsed: process.memoryUsage().heapUsed,
109
- error: error instanceof Error ? error.message : String(error),
110
- })
111
- ),
112
- ),
141
+ }),
113
142
  }
114
143
 
115
144
  // ============================================================================
@@ -120,6 +149,9 @@ const handlers = {
120
149
  WorkerRunner.launch(
121
150
  Layer.provide(
122
151
  WorkerRunner.layerSerialized(PageMessage, handlers),
123
- Layer.merge(NodeWorkerRunner.layer, NodeContext.layer),
152
+ Layer.mergeAll(
153
+ NodeWorkerRunner.layer,
154
+ NodeContext.layer,
155
+ ),
124
156
  ),
125
157
  ).pipe(NodeRuntime.runMain)
@@ -2,18 +2,15 @@
2
2
  * Worker that runs a Polen server for SSG.
3
3
  * This is executed in a child process using Effect Worker API.
4
4
  */
5
- import { debugPolen } from '#singletons/debug'
6
5
  import { WorkerRunner } from '@effect/platform'
7
6
  import { NodeRuntime, NodeWorkerRunner } from '@effect/platform-node'
8
- import { Duration, Effect, Layer, Scope } from 'effect'
7
+ import { Duration, Effect, Layer, Ref, Scope } from 'effect'
9
8
  import { spawn } from 'node:child_process'
10
9
  import type { ChildProcess } from 'node:child_process'
11
10
  import { ServerMessage } from './worker-messages.js'
12
11
 
13
- const debug = debugPolen.sub(`api:ssg:server-runner`)
14
-
15
- // Store the server process for cleanup
16
- let serverProcess: ChildProcess | null = null
12
+ // Store the server process reference for cleanup
13
+ const serverProcessRef = Ref.unsafeMake<ChildProcess | null>(null)
17
14
 
18
15
  // ============================================================================
19
16
  // Handlers
@@ -23,20 +20,21 @@ const handlers = {
23
20
  StartServer: ({ serverPath, port }: { serverPath: string; port: number }) =>
24
21
  Effect.gen(function*() {
25
22
  // If there's already a server running, stop it first
26
- if (serverProcess) {
27
- serverProcess.kill('SIGTERM')
23
+ const existingProcess = yield* Ref.get(serverProcessRef)
24
+ if (existingProcess) {
25
+ existingProcess.kill('SIGTERM')
28
26
  yield* Effect.sleep(Duration.millis(500))
29
- if (!serverProcess.killed) {
30
- serverProcess.kill('SIGKILL')
27
+ if (!existingProcess.killed) {
28
+ existingProcess.kill('SIGKILL')
31
29
  }
32
- serverProcess = null
30
+ yield* Ref.set(serverProcessRef, null)
33
31
  }
34
32
 
35
33
  // Start the server process
36
- const startServer = Effect.sync((): ChildProcess => {
37
- debug(`Starting server with command: node ${serverPath}`)
34
+ yield* Effect.logDebug(`Starting server with command: node ${serverPath}`)
38
35
 
39
- serverProcess = spawn('node', [serverPath], {
36
+ const proc = yield* Effect.sync(() => {
37
+ const serverProc = spawn('node', [serverPath], {
40
38
  env: {
41
39
  ...process.env,
42
40
  PORT: port.toString(),
@@ -44,18 +42,23 @@ const handlers = {
44
42
  stdio: ['ignore', 'pipe', 'pipe'],
45
43
  })
46
44
 
47
- serverProcess.stdout?.on('data', (data) => {
48
- debug(`[Server ${port}] stdout`, data.toString().trim())
45
+ // Log server output
46
+ serverProc.stdout?.on('data', (data) => {
47
+ Effect.logDebug(`[Server ${port}] stdout: ${data.toString().trim()}`).pipe(
48
+ Effect.runSync,
49
+ )
49
50
  })
50
51
 
51
- serverProcess.stderr?.on('data', (data) => {
52
- debug(`[Server ${port}] stderr`, data.toString().trim())
52
+ serverProc.stderr?.on('data', (data) => {
53
+ Effect.logDebug(`[Server ${port}] stderr: ${data.toString().trim()}`).pipe(
54
+ Effect.runSync,
55
+ )
53
56
  })
54
57
 
55
- return serverProcess
58
+ return serverProc
56
59
  })
57
60
 
58
- const proc: ChildProcess = yield* startServer
61
+ yield* Ref.set(serverProcessRef, proc)
59
62
 
60
63
  // Wait for server to be ready with proper interruption support
61
64
  const waitForReady = Effect.async<void>((resume) => {
@@ -80,7 +83,7 @@ const handlers = {
80
83
  try {
81
84
  const response = await fetch(`http://localhost:${port}/`)
82
85
  if (response.ok || response.status === 404) {
83
- debug(`[Server ${port}] Ready!`)
86
+ Effect.logDebug(`[Server ${port}] Ready!`).pipe(Effect.runSync)
84
87
  if (checkInterval) clearInterval(checkInterval)
85
88
  proc.removeListener('error', errorHandler)
86
89
  proc.removeListener('exit', exitHandler)
@@ -114,33 +117,25 @@ const handlers = {
114
117
  Effect.die(new Error(`Server on port ${port} failed to start within 30 seconds`))),
115
118
  )
116
119
 
117
- // Add finalizer to ensure cleanup
118
- yield* Effect.addFinalizer(() =>
119
- Effect.sync(() => {
120
- debug(`Finalizer: Stopping server on port ${port}`)
121
- if (serverProcess && !serverProcess.killed) {
122
- serverProcess.kill('SIGTERM')
123
- // Try to kill forcefully after a brief wait
124
- setTimeout(() => {
125
- if (serverProcess && !serverProcess.killed) {
126
- serverProcess.kill('SIGKILL')
127
- }
128
- serverProcess = null
129
- }, 100)
130
- }
131
- })
132
- )
133
- }).pipe(Effect.scoped),
134
- StopServer: () =>
120
+ yield* Effect.logDebug(`Server on port ${port} started successfully`)
121
+ }),
122
+ StopServer: ({ port }: { port?: number | undefined }) =>
135
123
  Effect.gen(function*() {
136
- if (serverProcess) {
137
- serverProcess.kill('SIGTERM')
124
+ const serverProc = yield* Ref.get(serverProcessRef)
125
+ if (serverProc) {
126
+ if (port !== undefined) {
127
+ yield* Effect.logDebug(`Stopping server on port ${port}`)
128
+ }
129
+ serverProc.kill('SIGTERM')
138
130
  // Give it time to shut down gracefully
139
131
  yield* Effect.sleep(Duration.millis(500))
140
- if (!serverProcess.killed) {
141
- serverProcess.kill('SIGKILL')
132
+ if (!serverProc.killed) {
133
+ serverProc.kill('SIGKILL')
134
+ }
135
+ yield* Ref.set(serverProcessRef, null)
136
+ if (port !== undefined) {
137
+ yield* Effect.logDebug(`Server on port ${port} stopped`)
142
138
  }
143
- serverProcess = null
144
139
  }
145
140
  }),
146
141
  }
@@ -16,6 +16,14 @@ const GenerateResultSchema = S.Struct({
16
16
  duration: S.Number,
17
17
  memoryUsed: S.Number,
18
18
  error: S.optional(S.String),
19
+ failures: S.optional(
20
+ S.Array(
21
+ S.Struct({
22
+ route: S.String,
23
+ error: S.String,
24
+ }),
25
+ ),
26
+ ),
19
27
  })
20
28
 
21
29
  export type GenerateResult = S.Schema.Type<typeof GenerateResultSchema>
@@ -40,7 +48,9 @@ export class StopServerMessage extends S.TaggedRequest<StopServerMessage>()(
40
48
  'StopServer',
41
49
  {
42
50
  failure: S.Never,
43
- payload: {},
51
+ payload: {
52
+ port: S.optional(S.Number),
53
+ },
44
54
  success: S.Void,
45
55
  },
46
56
  ) {}
@@ -14,6 +14,7 @@ import { Link } from './Link.js'
14
14
  export const ReferenceLink = forwardRef<
15
15
  HTMLAnchorElement,
16
16
  {
17
+ className?: string
17
18
  /** The GraphQL type name */
18
19
  type: string
19
20
  /** Optional field name for field-specific links */
@@ -14,15 +14,27 @@ export const TypeLink: React.FC<{
14
14
  const hasDescription = type.description && type.description.trim() !== ''
15
15
 
16
16
  const linkContent = (
17
- // <a href='https://foo.bar'>
18
- <ReferenceLink type={type.name}>
19
- <Flex align='center' gap='1' display='inline-flex'>
20
- <TypeKindIcon kind={kind} />
21
- {` `}
22
- <Code color={typeKindTokensIndex[kind].color} variant='ghost'>{type.name}</Code>
23
- </Flex>
24
- </ReferenceLink>
25
- // {/*</a>*/}
17
+ <>
18
+ <style>
19
+ {`
20
+ .type-link-content:hover code:not(:first-child) {
21
+ text-decoration: underline;
22
+ text-underline-offset: 2px;
23
+ }
24
+ `}
25
+ </style>
26
+ <ReferenceLink type={type.name} className='type-link-content'>
27
+ <Flex
28
+ align='center'
29
+ gap='1'
30
+ display='inline-flex'
31
+ >
32
+ <TypeKindIcon kind={kind} />
33
+ {` `}
34
+ <Code color={typeKindTokensIndex[kind].color} variant='ghost'>{type.name}</Code>
35
+ </Flex>
36
+ </ReferenceLink>
37
+ </>
26
38
  )
27
39
 
28
40
  // Only show HoverCard if showDescription is true AND description exists
@@ -3,6 +3,7 @@ import { Vite } from '#dep/vite/index'
3
3
  import { Catalog } from '#lib/catalog/$'
4
4
  import { FileRouter } from '#lib/file-router/$'
5
5
  import { SchemaDefinition } from '#lib/schema-definition/$'
6
+ import { Version } from '#lib/version/$'
6
7
  import { debugPolen } from '#singletons/debug'
7
8
  import * as NodeFileSystem from '@effect/platform-node/NodeFileSystem'
8
9
  import consola from 'consola'
@@ -102,12 +103,14 @@ function processVersionedCatalog(
102
103
  ): void {
103
104
  for (const schema of Catalog.Versioned.getAll(catalog)) {
104
105
  const version = schema.version
105
- routes.push(`/reference/version/${version}`)
106
+ // Properly encode the version to its string representation
107
+ const versionValue = Version.encodeSync(version)
108
+ routes.push(`/reference/version/${versionValue}`)
106
109
 
107
110
  processSchemaDefinition(
108
111
  schema.definition,
109
112
  routes,
110
- `/reference/version/${version}`,
113
+ `/reference/version/${versionValue}`,
111
114
  )
112
115
  }
113
116
  }
@@ -1,2 +0,0 @@
1
- export * as ExtensibleData from './extensible-data.js';
2
- //# sourceMappingURL=$.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"$.d.ts","sourceRoot":"","sources":["../../../src/lib/extensible-data/$.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAA"}
@@ -1,2 +0,0 @@
1
- export * as ExtensibleData from './extensible-data.js';
2
- //# sourceMappingURL=$.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"$.js","sourceRoot":"","sources":["../../../src/lib/extensible-data/$.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAA"}
@@ -1,17 +0,0 @@
1
- import type { ComputedRef } from '@vue/reactivity';
2
- type Join<$Data> = (chunks: $Data[]) => $Data;
3
- type Create<$Data> = () => $Data;
4
- interface DataTypeOperations<$Data> {
5
- join: Join<$Data>;
6
- create: Create<$Data>;
7
- }
8
- export declare const create: <$Data extends object = object>(dataTypeOperations: DataTypeOperations<$Data>) => ExtensibleData<$Data>;
9
- export declare class ExtensibleData<$Data extends object = object> {
10
- value: ComputedRef<$Data>;
11
- private namespacedReactiveData;
12
- private dataTypeOperations;
13
- constructor(dataTypeOperations: DataTypeOperations<$Data>);
14
- get(namespace: string): $Data;
15
- }
16
- export {};
17
- //# sourceMappingURL=extensible-data.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extensible-data.d.ts","sourceRoot":"","sources":["../../../src/lib/extensible-data/extensible-data.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAmB,MAAM,iBAAiB,CAAA;AAEnE,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,CAAA;AAC7C,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,KAAK,CAAA;AAEhC,UAAU,kBAAkB,CAAC,KAAK;IAChC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;CACtB;AAED,eAAO,MAAM,MAAM,GAAI,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,oBAAoB,kBAAkB,CAAC,KAAK,CAAC,0BAElG,CAAA;AAED,qBAAa,cAAc,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM;IAChD,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,CAI9B;IAEF,OAAO,CAAC,sBAAsB,CAAqC;IAEnE,OAAO,CAAC,kBAAkB,CAA2B;gBAEzC,kBAAkB,EAAE,kBAAkB,CAAC,KAAK,CAAC;IAIzD,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK;CAO9B"}
@@ -1,24 +0,0 @@
1
- import { computed, reactive } from '@vue/reactivity';
2
- export const create = (dataTypeOperations) => {
3
- return new ExtensibleData(dataTypeOperations);
4
- };
5
- export class ExtensibleData {
6
- value = computed(() => {
7
- const namespacedDataItems = Array.from(this.namespacedReactiveData.values());
8
- const data = this.dataTypeOperations.join(namespacedDataItems);
9
- return data;
10
- });
11
- namespacedReactiveData = reactive(new Map());
12
- dataTypeOperations;
13
- constructor(dataTypeOperations) {
14
- this.dataTypeOperations = dataTypeOperations;
15
- }
16
- get(namespace) {
17
- if (!this.namespacedReactiveData.has(namespace)) {
18
- const data = this.dataTypeOperations.create();
19
- this.namespacedReactiveData.set(namespace, data);
20
- }
21
- return this.namespacedReactiveData.get(namespace);
22
- }
23
- }
24
- //# sourceMappingURL=extensible-data.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extensible-data.js","sourceRoot":"","sources":["../../../src/lib/extensible-data/extensible-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAWpD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAgC,kBAA6C,EAAE,EAAE;IACrG,OAAO,IAAI,cAAc,CAAQ,kBAAkB,CAAC,CAAA;AACtD,CAAC,CAAA;AAED,MAAM,OAAO,cAAc;IAClB,KAAK,GAAuB,QAAQ,CAAC,GAAG,EAAE;QAC/C,MAAM,mBAAmB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAA;QAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,mBAA8B,CAAC,CAAA;QACzE,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;IAEM,sBAAsB,GAAG,QAAQ,CAAC,IAAI,GAAG,EAAiB,CAAC,CAAA;IAE3D,kBAAkB,CAA2B;IAErD,YAAY,kBAA6C;QACvD,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAA;IAC9C,CAAC;IAED,GAAG,CAAC,SAAiB;QACnB,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAA;YAC7C,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,EAAE,IAA8B,CAAC,CAAA;QAC5E,CAAC;QACD,OAAO,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,SAAS,CAAW,CAAA;IAC7D,CAAC;CACF"}
@@ -1,2 +0,0 @@
1
- export * as VitePluginReactiveData from './vite-plugin-reactive-data.js';
2
- //# sourceMappingURL=$.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"$.d.ts","sourceRoot":"","sources":["../../../src/lib/vite-plugin-reactive-data/$.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,sBAAsB,MAAM,gCAAgC,CAAA"}
@@ -1,2 +0,0 @@
1
- export * as VitePluginReactiveData from './vite-plugin-reactive-data.js';
2
- //# sourceMappingURL=$.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"$.js","sourceRoot":"","sources":["../../../src/lib/vite-plugin-reactive-data/$.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,sBAAsB,MAAM,gCAAgC,CAAA"}
@@ -1,32 +0,0 @@
1
- import type { VitePluginJson } from '#lib/vite-plugin-json';
2
- import { type ComputedRef } from '@vue/reactivity';
3
- import type { Plugin } from 'vite';
4
- interface ReactiveDataOptions {
5
- /**
6
- * Virtual module ID (e.g., 'virtual:polen/navbar') that this data will be exported from.
7
- * The appropriate extension will be appended automatically based on moduleType.
8
- */
9
- moduleId: string;
10
- /**
11
- * The reactive data to expose.
12
- * Can be either:
13
- * - A Vue computed ref (recommended)
14
- * - A function that returns reactive data
15
- * - A reactive value directly
16
- */
17
- data: ComputedRef<object | unknown[]> | (() => object | unknown[]) | object | unknown[];
18
- /**
19
- * JSON codec to use
20
- * Default: JSON
21
- * Only used when includeJsonPlugin is true
22
- */
23
- codec?: VitePluginJson.Codec;
24
- /**
25
- * Custom plugin name. Can use to help identify this plugin in logs if using many instances of this plugin.
26
- @default 'reactive-data'
27
- */
28
- name?: string;
29
- }
30
- export declare const create: (options: ReactiveDataOptions) => Plugin;
31
- export {};
32
- //# sourceMappingURL=vite-plugin-reactive-data.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite-plugin-reactive-data.d.ts","sourceRoot":"","sources":["../../../src/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAE3D,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,iBAAiB,CAAA;AACjE,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAA;AAEjD,UAAU,mBAAmB;IAC3B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;OAMG;IACH,IAAI,EAAE,WAAW,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,GAAG,MAAM,GAAG,OAAO,EAAE,CAAA;IACvF;;;;OAIG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC,KAAK,CAAA;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAID,eAAO,MAAM,MAAM,GAAI,SAAS,mBAAmB,KAAG,MAyFrD,CAAA"}
@@ -1,85 +0,0 @@
1
- import { debugPolen } from '#singletons/debug';
2
- import { effect, isRef } from '@vue/reactivity';
3
- const pluginDebug = debugPolen.sub(`vite-reactive-data`);
4
- export const create = (options) => {
5
- const codec = options.codec ?? JSON;
6
- const moduleId = options.moduleId;
7
- const name = options.name ?? `reactive-data`;
8
- const debug = pluginDebug.sub(name);
9
- debug(`constructor`, { moduleId });
10
- let $server;
11
- let $invalidationScheduled = false;
12
- const tryInvalidate = () => {
13
- $invalidationScheduled = false;
14
- if (!$server)
15
- throw new Error(`Server not available yet - this should be impossible`);
16
- const moduleNode = $server.moduleGraph.getModuleById(moduleId);
17
- if (moduleNode) {
18
- debug(`invalidate`, { id: moduleNode.id });
19
- $server.moduleGraph.invalidateModule(moduleNode);
20
- }
21
- else {
22
- debug(`cannot invalidate`, {
23
- reason: `notInModuleGraph`,
24
- moduleId,
25
- hint: `maybe it was not loaded yet`,
26
- });
27
- }
28
- };
29
- const scheduleInvalidate = () => {
30
- if ($invalidationScheduled)
31
- return; // already scheduled
32
- $invalidationScheduled = true;
33
- if (!$server)
34
- return; // server will flush when ready
35
- tryInvalidate();
36
- };
37
- // Helper to get the current data value
38
- const getData = () => {
39
- if (isRef(options.data)) {
40
- return options.data.value;
41
- }
42
- else if (typeof options.data === `function`) {
43
- return options.data();
44
- }
45
- else {
46
- return options.data;
47
- }
48
- };
49
- // Set up reactive effect immediately
50
- effect(() => {
51
- // Access data to track dependencies
52
- const data = getData();
53
- debug(`effect triggered`, { data });
54
- scheduleInvalidate();
55
- });
56
- return {
57
- name,
58
- configureServer(_server) {
59
- debug(`hook configureServer`);
60
- $server = _server;
61
- if ($invalidationScheduled) {
62
- debug(`try invalidate scheduled before server was ready`);
63
- tryInvalidate();
64
- }
65
- },
66
- resolveId(id) {
67
- if (id === moduleId) {
68
- return moduleId;
69
- }
70
- },
71
- // todo make use of Vite's builtin json plugin
72
- // for example, call it here somehow
73
- load(id) {
74
- if (id !== moduleId)
75
- return;
76
- const data = getData();
77
- debug(`hook load`, { data });
78
- return {
79
- code: codec.stringify(data),
80
- map: null,
81
- };
82
- },
83
- };
84
- };
85
- //# sourceMappingURL=vite-plugin-reactive-data.js.map