diff --git a/.changeset/tiny-pants-scream.md b/.changeset/tiny-pants-scream.md
new file mode 100644
index 00000000000..c7689f9e9b5
--- /dev/null
+++ b/.changeset/tiny-pants-scream.md
@@ -0,0 +1,7 @@
+---
+'@builder.io/qwik': minor
+---
+
+FEAT: add monorepo support to the `qwik add` command by adding a `projectDir` param
+
+That way you can run `qwik add --projectDir=packages/my-package` and it will add the feature to the specified project/package (sub) folder, instead of the root folder.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6206f86e163..b739db82458 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -764,7 +764,7 @@ jobs:
- run: pnpm install --frozen-lockfile
- name: CLI E2E Tests
- run: pnpm run test.e2e-cli
+ run: pnpm run test.e2e.cli
########### LINT PACKAGES ############
lint-package:
diff --git a/e2e/qwik-cli-e2e/README.md b/e2e/qwik-cli-e2e/README.md
index 959a75de13a..3320cf62cd1 100644
--- a/e2e/qwik-cli-e2e/README.md
+++ b/e2e/qwik-cli-e2e/README.md
@@ -4,7 +4,7 @@ This package provides isolated E2E tests by generating a new application with lo
## Description
-Tests can be invoked by running `pnpm run test.e2e-cli`.
+Tests can be invoked by running `pnpm run test.e2e.cli`.
**Note that running E2E tests requires the workspace projects to be prebuilt manually!**
@@ -16,8 +16,8 @@ E2E project does the following internally:
- By default `outputDir` is an auto-generated one using `tmp` npm package. The application that is created here will be removed after the test is executed
- It is possible to install into custom folder using environment variable `TEMP_E2E_PATH`. Here's how the command would look like in this case:
- - with absolute path `TEMP_E2E_PATH=/Users/name/projects/tests pnpm run test.e2e-cli`
- - with path relative to the qwik workspace `TEMP_E2E_PATH=temp/e2e-folder pnpm run test.e2e-cli`
+ - with absolute path `TEMP_E2E_PATH=/Users/name/projects/tests pnpm run test.e2e.cli`
+ - with path relative to the qwik workspace `TEMP_E2E_PATH=temp/e2e-folder pnpm run test.e2e.cli`
Note that provided folder should exist. If custom path is used, generated application will not be removed after the test completes, which is helpful for debugging.
diff --git a/e2e/qwik-cli-e2e/package.json b/e2e/qwik-cli-e2e/package.json
index 9793d3663e9..b6c2ebf232d 100644
--- a/e2e/qwik-cli-e2e/package.json
+++ b/e2e/qwik-cli-e2e/package.json
@@ -6,6 +6,6 @@
"private": true,
"scripts": {
"e2e": "vitest run --config=vite.config.ts",
- "e2e:watch": "vitest watch --config=vite.config.ts"
+ "e2e.watch": "vitest watch --config=vite.config.ts"
}
}
diff --git a/package.json b/package.json
index 211229e78b0..b7cb4027e30 100644
--- a/package.json
+++ b/package.json
@@ -139,6 +139,7 @@
"execa": "8.0.1",
"express": "4.20.0",
"install": "0.13.0",
+ "memfs": "4.14.0",
"monaco-editor": "0.45.0",
"mri": "1.2.0",
"path-browserify": "1.0.1",
@@ -241,7 +242,7 @@
"start": "concurrently \"npm:build.watch\" \"npm:tsc.watch\" -n build,tsc -c green,cyan",
"test": "pnpm build.full && pnpm test.unit && pnpm test.e2e",
"test.e2e": "pnpm test.e2e.chromium && pnpm test.e2e.webkit",
- "test.e2e-cli": "pnpm --filter qwik-cli-e2e e2e",
+ "test.e2e.cli": "pnpm --filter qwik-cli-e2e e2e",
"test.e2e.chromium": "playwright test starters --browser=chromium --config starters/playwright.config.ts",
"test.e2e.chromium.debug": "PWDEBUG=1 playwright test starters --browser=chromium --config starters/playwright.config.ts",
"test.e2e.city": "playwright test starters/e2e/qwikcity --browser=chromium --config starters/playwright.config.ts",
diff --git a/packages/docs/src/routes/docs/integrations/index.mdx b/packages/docs/src/routes/docs/integrations/index.mdx
index 43fc9d4dac5..c1a1e109912 100644
--- a/packages/docs/src/routes/docs/integrations/index.mdx
+++ b/packages/docs/src/routes/docs/integrations/index.mdx
@@ -55,6 +55,8 @@ bun run qwik add
This command will prompt you to select the integration you want to add. Once selected, the integration will be added to your application and you can start using it.
+> **For Monorepos:** you can add integrations to a specific package by running the command with the `--projectDir=some/subDir` param.
+
### List of possible integrations
diff --git a/packages/qwik/src/cli/add/run-add-interactive.ts b/packages/qwik/src/cli/add/run-add-interactive.ts
index 41a38dd0a2c..a8ed1b3becf 100644
--- a/packages/qwik/src/cli/add/run-add-interactive.ts
+++ b/packages/qwik/src/cli/add/run-add-interactive.ts
@@ -1,8 +1,8 @@
import { intro, isCancel, log, outro, select, spinner } from '@clack/prompts';
import { bgBlue, bgMagenta, blue, bold, cyan, magenta } from 'kleur/colors';
-import type { IntegrationData, UpdateAppResult } from '../types';
+import type { IntegrationData, UpdateAppOptions, UpdateAppResult } from '../types';
import { loadIntegrations, sortIntegrationsAndReturnAsClackOptions } from '../utils/integrations';
-import { bye, getPackageManager, note, panic, printHeader } from '../utils/utils';
+import { bye, getPackageManager, note, panic } from '../utils/utils';
/* eslint-disable no-console */
import { relative } from 'node:path';
@@ -16,8 +16,6 @@ export async function runAddInteractive(app: AppCommand, id: string | undefined)
const integrations = await loadIntegrations();
let integration: IntegrationData | undefined;
- printHeader();
-
if (typeof id === 'string') {
// cli passed a flag with the integration id to add
integration = integrations.find((i) => i.id === id);
@@ -62,11 +60,17 @@ export async function runAddInteractive(app: AppCommand, id: string | undefined)
runInstall = true;
}
- const result = await updateApp(pkgManager, {
+ const updateAppOptions: UpdateAppOptions = {
rootDir: app.rootDir,
integration: integration.id,
installDeps: runInstall,
- });
+ };
+ const projectDir = app.getArg('projectDir');
+ if (projectDir) {
+ updateAppOptions.projectDir = projectDir;
+ }
+
+ const result = await updateApp(pkgManager, updateAppOptions);
if (app.getArg('skipConfirmation') !== 'true') {
await logUpdateAppResult(pkgManager, result);
diff --git a/packages/qwik/src/cli/add/update-app.ts b/packages/qwik/src/cli/add/update-app.ts
index 21c5c916902..200b701d9b9 100644
--- a/packages/qwik/src/cli/add/update-app.ts
+++ b/packages/qwik/src/cli/add/update-app.ts
@@ -1,13 +1,13 @@
-import type { FsUpdates, UpdateAppOptions, UpdateAppResult } from '../types';
-import { dirname } from 'node:path';
+import { log, spinner } from '@clack/prompts';
+import { bgRed, cyan } from 'kleur/colors';
import fs from 'node:fs';
-import { panic } from '../utils/utils';
-import { loadIntegrations } from '../utils/integrations';
+import { dirname } from 'node:path';
+import type { FsUpdates, UpdateAppOptions, UpdateAppResult } from '../types';
import { installDeps } from '../utils/install-deps';
+import { loadIntegrations } from '../utils/integrations';
+import { panic } from '../utils/utils';
import { mergeIntegrationDir } from './update-files';
import { updateViteConfigs } from './update-vite-config';
-import { bgRed, cyan } from 'kleur/colors';
-import { spinner, log } from '@clack/prompts';
export async function updateApp(pkgManager: string, opts: UpdateAppOptions) {
const integrations = await loadIntegrations();
@@ -29,7 +29,13 @@ export async function updateApp(pkgManager: string, opts: UpdateAppOptions) {
};
}
- await mergeIntegrationDir(fileUpdates, opts, integration.dir, opts.rootDir);
+ await mergeIntegrationDir(
+ fileUpdates,
+ opts,
+ integration.dir,
+ opts.rootDir,
+ integration.alwaysInRoot
+ );
if ((globalThis as any).CODE_MOD) {
await updateViteConfigs(fileUpdates, integration, opts.rootDir);
diff --git a/packages/qwik/src/cli/add/update-files.ts b/packages/qwik/src/cli/add/update-files.ts
index 29a9009cbe1..875c8dce0d0 100644
--- a/packages/qwik/src/cli/add/update-files.ts
+++ b/packages/qwik/src/cli/add/update-files.ts
@@ -1,13 +1,14 @@
import fs from 'node:fs';
-import type { FsUpdates, UpdateAppOptions } from '../types';
import { extname, join } from 'node:path';
+import type { FsUpdates, UpdateAppOptions } from '../types';
import { getPackageManager } from '../utils/utils';
export async function mergeIntegrationDir(
fileUpdates: FsUpdates,
opts: UpdateAppOptions,
srcDir: string,
- destDir: string
+ destDir: string,
+ alwaysInRoot?: string[]
) {
const items = await fs.promises.readdir(srcDir);
await Promise.all(
@@ -15,35 +16,39 @@ export async function mergeIntegrationDir(
const destName = itemName === 'gitignore' ? '.gitignore' : itemName;
const ext = extname(destName);
const srcChildPath = join(srcDir, itemName);
- const destChildPath = join(destDir, destName);
+
+ const destRootPath = join(destDir, destName);
+
const s = await fs.promises.stat(srcChildPath);
if (s.isDirectory()) {
- await mergeIntegrationDir(fileUpdates, opts, srcChildPath, destChildPath);
+ await mergeIntegrationDir(fileUpdates, opts, srcChildPath, destRootPath, alwaysInRoot);
} else if (s.isFile()) {
+ const finalDestPath = getFinalDestPath(opts, destRootPath, destDir, destName, alwaysInRoot);
+
if (destName === 'package.json') {
- await mergePackageJsons(fileUpdates, srcChildPath, destChildPath);
+ await mergePackageJsons(fileUpdates, srcChildPath, destRootPath);
} else if (destName === 'settings.json') {
- await mergeJsons(fileUpdates, srcChildPath, destChildPath);
+ await mergeJsons(fileUpdates, srcChildPath, finalDestPath);
} else if (destName === 'README.md') {
- await mergeReadmes(fileUpdates, srcChildPath, destChildPath);
+ await mergeReadmes(fileUpdates, srcChildPath, finalDestPath);
} else if (
destName === '.gitignore' ||
destName === '.prettierignore' ||
destName === '.eslintignore'
) {
- await mergeIgnoresFile(fileUpdates, srcChildPath, destChildPath);
+ await mergeIgnoresFile(fileUpdates, srcChildPath, destRootPath);
} else if (ext === '.css') {
- await mergeCss(fileUpdates, srcChildPath, destChildPath, opts);
- } else if (fs.existsSync(destChildPath)) {
+ await mergeCss(fileUpdates, srcChildPath, finalDestPath, opts);
+ } else if (fs.existsSync(finalDestPath)) {
fileUpdates.files.push({
- path: destChildPath,
+ path: finalDestPath,
content: await fs.promises.readFile(srcChildPath),
type: 'overwrite',
});
} else {
fileUpdates.files.push({
- path: destChildPath,
+ path: finalDestPath,
content: await fs.promises.readFile(srcChildPath),
type: 'create',
});
@@ -53,6 +58,30 @@ export async function mergeIntegrationDir(
);
}
+function getFinalDestPath(
+ opts: UpdateAppOptions,
+ destRootPath: string,
+ destDir: string,
+ destName: string,
+ alwaysInRoot?: string[]
+) {
+ // If the integration has a projectDir, copy the files to the projectDir
+ // Unless that path is part of "alwaysInRoot"
+ const projectDir = opts.projectDir ? opts.projectDir : '';
+ const rootDirEndIndex = destDir.indexOf(opts.rootDir) + opts.rootDir.length;
+ const destWithoutRoot = destDir.slice(rootDirEndIndex);
+
+ const destChildPath = join(opts.rootDir, projectDir, destWithoutRoot, destName);
+
+ const finalDestPath =
+ alwaysInRoot &&
+ alwaysInRoot.some((rootItem) => destName.includes(rootItem) || destDir.includes(rootItem))
+ ? destRootPath
+ : destChildPath;
+
+ return finalDestPath;
+}
+
async function mergePackageJsons(fileUpdates: FsUpdates, srcPath: string, destPath: string) {
const srcContent = await fs.promises.readFile(srcPath, 'utf-8');
try {
diff --git a/packages/qwik/src/cli/add/update-files.unit.ts b/packages/qwik/src/cli/add/update-files.unit.ts
new file mode 100644
index 00000000000..47b9b4c8f9b
--- /dev/null
+++ b/packages/qwik/src/cli/add/update-files.unit.ts
@@ -0,0 +1,98 @@
+import { fs } from 'memfs';
+import { join } from 'path';
+import { describe, expect, test, vi } from 'vitest';
+import type { FsUpdates, UpdateAppOptions } from '../types';
+import { mergeIntegrationDir } from './update-files';
+
+vi.mock('node:fs', () => ({
+ default: fs,
+}));
+
+function setup() {
+ const fakeSrcDir = 'srcDir/subSrcDir';
+ createFakeFiles(fakeSrcDir);
+
+ const fakeDestDir = 'destDir/subDestDir';
+
+ const fakeFileUpdates: FsUpdates = {
+ files: [],
+ installedDeps: {},
+ installedScripts: [],
+ };
+
+ const fakeOpts: UpdateAppOptions = {
+ rootDir: fakeDestDir,
+ integration: 'integration',
+ };
+
+ return {
+ fakeSrcDir,
+ fakeDestDir,
+ fakeFileUpdates,
+ fakeOpts,
+ };
+}
+
+function createFakeFiles(dir: string) {
+ // Create fake src files
+ fs.mkdirSync(join(dir, 'src'), { recursive: true });
+ fs.writeFileSync(join(dir, 'fake.ts'), 'fake file');
+ fs.writeFileSync(join(dir, 'package.json'), '{"name": "fake"}');
+ fs.writeFileSync(join(dir, 'src', 'global.css'), 'p{color: red}');
+}
+
+describe('mergeIntegrationDir', () => {
+ test('should merge integration directory', async () => {
+ const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup();
+
+ await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir);
+
+ const actualResults = fakeFileUpdates.files.map((f) => f.path);
+ const expectedResults = [
+ 'destDir/subDestDir/fake.ts',
+ 'destDir/subDestDir/package.json',
+ 'destDir/subDestDir/src/global.css',
+ ];
+
+ expect(actualResults).toEqual(expectedResults);
+ });
+
+ test('should merge integration directory in a monorepo', async () => {
+ const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup();
+
+ // Create a global file in the destination director
+ const monorepoSubDir = join(fakeDestDir, 'apps', 'subpackage', 'src');
+ fs.mkdirSync(monorepoSubDir, { recursive: true });
+ fs.writeFileSync(join(monorepoSubDir, 'global.css'), '/* CSS */');
+
+ // Add a file that should stay in the root
+ fs.writeFileSync(join(fakeSrcDir, 'should-stay-in-root.ts'), 'fake file');
+
+ // Creating a folder that should stay in the root
+ fs.mkdirSync(join(fakeSrcDir, 'should-stay'), { recursive: true });
+ fs.writeFileSync(join(fakeSrcDir, 'should-stay', 'should-also-stay.ts'), 'fake file');
+
+ fakeOpts.projectDir = 'apps/subpackage';
+ fakeOpts.installDeps = true;
+ const fakeAlwaysInRoot = ['should-stay-in-root.ts', 'should-stay'];
+
+ await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir, fakeAlwaysInRoot);
+
+ const actualResults = fakeFileUpdates.files.map((f) => f.path);
+ const expectedResults = [
+ `destDir/subDestDir/apps/subpackage/fake.ts`,
+ `destDir/subDestDir/should-stay-in-root.ts`,
+ `destDir/subDestDir/package.json`,
+ `destDir/subDestDir/should-stay/should-also-stay.ts`,
+ `destDir/subDestDir/apps/subpackage/src/global.css`,
+ ];
+
+ expect(actualResults).toEqual(expectedResults);
+
+ const actualGlobalCssContent = fakeFileUpdates.files.find(
+ (f) => f.path === `destDir/subDestDir/apps/subpackage/src/global.css`
+ )?.content;
+
+ expect(actualGlobalCssContent).toBe('p{color: red}\n\n/* CSS */\n');
+ });
+});
diff --git a/packages/qwik/src/cli/types.ts b/packages/qwik/src/cli/types.ts
index e1043da2394..efb444d6867 100644
--- a/packages/qwik/src/cli/types.ts
+++ b/packages/qwik/src/cli/types.ts
@@ -14,6 +14,7 @@ export interface UpdateAppOptions {
rootDir: string;
integration: string;
installDeps?: boolean;
+ projectDir?: string;
}
export interface UpdateAppResult {
@@ -43,6 +44,8 @@ export interface IntegrationData {
priority: number;
docs: string[];
viteConfig?: ViteConfigUpdates;
+ // Files and folders that should be copied to root ignoring `projectDir`
+ alwaysInRoot?: string[];
}
export type IntegrationType = 'app' | 'feature' | 'adapter';
@@ -77,14 +80,17 @@ export interface IntegrationPackageJson {
qwikTemplates?: string[];
types?: string;
type?: string;
- __qwik__?: {
- displayName?: string;
- nextSteps?: NextSteps;
- docs?: string[];
- priority: number;
- postInstall?: string;
- viteConfig?: ViteConfigUpdates;
- };
+ __qwik__?: QwikIntegrationConfig;
+}
+
+export interface QwikIntegrationConfig {
+ displayName?: string;
+ nextSteps?: NextSteps;
+ docs?: string[];
+ priority: number;
+ postInstall?: string;
+ viteConfig?: ViteConfigUpdates;
+ alwaysInRoot?: string[];
}
export interface EnsureImport {
diff --git a/packages/qwik/src/cli/utils/integrations.ts b/packages/qwik/src/cli/utils/integrations.ts
index a1baa2add10..99bfd386b8c 100644
--- a/packages/qwik/src/cli/utils/integrations.ts
+++ b/packages/qwik/src/cli/utils/integrations.ts
@@ -1,7 +1,7 @@
import fs from 'node:fs';
import { join } from 'node:path';
import type { IntegrationData, IntegrationType } from '../types';
-import { dashToTitleCase, readPackageJson, limitLength } from './utils';
+import { dashToTitleCase, limitLength, readPackageJson } from './utils';
let integrations: IntegrationData[] | null = null;
@@ -55,6 +55,7 @@ export async function loadIntegrations() {
pkgJson,
docs: pkgJson.__qwik__?.docs ?? [],
priority: pkgJson?.__qwik__?.priority ?? 0,
+ alwaysInRoot: pkgJson.__qwik__?.alwaysInRoot ?? [],
};
loadingIntegrations.push(integration);
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f9852ac1851..c6aa12be005 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -154,6 +154,9 @@ importers:
install:
specifier: 0.13.0
version: 0.13.0
+ memfs:
+ specifier: 4.14.0
+ version: 4.14.0
monaco-editor:
specifier: 0.45.0
version: 0.45.0
@@ -2410,79 +2413,67 @@ packages:
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-arm@1.0.5':
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-s390x@1.0.4':
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linux-x64@1.0.4':
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-linux-arm64@0.33.5':
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-arm@0.33.5':
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-s390x@0.33.5':
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@img/sharp-linux-x64@0.33.5':
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@img/sharp-linuxmusl-arm64@0.33.5':
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@img/sharp-linuxmusl-x64@0.33.5':
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- libc: [musl]
'@img/sharp-wasm32@0.33.5':
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
@@ -2539,6 +2530,24 @@ packages:
'@jridgewell/trace-mapping@0.3.9':
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
+ '@jsonjoy.com/base64@1.1.2':
+ resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==}
+ engines: {node: '>=10.0'}
+ peerDependencies:
+ tslib: '2'
+
+ '@jsonjoy.com/json-pack@1.1.0':
+ resolution: {integrity: sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==}
+ engines: {node: '>=10.0'}
+ peerDependencies:
+ tslib: '2'
+
+ '@jsonjoy.com/util@1.5.0':
+ resolution: {integrity: sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==}
+ engines: {node: '>=10.0'}
+ peerDependencies:
+ tslib: '2'
+
'@libsql/client@0.5.6':
resolution: {integrity: sha512-UBjmDoxz75Z2sHdP+ETCROpeLA/77VMesiff8R4UWK1rnaWbh6/YoCLDILMJL3Rh0udQeKxjL8MjXthqohax+g==}
@@ -3034,35 +3043,30 @@ packages:
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-arm64-glibc@2.4.1':
resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-arm64-musl@2.4.1':
resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@parcel/watcher-linux-x64-glibc@2.4.1':
resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@parcel/watcher-linux-x64-musl@2.4.1':
resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
- libc: [musl]
'@parcel/watcher-wasm@2.4.0':
resolution: {integrity: sha512-MNgQ4WCbBybqQ97KwR/hqJGYTg3+s8qHpgIyFWB2qJOBvoJWbXuJGmm4ZkPLq2bMaANqCZqrXwmKYagZTkMKZA==}
@@ -3167,55 +3171,46 @@ packages:
resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==}
cpu: [arm]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.19.0':
resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==}
cpu: [arm]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.19.0':
resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==}
cpu: [arm64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.19.0':
resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==}
cpu: [arm64]
os: [linux]
- libc: [musl]
'@rollup/rollup-linux-powerpc64le-gnu@4.19.0':
resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==}
cpu: [ppc64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.19.0':
resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==}
cpu: [riscv64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.19.0':
resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==}
cpu: [s390x]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.19.0':
resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==}
cpu: [x64]
os: [linux]
- libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.19.0':
resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==}
cpu: [x64]
os: [linux]
- libc: [musl]
'@rollup/rollup-win32-arm64-msvc@4.19.0':
resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==}
@@ -6194,6 +6189,10 @@ packages:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
+ hyperdyperid@1.2.0:
+ resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==}
+ engines: {node: '>=10.18'}
+
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
@@ -7097,6 +7096,10 @@ packages:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
+ memfs@4.14.0:
+ resolution: {integrity: sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==}
+ engines: {node: '>= 4.0.0'}
+
memoize-one@6.0.0:
resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==}
@@ -8721,6 +8724,7 @@ packages:
shikiji-core@0.9.19:
resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==}
+ deprecated: Shikiji is merged back to Shiki v1.0, please migrate over to get the latest updates
shikiji@0.9.19:
resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==}
@@ -9157,6 +9161,12 @@ packages:
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ thingies@1.21.0:
+ resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==}
+ engines: {node: '>=10.18'}
+ peerDependencies:
+ tslib: ^2
+
thread-stream@3.1.0:
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
@@ -9247,6 +9257,12 @@ packages:
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+ tree-dump@1.0.2:
+ resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==}
+ engines: {node: '>=10.0'}
+ peerDependencies:
+ tslib: '2'
+
tree-kill@1.2.2:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
@@ -11384,6 +11400,22 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
+ '@jsonjoy.com/base64@1.1.2(tslib@2.6.2)':
+ dependencies:
+ tslib: 2.6.2
+
+ '@jsonjoy.com/json-pack@1.1.0(tslib@2.6.2)':
+ dependencies:
+ '@jsonjoy.com/base64': 1.1.2(tslib@2.6.2)
+ '@jsonjoy.com/util': 1.5.0(tslib@2.6.2)
+ hyperdyperid: 1.2.0
+ thingies: 1.21.0(tslib@2.6.2)
+ tslib: 2.6.2
+
+ '@jsonjoy.com/util@1.5.0(tslib@2.6.2)':
+ dependencies:
+ tslib: 2.6.2
+
'@libsql/client@0.5.6(bufferutil@4.0.8)(utf-8-validate@5.0.10)':
dependencies:
'@libsql/core': 0.5.6
@@ -15871,6 +15903,8 @@ snapshots:
human-signals@5.0.0: {}
+ hyperdyperid@1.2.0: {}
+
iconv-lite@0.4.24:
dependencies:
safer-buffer: 2.1.2
@@ -16915,6 +16949,13 @@ snapshots:
media-typer@0.3.0: {}
+ memfs@4.14.0:
+ dependencies:
+ '@jsonjoy.com/json-pack': 1.1.0(tslib@2.6.2)
+ '@jsonjoy.com/util': 1.5.0(tslib@2.6.2)
+ tree-dump: 1.0.2(tslib@2.6.2)
+ tslib: 2.6.2
+
memoize-one@6.0.0: {}
memoizee@0.4.15:
@@ -19463,6 +19504,10 @@ snapshots:
dependencies:
any-promise: 1.3.0
+ thingies@1.21.0(tslib@2.6.2):
+ dependencies:
+ tslib: 2.6.2
+
thread-stream@3.1.0:
dependencies:
real-require: 0.2.0
@@ -19536,6 +19581,10 @@ snapshots:
tr46@0.0.3: {}
+ tree-dump@1.0.2(tslib@2.6.2):
+ dependencies:
+ tslib: 2.6.2
+
tree-kill@1.2.2: {}
treeify@1.1.0: {}
diff --git a/scripts/build.ts b/scripts/build.ts
index af9e2fb1c07..11862ab3b34 100644
--- a/scripts/build.ts
+++ b/scripts/build.ts
@@ -29,7 +29,7 @@ import { submoduleTesting } from './submodule-testing';
import { buildSupabaseAuthHelpers } from './supabase-auth-helpers';
import { tsc, tscQwik, tscQwikCity } from './tsc';
import { tscDocs } from './tsc-docs';
-import { type BuildConfig, emptyDir, ensureDir, panic } from './util';
+import { emptyDir, ensureDir, panic, type BuildConfig } from './util';
import { validateBuild } from './validate-build';
/**
@@ -181,6 +181,7 @@ export async function build(config: BuildConfig) {
join(config.srcQwikDir, '..', 'dist', 'core.prod.cjs')
);
},
+ [join(config.srcQwikDir, 'cli')]: () => submoduleCli(config),
[join(config.srcQwikDir, 'optimizer')]: () => submoduleOptimizer(config),
[join(config.srcQwikDir, 'prefetch-service-worker')]: () => submoduleQwikPrefetch(config),
[join(config.srcQwikDir, 'server')]: () => submoduleServer(config),
diff --git a/starters/features/drizzle/package.json b/starters/features/drizzle/package.json
index 55053a22e5f..91f11a52909 100644
--- a/starters/features/drizzle/package.json
+++ b/starters/features/drizzle/package.json
@@ -22,7 +22,8 @@
" Check out the Drizzle docs for more info:",
" - https://orm.drizzle.team/docs/overview"
]
- }
+ },
+ "alwaysInRoot": []
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.9",
diff --git a/starters/features/postcss/package.json b/starters/features/postcss/package.json
index 46afb605b45..c912138995a 100644
--- a/starters/features/postcss/package.json
+++ b/starters/features/postcss/package.json
@@ -7,6 +7,9 @@
"docs": [
"https://qwik.dev/integrations/integration/postcss/",
"https://github.com/postcss/postcss-load-config"
+ ],
+ "alwaysInRoot": [
+ ".vscode"
]
},
"devDependencies": {
diff --git a/starters/features/prisma/package.json b/starters/features/prisma/package.json
index 6d5d4269527..a57436a0455 100644
--- a/starters/features/prisma/package.json
+++ b/starters/features/prisma/package.json
@@ -20,7 +20,8 @@
" Check out the Prisma docs for more info:",
" - https://www.prisma.io/docs/getting-started"
]
- }
+ },
+ "alwaysInRoot": []
},
"devDependencies": {
"@prisma/client": "5.3.1",
diff --git a/starters/features/tailwind/package.json b/starters/features/tailwind/package.json
index 352f488aefe..3d6493adcb1 100644
--- a/starters/features/tailwind/package.json
+++ b/starters/features/tailwind/package.json
@@ -7,6 +7,9 @@
"docs": [
"https://qwik.dev/integrations/integration/tailwind/",
"https://tailwindcss.com/docs/utility-first"
+ ],
+ "alwaysInRoot": [
+ ".vscode"
]
},
"devDependencies": {
diff --git a/starters/features/turso/package.json b/starters/features/turso/package.json
index a73fbb2bc8d..7e4fa662fb2 100644
--- a/starters/features/turso/package.json
+++ b/starters/features/turso/package.json
@@ -19,7 +19,10 @@
" To get an authentication token for the database, run:",
" turso db tokens create "
]
- }
+ },
+ "alwaysInRoot": [
+ ".env.local"
+ ]
},
"dependencies": {
"@libsql/client": "latest"