@rs-x/cli 2.0.0-next.15 → 2.0.0-next.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/rsx.cjs +337 -7
- package/package.json +1 -1
- package/{rs-x-vscode-extension-2.0.0-next.15.vsix → rs-x-vscode-extension-2.0.0-next.17.vsix} +0 -0
- package/templates/next-demo/README.md +26 -0
- package/templates/next-demo/app/globals.css +431 -0
- package/templates/next-demo/app/layout.tsx +22 -0
- package/templates/next-demo/app/page.tsx +5 -0
- package/templates/next-demo/components/demo-app.tsx +114 -0
- package/templates/next-demo/components/virtual-table-row.tsx +40 -0
- package/templates/next-demo/components/virtual-table-shell.tsx +86 -0
- package/templates/next-demo/hooks/use-virtual-table-controller.ts +26 -0
- package/templates/next-demo/hooks/use-virtual-table-viewport.ts +41 -0
- package/templates/next-demo/lib/row-data.ts +35 -0
- package/templates/next-demo/lib/row-model.ts +45 -0
- package/templates/next-demo/lib/rsx-bootstrap.ts +46 -0
- package/templates/next-demo/lib/virtual-table-controller.ts +247 -0
- package/templates/next-demo/lib/virtual-table-data.service.ts +126 -0
- package/templates/vue-demo/README.md +27 -0
- package/templates/vue-demo/src/App.vue +89 -0
- package/templates/vue-demo/src/components/VirtualTableRow.vue +33 -0
- package/templates/vue-demo/src/components/VirtualTableShell.vue +58 -0
- package/templates/vue-demo/src/composables/use-virtual-table-controller.ts +33 -0
- package/templates/vue-demo/src/composables/use-virtual-table-viewport.ts +40 -0
- package/templates/vue-demo/src/env.d.ts +6 -0
- package/templates/vue-demo/src/lib/row-data.ts +35 -0
- package/templates/vue-demo/src/lib/row-model.ts +45 -0
- package/templates/vue-demo/src/lib/rsx-bootstrap.ts +46 -0
- package/templates/vue-demo/src/lib/virtual-table-controller.ts +247 -0
- package/templates/vue-demo/src/lib/virtual-table-data.service.ts +126 -0
- package/templates/vue-demo/src/main.ts +12 -0
- package/templates/vue-demo/src/style.css +440 -0
package/bin/rsx.cjs
CHANGED
|
@@ -27,6 +27,18 @@ const REACT_DEMO_TEMPLATE_DIR = path.join(
|
|
|
27
27
|
'templates',
|
|
28
28
|
'react-demo',
|
|
29
29
|
);
|
|
30
|
+
const VUE_DEMO_TEMPLATE_DIR = path.join(
|
|
31
|
+
__dirname,
|
|
32
|
+
'..',
|
|
33
|
+
'templates',
|
|
34
|
+
'vue-demo',
|
|
35
|
+
);
|
|
36
|
+
const NEXT_DEMO_TEMPLATE_DIR = path.join(
|
|
37
|
+
__dirname,
|
|
38
|
+
'..',
|
|
39
|
+
'templates',
|
|
40
|
+
'next-demo',
|
|
41
|
+
);
|
|
30
42
|
const RUNTIME_PACKAGES = [
|
|
31
43
|
'@rs-x/core',
|
|
32
44
|
'@rs-x/state-manager',
|
|
@@ -663,6 +675,77 @@ function writeFileWithDryRun(filePath, content, dryRun) {
|
|
|
663
675
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
664
676
|
}
|
|
665
677
|
|
|
678
|
+
function stripJsonComments(content) {
|
|
679
|
+
let result = '';
|
|
680
|
+
let inString = false;
|
|
681
|
+
let stringDelimiter = '"';
|
|
682
|
+
let inLineComment = false;
|
|
683
|
+
let inBlockComment = false;
|
|
684
|
+
|
|
685
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
686
|
+
const current = content[index];
|
|
687
|
+
const next = content[index + 1];
|
|
688
|
+
|
|
689
|
+
if (inLineComment) {
|
|
690
|
+
if (current === '\n') {
|
|
691
|
+
inLineComment = false;
|
|
692
|
+
result += current;
|
|
693
|
+
}
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
if (inBlockComment) {
|
|
698
|
+
if (current === '*' && next === '/') {
|
|
699
|
+
inBlockComment = false;
|
|
700
|
+
index += 1;
|
|
701
|
+
}
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
if (inString) {
|
|
706
|
+
result += current;
|
|
707
|
+
if (current === '\\') {
|
|
708
|
+
index += 1;
|
|
709
|
+
if (index < content.length) {
|
|
710
|
+
result += content[index];
|
|
711
|
+
}
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (current === stringDelimiter) {
|
|
715
|
+
inString = false;
|
|
716
|
+
}
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (current === '"' || current === "'") {
|
|
721
|
+
inString = true;
|
|
722
|
+
stringDelimiter = current;
|
|
723
|
+
result += current;
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
if (current === '/' && next === '/') {
|
|
728
|
+
inLineComment = true;
|
|
729
|
+
index += 1;
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
if (current === '/' && next === '*') {
|
|
734
|
+
inBlockComment = true;
|
|
735
|
+
index += 1;
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
result += current;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
function parseJsonc(content) {
|
|
746
|
+
return JSON.parse(stripJsonComments(content.replace(/^\uFEFF/u, '')));
|
|
747
|
+
}
|
|
748
|
+
|
|
666
749
|
function copyPathWithDryRun(sourcePath, targetPath, dryRun) {
|
|
667
750
|
if (dryRun) {
|
|
668
751
|
logInfo(`[dry-run] copy ${sourcePath} -> ${targetPath}`);
|
|
@@ -714,7 +797,7 @@ function upsertTypescriptPluginInTsConfig(configPath, dryRun) {
|
|
|
714
797
|
return;
|
|
715
798
|
}
|
|
716
799
|
|
|
717
|
-
const tsConfig =
|
|
800
|
+
const tsConfig = parseJsonc(fs.readFileSync(configPath, 'utf8'));
|
|
718
801
|
const compilerOptions = tsConfig.compilerOptions ?? {};
|
|
719
802
|
const plugins = Array.isArray(compilerOptions.plugins)
|
|
720
803
|
? compilerOptions.plugins
|
|
@@ -742,6 +825,26 @@ function upsertTypescriptPluginInTsConfig(configPath, dryRun) {
|
|
|
742
825
|
fs.writeFileSync(configPath, `${JSON.stringify(tsConfig, null, 2)}\n`, 'utf8');
|
|
743
826
|
}
|
|
744
827
|
|
|
828
|
+
function ensureTsConfigIncludePattern(configPath, pattern, dryRun) {
|
|
829
|
+
if (!fs.existsSync(configPath)) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const tsConfig = parseJsonc(fs.readFileSync(configPath, 'utf8'));
|
|
834
|
+
const include = Array.isArray(tsConfig.include) ? tsConfig.include : [];
|
|
835
|
+
if (!include.includes(pattern)) {
|
|
836
|
+
include.push(pattern);
|
|
837
|
+
}
|
|
838
|
+
tsConfig.include = include;
|
|
839
|
+
|
|
840
|
+
if (dryRun) {
|
|
841
|
+
logInfo(`[dry-run] patch ${configPath}`);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
fs.writeFileSync(configPath, `${JSON.stringify(tsConfig, null, 2)}\n`, 'utf8');
|
|
846
|
+
}
|
|
847
|
+
|
|
745
848
|
function toFileDependencySpec(fromDir, targetPath) {
|
|
746
849
|
const relative = path.relative(fromDir, targetPath).replace(/\\/gu, '/');
|
|
747
850
|
const normalized = relative.startsWith('.') ? relative : `./${relative}`;
|
|
@@ -792,6 +895,7 @@ function resolveProjectRsxSpecs(
|
|
|
792
895
|
) {
|
|
793
896
|
const includeAngularPackage = Boolean(options.includeAngularPackage);
|
|
794
897
|
const includeReactPackage = Boolean(options.includeReactPackage);
|
|
898
|
+
const includeVuePackage = Boolean(options.includeVuePackage);
|
|
795
899
|
const versionSpec = options.tag ? options.tag : RSX_PACKAGE_VERSION;
|
|
796
900
|
const defaults = {
|
|
797
901
|
'@rs-x/core': versionSpec,
|
|
@@ -801,6 +905,7 @@ function resolveProjectRsxSpecs(
|
|
|
801
905
|
'@rs-x/typescript-plugin': versionSpec,
|
|
802
906
|
...(includeAngularPackage ? { '@rs-x/angular': versionSpec } : {}),
|
|
803
907
|
...(includeReactPackage ? { '@rs-x/react': versionSpec } : {}),
|
|
908
|
+
...(includeVuePackage ? { '@rs-x/vue': versionSpec } : {}),
|
|
804
909
|
'@rs-x/cli': versionSpec,
|
|
805
910
|
};
|
|
806
911
|
|
|
@@ -812,6 +917,7 @@ function resolveProjectRsxSpecs(
|
|
|
812
917
|
'@rs-x/typescript-plugin': 'rs-x-typescript-plugin',
|
|
813
918
|
...(includeAngularPackage ? { '@rs-x/angular': 'rs-x-angular' } : {}),
|
|
814
919
|
...(includeReactPackage ? { '@rs-x/react': 'rs-x-react' } : {}),
|
|
920
|
+
...(includeVuePackage ? { '@rs-x/vue': 'rs-x-vue' } : {}),
|
|
815
921
|
'@rs-x/cli': 'rs-x-cli',
|
|
816
922
|
};
|
|
817
923
|
|
|
@@ -839,6 +945,11 @@ function resolveProjectRsxSpecs(
|
|
|
839
945
|
'rs-x-react': path.join(tarballsDir, 'rs-x-react'),
|
|
840
946
|
}
|
|
841
947
|
: {}),
|
|
948
|
+
...(includeVuePackage
|
|
949
|
+
? {
|
|
950
|
+
'rs-x-vue': path.join(tarballsDir, 'rs-x-vue'),
|
|
951
|
+
}
|
|
952
|
+
: {}),
|
|
842
953
|
'rs-x-cli': path.join(tarballsDir, 'rs-x-cli'),
|
|
843
954
|
};
|
|
844
955
|
|
|
@@ -887,6 +998,11 @@ function resolveProjectRsxSpecs(
|
|
|
887
998
|
'@rs-x/react': path.join(workspaceRoot, 'rs-x-react'),
|
|
888
999
|
}
|
|
889
1000
|
: {}),
|
|
1001
|
+
...(includeVuePackage
|
|
1002
|
+
? {
|
|
1003
|
+
'@rs-x/vue': path.join(workspaceRoot, 'rs-x-vue'),
|
|
1004
|
+
}
|
|
1005
|
+
: {}),
|
|
890
1006
|
'@rs-x/cli': path.join(workspaceRoot, 'rs-x-cli'),
|
|
891
1007
|
};
|
|
892
1008
|
|
|
@@ -1681,6 +1797,224 @@ function applyReactDemoStarter(projectRoot, projectName, pm, flags) {
|
|
|
1681
1797
|
}
|
|
1682
1798
|
}
|
|
1683
1799
|
|
|
1800
|
+
function applyVueDemoStarter(projectRoot, projectName, pm, flags) {
|
|
1801
|
+
const dryRun = Boolean(flags['dry-run']);
|
|
1802
|
+
const tag = resolveInstallTag(flags);
|
|
1803
|
+
const tarballsDir =
|
|
1804
|
+
typeof flags['tarballs-dir'] === 'string'
|
|
1805
|
+
? path.resolve(process.cwd(), flags['tarballs-dir'])
|
|
1806
|
+
: typeof process.env.RSX_TARBALLS_DIR === 'string' &&
|
|
1807
|
+
process.env.RSX_TARBALLS_DIR.trim().length > 0
|
|
1808
|
+
? path.resolve(process.cwd(), process.env.RSX_TARBALLS_DIR)
|
|
1809
|
+
: null;
|
|
1810
|
+
const workspaceRoot = findRepoRoot(projectRoot);
|
|
1811
|
+
const rsxSpecs = resolveProjectRsxSpecs(
|
|
1812
|
+
projectRoot,
|
|
1813
|
+
workspaceRoot,
|
|
1814
|
+
tarballsDir,
|
|
1815
|
+
{ tag, includeVuePackage: true },
|
|
1816
|
+
);
|
|
1817
|
+
|
|
1818
|
+
const templateFiles = ['README.md', 'src'];
|
|
1819
|
+
for (const entry of templateFiles) {
|
|
1820
|
+
copyPathWithDryRun(
|
|
1821
|
+
path.join(VUE_DEMO_TEMPLATE_DIR, entry),
|
|
1822
|
+
path.join(projectRoot, entry),
|
|
1823
|
+
dryRun,
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
const staleVueFiles = [
|
|
1828
|
+
path.join(projectRoot, 'public'),
|
|
1829
|
+
];
|
|
1830
|
+
for (const stalePath of staleVueFiles) {
|
|
1831
|
+
removeFileOrDirectoryWithDryRun(stalePath, dryRun);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
const readmePath = path.join(projectRoot, 'README.md');
|
|
1835
|
+
if (fs.existsSync(readmePath)) {
|
|
1836
|
+
const readmeSource = fs.readFileSync(readmePath, 'utf8');
|
|
1837
|
+
const nextReadme = readmeSource.replace(
|
|
1838
|
+
/^#\s+rsx-vue-example/mu,
|
|
1839
|
+
`# ${projectName}`,
|
|
1840
|
+
);
|
|
1841
|
+
if (dryRun) {
|
|
1842
|
+
logInfo(`[dry-run] patch ${readmePath}`);
|
|
1843
|
+
} else {
|
|
1844
|
+
fs.writeFileSync(readmePath, nextReadme, 'utf8');
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
1849
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
1850
|
+
logError(`package.json not found in generated Vue app: ${packageJsonPath}`);
|
|
1851
|
+
process.exit(1);
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
1855
|
+
packageJson.name = projectName;
|
|
1856
|
+
packageJson.private = true;
|
|
1857
|
+
packageJson.version = '0.1.0';
|
|
1858
|
+
packageJson.type = 'module';
|
|
1859
|
+
packageJson.scripts = {
|
|
1860
|
+
'build:rsx': 'rsx build --project tsconfig.app.json --no-emit --prod',
|
|
1861
|
+
'typecheck:rsx': 'rsx typecheck --project tsconfig.app.json',
|
|
1862
|
+
dev: 'npm run build:rsx && vite',
|
|
1863
|
+
build: 'npm run build:rsx && vue-tsc -b && vite build',
|
|
1864
|
+
preview: 'vite preview',
|
|
1865
|
+
};
|
|
1866
|
+
packageJson.rsx = {
|
|
1867
|
+
build: {
|
|
1868
|
+
preparse: true,
|
|
1869
|
+
preparseFile: 'src/rsx-generated/rsx-aot-preparsed.generated.ts',
|
|
1870
|
+
compiled: true,
|
|
1871
|
+
compiledFile: 'src/rsx-generated/rsx-aot-compiled.generated.ts',
|
|
1872
|
+
compiledResolvedEvaluator: false,
|
|
1873
|
+
},
|
|
1874
|
+
};
|
|
1875
|
+
packageJson.dependencies = {
|
|
1876
|
+
vue: packageJson.dependencies?.vue ?? '^3.5.30',
|
|
1877
|
+
'@rs-x/core': rsxSpecs['@rs-x/core'],
|
|
1878
|
+
'@rs-x/state-manager': rsxSpecs['@rs-x/state-manager'],
|
|
1879
|
+
'@rs-x/expression-parser': rsxSpecs['@rs-x/expression-parser'],
|
|
1880
|
+
'@rs-x/vue': rsxSpecs['@rs-x/vue'],
|
|
1881
|
+
};
|
|
1882
|
+
packageJson.devDependencies = {
|
|
1883
|
+
...(packageJson.devDependencies ?? {}),
|
|
1884
|
+
'@rs-x/cli': rsxSpecs['@rs-x/cli'],
|
|
1885
|
+
'@rs-x/compiler': rsxSpecs['@rs-x/compiler'],
|
|
1886
|
+
'@rs-x/typescript-plugin': rsxSpecs['@rs-x/typescript-plugin'],
|
|
1887
|
+
};
|
|
1888
|
+
|
|
1889
|
+
if (dryRun) {
|
|
1890
|
+
logInfo(`[dry-run] patch ${packageJsonPath}`);
|
|
1891
|
+
} else {
|
|
1892
|
+
fs.writeFileSync(
|
|
1893
|
+
packageJsonPath,
|
|
1894
|
+
`${JSON.stringify(packageJson, null, 2)}\n`,
|
|
1895
|
+
'utf8',
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
const tsConfigAppPath = path.join(projectRoot, 'tsconfig.app.json');
|
|
1900
|
+
if (fs.existsSync(tsConfigAppPath)) {
|
|
1901
|
+
upsertTypescriptPluginInTsConfig(tsConfigAppPath, dryRun);
|
|
1902
|
+
ensureTsConfigIncludePattern(tsConfigAppPath, 'src/**/*.d.ts', dryRun);
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
if (!Boolean(flags['skip-install'])) {
|
|
1906
|
+
logInfo(`Refreshing ${pm} dependencies for the RS-X Vue starter...`);
|
|
1907
|
+
run(pm, ['install'], { dryRun });
|
|
1908
|
+
logOk('Vue starter dependencies are up to date.');
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
function applyNextDemoStarter(projectRoot, projectName, pm, flags) {
|
|
1913
|
+
const dryRun = Boolean(flags['dry-run']);
|
|
1914
|
+
const tag = resolveInstallTag(flags);
|
|
1915
|
+
const tarballsDir =
|
|
1916
|
+
typeof flags['tarballs-dir'] === 'string'
|
|
1917
|
+
? path.resolve(process.cwd(), flags['tarballs-dir'])
|
|
1918
|
+
: typeof process.env.RSX_TARBALLS_DIR === 'string' &&
|
|
1919
|
+
process.env.RSX_TARBALLS_DIR.trim().length > 0
|
|
1920
|
+
? path.resolve(process.cwd(), process.env.RSX_TARBALLS_DIR)
|
|
1921
|
+
: null;
|
|
1922
|
+
const workspaceRoot = findRepoRoot(projectRoot);
|
|
1923
|
+
const rsxSpecs = resolveProjectRsxSpecs(
|
|
1924
|
+
projectRoot,
|
|
1925
|
+
workspaceRoot,
|
|
1926
|
+
tarballsDir,
|
|
1927
|
+
{ tag, includeReactPackage: true },
|
|
1928
|
+
);
|
|
1929
|
+
|
|
1930
|
+
const templateFiles = ['README.md', 'app', 'components', 'hooks', 'lib'];
|
|
1931
|
+
for (const entry of templateFiles) {
|
|
1932
|
+
copyPathWithDryRun(
|
|
1933
|
+
path.join(NEXT_DEMO_TEMPLATE_DIR, entry),
|
|
1934
|
+
path.join(projectRoot, entry),
|
|
1935
|
+
dryRun,
|
|
1936
|
+
);
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
const readmePath = path.join(projectRoot, 'README.md');
|
|
1940
|
+
if (fs.existsSync(readmePath)) {
|
|
1941
|
+
const readmeSource = fs.readFileSync(readmePath, 'utf8');
|
|
1942
|
+
const nextReadme = readmeSource.replace(
|
|
1943
|
+
/^#\s+rsx-next-example/mu,
|
|
1944
|
+
`# ${projectName}`,
|
|
1945
|
+
);
|
|
1946
|
+
if (dryRun) {
|
|
1947
|
+
logInfo(`[dry-run] patch ${readmePath}`);
|
|
1948
|
+
} else {
|
|
1949
|
+
fs.writeFileSync(readmePath, nextReadme, 'utf8');
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
const publicDir = path.join(projectRoot, 'public');
|
|
1954
|
+
removeFileOrDirectoryWithDryRun(publicDir, dryRun);
|
|
1955
|
+
|
|
1956
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
1957
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
1958
|
+
logError(`package.json not found in generated Next.js app: ${packageJsonPath}`);
|
|
1959
|
+
process.exit(1);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
1963
|
+
packageJson.name = projectName;
|
|
1964
|
+
packageJson.private = true;
|
|
1965
|
+
packageJson.version = '0.1.0';
|
|
1966
|
+
packageJson.scripts = {
|
|
1967
|
+
...packageJson.scripts,
|
|
1968
|
+
'build:rsx': 'rsx build --project tsconfig.json --no-emit --prod',
|
|
1969
|
+
dev: 'npm run build:rsx && next dev',
|
|
1970
|
+
build: 'npm run build:rsx && next build',
|
|
1971
|
+
start: 'next start',
|
|
1972
|
+
};
|
|
1973
|
+
packageJson.rsx = {
|
|
1974
|
+
build: {
|
|
1975
|
+
preparse: true,
|
|
1976
|
+
preparseFile: 'app/rsx-generated/rsx-aot-preparsed.generated.ts',
|
|
1977
|
+
compiled: true,
|
|
1978
|
+
compiledFile: 'app/rsx-generated/rsx-aot-compiled.generated.ts',
|
|
1979
|
+
compiledResolvedEvaluator: false,
|
|
1980
|
+
},
|
|
1981
|
+
};
|
|
1982
|
+
packageJson.dependencies = {
|
|
1983
|
+
...(packageJson.dependencies ?? {}),
|
|
1984
|
+
'@rs-x/core': rsxSpecs['@rs-x/core'],
|
|
1985
|
+
'@rs-x/state-manager': rsxSpecs['@rs-x/state-manager'],
|
|
1986
|
+
'@rs-x/expression-parser': rsxSpecs['@rs-x/expression-parser'],
|
|
1987
|
+
'@rs-x/react': rsxSpecs['@rs-x/react'],
|
|
1988
|
+
};
|
|
1989
|
+
packageJson.devDependencies = {
|
|
1990
|
+
...(packageJson.devDependencies ?? {}),
|
|
1991
|
+
'@rs-x/cli': rsxSpecs['@rs-x/cli'],
|
|
1992
|
+
'@rs-x/compiler': rsxSpecs['@rs-x/compiler'],
|
|
1993
|
+
'@rs-x/typescript-plugin': rsxSpecs['@rs-x/typescript-plugin'],
|
|
1994
|
+
};
|
|
1995
|
+
|
|
1996
|
+
if (dryRun) {
|
|
1997
|
+
logInfo(`[dry-run] patch ${packageJsonPath}`);
|
|
1998
|
+
} else {
|
|
1999
|
+
fs.writeFileSync(
|
|
2000
|
+
packageJsonPath,
|
|
2001
|
+
`${JSON.stringify(packageJson, null, 2)}\n`,
|
|
2002
|
+
'utf8',
|
|
2003
|
+
);
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
const tsConfigPath = path.join(projectRoot, 'tsconfig.json');
|
|
2007
|
+
if (fs.existsSync(tsConfigPath)) {
|
|
2008
|
+
upsertTypescriptPluginInTsConfig(tsConfigPath, dryRun);
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
if (!Boolean(flags['skip-install'])) {
|
|
2012
|
+
logInfo(`Refreshing ${pm} dependencies for the RS-X Next.js starter...`);
|
|
2013
|
+
run(pm, ['install'], { dryRun });
|
|
2014
|
+
logOk('Next.js starter dependencies are up to date.');
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
1684
2018
|
async function runProjectWithTemplate(template, flags) {
|
|
1685
2019
|
const normalizedTemplate = normalizeProjectTemplate(template);
|
|
1686
2020
|
if (!normalizedTemplate) {
|
|
@@ -1720,15 +2054,11 @@ async function runProjectWithTemplate(template, flags) {
|
|
|
1720
2054
|
return;
|
|
1721
2055
|
}
|
|
1722
2056
|
if (normalizedTemplate === 'nextjs') {
|
|
1723
|
-
|
|
2057
|
+
applyNextDemoStarter(projectRoot, projectName, pm, flags);
|
|
1724
2058
|
return;
|
|
1725
2059
|
}
|
|
1726
2060
|
if (normalizedTemplate === 'vuejs') {
|
|
1727
|
-
|
|
1728
|
-
...flags,
|
|
1729
|
-
entry: flags.entry ?? 'src/main.ts',
|
|
1730
|
-
});
|
|
1731
|
-
applyVueRsxTemplate(projectRoot, dryRun);
|
|
2061
|
+
applyVueDemoStarter(projectRoot, projectName, pm, flags);
|
|
1732
2062
|
}
|
|
1733
2063
|
});
|
|
1734
2064
|
|
package/package.json
CHANGED
package/{rs-x-vscode-extension-2.0.0-next.15.vsix → rs-x-vscode-extension-2.0.0-next.17.vsix}
RENAMED
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# rsx-next-example
|
|
2
|
+
|
|
3
|
+
Website & docs: https://www.rsxjs.com/
|
|
4
|
+
|
|
5
|
+
This starter shows how to use RS-X in a Next.js app-router project with a
|
|
6
|
+
million-row virtual table that keeps rendering and expression memory bounded.
|
|
7
|
+
|
|
8
|
+
## Scripts
|
|
9
|
+
|
|
10
|
+
- `npm run dev` starts the Next.js dev server after running the RS-X build step
|
|
11
|
+
- `npm run build` generates RS-X artifacts and builds the production app
|
|
12
|
+
- `npm run start` starts the production server
|
|
13
|
+
|
|
14
|
+
## Structure
|
|
15
|
+
|
|
16
|
+
- `app/` contains the Next.js route files and global styles
|
|
17
|
+
- `components/` contains the client-side UI components
|
|
18
|
+
- `hooks/` contains reusable React hooks
|
|
19
|
+
- `lib/` contains the RS-X bootstrap and virtual-table state/data utilities
|
|
20
|
+
|
|
21
|
+
## Notes
|
|
22
|
+
|
|
23
|
+
- The demo defaults to dark mode.
|
|
24
|
+
- The UI uses `@rs-x/react` hooks in a Next.js client component tree.
|
|
25
|
+
- The generated RS-X cache files in `app/rsx-generated` are created by
|
|
26
|
+
`npm run build:rsx`; they are not checked into the starter template.
|