diff --git a/examples/default-provider/package-lock.json b/examples/default-provider/package-lock.json index 26be3bf..13de5fc 100644 --- a/examples/default-provider/package-lock.json +++ b/examples/default-provider/package-lock.json @@ -25,7 +25,7 @@ } }, "../..": { - "version": "1.2.0", + "version": "1.3.2", "license": "MIT", "dependencies": { "@aws-sdk/client-s3": "^3.540.0", @@ -33,7 +33,7 @@ "@mux/mux-node": "8.8.0", "@mux/mux-player-react": "2.9.0", "@mux/mux-video-react": "0.11.2", - "@next/env": "^14.2.12", + "@next/env": "^15.0.2", "@paralleldrive/cuid2": "^2.2.2", "@vercel/blob": "^0.23.3", "chalk": "^4.1.2", @@ -54,17 +54,17 @@ "c8": "^9.1.0", "esbuild": "^0.21.5", "glob": "^10.4.2", - "next": "^14.2.12", + "next": "^15.0.2", "react": "^18.3.1", "react-test-renderer": "^18.3.1", "tsx": "3.13.0", "typescript": "^5.5.2" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18", + "@types/react": "^17.0.0 || ^17.0.0-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0", "next": ">=12.0.0", - "react": "^17.0.2 || ^18", - "react-dom": "^17.0.2 || ^18" + "react": "^17.0.2 || ^17.0.0-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0", + "react-dom": "^17.0.2 || ^17.0.2-0 || ^18 || ^18.0.0-0 || ^19 || ^19.0.0-0" }, "peerDependenciesMeta": { "@types/react": { diff --git a/package-lock.json b/package-lock.json index e5f049a..5b15a9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "chalk": "^4.1.2", "chokidar": "^3.6.0", "magicast": "^0.3.4", + "resolve": "^1.22.8", "symlink-dir": "^5.2.1", "undici": "^5.28.4", "yargs": "^17.7.2" @@ -31,6 +32,7 @@ "@types/dotenv-flow": "^3.3.3", "@types/node": "^20.14.9", "@types/react": "18.3.3", + "@types/resolve": "^1.20.6", "@types/yargs": "^17.0.32", "c8": "^9.1.0", "esbuild": "^0.21.5", @@ -2992,6 +2994,13 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/wrap-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", @@ -3873,9 +3882,10 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3945,6 +3955,21 @@ "node": ">=8" } }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "license": "MIT", @@ -4401,6 +4426,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", @@ -4583,6 +4614,23 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -4914,6 +4962,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/symlink-dir": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/symlink-dir/-/symlink-dir-5.2.1.tgz", diff --git a/package.json b/package.json index 6056d64..39582a4 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "@types/dotenv-flow": "^3.3.3", "@types/node": "^20.14.9", "@types/react": "18.3.3", + "@types/resolve": "^1.20.6", "@types/yargs": "^17.0.32", "c8": "^9.1.0", "esbuild": "^0.21.5", @@ -99,6 +100,7 @@ "chalk": "^4.1.2", "chokidar": "^3.6.0", "magicast": "^0.3.4", + "resolve": "^1.22.8", "symlink-dir": "^5.2.1", "undici": "^5.28.4", "yargs": "^17.7.2" diff --git a/src/cli/lib/json-configs.ts b/src/cli/lib/json-configs.ts index eb3a39c..982933d 100644 --- a/src/cli/lib/json-configs.ts +++ b/src/cli/lib/json-configs.ts @@ -1,6 +1,4 @@ import { readFile } from 'node:fs/promises'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import { PACKAGE_NAME } from '../../constants.js'; @@ -44,11 +42,3 @@ export async function checkPackageJsonForNextVideo(packagePath: string = './pack return !!(json.devDependencies?.[PACKAGE_NAME] || json.dependencies?.[PACKAGE_NAME]); } - -export async function getNextVideoVersion() { - const scriptDir = path.dirname(fileURLToPath(import.meta.url)); - const scriptRoot = path.join(scriptDir, '..', '..', '..'); - const packagePath = path.join(scriptRoot, 'package.json'); - const pkg = JSON.parse(await readFile(packagePath, 'utf-8')); - return pkg.version; -} diff --git a/src/cli/sync.ts b/src/cli/sync.ts index 4d2ba3c..2870845 100644 --- a/src/cli/sync.ts +++ b/src/cli/sync.ts @@ -6,11 +6,11 @@ import { cwd } from 'node:process'; import { readdir } from 'node:fs/promises'; import path from 'node:path'; -import log from '../utils/logger.js'; import { callHandler } from '../process.js'; import { createAsset, getAsset } from '../assets.js'; import { getVideoConfig } from '../config.js'; -import { getNextVideoVersion } from './lib/json-configs.js'; +import { getPackageVersion } from '../utils/utils.js'; +import log from '../utils/logger.js'; export const command = 'sync'; export const desc = @@ -56,7 +56,7 @@ function watcher(dir: string) { export async function handler(argv: Arguments) { const directoryPath = path.join(cwd(), argv.dir as string); - const version = await getNextVideoVersion(); + const version = getPackageVersion('next-video'); log.space(log.label(`▶︎ next-video ${version}`)); log.space(); diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 9046a0a..ad86b3d 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -25,7 +25,7 @@ export function add(...messages: any[]) { } export function warning(...messages: any[]) { - base('log', chalk.yellow.bold('!'), ...messages); + base('log', chalk.yellow.bold('⚠'), ...messages); } export function error(...messages: any[]) { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index d9bfbec..a25d2cb 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,3 +1,32 @@ +import fs from 'node:fs'; +import resolve from 'resolve'; + +export function getPackageVersion(packageName: string) { + const packageJsonPath = resolvePackageJson(packageName); + if (packageJsonPath) { + try { + const packageJson: { version: string } = JSON.parse( + fs.readFileSync(packageJsonPath, { encoding: 'utf-8' }), + ); + return packageJson.version; + } catch { + // noop + } + } + return undefined; +} + +function resolvePackageJson(packageName: string) { + try { + return resolve.sync(`${packageName}/package.json`, { + basedir: process.cwd(), + preserveSymlinks: true, + }); + } catch { + return undefined; + } +} + export function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/src/with-next-video.ts b/src/with-next-video.ts index c641388..e1f9e73 100644 --- a/src/with-next-video.ts +++ b/src/with-next-video.ts @@ -1,11 +1,15 @@ import symlinkDir from 'symlink-dir'; import { join, dirname } from 'node:path'; -import fs from 'node:fs/promises'; +import fs from 'node:fs'; import { env } from 'node:process'; import { fileURLToPath } from 'node:url'; +import logger from './utils/logger.js'; +import { getPackageVersion } from './utils/utils.js'; import { setVideoConfig } from './config.js'; import type { VideoConfig } from './config.js'; +let hasWarned = false; + export function withNextVideo(nextConfig: any, videoConfig?: VideoConfig) { const videoConfigComplete = setVideoConfig(videoConfig); const { path, folder, provider } = videoConfigComplete; @@ -36,19 +40,43 @@ export function withNextVideo(nextConfig: any, videoConfig?: VideoConfig) { symlinkDir(VIDEOS_PATH, TMP_PUBLIC_VIDEOS_PATH); process.on('exit', async () => { - await fs.unlink(TMP_PUBLIC_VIDEOS_PATH); + fs.unlinkSync(TMP_PUBLIC_VIDEOS_PATH); }); } - const experimental = { ...nextConfig.experimental }; + const nextVersion = getPackageVersion('next'); + + if (nextVersion && nextVersion.startsWith('15.')) { + nextConfig.outputFileTracingIncludes = { + ...nextConfig.outputFileTracingIncludes, + [path]: [`./${folder}/**/*.json`], + }; + } else { + const experimental = { ...nextConfig.experimental }; + experimental.outputFileTracingIncludes = { + ...experimental.outputFileTracingIncludes, + [path]: [`./${folder}/**/*.json`], + }; + nextConfig.experimental = experimental; + } + + if (!hasWarned && process.env.TURBOPACK && !process.env.NEXT_VIDEO_SUPPRESS_TURBOPACK_WARNING) { + hasWarned = true; - experimental.outputFileTracingIncludes = { - ...experimental.outputFileTracingIncludes, - [path]: [`./${folder}/**/*.json`], - }; + const nextVideoVersion = getPackageVersion('next-video'); + + logger.space(logger.label(`▶︎ next-video ${nextVideoVersion}\n`)); + logger.warning( + `You are using next-video with \`next ${ + process.env.NODE_ENV === 'development' ? 'dev' : 'build' + } --turbo\`. next-video doesn't yet fully support Turbopack.\n We recommend temporarily removing the \`--turbo\` flag for use with next-video.\n` + ); + logger.warning( + `Follow this issue for progress on next-video + Turbopack: https://github.com/muxinc/next-video/issues/266.\n (You can suppress this warning by setting NEXT_VIDEO_SUPPRESS_TURBOPACK_WARNING=1 as environment variable)\n` + ); + } return Object.assign({}, nextConfig, { - experimental, webpack(config: any, options: any) { if (!options.defaultLoaders) { throw new Error(