@tanstack/create 0.68.2 → 0.68.3
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/CHANGELOG.md +6 -0
- package/dist/edge-add-ons.js +106 -0
- package/dist/edge-config-file.js +15 -0
- package/dist/edge-create-app.js +438 -0
- package/dist/edge-environment.js +141 -0
- package/dist/edge-file-helpers.js +88 -0
- package/dist/edge-frameworks.js +33 -0
- package/dist/edge-package-json.js +146 -0
- package/dist/edge-path.js +62 -0
- package/dist/edge-render.js +31 -0
- package/dist/edge-template-file.js +141 -0
- package/dist/edge.js +7 -0
- package/dist/frameworks/react/add-ons/storybook/info.json +5 -10
- package/dist/generated/create-manifest.js +4683 -0
- package/dist/manifest-types.js +1 -0
- package/dist/manifest.js +1 -0
- package/dist/types/custom-add-ons/add-on.d.ts +5 -3
- package/dist/types/edge-add-ons.d.ts +5 -0
- package/dist/types/edge-config-file.d.ts +8 -0
- package/dist/types/edge-create-app.d.ts +2 -0
- package/dist/types/edge-environment.d.ts +19 -0
- package/dist/types/edge-file-helpers.d.ts +7 -0
- package/dist/types/edge-frameworks.d.ts +7 -0
- package/dist/types/edge-package-json.d.ts +3 -0
- package/dist/types/edge-path.d.ts +5 -0
- package/dist/types/edge-render.d.ts +1 -0
- package/dist/types/edge-template-file.d.ts +2 -0
- package/dist/types/edge.d.ts +9 -0
- package/dist/types/generated/create-manifest.d.ts +36 -0
- package/dist/types/manifest-types.d.ts +4 -0
- package/dist/types/manifest.d.ts +1 -0
- package/dist/types/types.d.ts +96 -56
- package/dist/types.js +5 -3
- package/package.json +25 -5
- package/scripts/generate-manifest.mjs +407 -0
- package/src/edge-add-ons.ts +138 -0
- package/src/edge-config-file.ts +35 -0
- package/src/edge-create-app.ts +594 -0
- package/src/edge-environment.ts +175 -0
- package/src/edge-file-helpers.ts +112 -0
- package/src/edge-frameworks.ts +54 -0
- package/src/edge-package-json.ts +212 -0
- package/src/edge-path.ts +77 -0
- package/src/edge-render.ts +32 -0
- package/src/edge-template-file.ts +204 -0
- package/src/edge.ts +43 -0
- package/src/frameworks/react/add-ons/storybook/info.json +5 -10
- package/src/generated/create-manifest.ts +6490 -0
- package/src/manifest-types.ts +8 -0
- package/src/manifest.ts +1 -0
- package/src/types.ts +5 -3
- package/tests/edge-import.test.ts +31 -0
- package/tests/edge-manifest.test.ts +168 -0
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.ts +0 -17
- package/dist/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.ts +0 -15
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.ts +0 -67
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +0 -47
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.stories.tsx +0 -92
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +0 -29
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/index.ts +0 -14
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.ts +0 -43
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +0 -39
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.ts +0 -53
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +0 -52
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.ts +0 -55
- package/dist/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +0 -57
- package/dist/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +0 -93
- package/dist/frameworks/react/add-ons/storybook/package.json +0 -10
- package/src/frameworks/react/add-ons/storybook/assets/_dot_storybook/main.ts +0 -17
- package/src/frameworks/react/add-ons/storybook/assets/_dot_storybook/preview.ts +0 -15
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.stories.ts +0 -67
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/button.tsx +0 -47
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.stories.tsx +0 -92
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/dialog.tsx +0 -29
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/index.ts +0 -14
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.stories.ts +0 -43
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/input.tsx +0 -39
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.stories.ts +0 -53
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/radio-group.tsx +0 -52
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.stories.ts +0 -55
- package/src/frameworks/react/add-ons/storybook/assets/src/components/storybook/slider.tsx +0 -57
- package/src/frameworks/react/add-ons/storybook/assets/src/routes/demo/storybook.tsx +0 -93
- package/src/frameworks/react/add-ons/storybook/package.json +0 -10
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { cleanUpFileArray, cleanUpFiles } from './edge-file-helpers.js'
|
|
2
|
+
import {
|
|
3
|
+
basenamePath,
|
|
4
|
+
dirnamePath,
|
|
5
|
+
joinPaths,
|
|
6
|
+
normalizePath,
|
|
7
|
+
} from './edge-path.js'
|
|
8
|
+
|
|
9
|
+
import type { Environment } from './types.js'
|
|
10
|
+
|
|
11
|
+
export interface MemoryEnvironmentOutput {
|
|
12
|
+
files: Record<string, string>
|
|
13
|
+
deletedFiles: Array<string>
|
|
14
|
+
commands: Array<{ command: string; args: Array<string> }>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function hasDirectory(files: Record<string, string>, path: string) {
|
|
18
|
+
const directory = normalizePath(path)
|
|
19
|
+
const prefix = directory.endsWith('/') ? directory : `${directory}/`
|
|
20
|
+
return Object.keys(files).some((file) => file.startsWith(prefix))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createMissingDirectoryError(path: string) {
|
|
24
|
+
return new Error(`Directory not found: ${path}`)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createMemoryEnvironment(returnPathsRelativeTo: string = '') {
|
|
28
|
+
const output: MemoryEnvironmentOutput = {
|
|
29
|
+
files: {},
|
|
30
|
+
commands: [],
|
|
31
|
+
deletedFiles: [],
|
|
32
|
+
}
|
|
33
|
+
const files: Record<string, string> = {}
|
|
34
|
+
let errors: Array<string> = []
|
|
35
|
+
|
|
36
|
+
const environment: Environment = {
|
|
37
|
+
startRun: () => {
|
|
38
|
+
errors = []
|
|
39
|
+
output.files = {}
|
|
40
|
+
output.commands = []
|
|
41
|
+
output.deletedFiles = []
|
|
42
|
+
},
|
|
43
|
+
finishRun: () => {
|
|
44
|
+
output.files = Object.keys(files).reduce<Record<string, string>>(
|
|
45
|
+
(acc, file) => {
|
|
46
|
+
acc[file] = files[file]
|
|
47
|
+
return acc
|
|
48
|
+
},
|
|
49
|
+
{},
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if (returnPathsRelativeTo.length) {
|
|
53
|
+
output.files = cleanUpFiles(output.files, returnPathsRelativeTo)
|
|
54
|
+
output.deletedFiles = cleanUpFileArray(
|
|
55
|
+
output.deletedFiles,
|
|
56
|
+
returnPathsRelativeTo,
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
getErrors: () => errors,
|
|
61
|
+
|
|
62
|
+
appendFile: (path: string, contents: string) => {
|
|
63
|
+
const normalized = normalizePath(path)
|
|
64
|
+
files[normalized] = `${files[normalized] ?? ''}${contents}`
|
|
65
|
+
return Promise.resolve()
|
|
66
|
+
},
|
|
67
|
+
copyFile: (from: string, to: string) => {
|
|
68
|
+
const normalizedFrom = normalizePath(from)
|
|
69
|
+
const normalizedTo = normalizePath(to)
|
|
70
|
+
if (!(normalizedFrom in files)) {
|
|
71
|
+
throw new Error(`File not found: ${from}`)
|
|
72
|
+
}
|
|
73
|
+
files[normalizedTo] = files[normalizedFrom]
|
|
74
|
+
return Promise.resolve()
|
|
75
|
+
},
|
|
76
|
+
writeFile: (path: string, contents: string) => {
|
|
77
|
+
files[normalizePath(path)] = contents
|
|
78
|
+
return Promise.resolve()
|
|
79
|
+
},
|
|
80
|
+
writeFileBase64: (path: string, base64Contents: string) => {
|
|
81
|
+
files[normalizePath(path)] = base64Contents
|
|
82
|
+
return Promise.resolve()
|
|
83
|
+
},
|
|
84
|
+
execute: (command: string, args: Array<string>) => {
|
|
85
|
+
output.commands.push({
|
|
86
|
+
command,
|
|
87
|
+
args,
|
|
88
|
+
})
|
|
89
|
+
return Promise.resolve({ stdout: '' })
|
|
90
|
+
},
|
|
91
|
+
deleteFile: (path: string) => {
|
|
92
|
+
const normalized = normalizePath(path)
|
|
93
|
+
output.deletedFiles.push(normalized)
|
|
94
|
+
delete files[normalized]
|
|
95
|
+
return Promise.resolve()
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
exists: (path: string) => {
|
|
99
|
+
const normalized = normalizePath(path)
|
|
100
|
+
return normalized in files || hasDirectory(files, normalized)
|
|
101
|
+
},
|
|
102
|
+
isDirectory: (path: string) => hasDirectory(files, path),
|
|
103
|
+
readFile: (path: string) => {
|
|
104
|
+
const normalized = normalizePath(path)
|
|
105
|
+
if (!(normalized in files)) {
|
|
106
|
+
throw new Error(`File not found: ${path}`)
|
|
107
|
+
}
|
|
108
|
+
return Promise.resolve(files[normalized])
|
|
109
|
+
},
|
|
110
|
+
readdir: (path: string) => {
|
|
111
|
+
const normalized = normalizePath(path)
|
|
112
|
+
const directory = normalized === '.' ? '' : normalized
|
|
113
|
+
const prefix = directory ? `${directory}/` : ''
|
|
114
|
+
|
|
115
|
+
if (directory && !hasDirectory(files, directory)) {
|
|
116
|
+
throw createMissingDirectoryError(path)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const entries = new Set<string>()
|
|
120
|
+
for (const file of Object.keys(files)) {
|
|
121
|
+
if (!file.startsWith(prefix)) {
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const rest = file.slice(prefix.length)
|
|
126
|
+
const entry = rest.split('/')[0]
|
|
127
|
+
if (entry) {
|
|
128
|
+
entries.add(entry)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return Promise.resolve(Array.from(entries))
|
|
133
|
+
},
|
|
134
|
+
rimraf: (path: string) => {
|
|
135
|
+
const normalized = normalizePath(path)
|
|
136
|
+
const prefix = normalized.endsWith('/') ? normalized : `${normalized}/`
|
|
137
|
+
for (const file of Object.keys(files)) {
|
|
138
|
+
if (file === normalized || file.startsWith(prefix)) {
|
|
139
|
+
delete files[file]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return Promise.resolve()
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
appName: 'TanStack',
|
|
146
|
+
|
|
147
|
+
startStep: () => {},
|
|
148
|
+
finishStep: () => {},
|
|
149
|
+
|
|
150
|
+
intro: () => {},
|
|
151
|
+
outro: () => {},
|
|
152
|
+
info: () => {},
|
|
153
|
+
error: (_title?: string, message?: string) => {
|
|
154
|
+
if (message) {
|
|
155
|
+
errors.push(message)
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
warn: () => {},
|
|
159
|
+
confirm: () => Promise.resolve(true),
|
|
160
|
+
spinner: () => ({
|
|
161
|
+
start: () => {},
|
|
162
|
+
stop: () => {},
|
|
163
|
+
}),
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
environment,
|
|
168
|
+
output,
|
|
169
|
+
paths: {
|
|
170
|
+
basename: basenamePath,
|
|
171
|
+
dirname: dirnamePath,
|
|
172
|
+
join: joinPaths,
|
|
173
|
+
},
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { basenamePath, extnamePath } from './edge-path.js'
|
|
2
|
+
import { hasDrive, stripDrive } from './utils.js'
|
|
3
|
+
|
|
4
|
+
const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico']
|
|
5
|
+
|
|
6
|
+
export function isBinaryFile(path: string): boolean {
|
|
7
|
+
return BINARY_EXTENSIONS.includes(extnamePath(path))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isBase64(content: string): boolean {
|
|
11
|
+
return content.startsWith('base64::')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function toCleanPath(absolutePath: string, baseDir: string): string {
|
|
15
|
+
const normalizedPath = absolutePath.replace(/\\/g, '/')
|
|
16
|
+
const normalizedBase = baseDir.replace(/\\/g, '/')
|
|
17
|
+
let cleanPath = normalizedPath
|
|
18
|
+
if (normalizedPath.startsWith(normalizedBase)) {
|
|
19
|
+
cleanPath = normalizedPath.slice(normalizedBase.length)
|
|
20
|
+
} else if (hasDrive(normalizedPath) !== hasDrive(normalizedBase)) {
|
|
21
|
+
const pathNoDrive = stripDrive(normalizedPath)
|
|
22
|
+
const baseNoDrive = stripDrive(normalizedBase)
|
|
23
|
+
if (pathNoDrive.startsWith(baseNoDrive)) {
|
|
24
|
+
cleanPath = pathNoDrive.slice(baseNoDrive.length)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (cleanPath.startsWith('/')) {
|
|
28
|
+
cleanPath = cleanPath.slice(1)
|
|
29
|
+
}
|
|
30
|
+
return cleanPath
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function relativePath(
|
|
34
|
+
from: string,
|
|
35
|
+
to: string,
|
|
36
|
+
stripExtension: boolean = false,
|
|
37
|
+
) {
|
|
38
|
+
const normalized = from.replace(/\\/g, '/')
|
|
39
|
+
const cleanedFrom = normalized.startsWith('./')
|
|
40
|
+
? normalized.slice(2)
|
|
41
|
+
: normalized
|
|
42
|
+
const cleanedTo = to.startsWith('./') ? to.slice(2) : to
|
|
43
|
+
|
|
44
|
+
const fromSegments = cleanedFrom.split('/')
|
|
45
|
+
const toSegments = cleanedTo.split('/')
|
|
46
|
+
|
|
47
|
+
fromSegments.pop()
|
|
48
|
+
toSegments.pop()
|
|
49
|
+
|
|
50
|
+
let commonIndex = 0
|
|
51
|
+
while (
|
|
52
|
+
commonIndex < fromSegments.length &&
|
|
53
|
+
commonIndex < toSegments.length &&
|
|
54
|
+
fromSegments[commonIndex] === toSegments[commonIndex]
|
|
55
|
+
) {
|
|
56
|
+
commonIndex++
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const upLevels = fromSegments.length - commonIndex
|
|
60
|
+
const downLevels = toSegments.slice(commonIndex)
|
|
61
|
+
const target = stripExtension ? to.replace(extnamePath(to), '') : to
|
|
62
|
+
|
|
63
|
+
if (upLevels === 0 && downLevels.length === 0) {
|
|
64
|
+
return `./${basenamePath(target)}`
|
|
65
|
+
} else if (upLevels === 0 && downLevels.length > 0) {
|
|
66
|
+
return `./${downLevels.join('/')}/${basenamePath(target)}`
|
|
67
|
+
} else {
|
|
68
|
+
const relative = [...Array(upLevels).fill('..'), ...downLevels].join('/')
|
|
69
|
+
return `${relative}/${basenamePath(target)}`
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isDemoFilePath(path?: string): boolean {
|
|
74
|
+
if (!path) return false
|
|
75
|
+
const normalized = path.replace(/\\/g, '/')
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
normalized.includes('/routes/demo/') ||
|
|
79
|
+
normalized.includes('/routes/example/')
|
|
80
|
+
) {
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const filename = normalized.split('/').pop() || ''
|
|
85
|
+
return (
|
|
86
|
+
filename.startsWith('demo.') ||
|
|
87
|
+
filename.startsWith('demo-') ||
|
|
88
|
+
filename.startsWith('example.') ||
|
|
89
|
+
filename.startsWith('example-')
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function cleanUpFiles(
|
|
94
|
+
files: Record<string, string>,
|
|
95
|
+
targetDir?: string,
|
|
96
|
+
) {
|
|
97
|
+
return Object.keys(files).reduce<Record<string, string>>((acc, file) => {
|
|
98
|
+
if (basenamePath(file) !== '.cta.json') {
|
|
99
|
+
acc[targetDir ? toCleanPath(file, targetDir) : file] = files[file]
|
|
100
|
+
}
|
|
101
|
+
return acc
|
|
102
|
+
}, {})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function cleanUpFileArray(files: Array<string>, targetDir?: string) {
|
|
106
|
+
return files.reduce<Array<string>>((acc, file) => {
|
|
107
|
+
if (basenamePath(file) !== '.cta.json') {
|
|
108
|
+
acc.push(targetDir ? toCleanPath(file, targetDir) : file)
|
|
109
|
+
}
|
|
110
|
+
return acc
|
|
111
|
+
}, [])
|
|
112
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createManifestFrameworks } from './generated/create-manifest.js'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
AddOn,
|
|
5
|
+
AddOnCompiled,
|
|
6
|
+
Framework,
|
|
7
|
+
FrameworkDefinition,
|
|
8
|
+
} from './types.js'
|
|
9
|
+
|
|
10
|
+
function createAddOn(addOn: AddOnCompiled): AddOn {
|
|
11
|
+
return {
|
|
12
|
+
...addOn,
|
|
13
|
+
getFiles: () => Promise.resolve(Object.keys(addOn.files)),
|
|
14
|
+
getFileContents: (path: string) => Promise.resolve(addOn.files[path]),
|
|
15
|
+
getDeletedFiles: () => Promise.resolve(addOn.deletedFiles),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createFrameworkFromManifest(
|
|
20
|
+
framework: Omit<FrameworkDefinition, 'addOns'> & {
|
|
21
|
+
addOns: Array<AddOnCompiled>
|
|
22
|
+
},
|
|
23
|
+
): Framework {
|
|
24
|
+
const addOns = framework.addOns.map(createAddOn)
|
|
25
|
+
const { addOns: _addOns, base, ...rest } = framework
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
...rest,
|
|
29
|
+
getFiles: () => Promise.resolve(Object.keys(base)),
|
|
30
|
+
getFileContents: (path: string) => Promise.resolve(base[path]),
|
|
31
|
+
getDeletedFiles: () => Promise.resolve([]),
|
|
32
|
+
getAddOns: () => addOns,
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const frameworks = createManifestFrameworks().map(createFrameworkFromManifest)
|
|
37
|
+
|
|
38
|
+
export function getFrameworkById(id: string) {
|
|
39
|
+
if (id === 'react-cra') {
|
|
40
|
+
return frameworks.find((framework) => framework.id === 'react')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return frameworks.find((framework) => framework.id === id)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getFrameworkByName(name: string) {
|
|
47
|
+
return frameworks.find(
|
|
48
|
+
(framework) => framework.name.toLowerCase() === name.toLowerCase(),
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getFrameworks() {
|
|
53
|
+
return frameworks
|
|
54
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { render } from './edge-render.js'
|
|
2
|
+
import { formatCommand, sortObject } from './utils.js'
|
|
3
|
+
import { getPackageManagerExecuteCommand } from './package-manager.js'
|
|
4
|
+
|
|
5
|
+
import type { Options } from './types.js'
|
|
6
|
+
|
|
7
|
+
export function mergePackageJSON(
|
|
8
|
+
packageJSON: Record<string, unknown>,
|
|
9
|
+
overlayPackageJSON?: Record<string, unknown>,
|
|
10
|
+
) {
|
|
11
|
+
const packageDependencies =
|
|
12
|
+
packageJSON.dependencies && typeof packageJSON.dependencies === 'object'
|
|
13
|
+
? (packageJSON.dependencies as Record<string, string>)
|
|
14
|
+
: {}
|
|
15
|
+
const overlayDependencies =
|
|
16
|
+
overlayPackageJSON?.dependencies &&
|
|
17
|
+
typeof overlayPackageJSON.dependencies === 'object'
|
|
18
|
+
? (overlayPackageJSON.dependencies as Record<string, string>)
|
|
19
|
+
: {}
|
|
20
|
+
const packageDevDependencies =
|
|
21
|
+
packageJSON.devDependencies && typeof packageJSON.devDependencies === 'object'
|
|
22
|
+
? (packageJSON.devDependencies as Record<string, string>)
|
|
23
|
+
: {}
|
|
24
|
+
const overlayDevDependencies =
|
|
25
|
+
overlayPackageJSON?.devDependencies &&
|
|
26
|
+
typeof overlayPackageJSON.devDependencies === 'object'
|
|
27
|
+
? (overlayPackageJSON.devDependencies as Record<string, string>)
|
|
28
|
+
: {}
|
|
29
|
+
const packageScripts =
|
|
30
|
+
packageJSON.scripts && typeof packageJSON.scripts === 'object'
|
|
31
|
+
? (packageJSON.scripts as Record<string, string>)
|
|
32
|
+
: {}
|
|
33
|
+
const overlayScripts =
|
|
34
|
+
overlayPackageJSON?.scripts && typeof overlayPackageJSON.scripts === 'object'
|
|
35
|
+
? (overlayPackageJSON.scripts as Record<string, string>)
|
|
36
|
+
: {}
|
|
37
|
+
|
|
38
|
+
const mergedPackageJSON: Record<string, unknown> = {
|
|
39
|
+
...packageJSON,
|
|
40
|
+
...(overlayPackageJSON || {}),
|
|
41
|
+
dependencies: {
|
|
42
|
+
...packageDependencies,
|
|
43
|
+
...overlayDependencies,
|
|
44
|
+
},
|
|
45
|
+
devDependencies: {
|
|
46
|
+
...packageDevDependencies,
|
|
47
|
+
...overlayDevDependencies,
|
|
48
|
+
},
|
|
49
|
+
scripts: {
|
|
50
|
+
...packageScripts,
|
|
51
|
+
...overlayScripts,
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const packagePnpm =
|
|
56
|
+
packageJSON.pnpm && typeof packageJSON.pnpm === 'object'
|
|
57
|
+
? (packageJSON.pnpm as Record<string, unknown>)
|
|
58
|
+
: undefined
|
|
59
|
+
const overlayPnpm =
|
|
60
|
+
overlayPackageJSON?.pnpm && typeof overlayPackageJSON.pnpm === 'object'
|
|
61
|
+
? (overlayPackageJSON.pnpm as Record<string, unknown>)
|
|
62
|
+
: undefined
|
|
63
|
+
|
|
64
|
+
const baseOnlyBuiltDependencies = Array.isArray(
|
|
65
|
+
packagePnpm?.onlyBuiltDependencies,
|
|
66
|
+
)
|
|
67
|
+
? packagePnpm.onlyBuiltDependencies
|
|
68
|
+
: []
|
|
69
|
+
const overlayOnlyBuiltDependencies = Array.isArray(
|
|
70
|
+
overlayPnpm?.onlyBuiltDependencies,
|
|
71
|
+
)
|
|
72
|
+
? overlayPnpm.onlyBuiltDependencies
|
|
73
|
+
: []
|
|
74
|
+
|
|
75
|
+
const onlyBuiltDependencies = [
|
|
76
|
+
...new Set([
|
|
77
|
+
...baseOnlyBuiltDependencies,
|
|
78
|
+
...overlayOnlyBuiltDependencies,
|
|
79
|
+
]),
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
if (packagePnpm || overlayPnpm) {
|
|
83
|
+
mergedPackageJSON.pnpm = {
|
|
84
|
+
...packagePnpm,
|
|
85
|
+
...overlayPnpm,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (onlyBuiltDependencies.length) {
|
|
89
|
+
const mergedPnpm = mergedPackageJSON.pnpm as Record<string, unknown>
|
|
90
|
+
mergedPnpm.onlyBuiltDependencies = onlyBuiltDependencies
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return mergedPackageJSON
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function createPackageJSON(options: Options) {
|
|
98
|
+
const packageManager = options.packageManager
|
|
99
|
+
|
|
100
|
+
function getPackageManagerExecuteScript(
|
|
101
|
+
pkg: string,
|
|
102
|
+
args: Array<string> = [],
|
|
103
|
+
) {
|
|
104
|
+
return formatCommand(getPackageManagerExecuteCommand(packageManager, pkg, args))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let packageJSON: Record<string, unknown> = {
|
|
108
|
+
...(JSON.parse(
|
|
109
|
+
JSON.stringify(options.framework.basePackageJSON),
|
|
110
|
+
) as Record<string, unknown>),
|
|
111
|
+
name: options.projectName,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const additions: Array<Record<string, unknown> | undefined> = [
|
|
115
|
+
options.framework.optionalPackages.typescript,
|
|
116
|
+
options.framework.optionalPackages.tailwindcss,
|
|
117
|
+
options.mode ? options.framework.optionalPackages[options.mode] : undefined,
|
|
118
|
+
]
|
|
119
|
+
for (const addition of additions.filter(
|
|
120
|
+
(addition): addition is Record<string, unknown> => Boolean(addition),
|
|
121
|
+
)) {
|
|
122
|
+
packageJSON = mergePackageJSON(packageJSON, addition)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
for (const addOn of options.chosenAddOns) {
|
|
126
|
+
let addOnPackageJSON = addOn.packageAdditions as
|
|
127
|
+
| Record<string, unknown>
|
|
128
|
+
| undefined
|
|
129
|
+
|
|
130
|
+
if (addOn.packageTemplate) {
|
|
131
|
+
const templateValues = {
|
|
132
|
+
packageManager: options.packageManager,
|
|
133
|
+
projectName: options.projectName,
|
|
134
|
+
typescript: true,
|
|
135
|
+
tailwind: true,
|
|
136
|
+
js: 'ts',
|
|
137
|
+
jsx: 'tsx',
|
|
138
|
+
fileRouter: options.mode === 'file-router',
|
|
139
|
+
codeRouter: options.mode === 'code-router',
|
|
140
|
+
routerOnly: options.routerOnly === true,
|
|
141
|
+
addOnEnabled: options.chosenAddOns.reduce<Record<string, boolean>>(
|
|
142
|
+
(acc, addon) => {
|
|
143
|
+
acc[addon.id] = true
|
|
144
|
+
return acc
|
|
145
|
+
},
|
|
146
|
+
{},
|
|
147
|
+
),
|
|
148
|
+
addOnOption: options.addOnOptions,
|
|
149
|
+
addOns: options.chosenAddOns,
|
|
150
|
+
getPackageManagerExecuteScript,
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
addOnPackageJSON = JSON.parse(render(addOn.packageTemplate, templateValues))
|
|
155
|
+
} catch (error) {
|
|
156
|
+
console.error(
|
|
157
|
+
`Error processing package.json.ejs for add-on ${addOn.id}:`,
|
|
158
|
+
error,
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
packageJSON = mergePackageJSON(packageJSON, addOnPackageJSON)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (options.starter) {
|
|
167
|
+
packageJSON = mergePackageJSON(
|
|
168
|
+
packageJSON,
|
|
169
|
+
options.starter.packageAdditions as Record<string, unknown> | undefined,
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const dependencies = packageJSON.dependencies as
|
|
174
|
+
| Record<string, string>
|
|
175
|
+
| undefined
|
|
176
|
+
const devDependencies = packageJSON.devDependencies as
|
|
177
|
+
| Record<string, string>
|
|
178
|
+
| undefined
|
|
179
|
+
const scripts = packageJSON.scripts as Record<string, string> | undefined
|
|
180
|
+
|
|
181
|
+
if (options.routerOnly) {
|
|
182
|
+
if (options.framework.id === 'react') {
|
|
183
|
+
delete dependencies?.['@tanstack/react-start']
|
|
184
|
+
delete dependencies?.['@tanstack/react-router-ssr-query']
|
|
185
|
+
packageJSON.devDependencies = {
|
|
186
|
+
...(devDependencies ?? {}),
|
|
187
|
+
'@tanstack/router-plugin':
|
|
188
|
+
devDependencies?.['@tanstack/router-plugin'] ?? 'latest',
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (options.framework.id === 'solid') {
|
|
193
|
+
delete dependencies?.['@tanstack/solid-start']
|
|
194
|
+
delete dependencies?.['@tanstack/solid-router-ssr-query']
|
|
195
|
+
delete scripts?.start
|
|
196
|
+
packageJSON.devDependencies = {
|
|
197
|
+
...(devDependencies ?? {}),
|
|
198
|
+
'@tanstack/router-plugin':
|
|
199
|
+
devDependencies?.['@tanstack/router-plugin'] ?? 'latest',
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
packageJSON.dependencies = sortObject(
|
|
205
|
+
(packageJSON.dependencies ?? {}) as Record<string, string>,
|
|
206
|
+
)
|
|
207
|
+
packageJSON.devDependencies = sortObject(
|
|
208
|
+
(packageJSON.devDependencies ?? {}) as Record<string, string>,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
return packageJSON
|
|
212
|
+
}
|
package/src/edge-path.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export function normalizePath(path: string): string {
|
|
2
|
+
const normalized = path.replace(/\\/g, '/')
|
|
3
|
+
const isAbsolute = normalized.startsWith('/')
|
|
4
|
+
const parts: Array<string> = []
|
|
5
|
+
|
|
6
|
+
for (const part of normalized.split('/')) {
|
|
7
|
+
if (!part || part === '.') {
|
|
8
|
+
continue
|
|
9
|
+
}
|
|
10
|
+
if (part === '..') {
|
|
11
|
+
if (parts.length && parts[parts.length - 1] !== '..') {
|
|
12
|
+
parts.pop()
|
|
13
|
+
} else if (!isAbsolute) {
|
|
14
|
+
parts.push(part)
|
|
15
|
+
}
|
|
16
|
+
continue
|
|
17
|
+
}
|
|
18
|
+
parts.push(part)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const joined = parts.join('/')
|
|
22
|
+
if (isAbsolute) {
|
|
23
|
+
return joined ? `/${joined}` : '/'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return joined || '.'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function joinPaths(...paths: Array<string | undefined>): string {
|
|
30
|
+
const filtered = paths.filter(
|
|
31
|
+
(path): path is string => typeof path === 'string' && path.length > 0,
|
|
32
|
+
)
|
|
33
|
+
if (!filtered.length) {
|
|
34
|
+
return '.'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return normalizePath(filtered.join('/'))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function basenamePath(path: string): string {
|
|
41
|
+
const normalized = normalizePath(path)
|
|
42
|
+
if (normalized === '/') {
|
|
43
|
+
return ''
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return normalized.split('/').pop() ?? ''
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function dirnamePath(path: string): string {
|
|
50
|
+
const normalized = normalizePath(path)
|
|
51
|
+
if (normalized === '/') {
|
|
52
|
+
return '/'
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const parts = normalized.split('/')
|
|
56
|
+
parts.pop()
|
|
57
|
+
|
|
58
|
+
if (!parts.length) {
|
|
59
|
+
return '.'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (parts.length === 1 && parts[0] === '') {
|
|
63
|
+
return '/'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return parts.join('/') || '.'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function extnamePath(path: string): string {
|
|
70
|
+
const basename = basenamePath(path)
|
|
71
|
+
const index = basename.lastIndexOf('.')
|
|
72
|
+
if (index <= 0) {
|
|
73
|
+
return ''
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return basename.slice(index)
|
|
77
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { renderManifestTemplate } from './generated/create-manifest.js'
|
|
2
|
+
|
|
3
|
+
export function render(template: string, data?: Record<string, any>) {
|
|
4
|
+
return renderManifestTemplate(template, {
|
|
5
|
+
packageManager: undefined,
|
|
6
|
+
projectName: undefined,
|
|
7
|
+
typescript: undefined,
|
|
8
|
+
tailwind: undefined,
|
|
9
|
+
js: undefined,
|
|
10
|
+
jsx: undefined,
|
|
11
|
+
fileRouter: undefined,
|
|
12
|
+
codeRouter: undefined,
|
|
13
|
+
routerOnly: undefined,
|
|
14
|
+
includeExamples: undefined,
|
|
15
|
+
addOnEnabled: {},
|
|
16
|
+
addOnOption: {},
|
|
17
|
+
addOns: [],
|
|
18
|
+
integrations: [],
|
|
19
|
+
routes: [],
|
|
20
|
+
getPackageManagerAddScript: () => '',
|
|
21
|
+
getPackageManagerRunScript: () => '',
|
|
22
|
+
getPackageManagerExecuteScript: () => '',
|
|
23
|
+
relativePath: () => '',
|
|
24
|
+
integrationImportContent: () => '',
|
|
25
|
+
integrationImportCode: () => '',
|
|
26
|
+
renderTemplate: () => '',
|
|
27
|
+
ignoreFile: () => {
|
|
28
|
+
throw new Error('ignoreFile')
|
|
29
|
+
},
|
|
30
|
+
...(data ?? {}),
|
|
31
|
+
})
|
|
32
|
+
}
|