From 943d7bb446d9bfdf43fd842eccaa84e8c6c0377e Mon Sep 17 00:00:00 2001 From: Shai Reznik Date: Mon, 11 Nov 2024 23:30:40 +0200 Subject: [PATCH] add `outDir` param to the cli --- .changeset/tiny-pants-scream.md | 7 ++ .github/workflows/ci.yml | 2 +- e2e/qwik-cli-e2e/README.md | 6 +- e2e/qwik-cli-e2e/package.json | 2 +- package.json | 3 +- .../qwik/src/cli/add/run-add-interactive.ts | 16 +-- packages/qwik/src/cli/add/update-app.ts | 20 ++-- packages/qwik/src/cli/add/update-files.ts | 60 ++++++++--- .../qwik/src/cli/add/update-files.unit.ts | 94 ++++++++++++++++ packages/qwik/src/cli/types.ts | 22 ++-- packages/qwik/src/cli/utils/integrations.ts | 3 +- pnpm-lock.yaml | 101 +++++++++++++----- scripts/build.ts | 3 +- starters/features/tailwind/package.json | 3 + 14 files changed, 275 insertions(+), 67 deletions(-) create mode 100644 .changeset/tiny-pants-scream.md create mode 100644 packages/qwik/src/cli/add/update-files.unit.ts 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/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..d137677711d 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,37 @@ 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 destDirParts = destDir.split('/'); + const rootDirIndex = destDirParts.indexOf(opts.rootDir); + const destChildPath = + rootDirIndex !== -1 + ? join( + ...destDirParts.slice(0, rootDirIndex + 1), + projectDir, + ...destDirParts.slice(rootDirIndex + 1), + destName + ) + : join(destDir, projectDir, 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..ad4094ddcc0 --- /dev/null +++ b/packages/qwik/src/cli/add/update-files.unit.ts @@ -0,0 +1,94 @@ +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'; + createFakeFiles(fakeSrcDir); + + const fakeDestDir = 'destDir'; + + const fakeFileUpdates: FsUpdates = { + files: [], + installedDeps: {}, + installedScripts: [], + }; + + const fakeOpts: UpdateAppOptions = { + rootDir: fakeDestDir, + integration: 'integration', + }; + + return { + fakeSrcDir, + fakeDestDir, + fakeFileUpdates, + fakeOpts, + }; +} + +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 expectedResult = ['destDir/fake.ts', 'destDir/package.json', 'destDir/src/global.css']; + + expect(actualResults).toEqual(expectedResult); + }); + + 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 expectedResult = [ + `destDir/apps/subpackage/fake.ts`, + `destDir/should-stay-in-root.ts`, + `destDir/package.json`, + `destDir/should-stay/should-also-stay.ts`, + `destDir/apps/subpackage/src/global.css`, + ]; + + expect(actualResults).toEqual(expectedResult); + + const actualGlobalCssContent = fakeFileUpdates.files.find( + (f) => f.path === `destDir/apps/subpackage/src/global.css` + )?.content; + + expect(actualGlobalCssContent).toBe('p{color: red}\n\n/* CSS */\n'); + }); +}); + +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}'); +} 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/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": {