Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion packages/create-video/src/pkg-managers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from 'node:path';
import {Log} from './log';
import type {Template} from './templates';

export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'nub';

const shouldUseBun = (): boolean => {
if (
Expand Down Expand Up @@ -41,6 +41,10 @@ const shouldUsePnpm = (): boolean => {
};

export const selectPackageManager = (): PackageManager => {
if (process.env.npm_config_user_agent?.includes('nub/')) {
return 'nub';
}

if (shouldUseYarn()) {
return 'yarn';
}
Expand Down Expand Up @@ -72,6 +76,10 @@ export const getInstallCommand = (manager: PackageManager) => {
if (manager === 'bun') {
return `bun install`;
}

if (manager === 'nub') {
return `nub install`;
}
};

const getStartCommand = (manager: PackageManager) => {
Expand All @@ -90,6 +98,10 @@ const getStartCommand = (manager: PackageManager) => {
if (manager === 'bun') {
return `bun run dev`;
}

if (manager === 'nub') {
return `nub run dev`;
}
};

export const getRunCommand = (manager: PackageManager) => {
Expand All @@ -109,6 +121,10 @@ export const getRunCommand = (manager: PackageManager) => {
return `bun run`;
}

if (manager === 'nub') {
return `nub run`;
}

throw new TypeError('unknown package manager');
};

Expand All @@ -129,6 +145,10 @@ export const getRenderCommand = (manager: PackageManager) => {
return `bunx remotion render`;
}

if (manager === 'nub') {
return `nubx remotion render`;
}

throw new TypeError('unknown package manager');
};

Expand All @@ -149,6 +169,10 @@ export const getUpgradeCommand = (manager: PackageManager) => {
return `bunx remotion upgrade`;
}

if (manager === 'nub') {
return `nubx remotion upgrade`;
}

throw new TypeError('unknown package manager');
};

Expand Down
2 changes: 1 addition & 1 deletion packages/create-video/src/test/patch-package-json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {expect, test} from 'bun:test';
import {patchPackageJson} from '../patch-package-json';
import type {PackageManager} from '../pkg-managers';

const packageManagers: PackageManager[] = ['npm', 'pnpm', 'yarn', 'bun'];
const packageManagers: PackageManager[] = ['npm', 'pnpm', 'yarn', 'bun', 'nub'];

for (const packageManager of packageManagers) {
test(`Using ${packageManager} package manager provides the correct "packageManager" entry in package.json`, () => {
Expand Down
63 changes: 63 additions & 0 deletions packages/create-video/src/test/pkg-managers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {expect, test} from 'bun:test';
import {
getDevCommand,
getInstallCommand,
getRenderCommand,
getRunCommand,
getUpgradeCommand,
selectPackageManager,
} from '../pkg-managers';
import {FEATURED_TEMPLATES} from '../templates';

test('detects Nub and uses Nub commands', () => {
const previousUserAgent = process.env.npm_config_user_agent;
const previousExecPath = process.env.npm_execpath;
const previousArgv = process.env.npm_config_argv;

try {
process.env.npm_config_user_agent = 'nub/0.8.2 yarn/1.22.22';
process.env.npm_execpath = '/path/to/yarn.js';
process.env.npm_config_argv = JSON.stringify({remain: ['dlx']});

expect(selectPackageManager()).toBe('nub');

const blankTemplate = FEATURED_TEMPLATES.find(
(template) => template.cliId === 'blank',
);
if (!blankTemplate) {
throw new Error('Blank template not found');
}

expect([
getInstallCommand('nub'),
getDevCommand('nub', blankTemplate),
getRunCommand('nub'),
getRenderCommand('nub'),
getUpgradeCommand('nub'),
]).toEqual([
'nub install',
'nub run dev',
'nub run',
'nubx remotion render',
'nubx remotion upgrade',
]);
} finally {
if (previousUserAgent === undefined) {
delete process.env.npm_config_user_agent;
} else {
process.env.npm_config_user_agent = previousUserAgent;
}

if (previousExecPath === undefined) {
delete process.env.npm_execpath;
} else {
process.env.npm_execpath = previousExecPath;
}

if (previousArgv === undefined) {
delete process.env.npm_config_argv;
} else {
process.env.npm_config_argv = previousArgv;
}
}
});
9 changes: 9 additions & 0 deletions packages/docs/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ values={[
{ label: 'bun', value: 'bun', },
{ label: 'pnpm', value: 'pnpm', },
{ label: 'yarn', value: 'yarn', },
{ label: 'nub', value: 'nub', },
]
}>
<TabItem value="npm">
Expand All @@ -82,6 +83,14 @@ yarn create video

</TabItem>

<TabItem value="nub">

```bash title="Use Nub as the package manager"
nubx create-video@latest
```

</TabItem>

<TabItem value="bun">

```bash title="Use Bun as the package manager and runtime"
Expand Down
25 changes: 17 additions & 8 deletions packages/docs/src/components/Elements/ElementPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ export const ElementPage: React.FC<ElementPageProps> = ({
const [isSourceVisible, setIsSourceVisible] = useState(false);
const [isBrowserStudioActionVisible, setIsBrowserStudioActionVisible] =
useState(false);
const [isEmbeddedInStudio, setIsEmbeddedInStudio] = useState(false);
const [isEmbeddedInStudio, setIsEmbeddedInStudio] = useState<boolean | null>(
null,
);
const posterRef = useRef<HTMLImageElement>(null);
const sourceId = useId();
const {height: previewHeight, width: previewWidth} =
Expand Down Expand Up @@ -124,7 +126,10 @@ export const ElementPage: React.FC<ElementPageProps> = ({
}

setIsInstallHintVisible(false);
setInstallStatus({type: 'installing'});
if (!isEmbeddedInStudio) {
setInstallStatus({type: 'installing'});
}

const result = await installInStudio({payload: elementPayload});
if (!result.success) {
setInstallStatus({
Expand All @@ -135,18 +140,22 @@ export const ElementPage: React.FC<ElementPageProps> = ({
return;
}

const {target} = result;
setInstallStatus({
type: 'success',
message: `Sent to ${target.projectName ?? 'Remotion Studio'} (currently ${target.compositionId}). Confirm the installation destination in Studio.`,
});
if (isEmbeddedInStudio) {
setInstallStatus({type: 'idle'});
} else {
const {target} = result;
setInstallStatus({
type: 'success',
message: `Sent to ${target.projectName ?? 'Remotion Studio'} (currently ${target.compositionId}). Confirm the installation destination in Studio.`,
});
}

if (window.location.origin === 'https://www.remotion.dev') {
navigator.sendBeacon(
`https://www.remotion.pro/api/track/element-install-request?slug=${encodeURIComponent(definition.slug)}`,
);
}
}, [definition.slug, elementPayload]);
}, [definition.slug, elementPayload, isEmbeddedInStudio]);

