eprec 1.1.0 → 1.2.0

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.
@@ -27,11 +27,9 @@ export function Layout({
27
27
  </head>
28
28
  <body>
29
29
  <div id="root">${children ?? ''}</div>
30
- ${
31
- entryScript
32
- ? html`<script type="module" src="${entryScript}"></script>`
33
- : ''
34
- }
30
+ ${entryScript
31
+ ? html`<script type="module" src="${entryScript}"></script>`
32
+ : ''}
35
33
  </body>
36
34
  </html>`
37
35
  }
package/app/router.tsx CHANGED
@@ -76,6 +76,7 @@ const cacheControl =
76
76
  export function createAppRouter(rootDir: string) {
77
77
  const router = createRouter({
78
78
  middleware: [
79
+ bunStaticFiles(path.join(rootDir, 'fixtures'), { cacheControl }),
79
80
  bunStaticFiles(path.join(rootDir, 'public'), { cacheControl }),
80
81
  bunStaticFiles(path.join(rootDir, 'app'), {
81
82
  filter: (pathname) => pathname.startsWith('assets/'),
@@ -88,15 +89,18 @@ export function createAppRouter(rootDir: string) {
88
89
  title: 'Not Found',
89
90
  entryScript: false,
90
91
  children: html`<main class="app-shell">
91
- <h1 class="app-title">404 - Not Found</h1>
92
- </main>`,
92
+ <h1 class="app-title">404 - Not Found</h1>
93
+ </main>`,
93
94
  }),
94
95
  { status: 404 },
95
96
  )
96
97
  },
97
98
  })
98
99
 
99
- router.map(routes.index, indexHandlers)
100
+ router.map(routes.index, {
101
+ middleware: indexHandlers.middleware,
102
+ action: indexHandlers.loader,
103
+ })
100
104
 
101
105
  return router
102
106
  }
