create-esmx 3.0.0-rc.45 → 3.0.0-rc.47
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/dist/cli.integration.test.mjs +11 -7
- package/dist/cli.mjs +19 -18
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +1 -0
- package/dist/project.mjs +2 -2
- package/dist/project.test.mjs +21 -43
- package/dist/types.d.ts +1 -0
- package/dist/utils/project-name.d.ts +32 -14
- package/dist/utils/project-name.mjs +36 -11
- package/dist/utils/project-name.test.d.ts +0 -3
- package/dist/utils/project-name.test.mjs +251 -105
- package/package.json +5 -4
- package/src/cli.integration.test.ts +11 -7
- package/src/cli.ts +23 -19
- package/src/index.ts +2 -0
- package/src/project.test.ts +21 -46
- package/src/project.ts +6 -3
- package/src/types.ts +1 -0
- package/src/utils/project-name.test.ts +299 -203
- package/src/utils/project-name.ts +73 -27
- package/template/vue2-csr/README.md +80 -0
- package/template/vue2-csr/package.json +26 -0
- package/template/vue2-csr/src/components/hello-world.vue +77 -0
- package/template/vue2-csr/src/entry.node.ts +32 -0
- package/template/vue2-csr/src/entry.server.ts +26 -0
- package/template/{vue2 → vue2-ssr}/package.json +1 -1
- package/template/vue2-ssr/src/app.vue +127 -0
- package/template/vue2-ssr/src/create-app.ts +11 -0
- package/template/vue2-ssr/src/entry.client.ts +5 -0
- package/template/{vue2 → vue2-ssr}/src/entry.node.ts +1 -1
- package/template/vue2-ssr/tsconfig.json +26 -0
- /package/template/{vue2 → vue2-csr}/src/app.vue +0 -0
- /package/template/{vue2 → vue2-csr}/src/create-app.ts +0 -0
- /package/template/{vue2 → vue2-csr}/src/entry.client.ts +0 -0
- /package/template/{vue2 → vue2-csr}/tsconfig.json +0 -0
- /package/template/{vue2 → vue2-ssr}/README.md +0 -0
- /package/template/{vue2 → vue2-ssr}/src/components/hello-world.vue +0 -0
- /package/template/{vue2 → vue2-ssr}/src/entry.server.ts +0 -0
|
@@ -1,186 +1,332 @@
|
|
|
1
|
-
import { basename } from "node:path";
|
|
2
1
|
import { describe, expect, it } from "vitest";
|
|
3
2
|
import { formatProjectName } from "./project-name.mjs";
|
|
3
|
+
const isWindows = process.platform === "win32";
|
|
4
|
+
const isUnix = !isWindows;
|
|
4
5
|
describe("project-name utilities", () => {
|
|
5
6
|
describe("formatProjectName", () => {
|
|
6
7
|
it("should handle simple project name", () => {
|
|
7
8
|
const input = "foo";
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
expect(result.
|
|
9
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
10
|
+
const result = formatProjectName(input, cwd);
|
|
11
|
+
expect(result.name).toBe("foo");
|
|
12
|
+
if (isWindows) {
|
|
13
|
+
expect(result.root).toBe("C:\\workspace\\foo");
|
|
14
|
+
} else {
|
|
15
|
+
expect(result.root).toBe("/home/user/foo");
|
|
16
|
+
}
|
|
11
17
|
});
|
|
12
18
|
it("should handle nested path project name", () => {
|
|
13
|
-
const input = "foo/bar";
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
expect(result.
|
|
19
|
+
const input = isWindows ? "foo\\bar" : "foo/bar";
|
|
20
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
21
|
+
const result = formatProjectName(input, cwd);
|
|
22
|
+
expect(result.name).toBe("bar");
|
|
23
|
+
if (isWindows) {
|
|
24
|
+
expect(result.root).toBe("C:\\workspace\\foo\\bar");
|
|
25
|
+
} else {
|
|
26
|
+
expect(result.root).toBe("/home/user/foo/bar");
|
|
27
|
+
}
|
|
17
28
|
});
|
|
18
29
|
it("should handle scoped package name", () => {
|
|
19
30
|
const input = "@scope/foo";
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
expect(result.
|
|
31
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
32
|
+
const result = formatProjectName(input, cwd);
|
|
33
|
+
expect(result.name).toBe("@scope/foo");
|
|
34
|
+
if (isWindows) {
|
|
35
|
+
expect(result.root).toBe("C:\\workspace\\@scope\\foo");
|
|
36
|
+
} else {
|
|
37
|
+
expect(result.root).toBe("/home/user/@scope/foo");
|
|
38
|
+
}
|
|
23
39
|
});
|
|
24
40
|
it("should handle relative path project name", () => {
|
|
25
|
-
const input = "./foo/bar";
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
expect(result.
|
|
41
|
+
const input = isWindows ? ".\\foo\\bar" : "./foo/bar";
|
|
42
|
+
const cwd = isWindows ? "C:\\workspace\\current" : "/home/user/current";
|
|
43
|
+
const result = formatProjectName(input, cwd);
|
|
44
|
+
expect(result.name).toBe("bar");
|
|
45
|
+
if (isWindows) {
|
|
46
|
+
expect(result.root).toBe("C:\\workspace\\current\\foo\\bar");
|
|
47
|
+
} else {
|
|
48
|
+
expect(result.root).toBe("/home/user/current/foo/bar");
|
|
49
|
+
}
|
|
29
50
|
});
|
|
30
51
|
it("should handle absolute path project name", () => {
|
|
31
|
-
const input = "/root/path/to/foo";
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
const input = isWindows ? "C:\\projects\\my-app" : "/root/path/to/foo";
|
|
53
|
+
const cwd = isWindows ? "D:\\workspace" : "/home/user";
|
|
54
|
+
const result = formatProjectName(input, cwd);
|
|
55
|
+
if (isWindows) {
|
|
56
|
+
expect(result.name).toBe("my-app");
|
|
57
|
+
expect(result.root).toBe("C:\\projects\\my-app");
|
|
58
|
+
} else {
|
|
59
|
+
expect(result.name).toBe("foo");
|
|
60
|
+
expect(result.root).toBe("/root/path/to/foo");
|
|
61
|
+
}
|
|
35
62
|
});
|
|
36
63
|
it("should handle current directory", () => {
|
|
37
64
|
const input = ".";
|
|
38
|
-
const
|
|
39
|
-
const result = formatProjectName(input);
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
const cwd = isWindows ? "C:\\Users\\Developer\\Projects\\WindowsApp" : "/home/user/projects/my-app";
|
|
66
|
+
const result = formatProjectName(input, cwd);
|
|
67
|
+
if (isWindows) {
|
|
68
|
+
expect(result.name).toBe("WindowsApp");
|
|
69
|
+
expect(result.root).toBe(
|
|
70
|
+
"C:\\Users\\Developer\\Projects\\WindowsApp"
|
|
71
|
+
);
|
|
72
|
+
} else {
|
|
73
|
+
expect(result.name).toBe("my-app");
|
|
74
|
+
expect(result.root).toBe("/home/user/projects/my-app");
|
|
75
|
+
}
|
|
42
76
|
});
|
|
43
77
|
it("should handle project name with trailing slashes", () => {
|
|
44
|
-
const input = "foo/
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
expect(result.
|
|
78
|
+
const input = isWindows ? "foo\\" : "foo/";
|
|
79
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
80
|
+
const result = formatProjectName(input, cwd);
|
|
81
|
+
expect(result.name).toBe("foo");
|
|
82
|
+
if (isWindows) {
|
|
83
|
+
expect(result.root).toBe("C:\\workspace\\foo");
|
|
84
|
+
} else {
|
|
85
|
+
expect(result.root).toBe("/home/user/foo");
|
|
86
|
+
}
|
|
48
87
|
});
|
|
49
88
|
it("should handle project name with multiple trailing slashes", () => {
|
|
50
|
-
const input = "
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
expect(result.
|
|
89
|
+
const input = isWindows ? "foo\\\\\\" : "foo///";
|
|
90
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
91
|
+
const result = formatProjectName(input, cwd);
|
|
92
|
+
expect(result.name).toBe("foo");
|
|
93
|
+
if (isWindows) {
|
|
94
|
+
expect(result.root).toBe("C:\\workspace\\foo");
|
|
95
|
+
} else {
|
|
96
|
+
expect(result.root).toBe("/home/user/foo");
|
|
97
|
+
}
|
|
54
98
|
});
|
|
55
99
|
it("should handle deep nested path", () => {
|
|
56
|
-
const input = "
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
expect(result.
|
|
100
|
+
const input = isWindows ? "path\\to\\nested\\project" : "path/to/nested/project";
|
|
101
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
102
|
+
const result = formatProjectName(input, cwd);
|
|
103
|
+
expect(result.name).toBe("project");
|
|
104
|
+
if (isWindows) {
|
|
105
|
+
expect(result.root).toBe(
|
|
106
|
+
"C:\\workspace\\path\\to\\nested\\project"
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
expect(result.root).toBe("/home/user/path/to/nested/project");
|
|
110
|
+
}
|
|
60
111
|
});
|
|
61
112
|
it("should handle scoped package with nested path", () => {
|
|
62
|
-
const input = "
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
expect(result.
|
|
113
|
+
const input = isWindows ? "@company\\ui\\library" : "@company/ui/library";
|
|
114
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
115
|
+
const result = formatProjectName(input, cwd);
|
|
116
|
+
expect(result.name).toBe(input);
|
|
117
|
+
if (isWindows) {
|
|
118
|
+
expect(result.root).toBe(
|
|
119
|
+
"C:\\workspace\\@company\\ui\\library"
|
|
120
|
+
);
|
|
121
|
+
} else {
|
|
122
|
+
expect(result.root).toBe("/home/user/@company/ui/library");
|
|
123
|
+
}
|
|
66
124
|
});
|
|
67
125
|
it("should handle scoped package starting with @", () => {
|
|
68
|
-
const input = "@
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
expect(result.
|
|
126
|
+
const input = "@my-org/my-package";
|
|
127
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
128
|
+
const result = formatProjectName(input, cwd);
|
|
129
|
+
expect(result.name).toBe("@my-org/my-package");
|
|
130
|
+
if (isWindows) {
|
|
131
|
+
expect(result.root).toBe("C:\\workspace\\@my-org\\my-package");
|
|
132
|
+
} else {
|
|
133
|
+
expect(result.root).toBe("/home/user/@my-org/my-package");
|
|
134
|
+
}
|
|
72
135
|
});
|
|
73
136
|
it("should handle empty path segment", () => {
|
|
74
|
-
const input = "
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
expect(result.
|
|
137
|
+
const input = isWindows ? "path\\\\with\\\\segments" : "path//with//segments";
|
|
138
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
139
|
+
const result = formatProjectName(input, cwd);
|
|
140
|
+
expect(result.name).toBe("segments");
|
|
141
|
+
if (isWindows) {
|
|
142
|
+
expect(result.root).toBe("C:\\workspace\\path\\with\\segments");
|
|
143
|
+
} else {
|
|
144
|
+
expect(result.root).toBe("/home/user/path/with/segments");
|
|
145
|
+
}
|
|
78
146
|
});
|
|
79
147
|
it("should handle single character project name", () => {
|
|
80
148
|
const input = "a";
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
expect(result.
|
|
149
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
150
|
+
const result = formatProjectName(input, cwd);
|
|
151
|
+
expect(result.name).toBe("a");
|
|
152
|
+
if (isWindows) {
|
|
153
|
+
expect(result.root).toBe("C:\\workspace\\a");
|
|
154
|
+
} else {
|
|
155
|
+
expect(result.root).toBe("/home/user/a");
|
|
156
|
+
}
|
|
84
157
|
});
|
|
85
158
|
it("should handle project name with numbers and hyphens", () => {
|
|
86
|
-
const input = "my-project-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
expect(result.
|
|
159
|
+
const input = "my-project-123";
|
|
160
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
161
|
+
const result = formatProjectName(input, cwd);
|
|
162
|
+
expect(result.name).toBe("my-project-123");
|
|
163
|
+
if (isWindows) {
|
|
164
|
+
expect(result.root).toBe("C:\\workspace\\my-project-123");
|
|
165
|
+
} else {
|
|
166
|
+
expect(result.root).toBe("/home/user/my-project-123");
|
|
167
|
+
}
|
|
90
168
|
});
|
|
91
169
|
it("should handle project name ending with slash", () => {
|
|
92
|
-
const input = "
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
expect(result.
|
|
170
|
+
const input = isWindows ? "my-project\\" : "my-project/";
|
|
171
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
172
|
+
const result = formatProjectName(input, cwd);
|
|
173
|
+
expect(result.name).toBe("my-project");
|
|
174
|
+
if (isWindows) {
|
|
175
|
+
expect(result.root).toBe("C:\\workspace\\my-project");
|
|
176
|
+
} else {
|
|
177
|
+
expect(result.root).toBe("/home/user/my-project");
|
|
178
|
+
}
|
|
96
179
|
});
|
|
97
180
|
it("should fall back to default name when path ends with slash and no name", () => {
|
|
98
181
|
const input = "/";
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
expect(result.
|
|
182
|
+
const cwd = isWindows ? "C:\\workspace" : "/home/user";
|
|
183
|
+
const result = formatProjectName(input, cwd);
|
|
184
|
+
expect(result.root).toBe("/");
|
|
185
|
+
expect(result.name).toBe("esmx-project");
|
|
102
186
|
});
|
|
103
|
-
it(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
187
|
+
it.runIf(isWindows)(
|
|
188
|
+
"should handle Windows-style absolute paths",
|
|
189
|
+
() => {
|
|
190
|
+
const input = "C:\\projects\\my-app";
|
|
191
|
+
const cwd = "D:\\workspace";
|
|
192
|
+
const result = formatProjectName(input, cwd);
|
|
193
|
+
expect(result.name).toBe("my-app");
|
|
194
|
+
expect(result.root).toMatch(/projects[\\\/]my-app/);
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
it.runIf(isWindows)("should handle Windows UNC paths", () => {
|
|
198
|
+
const input = "\\\\server\\share\\project";
|
|
199
|
+
const cwd = "C:\\workspace";
|
|
200
|
+
const result = formatProjectName(input, cwd);
|
|
201
|
+
expect(result.name).toBe("project");
|
|
202
|
+
expect(result.root).toMatch(/project$/);
|
|
108
203
|
});
|
|
109
|
-
it("should handle mixed path separators", () => {
|
|
110
|
-
const input = "path\\to/
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
expect(result.
|
|
204
|
+
it.runIf(isUnix)("should handle mixed path separators on Unix", () => {
|
|
205
|
+
const input = "path\\to/mixed/separators";
|
|
206
|
+
const cwd = "/home/user";
|
|
207
|
+
const result = formatProjectName(input, cwd);
|
|
208
|
+
expect(result.name).toBe("separators");
|
|
209
|
+
expect(result.root).toBe("/home/user/path\\to/mixed/separators");
|
|
114
210
|
});
|
|
211
|
+
it.runIf(isWindows)(
|
|
212
|
+
"should handle Windows-style relative paths",
|
|
213
|
+
() => {
|
|
214
|
+
const input = "foo\\bar";
|
|
215
|
+
const cwd = "C:\\workspace";
|
|
216
|
+
const result = formatProjectName(input, cwd);
|
|
217
|
+
expect(result.name).toBe("bar");
|
|
218
|
+
expect(result.root).toMatch(/workspace[\\\/]foo[\\\/]bar/);
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
it.runIf(isWindows)(
|
|
222
|
+
"should handle Windows-style trailing backslashes",
|
|
223
|
+
() => {
|
|
224
|
+
const input = "foo\\bar\\\\\\";
|
|
225
|
+
const cwd = "C:\\workspace";
|
|
226
|
+
const result = formatProjectName(input, cwd);
|
|
227
|
+
expect(result.name).toBe("bar");
|
|
228
|
+
expect(result.root).toMatch(/workspace[\\\/]foo[\\\/]bar/);
|
|
229
|
+
}
|
|
230
|
+
);
|
|
115
231
|
});
|
|
116
232
|
describe("formatProjectName with cwd parameter", () => {
|
|
117
233
|
it('should use custom cwd when input is "."', () => {
|
|
118
234
|
const input = ".";
|
|
119
|
-
const customCwd = "/custom/
|
|
235
|
+
const customCwd = isWindows ? "C:\\custom\\path\\to\\project" : "/custom/path/to/project";
|
|
120
236
|
const result = formatProjectName(
|
|
121
237
|
input,
|
|
122
238
|
customCwd
|
|
123
239
|
);
|
|
124
|
-
expect(result.
|
|
125
|
-
expect(result.
|
|
240
|
+
expect(result.name).toBe("project");
|
|
241
|
+
expect(result.root).toBe(customCwd);
|
|
126
242
|
});
|
|
127
243
|
it("should fallback to process.cwd() when cwd is not provided", () => {
|
|
128
|
-
const input = "
|
|
129
|
-
const expectedPackageName = basename(process.cwd());
|
|
244
|
+
const input = "test-project";
|
|
130
245
|
const result = formatProjectName(input);
|
|
131
|
-
expect(result.
|
|
132
|
-
expect(result.
|
|
246
|
+
expect(result.name).toBe("test-project");
|
|
247
|
+
expect(result.root).toMatch(/test-project$/);
|
|
133
248
|
});
|
|
134
249
|
it('should ignore cwd parameter when input is not "."', () => {
|
|
135
250
|
const input = "my-project";
|
|
136
|
-
const customCwd = "/custom/
|
|
251
|
+
const customCwd = isWindows ? "C:\\custom\\path" : "/custom/path";
|
|
137
252
|
const result = formatProjectName(
|
|
138
253
|
input,
|
|
139
254
|
customCwd
|
|
140
255
|
);
|
|
141
|
-
expect(result.
|
|
142
|
-
|
|
256
|
+
expect(result.name).toBe("my-project");
|
|
257
|
+
if (isWindows) {
|
|
258
|
+
expect(result.root).toBe("C:\\custom\\path\\my-project");
|
|
259
|
+
} else {
|
|
260
|
+
expect(result.root).toBe("/custom/path/my-project");
|
|
261
|
+
}
|
|
143
262
|
});
|
|
144
263
|
it("should handle scoped packages with custom cwd", () => {
|
|
145
|
-
const input = "@scope/
|
|
146
|
-
const customCwd = "/
|
|
264
|
+
const input = "@scope/foo";
|
|
265
|
+
const customCwd = isWindows ? "C:\\custom\\workspace" : "/custom/workspace";
|
|
147
266
|
const result = formatProjectName(
|
|
148
267
|
input,
|
|
149
268
|
customCwd
|
|
150
269
|
);
|
|
151
|
-
expect(result.
|
|
152
|
-
|
|
270
|
+
expect(result.name).toBe("@scope/foo");
|
|
271
|
+
if (isWindows) {
|
|
272
|
+
expect(result.root).toBe("C:\\custom\\workspace\\@scope\\foo");
|
|
273
|
+
} else {
|
|
274
|
+
expect(result.root).toBe("/custom/workspace/@scope/foo");
|
|
275
|
+
}
|
|
153
276
|
});
|
|
154
277
|
it("should handle nested paths with custom cwd", () => {
|
|
155
|
-
const input = "
|
|
156
|
-
const customCwd = "/
|
|
278
|
+
const input = isWindows ? "foo\\bar" : "foo/bar";
|
|
279
|
+
const customCwd = isWindows ? "C:\\custom\\workspace" : "/custom/workspace";
|
|
157
280
|
const result = formatProjectName(
|
|
158
281
|
input,
|
|
159
282
|
customCwd
|
|
160
283
|
);
|
|
161
|
-
expect(result.
|
|
162
|
-
|
|
284
|
+
expect(result.name).toBe("bar");
|
|
285
|
+
if (isWindows) {
|
|
286
|
+
expect(result.root).toBe("C:\\custom\\workspace\\foo\\bar");
|
|
287
|
+
} else {
|
|
288
|
+
expect(result.root).toBe("/custom/workspace/foo/bar");
|
|
289
|
+
}
|
|
163
290
|
});
|
|
164
|
-
it(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
291
|
+
it.runIf(isUnix)(
|
|
292
|
+
"should handle Unix-style absolute paths in cwd",
|
|
293
|
+
() => {
|
|
294
|
+
const input = "/root/path/to/foo";
|
|
295
|
+
const customCwd = "/this/should/be/ignored";
|
|
296
|
+
const result = formatProjectName(
|
|
297
|
+
input,
|
|
298
|
+
customCwd
|
|
299
|
+
);
|
|
300
|
+
expect(result.name).toBe("foo");
|
|
301
|
+
expect(result.root).toBe("/root/path/to/foo");
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
it.runIf(isWindows)(
|
|
305
|
+
"should handle Windows-style absolute paths in cwd",
|
|
306
|
+
() => {
|
|
307
|
+
const input = "C:\\projects\\my-app";
|
|
308
|
+
const customCwd = "D:\\this\\should\\be\\ignored";
|
|
309
|
+
const result = formatProjectName(
|
|
310
|
+
input,
|
|
311
|
+
customCwd
|
|
312
|
+
);
|
|
313
|
+
expect(result.name).toBe("my-app");
|
|
314
|
+
expect(result.root).toBe("C:\\projects\\my-app");
|
|
315
|
+
}
|
|
316
|
+
);
|
|
317
|
+
it("should handle absolute input paths and ignore cwd", () => {
|
|
318
|
+
const input = isWindows ? "C:\\projects\\absolute-project" : "/projects/absolute-project";
|
|
319
|
+
const customCwd = isWindows ? "D:\\ignored" : "/ignored";
|
|
177
320
|
const result = formatProjectName(
|
|
178
321
|
input,
|
|
179
322
|
customCwd
|
|
180
323
|
);
|
|
181
|
-
expect(result.
|
|
182
|
-
|
|
183
|
-
|
|
324
|
+
expect(result.name).toBe("absolute-project");
|
|
325
|
+
if (isWindows) {
|
|
326
|
+
expect(result.root).toBe("C:\\projects\\absolute-project");
|
|
327
|
+
} else {
|
|
328
|
+
expect(result.root).toBe("/projects/absolute-project");
|
|
329
|
+
}
|
|
184
330
|
});
|
|
185
331
|
});
|
|
186
332
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-esmx",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.47",
|
|
4
4
|
"description": "A scaffold tool for creating Esmx projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"test": "vitest run --pass-with-no-tests",
|
|
15
15
|
"coverage": "vitest run --coverage --pass-with-no-tests",
|
|
16
16
|
"lint:js": "biome check --write --no-errors-on-unmatched",
|
|
17
|
-
"build": "unbuild"
|
|
17
|
+
"build": "unbuild",
|
|
18
|
+
"postbuild": "node build/postbuild.mjs"
|
|
18
19
|
},
|
|
19
20
|
"dependencies": {
|
|
20
21
|
"@clack/prompts": "^0.7.0",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
26
|
"@biomejs/biome": "1.9.4",
|
|
26
|
-
"@esmx/lint": "3.0.0-rc.
|
|
27
|
+
"@esmx/lint": "3.0.0-rc.47",
|
|
27
28
|
"@types/minimist": "^1.2.5",
|
|
28
29
|
"@types/node": "^24.0.0",
|
|
29
30
|
"@vitest/coverage-v8": "3.2.4",
|
|
@@ -68,5 +69,5 @@
|
|
|
68
69
|
"url": "https://github.com/esmnext/esmx/issues"
|
|
69
70
|
},
|
|
70
71
|
"homepage": "https://github.com/esmnext/esmx#readme",
|
|
71
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "3e55424b9029d259537a802032f3a1f54b6fb1e8"
|
|
72
73
|
}
|
|
@@ -133,7 +133,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
133
133
|
const projectPath = join(tmpDir, 'test-project');
|
|
134
134
|
|
|
135
135
|
await cli({
|
|
136
|
-
argv: ['test-project', '--template', 'vue2'],
|
|
136
|
+
argv: ['test-project', '--template', 'vue2-csr'],
|
|
137
137
|
cwd: tmpDir,
|
|
138
138
|
userAgent: 'npm/test'
|
|
139
139
|
});
|
|
@@ -141,7 +141,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
141
141
|
expect(existsSync(join(projectPath, 'package.json'))).toBe(true);
|
|
142
142
|
|
|
143
143
|
await cli({
|
|
144
|
-
argv: ['test-project', '--template', 'vue2', '--force'],
|
|
144
|
+
argv: ['test-project', '--template', 'vue2-csr', '--force'],
|
|
145
145
|
cwd: tmpDir,
|
|
146
146
|
userAgent: 'npm/test'
|
|
147
147
|
});
|
|
@@ -202,7 +202,11 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
202
202
|
const projectPath = join(tmpDir, 'non-existent-parent', 'test-project');
|
|
203
203
|
|
|
204
204
|
await cli({
|
|
205
|
-
argv: [
|
|
205
|
+
argv: [
|
|
206
|
+
'non-existent-parent/test-project',
|
|
207
|
+
'--template',
|
|
208
|
+
'vue2-csr'
|
|
209
|
+
],
|
|
206
210
|
cwd: tmpDir,
|
|
207
211
|
userAgent: 'npm/test'
|
|
208
212
|
});
|
|
@@ -222,7 +226,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
222
226
|
);
|
|
223
227
|
|
|
224
228
|
await cli({
|
|
225
|
-
argv: ['test-project', '--template', 'vue2', '--force'],
|
|
229
|
+
argv: ['test-project', '--template', 'vue2-csr', '--force'],
|
|
226
230
|
cwd: tmpDir,
|
|
227
231
|
userAgent: 'npm/test'
|
|
228
232
|
});
|
|
@@ -236,7 +240,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
236
240
|
await writeFile(testFile, 'existing content');
|
|
237
241
|
|
|
238
242
|
await cli({
|
|
239
|
-
argv: ['.', '--template', 'vue2', '--force'],
|
|
243
|
+
argv: ['.', '--template', 'vue2-csr', '--force'],
|
|
240
244
|
cwd: tmpDir,
|
|
241
245
|
userAgent: 'npm/test'
|
|
242
246
|
});
|
|
@@ -248,7 +252,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
248
252
|
|
|
249
253
|
it('should create project in current directory when target is "."', async () => {
|
|
250
254
|
await cli({
|
|
251
|
-
argv: ['.', '--template', 'vue2'],
|
|
255
|
+
argv: ['.', '--template', 'vue2-csr'],
|
|
252
256
|
cwd: tmpDir,
|
|
253
257
|
userAgent: 'npm/test'
|
|
254
258
|
});
|
|
@@ -269,7 +273,7 @@ describe('create-esmx CLI integration tests', () => {
|
|
|
269
273
|
const projectPath = join(tmpDir, projectName);
|
|
270
274
|
|
|
271
275
|
await cli({
|
|
272
|
-
argv: [projectName, '--template', 'vue2'],
|
|
276
|
+
argv: [projectName, '--template', 'vue2-csr'],
|
|
273
277
|
cwd: tmpDir,
|
|
274
278
|
userAgent: 'npm/test'
|
|
275
279
|
});
|
package/src/cli.ts
CHANGED
|
@@ -28,7 +28,7 @@ ${color.bold('Usage:')}
|
|
|
28
28
|
${createCmd} [project-name] [options]
|
|
29
29
|
|
|
30
30
|
${color.bold('Options:')}
|
|
31
|
-
-t, --template <template> Template to use (default: vue2)
|
|
31
|
+
-t, --template <template> Template to use (default: vue2-csr)
|
|
32
32
|
-n, --name <name> Project name or path
|
|
33
33
|
-f, --force Force overwrite existing directory
|
|
34
34
|
-h, --help Show help information
|
|
@@ -36,9 +36,9 @@ ${color.bold('Options:')}
|
|
|
36
36
|
|
|
37
37
|
${color.bold('Examples:')}
|
|
38
38
|
${createCmd} my-project
|
|
39
|
-
${createCmd} my-project -t vue2
|
|
39
|
+
${createCmd} my-project -t vue2-csr
|
|
40
40
|
${createCmd} my-project --force
|
|
41
|
-
${createCmd} . -f -t vue2
|
|
41
|
+
${createCmd} . -f -t vue2-csr
|
|
42
42
|
|
|
43
43
|
${color.bold('Available Templates:')}
|
|
44
44
|
${getAvailableTemplates()
|
|
@@ -80,7 +80,7 @@ async function getProjectName(
|
|
|
80
80
|
/**
|
|
81
81
|
* Get template type from arguments or prompt user
|
|
82
82
|
*/
|
|
83
|
-
async function getTemplateType(argTemplate?: string): Promise<string
|
|
83
|
+
async function getTemplateType(argTemplate?: string): Promise<string> {
|
|
84
84
|
const availableTemplates = getAvailableTemplates();
|
|
85
85
|
|
|
86
86
|
if (
|
|
@@ -101,14 +101,14 @@ async function getTemplateType(argTemplate?: string): Promise<string | symbol> {
|
|
|
101
101
|
options: options
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
return template
|
|
104
|
+
return String(template);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* Main function to create a project
|
|
109
109
|
*/
|
|
110
110
|
export async function cli(options: CliOptions = {}): Promise<void> {
|
|
111
|
-
const { argv, cwd, userAgent } = options;
|
|
111
|
+
const { argv, cwd, userAgent, version } = options;
|
|
112
112
|
const commandLineArgs = argv || process.argv.slice(2);
|
|
113
113
|
const workingDir = cwd || process.cwd();
|
|
114
114
|
|
|
@@ -150,10 +150,7 @@ export async function cli(options: CliOptions = {}): Promise<void> {
|
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
const {
|
|
154
|
-
projectNameInput,
|
|
155
|
-
workingDir
|
|
156
|
-
);
|
|
153
|
+
const { name, root } = formatProjectName(projectNameInput, workingDir);
|
|
157
154
|
|
|
158
155
|
const templateType = await getTemplateType(parsedArgs.template);
|
|
159
156
|
if (isCancel(templateType)) {
|
|
@@ -169,13 +166,13 @@ export async function cli(options: CliOptions = {}): Promise<void> {
|
|
|
169
166
|
const lintTypeCommand = getCommand('lint:type', userAgent);
|
|
170
167
|
|
|
171
168
|
await createProjectFromTemplate(
|
|
172
|
-
|
|
169
|
+
root,
|
|
173
170
|
templateType,
|
|
174
171
|
workingDir,
|
|
175
172
|
parsedArgs.force,
|
|
176
173
|
{
|
|
177
|
-
projectName:
|
|
178
|
-
esmxVersion: getEsmxVersion(),
|
|
174
|
+
projectName: name,
|
|
175
|
+
esmxVersion: version || getEsmxVersion(),
|
|
179
176
|
installCommand,
|
|
180
177
|
devCommand,
|
|
181
178
|
buildCommand,
|
|
@@ -187,12 +184,19 @@ export async function cli(options: CliOptions = {}): Promise<void> {
|
|
|
187
184
|
const installCmd = installCommand;
|
|
188
185
|
const devCmd = devCommand;
|
|
189
186
|
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
187
|
+
const targetDirForDisplay =
|
|
188
|
+
projectNameInput === '.' ? '.' : projectNameInput;
|
|
189
|
+
|
|
190
|
+
const steps = [
|
|
191
|
+
projectNameInput !== '.' ? `cd ${targetDirForDisplay}` : null,
|
|
192
|
+
installCmd,
|
|
193
|
+
`git init ${color.gray('(optional)')}`,
|
|
194
|
+
devCmd
|
|
195
|
+
].filter(Boolean);
|
|
196
|
+
|
|
197
|
+
const nextSteps = steps.map((step, index) => {
|
|
198
|
+
return color.reset(`${index + 1}. ${color.cyan(step)}`);
|
|
199
|
+
});
|
|
196
200
|
|
|
197
201
|
note(nextSteps.join('\n'), 'Next steps');
|
|
198
202
|
|
package/src/index.ts
CHANGED