const openInBrowserStudio = useCallback(() => {
if (elementPayload === null) {
Expand Down
4 changes: 4 additions & 0 deletions packages/example/remotion.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ Config.addElementLibrary({
url: 'https://remocn.dev/docs/typography',
displayName: 'Remocn',
});
Config.addElementLibrary({
url: 'http://localhost:3002/elements',
displayName: 'Local Elements',
});
2 changes: 1 addition & 1 deletion packages/renderer/src/options/package-manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const packageManagerOption = {
auto-detect the package manager based on your lockfile.
<br />
Acceptable values are <code>npm</code>, <code>yarn</code>,{' '}
<code>pnpm</code> and <code>bun</code>.
<code>pnpm</code>, <code>bun</code> and <code>nub</code>.
</>
);
},
Expand Down
1 change: 1 addition & 0 deletions packages/studio-server/src/helpers/install-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const getInstallCommand = ({
pnpm: ['i', ...additionalArgs, ...pkgList],
yarn: ['add', '--exact', ...additionalArgs, ...pkgList],
bun: ['i', ...additionalArgs, ...pkgList],
nub: ['add', ...additionalArgs, ...pkgList],
};

return commands[manager];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export const lockFilePaths: LockfilePath[] = [
installCommand: 'pnpm i',
startCommand: 'pnpm exec remotion studio',
},
{
path: 'nub.lock',
manager: 'nub',
installCommand: 'nub add',
startCommand: 'nubx remotion studio',
},
{
path: 'bun.lock',
manager: 'bun',
Expand Down
6 changes: 6 additions & 0 deletions packages/studio-server/src/test/install-dependency.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ test('installs without running dependency lifecycle scripts', async () => {
pnpm: 'pnpm-lock.yaml',
yarn: 'yarn.lock',
bun: 'bun.lock',
nub: 'nub.lock',
};
const temporaryDirectories: string[] = [];

Expand Down Expand Up @@ -125,6 +126,11 @@ test('installs without running dependency lifecycle scripts', async () => {
expect(spawnCalls).toHaveLength(1);
const [call] = spawnCalls;
expect(call.command).toBe(manager);
expect(call.args).toContain('lodash@4.17.21');
if (manager === 'nub') {
expect(call.args[0]).toBe('add');
}

if (manager === 'yarn') {
expect(call.args).not.toContain('--ignore-scripts');
expect(call.options.env?.YARN_ENABLE_SCRIPTS).toBe('false');
Expand Down
2 changes: 1 addition & 1 deletion packages/studio-shared/src/package-manager.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
export type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'nub';
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, {useCallback, useContext, useMemo} from 'react';
import {getBrowserStudioOperations} from '../../helpers/browser-studio-operations';
import {CURRENT_COLOR, LIGHT_TEXT} from '../../helpers/colors';
import {LIGHT_TEXT} from '../../helpers/colors';
import {BrowseElementsIcon} from '../../icons/browse-elements';
import {CaretDown} from '../../icons/caret';
import {SetSelectedModalContext} from '../../state/modals';
Expand All @@ -24,14 +23,6 @@ const browseElementsIconContainerStyle: React.CSSProperties = {
width: 22,
};

const browseElementsArrowStyle: React.CSSProperties = {
display: 'inline-block',
height: 12,
marginLeft: 4,
verticalAlign: -2,
width: 12,
};

const elementLibraryDropdownStyle: React.CSSProperties = {
borderRadius: 4,
height: 28,
Expand Down Expand Up @@ -68,24 +59,18 @@ const elementLibraryDropdownCaretStyle: React.CSSProperties = {
export const ElementLibraryButton: React.FC = () => {
const {setSelectedModal} = useContext(SetSelectedModalContext);
const {studioRuntimeConfig} = useSettings();
const isBrowserStudio = getBrowserStudioOperations() !== null;
const elementLibraries =
studioRuntimeConfig?.elementLibraries ?? noElementLibraries;

const openElementLibrary = useCallback(
(name: string, url: string) => {
if (isBrowserStudio) {
window.open(url, '_blank', 'noopener,noreferrer');
return;
}

setSelectedModal({
type: 'element-library',
name,
url,
});
},
[isBrowserStudio, setSelectedModal],
[setSelectedModal],
);

const openElementsLibrary = useCallback(() => {
Expand Down Expand Up @@ -162,7 +147,7 @@ export const ElementLibraryButton: React.FC = () => {
[elementLibraries, openElementLibrary, openElementsLibrary],
);

if (elementLibraries.length > 0 && !isBrowserStudio) {
if (elementLibraries.length > 0) {
return (
<SegmentedButton
segments={elementLibraryDropdownSegments}
Expand All @@ -180,29 +165,9 @@ export const ElementLibraryButton: React.FC = () => {
renderIcon={(color) => (
<BrowseElementsIcon color={color} style={browseElementsIconStyle} />
)}
title={
isBrowserStudio
? 'Open the Remotion Elements library in a new tab. Install an Element there to send it to this composition.'
: 'Browse the Remotion Elements library inside Studio.'
}
title="Browse the Remotion Elements library inside Studio."
>
Browse Elements
{isBrowserStudio ? (
<svg
aria-hidden="true"
viewBox="0 0 16 16"
style={browseElementsArrowStyle}
>
<path
d="M4 12 12 4M6 4h6v6"
fill="none"
stroke={CURRENT_COLOR}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
/>
</svg>
) : null}
</InspectorQuickAction>
);
};
1 change: 1 addition & 0 deletions packages/studio/src/components/UpdatesSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const commands: {
yarn: 'yarn remotion upgrade',
pnpm: 'pnpm exec remotion upgrade',
bun: 'bun remotion upgrade',
nub: 'nubx remotion upgrade',
unknown: 'npx remotion upgrade',
};

Expand Down
Loading