@@ -13,34 +13,37 @@ const indexHandler = {
13
13
  <span class="app-kicker">Eprec Studio</span>
14
14
  <h1 class="app-title">Editing workspace</h1>
15
15
  <p class="app-subtitle">
16
- Prepare edits with the CLI, then review them here.
16
+ Review transcript-based edits, refine cut ranges, and prepare
17
+ exports.
17
18
  </p>
18
19
  </header>
19
- <div class="app-grid">
20
- <section class="app-card">
21
- <h2>Workflow</h2>
22
- <ol class="app-list">
23
- <li>Run a CLI edit command.</li>
24
- <li>Open the workspace UI.</li>
25
- <li>Review and refine the cut list.</li>
26
- </ol>
27
- </section>
20
+ <section class="app-card app-card--full">
21
+ <h2>Timeline editor</h2>
22
+ <p class="app-muted">
23
+ Loading preview video, timeline controls, and cut ranges.
24
+ </p>
25
+ <div class="timeline-track timeline-track--skeleton"></div>
26
+ </section>
27
+ <div class="app-grid app-grid--two">
28
28
  <section class="app-card">
29
- <h2>UI status</h2>
30
- <p class="status-pill">UI booted</p>
29
+ <h2>Chapter plan</h2>
31
30
  <p class="app-muted">
32
- Client-side components load after the first paint.
31
+ Output names and skip flags appear after the client boots.
33
32
  </p>
34
33
  </section>
35
34
  <section class="app-card">
36
- <h2>Interaction check</h2>
37
- <p class="app-muted">Client bundle loads after this page.</p>
38
- <button class="counter-button" type="button" disabled>
39
- <span>Click count</span>
40
- <span class="counter-value">0</span>
41
- </button>
35
+ <h2>Command windows</h2>
36
+ <p class="app-muted">
37
+ Jarvis command detection will populate this panel.
38
+ </p>
42
39
  </section>
43
40
  </div>
41
+ <section class="app-card app-card--full">
42
+ <h2>Transcript search</h2>
43
+ <p class="app-muted">
44
+ Search and jump controls will load in the interactive UI.
45
+ </p>
46
+ </section>
44
47
  </main>`,
45
48
  }),
46
49
  )
package/app-server.ts CHANGED
@@ -34,7 +34,9 @@ async function getServerPort(nodeEnv: string, desiredPort: number) {
34
34
  }
35
35
  const port = await getPort({ port: desiredPort })
36
36
  if (port !== desiredPort) {
37
- console.warn(`⚠️ Port ${desiredPort} was taken, using port ${port} instead`)
37
+ console.warn(
38
+ `⚠️ Port ${desiredPort} was taken, using port ${port} instead`,
39
+ )
38
40
  }
39
41
  return port
40
42
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "eprec",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "1.2.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -12,7 +12,8 @@
12
12
  "format": "prettier --write .",
13
13
  "test": "bun test process-course utils.test.ts",
14
14
  "test:e2e": "bun test e2e",
15
- "test:all": "bun test",
15
+ "test:smoke": "bunx playwright test -c playwright-smoke-config.ts",
16
+ "test:all": "bun test '**/*.test.ts'",
16
17
  "validate": "bun run test"
17
18
  },
18
19
  "bin": {
@@ -33,6 +34,7 @@
33
34
  "prettier": "@epic-web/config/prettier",
34
35
  "devDependencies": {
35
36
  "@epic-web/config": "^1.21.3",
37
+ "@playwright/test": "^1.58.0",
36
38
  "@types/bun": "latest",
37
39
  "@types/yargs": "^17.0.35",
38
40
  "prettier": "^3.8.1"
@@ -31,9 +31,7 @@ async function resolvePackageExport(
31
31
 
32
32
  if (!(await packageJsonFile.exists())) return null
33
33
 
34
- const packageJson = JSON.parse(
35
- await packageJsonFile.text(),
36
- ) as PackageJson
34
+ const packageJson = JSON.parse(await packageJsonFile.text()) as PackageJson
37
35
 
38
36
  if (!packageJson.exports) {
39
37
  const entryFile = packageJson.module || packageJson.main
@@ -49,9 +47,7 @@ async function resolvePackageExport(
49
47
  if (!exportEntry) return null
50
48
 
51
49
  const exportPath =
52
- typeof exportEntry === 'string'
53
- ? exportEntry
54
- : exportEntry.default
50
+ typeof exportEntry === 'string' ? exportEntry : exportEntry.default
55
51
 
56
52
  if (!exportPath) return null
57
53
 
@@ -106,40 +102,40 @@ export function createBundlingRoutes(rootDir: string) {
106
102
  })
107
103
  }
108
104
 
109
- const buildResult = await Bun.build({
110
- entrypoints: [resolved],
111
- target: 'browser',
112
- minify: Bun.env.NODE_ENV === 'production',
113
- splitting: false,
114
- format: 'esm',
115
- sourcemap: Bun.env.NODE_ENV === 'production' ? 'none' : 'inline',
116
- jsx: { importSource: 'remix/component' },
117
- })
118
-
119
- if (!buildResult.success) {
120
- const errorMessage = buildResult.logs
121
- .map((log) => log.message)
122
- .join('\n')
123
- return new Response(errorMessage || 'Build failed', {
124
- status: 500,
105
+ const buildResult = await Bun.build({
106
+ entrypoints: [resolved],
107
+ target: 'browser',
108
+ minify: Bun.env.NODE_ENV === 'production',
109
+ splitting: false,
110
+ format: 'esm',
111
+ sourcemap: Bun.env.NODE_ENV === 'production' ? 'none' : 'inline',
112
+ jsx: { importSource: 'remix/component' },
113
+ })
114
+
115
+ if (!buildResult.success) {
116
+ const errorMessage = buildResult.logs
117
+ .map((log) => log.message)
118
+ .join('\n')
119
+ return new Response(errorMessage || 'Build failed', {
120
+ status: 500,
121
+ headers: {
122
+ 'Content-Type': 'text/plain',
123
+ ...BUNDLING_CORS_HEADERS,
124
+ },
125
+ })
126
+ }
127
+
128
+ const output = buildResult.outputs[0]
129
+ return new Response(output, {
125
130
  headers: {
126
- 'Content-Type': 'text/plain',
131
+ 'Content-Type': 'application/javascript',
132
+ 'Cache-Control':
133
+ Bun.env.NODE_ENV === 'production'
134
+ ? 'public, max-age=31536000, immutable'
135
+ : 'no-cache',
127
136
  ...BUNDLING_CORS_HEADERS,
128
137
  },
129
138
  })
130
- }
131
-
132
- const output = buildResult.outputs[0]
133
- return new Response(output, {
134
- headers: {
135
- 'Content-Type': 'application/javascript',
136
- 'Cache-Control':
137
- Bun.env.NODE_ENV === 'production'
138
- ? 'public, max-age=31536000, immutable'
139
- : 'no-cache',
140
- ...BUNDLING_CORS_HEADERS,
141
- },
142
- })
143
139
  },
144
140
 
145
141
  '/node_modules/*': async (request: Request) => {
@@ -172,39 +168,39 @@ export function createBundlingRoutes(rootDir: string) {
172
168
  })
173
169
  }
174
170
 
175
- const buildResult = await Bun.build({
176
- entrypoints: [filepath],
177
- target: 'browser',
178
- minify: Bun.env.NODE_ENV === 'production',
179
- splitting: false,
180
- format: 'esm',
181
- sourcemap: Bun.env.NODE_ENV === 'production' ? 'none' : 'inline',
182
- })
183
-
184
- if (!buildResult.success) {
185
- const errorMessage = buildResult.logs
186
- .map((log) => log.message)
187
- .join('\n')
188
- return new Response(errorMessage || 'Build failed', {
189
- status: 500,
171
+ const buildResult = await Bun.build({
172
+ entrypoints: [filepath],
173
+ target: 'browser',
174
+ minify: Bun.env.NODE_ENV === 'production',
175
+ splitting: false,
176
+ format: 'esm',
177
+ sourcemap: Bun.env.NODE_ENV === 'production' ? 'none' : 'inline',
178
+ })
179
+
180
+ if (!buildResult.success) {
181
+ const errorMessage = buildResult.logs
182
+ .map((log) => log.message)
183
+ .join('\n')
184
+ return new Response(errorMessage || 'Build failed', {
185
+ status: 500,
186
+ headers: {
187
+ 'Content-Type': 'text/plain',
188
+ ...BUNDLING_CORS_HEADERS,
189
+ },
190
+ })
191
+ }
192
+
193
+ const output = buildResult.outputs[0]
194
+ return new Response(output, {
190
195
  headers: {
191
- 'Content-Type': 'text/plain',
196
+ 'Content-Type': 'application/javascript',
197
+ 'Cache-Control':
198
+ Bun.env.NODE_ENV === 'production'
199
+ ? 'public, max-age=31536000, immutable'
200
+ : 'no-cache',
192
201
  ...BUNDLING_CORS_HEADERS,
193
202
  },
194
203
  })
195
- }
196
-
197
- const output = buildResult.outputs[0]
198
- return new Response(output, {
199
- headers: {
200
- 'Content-Type': 'application/javascript',
201
- 'Cache-Control':
202
- Bun.env.NODE_ENV === 'production'
203
- ? 'public, max-age=31536000, immutable'
204
- : 'no-cache',
205
- ...BUNDLING_CORS_HEADERS,
206
- },
207
- })
208
204
  },
209
205
  }
210
206
  }