Skip to content

Commit

Permalink
refactor(demo): refactor stackblitz to prepare for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
divdavem committed Mar 22, 2024
1 parent 3d84bcc commit 1149eca
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 237 deletions.
2 changes: 1 addition & 1 deletion demo/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
}
},
{
"files": ["svelte.config.js"],
"files": ["svelte.config.js", "vite.config.ts", "stackblitz/*.d.ts", "scripts/*.ts"],
"parserOptions": {
"project": ["tsconfig.json"]
},
Expand Down
28 changes: 7 additions & 21 deletions demo/scripts/includeSamples.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const includeSamples = (): Plugin => {
} else if (id.startsWith(samplePrefix) || id.startsWith(sampleDaisyui)) {
//check if samplePrefix or sampleTailwindPrefix
const matchedPrefix = id.startsWith(samplePrefix) ? samplePrefix : sampleDaisyui;
const cssFramework = matchedPrefix === sampleDaisyui ? 'daisyui' : 'bootstrap';
const parts = id.substring(matchedPrefix.length).split('/');
if (parts.length !== 2) {
throw new Error('Invalid sample path: ' + id);
Expand Down Expand Up @@ -113,38 +114,23 @@ export const includeSamples = (): Plugin => {
await addFile(
'angular',
`${sampleName}.component.ts`,
path.join(
__dirname,
`../../angular/demo/${matchedPrefix === sampleDaisyui ? 'daisyui' : 'bootstrap'}/src/app/samples/${componentName}/${sampleName}.route.ts`,
),
path.join(__dirname, `../../angular/demo/${cssFramework}/src/app/samples/${componentName}/${sampleName}.route.ts`),
);
await addFile(
'react',
`${sampleName}.tsx`,
path.join(
__dirname,
`../../react/demo/src/${
matchedPrefix === sampleDaisyui ? 'daisyui' : 'bootstrap'
}/samples/${componentName}/${normalizedSampleName}.route.tsx`,
),
path.join(__dirname, `../../react/demo/src/${cssFramework}/samples/${componentName}/${normalizedSampleName}.route.tsx`),
);
await addFile(
'svelte',
`${sampleName}.svelte`,
path.join(
__dirname,
`../../svelte/demo/src/${
matchedPrefix === sampleDaisyui ? 'daisyui' : 'bootstrap'
}/samples/${componentName}/${normalizedSampleName}.route.svelte`,
),
path.join(__dirname, `../../svelte/demo/src/${cssFramework}/samples/${componentName}/${normalizedSampleName}.route.svelte`),
);
const complementaryUrl = matchedPrefix === sampleDaisyui ? '/daisyui' : '/bootstrap';
let output = `export default {componentName:${JSON.stringify(componentName)}, style:'${
matchedPrefix === sampleDaisyui ? 'daisyui' : 'bootstrap'
}', sampleName:${JSON.stringify(sampleName)},files:{`;
const complementaryUrl = `/${cssFramework}`;
let output = `export default {componentName:${JSON.stringify(componentName)}, style:'${cssFramework}', sampleName:${JSON.stringify(sampleName)},files:{`;
(Object.keys(files) as Frameworks[]).forEach((framework) => {
const frameworkFiles = files[framework];
output += `${JSON.stringify(framework)}:{complementaryUrl: '${complementaryUrl}',entryPoint:${JSON.stringify(frameworkFiles[0].fileName)},files:{`;
output += `${JSON.stringify(framework)}:{complementaryUrl:${JSON.stringify(complementaryUrl)},entryPoint:${JSON.stringify(frameworkFiles[0].fileName)},files:{`;
frameworkFiles.forEach(({fileName, filePath}) => {
output += `[${JSON.stringify(fileName)}]: () => import(${JSON.stringify(filePath + rawSampleSuffix)}).then(file=>file.default),`;
});
Expand Down
48 changes: 48 additions & 0 deletions demo/scripts/listSamples.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type {SampleInfo} from '../src/lib/layout/sample';
import {globSync} from 'glob';
import path from 'path';
import type {Plugin} from 'vite';

const samplesListId = '@agnos-ui/samples';

export const getSamplesList = () => {
const mapFile =
(style: SampleInfo['style']) =>
(file: string): Pick<SampleInfo, 'componentName' | 'sampleName' | 'style'> => {
const parts = file
.replace(/\.route\.svelte$/, '')
.toLowerCase()
.split(path.sep);
if (parts.length !== 2) {
throw new Error(`Expected exactly two components in sample path: ${file} (in ${style})`);
}
return {style, componentName: parts[0], sampleName: parts[1]};
};
const filesBootstrap = globSync('**/*.route.svelte', {cwd: path.join(__dirname, '../../svelte/demo/src/bootstrap/samples')}).map(
mapFile('bootstrap'),
);
const filesDaisyui = globSync('**/*.route.svelte', {cwd: path.join(__dirname, '../../svelte/demo/src/daisyui/samples')}).map(mapFile('daisyui'));
return [...filesBootstrap, ...filesDaisyui];
};

export const listSamples = (): Plugin => ({
name: 'list-samples',
resolveId(id) {
if (id === samplesListId) {
return {id};
}
},
async load(id) {
if (id === samplesListId) {
let output = '';
const samples = getSamplesList();
let i = 0;
for (const sample of samples) {
output += `import sample${i} from ${JSON.stringify(`@agnos-ui/${sample.style === 'bootstrap' ? 'samples' : 'samples-daisyui'}/${sample.componentName}/${sample.sampleName}`)};\n`;
i++;
}
output += `export default [${samples.map((sample, i) => `sample${i}`).join(',\n')}];`;
return output;
}
},
});
201 changes: 5 additions & 196 deletions demo/src/lib/stackblitz/index.ts
Original file line number Diff line number Diff line change
@@ -1,203 +1,12 @@
import type {Frameworks} from '$lib/stores';
import type {Project} from '@stackblitz/sdk';
import stackblitz from '@stackblitz/sdk';
import type {AsyncFilesSet, SampleInfo} from '../layout/sample';
import type {SampleInfo} from '../layout/sample';
import {prepareStackblitzProject} from './prepareProject';
import {createFrameworkProcessors} from './unreleasedProcessors';

type StackblitzProcessor = (project: Project, sample: SampleInfo, framework: Frameworks) => Promise<void>;

const isBootstrapCondition = (sample: SampleInfo) => sample.style === 'bootstrap';
const isDaisyuiCondition = (sample: SampleInfo) => sample.style === 'daisyui';

const addAsyncFiles =
(files: AsyncFilesSet, prefix = '', removePrefix?: string, condition: (sample: SampleInfo) => boolean = () => true): StackblitzProcessor =>
async (project, sample) => {
if (condition(sample)) {
await Promise.all(
Object.keys(files).map(async (fileName) => {
const finalName = prefix + (removePrefix && fileName.startsWith(removePrefix) ? fileName.substring(removePrefix.length) : fileName);
project.files[finalName] = await files[fileName]();
}),
);
}
};

const frameworkCreateStackblitz: Record<Frameworks, StackblitzProcessor[]> = {
angular: [
addAsyncFiles(
import.meta.glob('./angular-bootstrap/**', {query: '?raw', import: 'default'}) as any,
'',
'./angular-bootstrap/',
isBootstrapCondition,
),
addAsyncFiles(import.meta.glob('./angular-daisyui/**', {query: '?raw', import: 'default'}) as any, '', './angular-daisyui/', isDaisyuiCondition),
async (project, sample) => {
project.files['src/main.ts'] =
`import {bootstrapApplication} from '@angular/platform-browser';\nimport MainComponent from './${sample.files.angular.entryPoint.replace(
/\.ts$/,
'',
)}';\nbootstrapApplication(MainComponent).catch((err) => console.error(err));`;
},
],
react: [
addAsyncFiles(
import.meta.glob('./react-bootstrap/**', {query: '?raw', import: 'default'}) as any,
'',
'./react-bootstrap/',
isBootstrapCondition,
),
addAsyncFiles(import.meta.glob('./react-daisyui/**', {query: '?raw', import: 'default'}) as any, '', './react-daisyui/', isDaisyuiCondition),
async (project, sample) => {
project.files['src/main.tsx'] = `import {createRoot} from "react-dom/client";\nimport "./main.css";\nimport App from ${JSON.stringify(
`./${sample.files.react.entryPoint.replace(/\.tsx?$/, '')}`,
)};\nconst rootElement = document.getElementById('root');\nconst root = createRoot(rootElement);\nroot.render(<App />)`;
},
],
svelte: [
addAsyncFiles(
import.meta.glob('./svelte-bootstrap/**', {query: '?raw', import: 'default'}) as any,
'',
'./svelte-bootstrap/',
isBootstrapCondition,
),
addAsyncFiles(import.meta.glob('./svelte-daisyui/**', {query: '?raw', import: 'default'}) as any, '', './svelte-daisyui/', isDaisyuiCondition),
async (project, sample) => {
project.files['src/main.ts'] = `import "./main.css";\nimport App from ${JSON.stringify(
`./${sample.files.svelte.entryPoint}`,
)};\nconst app = new App({target: document.getElementById('root')});\nexport default app;`;
project.template = 'node';
},
],
};

const isReleased = import.meta.env.AGNOSUI_VERSION !== '0.0.0';

if (isReleased) {
const setPackageJsonVersion: StackblitzProcessor = async ({files}, sample, framework) => {
const packageJson = JSON.parse(files['package.json']);
if (isBootstrapCondition(sample)) {
packageJson.devDependencies[`@agnos-ui/${framework}`] = import.meta.env.AGNOSUI_VERSION;
} else {
packageJson.devDependencies[`@agnos-ui/${framework}-headless`] = import.meta.env.AGNOSUI_VERSION;
}
files['package.json'] = JSON.stringify(packageJson, null, '\t');
};
frameworkCreateStackblitz.angular.push(setPackageJsonVersion);
frameworkCreateStackblitz.svelte.push(setPackageJsonVersion);
frameworkCreateStackblitz.react.push(setPackageJsonVersion);
} else {
const mergePackageJson: StackblitzProcessor = async ({files}) => {
const packageJson = JSON.parse(files['package.json']);
for (const file of Object.keys(files)) {
if (file.startsWith('packages/') && file.endsWith('/package.json')) {
const pkg = JSON.parse(files[file]);
packageJson.devDependencies[pkg.name] = `file:./packages/${pkg.name}`;
for (const key of Object.keys(pkg.dependencies ?? {})) {
if (!files[`packages/${key}/package.json`]) {
packageJson.devDependencies[key] = pkg.dependencies[key];
}
}
}
}
files['package.json'] = JSON.stringify(packageJson, null, '\t');
};

const corePackage = addAsyncFiles(
import.meta.glob(['../../../../core/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/core/',
'../../../../core/dist/',
);
const stylePackage = addAsyncFiles(
import.meta.glob(['../../../../style-bootstrap/**', '!**/*.map', '!**/*.scss'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/style-bootstrap/',
'../../../../style-bootstrap/',
isBootstrapCondition,
);
frameworkCreateStackblitz.angular.push(
corePackage,
stylePackage,
addAsyncFiles(
import.meta.glob(['../../../../angular/headless/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/angular-headless/',
'../../../../angular/headless/dist/',
),
addAsyncFiles(
import.meta.glob(['../../../../angular/lib/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/angular/',
'../../../../angular/lib/dist/',
isBootstrapCondition,
),
mergePackageJson,
);
frameworkCreateStackblitz.react.push(
corePackage,
stylePackage,
addAsyncFiles(
import.meta.glob(['../../../../react/headless/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/react-headless/',
'../../../../react/headless/dist/',
),
addAsyncFiles(
import.meta.glob(['../../../../react/lib/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/react/',
'../../../../react/lib/dist/',
isBootstrapCondition,
),
mergePackageJson,
);
frameworkCreateStackblitz.svelte.push(
corePackage,
stylePackage,
addAsyncFiles(
import.meta.glob(['../../../../svelte/headless/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/svelte-headless/',
'../../../../svelte/headless/dist/',
),
addAsyncFiles(
import.meta.glob(['../../../../svelte/lib/dist/**', '!**/*.map'], {
query: '?raw',
import: 'default',
}) as any,
'packages/@agnos-ui/svelte/',
'../../../../svelte/lib/dist/',
isBootstrapCondition,
),
mergePackageJson,
);
}
const frameworkProcessors = createFrameworkProcessors();

export const openInStackblitz = async (sample: SampleInfo, framework: Frameworks) => {
const project: Project = {
title: `AgnosUI ${framework} demo - ${sample.componentName} - ${sample.sampleName}`,
files: {},
template: 'node',
};
const filesInfo = sample.files[framework];
const {entryPoint, files} = filesInfo;
const processors = [addAsyncFiles(files, 'src/'), ...frameworkCreateStackblitz[framework]];
for (const processor of processors) {
await processor(project, sample, framework);
}
const openFile = [entryPoint, ...Object.keys(files).filter((file) => file != entryPoint)].map((file) => `src/${file}`).join(',');
const {project, openFile} = await prepareStackblitzProject(sample, framework, frameworkProcessors);
stackblitz.openProject(project, {newWindow: true, openFile});
};
Loading

0 comments on commit 1149eca

Please sign in to comment.