ReviewOS

also looking at this

craft-native/craft

chore(deps): refresh Vue patch and verify packed SSR

#312
Merged glennmichael123 wants to merge codex/vue-patch-consumers into main
4 files +75 -2
bun.lockmodified+0-0

Binary file. Nothing to show line by line.

package.jsonmodified+1-1
Changes to package.json
@@ -31,7 +31,7 @@
3131 "verify": "bun scripts/verify.ts",
3232 "verify:packages": "bun scripts/verify-packages.ts",
3333 "verify:npm": "bun scripts/npm-packages.ts",
34 "test:packages": "bun test scripts/npm-packages.test.ts scripts/mobile-package.test.ts scripts/svelte-package.test.ts scripts/scaffold-package.test.ts",
34 "test:packages": "bun test scripts/npm-packages.test.ts scripts/mobile-package.test.ts scripts/svelte-package.test.ts scripts/vue-package.test.ts scripts/scaffold-package.test.ts",
3535 "verify:create": "bun scripts/verify-create-craft.ts",
3636 "verify:cimports": "bun scripts/audit-cimports.ts",
3737 "verify:docs": "bun scripts/verify-doc-links.ts",
packages/vue/package.jsonmodified+1-1
Changes to packages/vue/package.json
@@ -42,7 +42,7 @@
4242 "vue": "^3.0.0"
4343 },
4444 "devDependencies": {
45 "vue": "^3.3.0",
45 "vue": "^3.5.43",
4646 "tsup": "^8.0.0",
4747 "typescript": "^7.0.2"
4848 }
scripts/vue-package.test.tsadded+73-0
Changes to scripts/vue-package.test.ts
@@ -0,0 +1,73 @@
1import { expect, test } from 'bun:test'
2import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
3import { createRequire } from 'node:module'
4import { tmpdir } from 'node:os'
5import { dirname, join, resolve } from 'node:path'
6
7test('packed Vue composables render on the server and expose usable types', () => {
8 const root = resolve(import.meta.dir, '..')
9 const packageDir = join(root, 'packages/vue')
10 const temp = mkdtempSync(join(tmpdir(), 'craft-vue-package-'))
11 const run = (args: string[], cwd = temp): void => {
12 const result = Bun.spawnSync(args, { cwd, stdout: 'pipe', stderr: 'pipe', timeout: 30_000 })
13 expect(`${result.stdout}\n${result.stderr}`).not.toContain('error TS')
14 expect(result.exitCode).toBe(0)
15 }
16 try {
17 run([process.execPath, 'run', 'build'], packageDir)
18 run([process.execPath, 'pm', 'pack', '--filename', join(temp, 'package.tgz')], packageDir)
19 const installed = join(temp, 'node_modules/@craft-native/vue')
20 mkdirSync(installed, { recursive: true })
21 run(['tar', '-xzf', join(temp, 'package.tgz'), '--strip-components=1', '-C', installed])
22 // Supply the actual installed peer, not a mock or a workspace Craft import.
23 const require = createRequire(join(packageDir, 'package.json'))
24 symlinkSync(dirname(require.resolve('vue/package.json')), join(temp, 'node_modules/vue'), 'junction')
25 writeFileSync(join(temp, 'consumer.mjs'), `
26import { strict as assert } from 'node:assert'
27import { createSSRApp, h } from 'vue'
28import { renderToString } from 'vue/server-renderer'
29import { useCraft, usePlatform } from '@craft-native/vue'
30assert.equal(typeof window, 'undefined')
31globalThis.setInterval = () => { throw new Error('SSR must not start bridge polling') }
32async function render(override) {
33 return renderToString(createSSRApp({
34 setup() {
35 const { craft, isReady } = useCraft()
36 const { platform, loading, error } = usePlatform()
37 assert.equal(craft.value, null)
38 assert.equal(isReady.value, false)
39 assert.equal(platform.value, null)
40 assert.equal(loading.value, true)
41 assert.equal(error.value, null)
42 if (override) isReady.value = true
43 return () => h('p', { 'data-ready': String(isReady.value) }, '<script>untrusted</script>')
44 }
45 }))
46}
47const first = await render(true)
48const second = await render(false)
49assert.ok(first.includes('data-ready="true"'))
50assert.ok(second.includes('data-ready="false"'))
51assert.ok(second.includes('&lt;script&gt;untrusted&lt;/script&gt;'))
52assert.ok(!second.includes('<script>'))
53`)
54 run([process.execPath, 'consumer.mjs'])
55 writeFileSync(join(temp, 'consumer.mts'), `
56import type { Ref } from 'vue'
57import { useCraft, usePlatform } from '@craft-native/vue'
58const ready: Ref<boolean> = useCraft().isReady
59const platform: Ref<{ platform: string; version: string } | null> = usePlatform().platform
60// @ts-expect-error readiness is boolean, not text
61const wrong: Ref<string> = useCraft().isReady
62void [ready, platform, wrong]
63`)
64 run([
65 process.execPath, join(root, 'packages/typescript/scripts/tsc.ts'),
66 'consumer.mts', '--noEmit', '--strict', '--module', 'nodenext',
67 '--moduleResolution', 'nodenext', '--target', 'esnext', '--ignoreConfig',
68 ])
69 }
70 finally {
71 rmSync(temp, { recursive: true, force: true })
72 }
73}, 60_000)