create-medusa-app 3.0.0-snapshot-20250410105645 → 3.0.0-snapshot-20251104004624
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 +157 -2
- package/dist/index.js +1 -0
- package/dist/utils/execute.js +7 -5
- package/dist/utils/facts.js +16 -16
- package/dist/utils/nextjs-utils.js +10 -5
- package/dist/utils/package-manager.js +68 -0
- package/dist/utils/postgres-client.js +1 -1
- package/dist/utils/prepare-project.js +10 -54
- package/dist/utils/project-creator/creator.js +3 -0
- package/dist/utils/project-creator/medusa-plugin-creator.js +1 -0
- package/dist/utils/project-creator/medusa-project-creator.js +7 -3
- package/dist/utils/project-creator/project-creator-factory.js +14 -0
- package/dist/utils/update-package-versions.js +23 -0
- package/package.json +11 -33
- package/src/index.ts +1 -0
- package/src/utils/create-db.ts +1 -1
- package/src/utils/execute.ts +7 -5
- package/src/utils/facts.ts +16 -16
- package/src/utils/logger.ts +1 -1
- package/src/utils/nextjs-utils.ts +13 -4
- package/src/utils/package-manager.ts +87 -0
- package/src/utils/postgres-client.ts +2 -2
- package/src/utils/prepare-project.ts +17 -52
- package/src/utils/project-creator/creator.ts +4 -0
- package/src/utils/project-creator/medusa-plugin-creator.ts +1 -0
- package/src/utils/project-creator/medusa-project-creator.ts +7 -3
- package/src/utils/project-creator/project-creator-factory.ts +18 -0
- package/src/utils/update-package-versions.ts +31 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,166 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## 3.0.0-snapshot-
|
|
3
|
+
## 3.0.0-snapshot-20251104004624
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#13910](https://github.com/medusajs/medusa/pull/13910) [`224ab39a81e8d3cf3d6fa3ff5eee82541f64728d`](https://github.com/medusajs/medusa/commit/224ab39a81e8d3cf3d6fa3ff5eee82541f64728d) Thanks [@adrien2p](https://github.com/adrien2p)! - chore(): Dependencies cleanup and improvements
|
|
8
|
+
|
|
9
|
+
- [#13940](https://github.com/medusajs/medusa/pull/13940) [`afb40d437b3cc4ceb015df70985b2f005f40eaff`](https://github.com/medusajs/medusa/commit/afb40d437b3cc4ceb015df70985b2f005f40eaff) Thanks [@adrien2p](https://github.com/adrien2p)! - chore(): Cleanup and organize deps
|
|
10
|
+
|
|
11
|
+
- [#13932](https://github.com/medusajs/medusa/pull/13932) [`37563987b8fe75c9acfe62957a33e8398977647a`](https://github.com/medusajs/medusa/commit/37563987b8fe75c9acfe62957a33e8398977647a) Thanks [@adrien2p](https://github.com/adrien2p)! - chore(): Fix dependencies vulnerabilities
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`224ab39a81e8d3cf3d6fa3ff5eee82541f64728d`](https://github.com/medusajs/medusa/commit/224ab39a81e8d3cf3d6fa3ff5eee82541f64728d), [`afb40d437b3cc4ceb015df70985b2f005f40eaff`](https://github.com/medusajs/medusa/commit/afb40d437b3cc4ceb015df70985b2f005f40eaff), [`37563987b8fe75c9acfe62957a33e8398977647a`](https://github.com/medusajs/medusa/commit/37563987b8fe75c9acfe62957a33e8398977647a)]:
|
|
14
|
+
- @medusajs/deps@3.0.0-snapshot-20251104004624
|
|
15
|
+
- @medusajs/telemetry@3.0.0-snapshot-20251104004624
|
|
16
|
+
|
|
17
|
+
## 2.11.2
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies []:
|
|
22
|
+
- @medusajs/deps@2.11.2
|
|
23
|
+
- @medusajs/telemetry@2.11.2
|
|
24
|
+
|
|
25
|
+
## 2.11.1
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- Updated dependencies []:
|
|
30
|
+
- @medusajs/deps@2.11.1
|
|
31
|
+
- @medusajs/telemetry@2.11.1
|
|
32
|
+
|
|
33
|
+
## 2.11.0
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- [#13439](https://github.com/medusajs/medusa/pull/13439) [`12a96a7c7015f011f5e29a1d387f835e514ba536`](https://github.com/medusajs/medusa/commit/12a96a7c7015f011f5e29a1d387f835e514ba536) Thanks [@adrien2p](https://github.com/adrien2p)! - chore(): Move peer deps into a single package and re export from framework
|
|
38
|
+
|
|
39
|
+
- [#13450](https://github.com/medusajs/medusa/pull/13450) [`8ece06d8ed6a197ebb370918c49a3ec5c21dd186`](https://github.com/medusajs/medusa/commit/8ece06d8ed6a197ebb370918c49a3ec5c21dd186) Thanks [@adrien2p](https://github.com/adrien2p)! - chore(): Upgrade mikro orm 6.5.4
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [[`0cbd9f0bc315b3eda1770ac301061f1576856387`](https://github.com/medusajs/medusa/commit/0cbd9f0bc315b3eda1770ac301061f1576856387), [`12a96a7c7015f011f5e29a1d387f835e514ba536`](https://github.com/medusajs/medusa/commit/12a96a7c7015f011f5e29a1d387f835e514ba536), [`41651721450c99e5f38cfbb87a6a47ab067ece86`](https://github.com/medusajs/medusa/commit/41651721450c99e5f38cfbb87a6a47ab067ece86), [`fc67fd0b36f53f0c0897df54ecea02061e65e816`](https://github.com/medusajs/medusa/commit/fc67fd0b36f53f0c0897df54ecea02061e65e816), [`c54c5ed6de2c9686f89aeef86c5c607c4b5f1cf3`](https://github.com/medusajs/medusa/commit/c54c5ed6de2c9686f89aeef86c5c607c4b5f1cf3), [`02b6d013822b9665f868c4ea6d1b5cfe58723459`](https://github.com/medusajs/medusa/commit/02b6d013822b9665f868c4ea6d1b5cfe58723459)]:
|
|
42
|
+
- @medusajs/deps@2.11.0
|
|
43
|
+
- @medusajs/telemetry@2.11.0
|
|
44
|
+
|
|
45
|
+
## 2.10.3
|
|
46
|
+
|
|
47
|
+
### Patch Changes
|
|
48
|
+
|
|
49
|
+
- Updated dependencies []:
|
|
50
|
+
- @medusajs/telemetry@2.10.3
|
|
51
|
+
|
|
52
|
+
## 2.10.2
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- Updated dependencies []:
|
|
57
|
+
- @medusajs/telemetry@2.10.2
|
|
58
|
+
|
|
59
|
+
## 2.10.1
|
|
60
|
+
|
|
61
|
+
### Patch Changes
|
|
62
|
+
|
|
63
|
+
- Updated dependencies []:
|
|
64
|
+
- @medusajs/telemetry@2.10.1
|
|
65
|
+
|
|
66
|
+
## 2.10.0
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- Updated dependencies []:
|
|
71
|
+
- @medusajs/telemetry@2.10.0
|
|
72
|
+
|
|
73
|
+
## 2.9.0
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- Updated dependencies []:
|
|
78
|
+
- @medusajs/telemetry@2.9.0
|
|
79
|
+
|
|
80
|
+
## 2.8.8
|
|
81
|
+
|
|
82
|
+
### Patch Changes
|
|
83
|
+
|
|
84
|
+
- Updated dependencies []:
|
|
85
|
+
- @medusajs/telemetry@2.8.8
|
|
86
|
+
|
|
87
|
+
## 2.8.7
|
|
88
|
+
|
|
89
|
+
### Patch Changes
|
|
90
|
+
|
|
91
|
+
- [#12882](https://github.com/medusajs/medusa/pull/12882) [`779ed018b9c1328d6554a0f3d3569147edaeae56`](https://github.com/medusajs/medusa/commit/779ed018b9c1328d6554a0f3d3569147edaeae56) Thanks [@adrien2p](https://github.com/adrien2p)! - feat(create-medusa-app): Allow to create project with specific medusa version
|
|
92
|
+
|
|
93
|
+
- Updated dependencies []:
|
|
94
|
+
- @medusajs/telemetry@2.8.7
|
|
95
|
+
|
|
96
|
+
## 2.8.6
|
|
97
|
+
|
|
98
|
+
### Patch Changes
|
|
99
|
+
|
|
100
|
+
- Updated dependencies []:
|
|
101
|
+
- @medusajs/telemetry@2.8.6
|
|
102
|
+
|
|
103
|
+
## 2.8.5
|
|
104
|
+
|
|
105
|
+
### Patch Changes
|
|
106
|
+
|
|
107
|
+
- [#12707](https://github.com/medusajs/medusa/pull/12707) [`774702153f389e59476ea0a027b8caeb5075f92a`](https://github.com/medusajs/medusa/commit/774702153f389e59476ea0a027b8caeb5075f92a) Thanks [@shahednasser](https://github.com/shahednasser)! - fix(create-medusa-app): remove "Created admin user" message
|
|
108
|
+
|
|
109
|
+
- [#12714](https://github.com/medusajs/medusa/pull/12714) [`2e861a94492a486e2cbdb8d442f25611be1bc3bf`](https://github.com/medusajs/medusa/commit/2e861a94492a486e2cbdb8d442f25611be1bc3bf) Thanks [@shahednasser](https://github.com/shahednasser)! - fix(create-medusa-app): ensure the same package manager is used consistently
|
|
110
|
+
|
|
111
|
+
- Updated dependencies []:
|
|
112
|
+
- @medusajs/telemetry@2.8.5
|
|
113
|
+
|
|
114
|
+
## 2.8.4
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- Updated dependencies []:
|
|
119
|
+
- @medusajs/telemetry@2.8.4
|
|
120
|
+
|
|
121
|
+
## 2.8.3
|
|
122
|
+
|
|
123
|
+
### Patch Changes
|
|
124
|
+
|
|
125
|
+
- Updated dependencies []:
|
|
126
|
+
- @medusajs/telemetry@2.8.3
|
|
127
|
+
|
|
128
|
+
## 2.8.2
|
|
129
|
+
|
|
130
|
+
### Patch Changes
|
|
131
|
+
|
|
132
|
+
- Updated dependencies []:
|
|
133
|
+
- @medusajs/telemetry@2.8.2
|
|
134
|
+
|
|
135
|
+
## 2.8.1
|
|
136
|
+
|
|
137
|
+
### Patch Changes
|
|
138
|
+
|
|
139
|
+
- Updated dependencies []:
|
|
140
|
+
- @medusajs/telemetry@2.8.1
|
|
141
|
+
|
|
142
|
+
## 2.8.0
|
|
143
|
+
|
|
144
|
+
### Patch Changes
|
|
145
|
+
|
|
146
|
+
- [#12360](https://github.com/medusajs/medusa/pull/12360) [`f74586e772f2800952e52b6eaceb25de93c1691c`](https://github.com/medusajs/medusa/commit/f74586e772f2800952e52b6eaceb25de93c1691c) Thanks [@shahednasser](https://github.com/shahednasser)! - fix(create-medusa-app): updates to text and prompts
|
|
147
|
+
|
|
148
|
+
- Updated dependencies []:
|
|
149
|
+
- @medusajs/telemetry@2.8.0
|
|
150
|
+
|
|
151
|
+
## 2.7.1
|
|
152
|
+
|
|
153
|
+
### Patch Changes
|
|
154
|
+
|
|
155
|
+
- Updated dependencies []:
|
|
156
|
+
- @medusajs/telemetry@2.7.1
|
|
157
|
+
|
|
158
|
+
## 2.7.0
|
|
4
159
|
|
|
5
160
|
### Patch Changes
|
|
6
161
|
|
|
7
162
|
- Updated dependencies []:
|
|
8
|
-
- @medusajs/telemetry@
|
|
163
|
+
- @medusajs/telemetry@2.7.0
|
|
9
164
|
|
|
10
165
|
## 2.6.1
|
|
11
166
|
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ program
|
|
|
6
6
|
.argument("[project-name]", "Name of the project to create.")
|
|
7
7
|
.option("--plugin", "Create a plugin instead of a project.")
|
|
8
8
|
.option("--repo-url <url>", "URL of repository to use to setup project.")
|
|
9
|
+
.option("--version <version>", "The version of Medusa packages to install.")
|
|
9
10
|
.option("--seed", "Seed the created database with demo data.")
|
|
10
11
|
.option("--skip-db", "Skips creating the database, running migrations, and seeding, and subsequently skips opening the browser.", false)
|
|
11
12
|
.option("--db-url <url>", "Skips database creation and sets the database URL to the provided URL. Throws an error if can't connect to the database. Will still run migrations and open the admin after project creation.")
|
package/dist/utils/execute.js
CHANGED
|
@@ -8,12 +8,14 @@ const execute = async (command, { verbose = false, needOutput = false }) => {
|
|
|
8
8
|
const childProcess = spawnSync(commandStr, {
|
|
9
9
|
...options,
|
|
10
10
|
shell: true,
|
|
11
|
-
stdio: needOutput
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
stdio: needOutput ?
|
|
12
|
+
"pipe" :
|
|
13
|
+
[process.stdin, process.stdout, process.stderr],
|
|
14
14
|
});
|
|
15
|
-
if (childProcess.error) {
|
|
16
|
-
throw childProcess.error
|
|
15
|
+
if (childProcess.error || childProcess.status !== 0) {
|
|
16
|
+
throw childProcess.error ||
|
|
17
|
+
childProcess.stderr?.toString() ||
|
|
18
|
+
`${commandStr} failed with status ${childProcess.status}`;
|
|
17
19
|
}
|
|
18
20
|
if (childProcess.signal &&
|
|
19
21
|
["SIGINT", "SIGTERM"].includes(childProcess.signal)) {
|
package/dist/utils/facts.js
CHANGED
|
@@ -2,24 +2,24 @@ import boxen from "boxen";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { emojify } from "node-emoji";
|
|
4
4
|
const facts = [
|
|
5
|
-
"
|
|
6
|
-
"Payment
|
|
7
|
-
"Tax-inclusive pricing allows you to set prices for products
|
|
5
|
+
"Specify a product's availability in one or more sales channels.",
|
|
6
|
+
"Payment providers can be configured per region.",
|
|
7
|
+
"Tax-inclusive pricing allows you to set prices for products and shipping options while delegating tax calculations to Medusa.",
|
|
8
8
|
"Medusa provides multi-currency and region support, with full control over prices for each currency and region.",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"Publishable-API Keys allow you to send requests to the
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"Medusa's store
|
|
16
|
-
"
|
|
17
|
-
"Modules
|
|
18
|
-
"
|
|
9
|
+
"Organize customers by customer groups and set special prices for them.",
|
|
10
|
+
"Specify the inventory of products per location and sales channel.",
|
|
11
|
+
"Publishable-API Keys allow you to send scoped requests to the server's store API routes.",
|
|
12
|
+
"API Routes expose business logic to clients, such as storefronts and admin customizations.",
|
|
13
|
+
"Subscribers are asynchronous functions that are executed when an event is emitted.",
|
|
14
|
+
"Data models represent tables in the database. They are created using Medusa's Data Modeling Language (DML).",
|
|
15
|
+
"Medusa's store API routes are prefixed by /store. The admin API routes are prefixed by /admin.",
|
|
16
|
+
"The JS SDK allows you to send requests to the Medusa server from your storefront or admin customizations.",
|
|
17
|
+
"Modules are reusable packages of functionalities related to a single commerce domain or integration.",
|
|
18
|
+
"Modules have a main service that provides data-management and integration functionalities.",
|
|
19
19
|
"Modules allow you to replace an entire functionality with your custom logic.",
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
20
|
+
"Infrastructure Modules are interchangeable modules that implement features and integrations related to the Medusa server's infrastructure.",
|
|
21
|
+
"Commerce Modules are built-in modules that provide core commerce logic specific to domains like Product, Cart and Order.",
|
|
22
|
+
"Workflows are a series of queries and actions, called steps, that complete a task.",
|
|
23
23
|
"A workflow's steps can be retried or rolled back in case of an error.",
|
|
24
24
|
];
|
|
25
25
|
export const getFact = () => {
|
|
@@ -7,6 +7,7 @@ import { isAbortError } from "./create-abort-controller.js";
|
|
|
7
7
|
import execute from "./execute.js";
|
|
8
8
|
import { displayFactBox } from "./facts.js";
|
|
9
9
|
import logMessage from "./log-message.js";
|
|
10
|
+
import { updatePackageVersions } from "./update-package-versions.js";
|
|
10
11
|
const NEXTJS_REPO = "https://github.com/medusajs/nextjs-starter-medusa";
|
|
11
12
|
const NEXTJS_BRANCH = "main";
|
|
12
13
|
export async function askForNextjsStarter() {
|
|
@@ -14,16 +15,16 @@ export async function askForNextjsStarter() {
|
|
|
14
15
|
{
|
|
15
16
|
type: "confirm",
|
|
16
17
|
name: "installNextjs",
|
|
17
|
-
message: `Would you like to
|
|
18
|
+
message: `Would you like to install the Next.js Starter Storefront? You can also install it later.`,
|
|
18
19
|
default: false,
|
|
19
20
|
},
|
|
20
21
|
]);
|
|
21
22
|
return installNextjs;
|
|
22
23
|
}
|
|
23
|
-
export async function installNextjsStarter({ directoryName, abortController, factBoxOptions, verbose = false, processManager, }) {
|
|
24
|
+
export async function installNextjsStarter({ directoryName, abortController, factBoxOptions, verbose = false, processManager, version, }) {
|
|
24
25
|
factBoxOptions.interval = displayFactBox({
|
|
25
26
|
...factBoxOptions,
|
|
26
|
-
title: "Installing Next.js Storefront...",
|
|
27
|
+
title: "Installing Next.js Starter Storefront...",
|
|
27
28
|
});
|
|
28
29
|
let nextjsDirectory = `${directoryName}-storefront`;
|
|
29
30
|
if (fs.existsSync(nextjsDirectory) &&
|
|
@@ -41,6 +42,10 @@ export async function installNextjsStarter({ directoryName, abortController, fac
|
|
|
41
42
|
env: process.env,
|
|
42
43
|
},
|
|
43
44
|
], { verbose });
|
|
45
|
+
if (version) {
|
|
46
|
+
const packageJsonPath = path.join(nextjsDirectory, "package.json");
|
|
47
|
+
updatePackageVersions(packageJsonPath, version, { applyChanges: true });
|
|
48
|
+
}
|
|
44
49
|
const execOptions = {
|
|
45
50
|
signal: abortController?.signal,
|
|
46
51
|
cwd: nextjsDirectory,
|
|
@@ -66,7 +71,7 @@ export async function installNextjsStarter({ directoryName, abortController, fac
|
|
|
66
71
|
process.exit();
|
|
67
72
|
}
|
|
68
73
|
logMessage({
|
|
69
|
-
message: `An error occurred while installing Next.js
|
|
74
|
+
message: `An error occurred while installing Next.js Starter Storefront: ${e}`,
|
|
70
75
|
type: "error",
|
|
71
76
|
});
|
|
72
77
|
}
|
|
@@ -77,7 +82,7 @@ export async function installNextjsStarter({ directoryName, abortController, fac
|
|
|
77
82
|
fs.renameSync(path.join(nextjsDirectory, ".env.template"), path.join(nextjsDirectory, ".env.local"));
|
|
78
83
|
displayFactBox({
|
|
79
84
|
...factBoxOptions,
|
|
80
|
-
message: `Installed Next.js Starter successfully in the ${nextjsDirectory} directory.`,
|
|
85
|
+
message: `Installed Next.js Starter Storefront successfully in the ${nextjsDirectory} directory.`,
|
|
81
86
|
});
|
|
82
87
|
return nextjsDirectory;
|
|
83
88
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import execute from "./execute.js";
|
|
2
|
+
export default class PackageManager {
|
|
3
|
+
packageManager;
|
|
4
|
+
processManager;
|
|
5
|
+
verbose;
|
|
6
|
+
constructor(processManager, verbose = false) {
|
|
7
|
+
this.processManager = processManager;
|
|
8
|
+
this.verbose = verbose;
|
|
9
|
+
}
|
|
10
|
+
async setPackageManager(execOptions) {
|
|
11
|
+
if (this.packageManager) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// check whether yarn is available
|
|
15
|
+
await this.processManager.runProcess({
|
|
16
|
+
process: async () => {
|
|
17
|
+
try {
|
|
18
|
+
await execute([`yarn -v`, execOptions], { verbose: this.verbose });
|
|
19
|
+
// yarn is available
|
|
20
|
+
this.packageManager = "yarn";
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
// yarn isn't available
|
|
24
|
+
// use npm
|
|
25
|
+
this.packageManager = "npm";
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
ignoreERESOLVE: true,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async installDependencies(execOptions) {
|
|
32
|
+
if (!this.packageManager) {
|
|
33
|
+
await this.setPackageManager(execOptions);
|
|
34
|
+
}
|
|
35
|
+
const command = this.packageManager === "yarn" ?
|
|
36
|
+
`yarn` : `npm install`;
|
|
37
|
+
await this.processManager.runProcess({
|
|
38
|
+
process: async () => {
|
|
39
|
+
await execute([command, execOptions], {
|
|
40
|
+
verbose: this.verbose
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
ignoreERESOLVE: true,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async runCommand(command, execOptions) {
|
|
47
|
+
if (!this.packageManager) {
|
|
48
|
+
await this.setPackageManager(execOptions);
|
|
49
|
+
}
|
|
50
|
+
const commandStr = this.getCommandStr(command);
|
|
51
|
+
await this.processManager.runProcess({
|
|
52
|
+
process: async () => {
|
|
53
|
+
await execute([commandStr, execOptions], {
|
|
54
|
+
verbose: this.verbose
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
ignoreERESOLVE: true,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
getCommandStr(command) {
|
|
61
|
+
if (!this.packageManager) {
|
|
62
|
+
throw new Error("Package manager not set");
|
|
63
|
+
}
|
|
64
|
+
return this.packageManager === "yarn"
|
|
65
|
+
? `yarn ${command}`
|
|
66
|
+
: `npm run ${command}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -3,6 +3,7 @@ import path from "path";
|
|
|
3
3
|
import execute from "./execute.js";
|
|
4
4
|
import { EOL } from "os";
|
|
5
5
|
import { displayFactBox } from "./facts.js";
|
|
6
|
+
import { updatePackageVersions } from "./update-package-versions.js";
|
|
6
7
|
const ADMIN_EMAIL = "admin@medusa-test.com";
|
|
7
8
|
let STORE_CORS = "http://localhost:8000";
|
|
8
9
|
let ADMIN_CORS = "http://localhost:5173,http://localhost:9000";
|
|
@@ -17,7 +18,7 @@ export default async (prepareOptions) => {
|
|
|
17
18
|
}
|
|
18
19
|
return prepareProject(prepareOptions);
|
|
19
20
|
};
|
|
20
|
-
async function preparePlugin({ directory, projectName, spinner, processManager, abortController, verbose = false, }) {
|
|
21
|
+
async function preparePlugin({ directory, projectName, spinner, processManager, abortController, verbose = false, packageManager, }) {
|
|
21
22
|
// initialize execution options
|
|
22
23
|
const execOptions = {
|
|
23
24
|
cwd: directory,
|
|
@@ -43,28 +44,14 @@ async function preparePlugin({ directory, projectName, spinner, processManager,
|
|
|
43
44
|
title: "Installing dependencies...",
|
|
44
45
|
processManager,
|
|
45
46
|
});
|
|
46
|
-
await
|
|
47
|
-
process: async () => {
|
|
48
|
-
try {
|
|
49
|
-
await execute([`yarn`, execOptions], { verbose });
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
// yarn isn't available
|
|
53
|
-
// use npm
|
|
54
|
-
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
|
55
|
-
verbose,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
ignoreERESOLVE: true,
|
|
60
|
-
});
|
|
47
|
+
await packageManager.installDependencies(execOptions);
|
|
61
48
|
factBoxOptions.interval = displayFactBox({
|
|
62
49
|
...factBoxOptions,
|
|
63
50
|
message: "Installed Dependencies",
|
|
64
51
|
});
|
|
65
52
|
displayFactBox({ ...factBoxOptions, message: "Finished Preparation" });
|
|
66
53
|
}
|
|
67
|
-
async function prepareProject({ directory, projectName, dbName, dbConnectionString, seed, spinner, processManager, abortController, skipDb, migrations, onboardingType = "default", nextjsDirectory = "", client, verbose = false, }) {
|
|
54
|
+
async function prepareProject({ directory, projectName, dbName, dbConnectionString, seed, spinner, processManager, abortController, skipDb, migrations, onboardingType = "default", nextjsDirectory = "", client, verbose = false, packageManager, version, }) {
|
|
68
55
|
// initialize execution options
|
|
69
56
|
const execOptions = {
|
|
70
57
|
cwd: directory,
|
|
@@ -90,6 +77,10 @@ async function prepareProject({ directory, projectName, dbName, dbConnectionStri
|
|
|
90
77
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
91
78
|
// Update name
|
|
92
79
|
packageJson.name = projectName;
|
|
80
|
+
// Update medusa dependencies versions
|
|
81
|
+
if (version) {
|
|
82
|
+
updatePackageVersions(packageJson, version);
|
|
83
|
+
}
|
|
93
84
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
94
85
|
// initialize the invite token to return
|
|
95
86
|
let inviteToken = undefined;
|
|
@@ -112,21 +103,7 @@ async function prepareProject({ directory, projectName, dbName, dbConnectionStri
|
|
|
112
103
|
title: "Installing dependencies...",
|
|
113
104
|
processManager,
|
|
114
105
|
});
|
|
115
|
-
await
|
|
116
|
-
process: async () => {
|
|
117
|
-
try {
|
|
118
|
-
await execute([`yarn`, execOptions], { verbose });
|
|
119
|
-
}
|
|
120
|
-
catch (e) {
|
|
121
|
-
// yarn isn't available
|
|
122
|
-
// use npm
|
|
123
|
-
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
|
124
|
-
verbose,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
ignoreERESOLVE: true,
|
|
129
|
-
});
|
|
106
|
+
await packageManager.installDependencies(execOptions);
|
|
130
107
|
factBoxOptions.interval = displayFactBox({
|
|
131
108
|
...factBoxOptions,
|
|
132
109
|
message: "Installed Dependencies",
|
|
@@ -167,11 +144,6 @@ async function prepareProject({ directory, projectName, dbName, dbConnectionStri
|
|
|
167
144
|
...factBoxOptions,
|
|
168
145
|
message: "Ran Migrations",
|
|
169
146
|
});
|
|
170
|
-
// create admin user
|
|
171
|
-
factBoxOptions.interval = displayFactBox({
|
|
172
|
-
...factBoxOptions,
|
|
173
|
-
title: "Creating an admin user...",
|
|
174
|
-
});
|
|
175
147
|
await processManager.runProcess({
|
|
176
148
|
process: async () => {
|
|
177
149
|
const proc = await execute([`npx medusa user -e ${ADMIN_EMAIL} --invite`, npxOptions], { verbose, needOutput: true });
|
|
@@ -180,10 +152,6 @@ async function prepareProject({ directory, projectName, dbName, dbConnectionStri
|
|
|
180
152
|
inviteToken = match?.groups?.token;
|
|
181
153
|
},
|
|
182
154
|
});
|
|
183
|
-
factBoxOptions.interval = displayFactBox({
|
|
184
|
-
...factBoxOptions,
|
|
185
|
-
message: "Created admin user",
|
|
186
|
-
});
|
|
187
155
|
// TODO for now we just seed the default data
|
|
188
156
|
// we should add onboarding seeding again if it makes
|
|
189
157
|
// since once we re-introduce the onboarding flow.
|
|
@@ -191,19 +159,7 @@ async function prepareProject({ directory, projectName, dbName, dbConnectionStri
|
|
|
191
159
|
...factBoxOptions,
|
|
192
160
|
title: "Seeding database...",
|
|
193
161
|
});
|
|
194
|
-
await
|
|
195
|
-
process: async () => {
|
|
196
|
-
try {
|
|
197
|
-
await execute([`yarn seed`, execOptions], { verbose });
|
|
198
|
-
}
|
|
199
|
-
catch (e) {
|
|
200
|
-
// yarn isn't available
|
|
201
|
-
// use npm
|
|
202
|
-
await execute([`npm run seed`, execOptions], { verbose });
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
ignoreERESOLVE: true,
|
|
206
|
-
});
|
|
162
|
+
await packageManager.runCommand("seed", execOptions);
|
|
207
163
|
displayFactBox({
|
|
208
164
|
...factBoxOptions,
|
|
209
165
|
message: "Seeded database with demo data",
|
|
@@ -2,12 +2,14 @@ import ora from "ora";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import createAbortController from "../create-abort-controller.js";
|
|
4
4
|
import ProcessManager from "../process-manager.js";
|
|
5
|
+
import PackageManager from "../package-manager.js";
|
|
5
6
|
// Base class for common project functionality
|
|
6
7
|
export class BaseProjectCreator {
|
|
7
8
|
options;
|
|
8
9
|
args;
|
|
9
10
|
spinner;
|
|
10
11
|
processManager;
|
|
12
|
+
packageManager;
|
|
11
13
|
abortController;
|
|
12
14
|
factBoxOptions;
|
|
13
15
|
projectName;
|
|
@@ -19,6 +21,7 @@ export class BaseProjectCreator {
|
|
|
19
21
|
this.args = args;
|
|
20
22
|
this.spinner = ora();
|
|
21
23
|
this.processManager = new ProcessManager();
|
|
24
|
+
this.packageManager = new PackageManager(this.processManager);
|
|
22
25
|
this.abortController = createAbortController(this.processManager);
|
|
23
26
|
this.projectName = projectName;
|
|
24
27
|
const basePath = typeof options.directoryPath === "string" ? options.directoryPath : "";
|
|
@@ -70,6 +70,7 @@ export class MedusaProjectCreator extends BaseProjectCreator {
|
|
|
70
70
|
factBoxOptions: this.factBoxOptions,
|
|
71
71
|
verbose: this.options.verbose,
|
|
72
72
|
processManager: this.processManager,
|
|
73
|
+
version: this.options.version,
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
}
|
|
@@ -121,6 +122,8 @@ export class MedusaProjectCreator extends BaseProjectCreator {
|
|
|
121
122
|
nextjsDirectory: this.nextjsDirectory,
|
|
122
123
|
client: this.client,
|
|
123
124
|
verbose: this.options.verbose,
|
|
125
|
+
packageManager: this.packageManager,
|
|
126
|
+
version: this.options.version,
|
|
124
127
|
});
|
|
125
128
|
}
|
|
126
129
|
finally {
|
|
@@ -170,11 +173,12 @@ export class MedusaProjectCreator extends BaseProjectCreator {
|
|
|
170
173
|
});
|
|
171
174
|
}
|
|
172
175
|
showSuccessMessage() {
|
|
176
|
+
const commandStr = this.packageManager.getCommandStr(`dev`);
|
|
173
177
|
logMessage({
|
|
174
|
-
message: boxen(chalk.green(`Change to the \`${this.projectName}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa
|
|
175
|
-
? `After you start the Medusa
|
|
178
|
+
message: boxen(chalk.green(`Change to the \`${this.projectName}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa application again with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}${this.inviteToken
|
|
179
|
+
? `After you start the Medusa application, you can create an admin user with the URL http://localhost:9000/app/invite?token=${this.inviteToken}&first_run=true${EOL}${EOL}`
|
|
176
180
|
: ""}${this.nextjsDirectory?.length
|
|
177
|
-
? `The Next.js Starter
|
|
181
|
+
? `The Next.js Starter Storefront was installed in the \`${this.nextjsDirectory}\` directory. Change to that directory and start it with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}`
|
|
178
182
|
: ""}Check out the Medusa documentation to start your development:${EOL}${EOL}https://docs.medusajs.com/${EOL}${EOL}Star us on GitHub if you like what we're building:${EOL}${EOL}https://github.com/medusajs/medusa/stargazers`), {
|
|
179
183
|
titleAlignment: "center",
|
|
180
184
|
textAlignment: "center",
|
|
@@ -36,6 +36,15 @@ export class ProjectCreatorFactory {
|
|
|
36
36
|
});
|
|
37
37
|
askProjectName = true;
|
|
38
38
|
}
|
|
39
|
+
else if (args[0].includes(".")) {
|
|
40
|
+
// We don't allow projects to have a dot in the name, as this causes issues for
|
|
41
|
+
// for MikroORM path resolutions.
|
|
42
|
+
logMessage({
|
|
43
|
+
message: `Project names cannot contain a dot (.) character. Please enter a different ${isPlugin ? "plugin" : "project"} name.`,
|
|
44
|
+
type: "error",
|
|
45
|
+
});
|
|
46
|
+
askProjectName = true;
|
|
47
|
+
}
|
|
39
48
|
}
|
|
40
49
|
return askProjectName
|
|
41
50
|
? await askForProjectName(directoryPath, isPlugin)
|
|
@@ -53,6 +62,11 @@ async function askForProjectName(directoryPath, isPlugin) {
|
|
|
53
62
|
return slugify(input).toLowerCase();
|
|
54
63
|
},
|
|
55
64
|
validate: (input) => {
|
|
65
|
+
// We don't allow projects to have a dot in the name, as this causes issues for
|
|
66
|
+
// for MikroORM path resolutions.
|
|
67
|
+
if (input.includes(".")) {
|
|
68
|
+
return `Project names cannot contain a dot (.) character. Please enter a different ${isPlugin ? "plugin" : "project"} name.`;
|
|
69
|
+
}
|
|
56
70
|
if (!input.length) {
|
|
57
71
|
return `Please enter a ${isPlugin ? "plugin" : "project"} name`;
|
|
58
72
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2
|
+
export function updatePackageVersions(packageJsonOrPath, version, { applyChanges = false } = {}) {
|
|
3
|
+
const packageJson = typeof packageJsonOrPath === "string"
|
|
4
|
+
? JSON.parse(readFileSync(packageJsonOrPath, "utf-8"))
|
|
5
|
+
: packageJsonOrPath;
|
|
6
|
+
if (packageJson.dependencies) {
|
|
7
|
+
for (const dependency of Object.keys(packageJson.dependencies)) {
|
|
8
|
+
if (dependency.startsWith("@medusajs/")) {
|
|
9
|
+
packageJson.dependencies[dependency] = version;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
if (packageJson.devDependencies) {
|
|
14
|
+
for (const dependency of Object.keys(packageJson.devDependencies)) {
|
|
15
|
+
if (dependency.startsWith("@medusajs/")) {
|
|
16
|
+
packageJson.devDependencies[dependency] = version;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (applyChanges && typeof packageJsonOrPath === "string") {
|
|
21
|
+
writeFileSync(packageJsonOrPath, JSON.stringify(packageJson, null, 2));
|
|
22
|
+
}
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-medusa-app",
|
|
3
|
-
"version": "3.0.0-snapshot-
|
|
3
|
+
"version": "3.0.0-snapshot-20251104004624",
|
|
4
4
|
"description": "Create a Medusa project using a single command.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -10,48 +10,26 @@
|
|
|
10
10
|
"dev": "node --loader ts-node/esm src/index.ts",
|
|
11
11
|
"start": "node dist/index.js",
|
|
12
12
|
"build": "tsc",
|
|
13
|
-
"watch": "tsc --watch"
|
|
13
|
+
"watch": "yarn run -T tsc --watch"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@medusajs/
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
16
|
+
"@medusajs/deps": "3.0.0-snapshot-20251104004624",
|
|
17
|
+
"@medusajs/telemetry": "3.0.0-snapshot-20251104004624",
|
|
18
|
+
"boxen": "^5.0.1",
|
|
19
|
+
"chalk": "^4.1.2",
|
|
20
|
+
"commander": "^11.0.0",
|
|
21
|
+
"inquirer": "^8.0.0",
|
|
21
22
|
"nanoid": "^4.0.2",
|
|
22
23
|
"node-emoji": "^2.0.2",
|
|
23
24
|
"node-fetch": "^3.3.1",
|
|
24
25
|
"open": "^9.1.0",
|
|
25
|
-
"ora": "^
|
|
26
|
-
"pg": "^8.11.3",
|
|
26
|
+
"ora": "^5.4.1",
|
|
27
27
|
"slugify": "^1.6.6",
|
|
28
28
|
"uuid": "^9.0.0",
|
|
29
|
-
"validator": "^13.
|
|
30
|
-
"wait-on": "^
|
|
29
|
+
"validator": "^13.15.20",
|
|
30
|
+
"wait-on": "^9.0.1",
|
|
31
31
|
"winston": "^3.9.0"
|
|
32
32
|
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"@types/chalk": "^2.2.0",
|
|
35
|
-
"@types/commander": "^2.12.2",
|
|
36
|
-
"@types/configstore": "^6.0.0",
|
|
37
|
-
"@types/inquirer": "^9.0.3",
|
|
38
|
-
"@types/node": "^20.12.11",
|
|
39
|
-
"@types/node-emoji": "^1.8.2",
|
|
40
|
-
"@types/pg": "^8.6.6",
|
|
41
|
-
"@types/uuid": "^9.0.1",
|
|
42
|
-
"@types/validator": "^13.7.17",
|
|
43
|
-
"@types/wait-on": "^5.3.1",
|
|
44
|
-
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
45
|
-
"@typescript-eslint/parser": "^6.19.0",
|
|
46
|
-
"configstore": "^6.0.0",
|
|
47
|
-
"eslint": "^8.40.0",
|
|
48
|
-
"eslint-config-google": "^0.14.0",
|
|
49
|
-
"eslint-config-prettier": "^8.8.0",
|
|
50
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
51
|
-
"prettier": "^2.8.8",
|
|
52
|
-
"ts-node": "^10.9.1",
|
|
53
|
-
"typescript": "^5.6.2"
|
|
54
|
-
},
|
|
55
33
|
"engines": {
|
|
56
34
|
"node": ">=14.16"
|
|
57
35
|
},
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ program
|
|
|
7
7
|
.argument("[project-name]", "Name of the project to create.")
|
|
8
8
|
.option("--plugin", "Create a plugin instead of a project.")
|
|
9
9
|
.option("--repo-url <url>", "URL of repository to use to setup project.")
|
|
10
|
+
.option("--version <version>", "The version of Medusa packages to install.")
|
|
10
11
|
.option("--seed", "Seed the created database with demo data.")
|
|
11
12
|
.option(
|
|
12
13
|
"--skip-db",
|
package/src/utils/create-db.ts
CHANGED
package/src/utils/execute.ts
CHANGED
|
@@ -32,13 +32,15 @@ const execute = async (
|
|
|
32
32
|
const childProcess = spawnSync(commandStr, {
|
|
33
33
|
...options,
|
|
34
34
|
shell: true,
|
|
35
|
-
stdio: needOutput
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
stdio: needOutput ?
|
|
36
|
+
"pipe" :
|
|
37
|
+
[process.stdin, process.stdout, process.stderr],
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
-
if (childProcess.error) {
|
|
41
|
-
throw childProcess.error
|
|
40
|
+
if (childProcess.error || childProcess.status !== 0) {
|
|
41
|
+
throw childProcess.error ||
|
|
42
|
+
childProcess.stderr?.toString() ||
|
|
43
|
+
`${commandStr} failed with status ${childProcess.status}`
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
if (
|
package/src/utils/facts.ts
CHANGED
|
@@ -14,24 +14,24 @@ export type FactBoxOptions = {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const facts = [
|
|
17
|
-
"
|
|
18
|
-
"Payment
|
|
19
|
-
"Tax-inclusive pricing allows you to set prices for products
|
|
17
|
+
"Specify a product's availability in one or more sales channels.",
|
|
18
|
+
"Payment providers can be configured per region.",
|
|
19
|
+
"Tax-inclusive pricing allows you to set prices for products and shipping options while delegating tax calculations to Medusa.",
|
|
20
20
|
"Medusa provides multi-currency and region support, with full control over prices for each currency and region.",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"Publishable-API Keys allow you to send requests to the
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"Medusa's store
|
|
28
|
-
"
|
|
29
|
-
"Modules
|
|
30
|
-
"
|
|
21
|
+
"Organize customers by customer groups and set special prices for them.",
|
|
22
|
+
"Specify the inventory of products per location and sales channel.",
|
|
23
|
+
"Publishable-API Keys allow you to send scoped requests to the server's store API routes.",
|
|
24
|
+
"API Routes expose business logic to clients, such as storefronts and admin customizations.",
|
|
25
|
+
"Subscribers are asynchronous functions that are executed when an event is emitted.",
|
|
26
|
+
"Data models represent tables in the database. They are created using Medusa's Data Modeling Language (DML).",
|
|
27
|
+
"Medusa's store API routes are prefixed by /store. The admin API routes are prefixed by /admin.",
|
|
28
|
+
"The JS SDK allows you to send requests to the Medusa server from your storefront or admin customizations.",
|
|
29
|
+
"Modules are reusable packages of functionalities related to a single commerce domain or integration.",
|
|
30
|
+
"Modules have a main service that provides data-management and integration functionalities.",
|
|
31
31
|
"Modules allow you to replace an entire functionality with your custom logic.",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
32
|
+
"Infrastructure Modules are interchangeable modules that implement features and integrations related to the Medusa server's infrastructure.",
|
|
33
|
+
"Commerce Modules are built-in modules that provide core commerce logic specific to domains like Product, Cart and Order.",
|
|
34
|
+
"Workflows are a series of queries and actions, called steps, that complete a task.",
|
|
35
35
|
"A workflow's steps can be retried or rolled back in case of an error.",
|
|
36
36
|
]
|
|
37
37
|
|
package/src/utils/logger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import winston from "winston"
|
|
2
2
|
|
|
3
3
|
const consoleTransport = new winston.transports.Console({
|
|
4
|
-
format: winston.format.printf((log) => log.message),
|
|
4
|
+
format: winston.format.printf((log) => log.message as string),
|
|
5
5
|
})
|
|
6
6
|
const options = {
|
|
7
7
|
transports: [consoleTransport],
|
|
@@ -8,6 +8,7 @@ import execute from "./execute.js"
|
|
|
8
8
|
import { displayFactBox, FactBoxOptions } from "./facts.js"
|
|
9
9
|
import logMessage from "./log-message.js"
|
|
10
10
|
import ProcessManager from "./process-manager.js"
|
|
11
|
+
import { updatePackageVersions } from "./update-package-versions.js"
|
|
11
12
|
|
|
12
13
|
const NEXTJS_REPO = "https://github.com/medusajs/nextjs-starter-medusa"
|
|
13
14
|
const NEXTJS_BRANCH = "main"
|
|
@@ -17,7 +18,7 @@ export async function askForNextjsStarter(): Promise<boolean> {
|
|
|
17
18
|
{
|
|
18
19
|
type: "confirm",
|
|
19
20
|
name: "installNextjs",
|
|
20
|
-
message: `Would you like to
|
|
21
|
+
message: `Would you like to install the Next.js Starter Storefront? You can also install it later.`,
|
|
21
22
|
default: false,
|
|
22
23
|
},
|
|
23
24
|
])
|
|
@@ -31,6 +32,7 @@ type InstallOptions = {
|
|
|
31
32
|
factBoxOptions: FactBoxOptions
|
|
32
33
|
verbose?: boolean
|
|
33
34
|
processManager: ProcessManager
|
|
35
|
+
version?: string
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export async function installNextjsStarter({
|
|
@@ -39,10 +41,11 @@ export async function installNextjsStarter({
|
|
|
39
41
|
factBoxOptions,
|
|
40
42
|
verbose = false,
|
|
41
43
|
processManager,
|
|
44
|
+
version,
|
|
42
45
|
}: InstallOptions): Promise<string> {
|
|
43
46
|
factBoxOptions.interval = displayFactBox({
|
|
44
47
|
...factBoxOptions,
|
|
45
|
-
title: "Installing Next.js Storefront...",
|
|
48
|
+
title: "Installing Next.js Starter Storefront...",
|
|
46
49
|
})
|
|
47
50
|
|
|
48
51
|
let nextjsDirectory = `${directoryName}-storefront`
|
|
@@ -70,6 +73,12 @@ export async function installNextjsStarter({
|
|
|
70
73
|
],
|
|
71
74
|
{ verbose }
|
|
72
75
|
)
|
|
76
|
+
|
|
77
|
+
if (version) {
|
|
78
|
+
const packageJsonPath = path.join(nextjsDirectory, "package.json")
|
|
79
|
+
updatePackageVersions(packageJsonPath, version, { applyChanges: true })
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
const execOptions = {
|
|
74
83
|
signal: abortController?.signal,
|
|
75
84
|
cwd: nextjsDirectory,
|
|
@@ -94,7 +103,7 @@ export async function installNextjsStarter({
|
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
logMessage({
|
|
97
|
-
message: `An error occurred while installing Next.js
|
|
106
|
+
message: `An error occurred while installing Next.js Starter Storefront: ${e}`,
|
|
98
107
|
type: "error",
|
|
99
108
|
})
|
|
100
109
|
}
|
|
@@ -111,7 +120,7 @@ export async function installNextjsStarter({
|
|
|
111
120
|
|
|
112
121
|
displayFactBox({
|
|
113
122
|
...factBoxOptions,
|
|
114
|
-
message: `Installed Next.js Starter successfully in the ${nextjsDirectory} directory.`,
|
|
123
|
+
message: `Installed Next.js Starter Storefront successfully in the ${nextjsDirectory} directory.`,
|
|
115
124
|
})
|
|
116
125
|
|
|
117
126
|
return nextjsDirectory
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import execute from "./execute.js"
|
|
2
|
+
import ProcessManager from "./process-manager.js"
|
|
3
|
+
|
|
4
|
+
export default class PackageManager {
|
|
5
|
+
protected packageManager?: "npm" | "yarn"
|
|
6
|
+
protected processManager: ProcessManager
|
|
7
|
+
protected verbose
|
|
8
|
+
|
|
9
|
+
constructor(processManager: ProcessManager, verbose = false) {
|
|
10
|
+
this.processManager = processManager
|
|
11
|
+
this.verbose = verbose
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async setPackageManager(execOptions: Record<string, unknown>): Promise<void> {
|
|
15
|
+
if (this.packageManager) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// check whether yarn is available
|
|
20
|
+
await this.processManager.runProcess({
|
|
21
|
+
process: async () => {
|
|
22
|
+
try {
|
|
23
|
+
await execute([`yarn -v`, execOptions], { verbose: this.verbose })
|
|
24
|
+
// yarn is available
|
|
25
|
+
this.packageManager = "yarn"
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// yarn isn't available
|
|
28
|
+
// use npm
|
|
29
|
+
this.packageManager = "npm"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
ignoreERESOLVE: true,
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async installDependencies(
|
|
37
|
+
execOptions: Record<string, unknown>,
|
|
38
|
+
) {
|
|
39
|
+
if (!this.packageManager) {
|
|
40
|
+
await this.setPackageManager(execOptions)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const command = this.packageManager === "yarn" ?
|
|
44
|
+
`yarn` : `npm install`
|
|
45
|
+
|
|
46
|
+
await this.processManager.runProcess({
|
|
47
|
+
process: async () => {
|
|
48
|
+
await execute([command, execOptions], {
|
|
49
|
+
verbose: this.verbose
|
|
50
|
+
})
|
|
51
|
+
},
|
|
52
|
+
ignoreERESOLVE: true,
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async runCommand(
|
|
57
|
+
command: string,
|
|
58
|
+
execOptions: Record<string, unknown>,
|
|
59
|
+
) {
|
|
60
|
+
if (!this.packageManager) {
|
|
61
|
+
await this.setPackageManager(execOptions)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const commandStr = this.getCommandStr(command)
|
|
65
|
+
|
|
66
|
+
await this.processManager.runProcess({
|
|
67
|
+
process: async () => {
|
|
68
|
+
await execute([commandStr, execOptions], {
|
|
69
|
+
verbose: this.verbose
|
|
70
|
+
})
|
|
71
|
+
},
|
|
72
|
+
ignoreERESOLVE: true,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getCommandStr(
|
|
77
|
+
command: string,
|
|
78
|
+
): string {
|
|
79
|
+
if (!this.packageManager) {
|
|
80
|
+
throw new Error("Package manager not set")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return this.packageManager === "yarn"
|
|
84
|
+
? `yarn ${command}`
|
|
85
|
+
: `npm run ${command}`
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -5,7 +5,9 @@ import execute from "./execute.js"
|
|
|
5
5
|
import { EOL } from "os"
|
|
6
6
|
import { displayFactBox, FactBoxOptions } from "./facts.js"
|
|
7
7
|
import ProcessManager from "./process-manager.js"
|
|
8
|
-
import type { Client } from "pg"
|
|
8
|
+
import type { Client } from "@medusajs/deps/pg"
|
|
9
|
+
import PackageManager from "./package-manager.js"
|
|
10
|
+
import { updatePackageVersions } from "./update-package-versions.js"
|
|
9
11
|
|
|
10
12
|
const ADMIN_EMAIL = "admin@medusa-test.com"
|
|
11
13
|
let STORE_CORS = "http://localhost:8000"
|
|
@@ -24,6 +26,7 @@ type PreparePluginOptions = {
|
|
|
24
26
|
processManager: ProcessManager
|
|
25
27
|
abortController?: AbortController
|
|
26
28
|
verbose?: boolean
|
|
29
|
+
packageManager: PackageManager
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
type PrepareProjectOptions = {
|
|
@@ -42,6 +45,8 @@ type PrepareProjectOptions = {
|
|
|
42
45
|
nextjsDirectory?: string
|
|
43
46
|
client: Client | null
|
|
44
47
|
verbose?: boolean
|
|
48
|
+
packageManager: PackageManager
|
|
49
|
+
version?: string
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
type PrepareOptions = PreparePluginOptions | PrepareProjectOptions
|
|
@@ -66,6 +71,7 @@ async function preparePlugin({
|
|
|
66
71
|
processManager,
|
|
67
72
|
abortController,
|
|
68
73
|
verbose = false,
|
|
74
|
+
packageManager,
|
|
69
75
|
}: PreparePluginOptions) {
|
|
70
76
|
// initialize execution options
|
|
71
77
|
const execOptions = {
|
|
@@ -98,20 +104,7 @@ async function preparePlugin({
|
|
|
98
104
|
processManager,
|
|
99
105
|
})
|
|
100
106
|
|
|
101
|
-
await
|
|
102
|
-
process: async () => {
|
|
103
|
-
try {
|
|
104
|
-
await execute([`yarn`, execOptions], { verbose })
|
|
105
|
-
} catch (e) {
|
|
106
|
-
// yarn isn't available
|
|
107
|
-
// use npm
|
|
108
|
-
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
|
109
|
-
verbose,
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
ignoreERESOLVE: true,
|
|
114
|
-
})
|
|
107
|
+
await packageManager.installDependencies(execOptions)
|
|
115
108
|
|
|
116
109
|
factBoxOptions.interval = displayFactBox({
|
|
117
110
|
...factBoxOptions,
|
|
@@ -136,6 +129,8 @@ async function prepareProject({
|
|
|
136
129
|
nextjsDirectory = "",
|
|
137
130
|
client,
|
|
138
131
|
verbose = false,
|
|
132
|
+
packageManager,
|
|
133
|
+
version,
|
|
139
134
|
}: PrepareProjectOptions) {
|
|
140
135
|
// initialize execution options
|
|
141
136
|
const execOptions = {
|
|
@@ -167,6 +162,11 @@ async function prepareProject({
|
|
|
167
162
|
// Update name
|
|
168
163
|
packageJson.name = projectName
|
|
169
164
|
|
|
165
|
+
// Update medusa dependencies versions
|
|
166
|
+
if (version) {
|
|
167
|
+
updatePackageVersions(packageJson, version)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
170
|
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
|
|
171
171
|
|
|
172
172
|
// initialize the invite token to return
|
|
@@ -196,20 +196,7 @@ async function prepareProject({
|
|
|
196
196
|
processManager,
|
|
197
197
|
})
|
|
198
198
|
|
|
199
|
-
await
|
|
200
|
-
process: async () => {
|
|
201
|
-
try {
|
|
202
|
-
await execute([`yarn`, execOptions], { verbose })
|
|
203
|
-
} catch (e) {
|
|
204
|
-
// yarn isn't available
|
|
205
|
-
// use npm
|
|
206
|
-
await execute([`npm install --legacy-peer-deps`, execOptions], {
|
|
207
|
-
verbose,
|
|
208
|
-
})
|
|
209
|
-
}
|
|
210
|
-
},
|
|
211
|
-
ignoreERESOLVE: true,
|
|
212
|
-
})
|
|
199
|
+
await packageManager.installDependencies(execOptions)
|
|
213
200
|
|
|
214
201
|
factBoxOptions.interval = displayFactBox({
|
|
215
202
|
...factBoxOptions,
|
|
@@ -262,12 +249,6 @@ async function prepareProject({
|
|
|
262
249
|
message: "Ran Migrations",
|
|
263
250
|
})
|
|
264
251
|
|
|
265
|
-
// create admin user
|
|
266
|
-
factBoxOptions.interval = displayFactBox({
|
|
267
|
-
...factBoxOptions,
|
|
268
|
-
title: "Creating an admin user...",
|
|
269
|
-
})
|
|
270
|
-
|
|
271
252
|
await processManager.runProcess({
|
|
272
253
|
process: async () => {
|
|
273
254
|
const proc = await execute(
|
|
@@ -283,11 +264,6 @@ async function prepareProject({
|
|
|
283
264
|
},
|
|
284
265
|
})
|
|
285
266
|
|
|
286
|
-
factBoxOptions.interval = displayFactBox({
|
|
287
|
-
...factBoxOptions,
|
|
288
|
-
message: "Created admin user",
|
|
289
|
-
})
|
|
290
|
-
|
|
291
267
|
// TODO for now we just seed the default data
|
|
292
268
|
// we should add onboarding seeding again if it makes
|
|
293
269
|
// since once we re-introduce the onboarding flow.
|
|
@@ -296,18 +272,7 @@ async function prepareProject({
|
|
|
296
272
|
title: "Seeding database...",
|
|
297
273
|
})
|
|
298
274
|
|
|
299
|
-
await
|
|
300
|
-
process: async () => {
|
|
301
|
-
try {
|
|
302
|
-
await execute([`yarn seed`, execOptions], { verbose })
|
|
303
|
-
} catch (e) {
|
|
304
|
-
// yarn isn't available
|
|
305
|
-
// use npm
|
|
306
|
-
await execute([`npm run seed`, execOptions], { verbose })
|
|
307
|
-
}
|
|
308
|
-
},
|
|
309
|
-
ignoreERESOLVE: true,
|
|
310
|
-
})
|
|
275
|
+
await packageManager.runCommand("seed", execOptions)
|
|
311
276
|
|
|
312
277
|
displayFactBox({
|
|
313
278
|
...factBoxOptions,
|
|
@@ -3,6 +3,7 @@ import path from "path"
|
|
|
3
3
|
import createAbortController from "../create-abort-controller.js"
|
|
4
4
|
import { FactBoxOptions } from "../facts.js"
|
|
5
5
|
import ProcessManager from "../process-manager.js"
|
|
6
|
+
import PackageManager from "../package-manager.js"
|
|
6
7
|
|
|
7
8
|
export interface ProjectOptions {
|
|
8
9
|
repoUrl?: string
|
|
@@ -15,6 +16,7 @@ export interface ProjectOptions {
|
|
|
15
16
|
withNextjsStarter?: boolean
|
|
16
17
|
verbose?: boolean
|
|
17
18
|
plugin?: boolean
|
|
19
|
+
version?: string
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export interface ProjectCreator {
|
|
@@ -25,6 +27,7 @@ export interface ProjectCreator {
|
|
|
25
27
|
export abstract class BaseProjectCreator {
|
|
26
28
|
protected spinner: Ora
|
|
27
29
|
protected processManager: ProcessManager
|
|
30
|
+
protected packageManager: PackageManager
|
|
28
31
|
protected abortController: AbortController
|
|
29
32
|
protected factBoxOptions: FactBoxOptions
|
|
30
33
|
protected projectName: string
|
|
@@ -39,6 +42,7 @@ export abstract class BaseProjectCreator {
|
|
|
39
42
|
) {
|
|
40
43
|
this.spinner = ora()
|
|
41
44
|
this.processManager = new ProcessManager()
|
|
45
|
+
this.packageManager = new PackageManager(this.processManager)
|
|
42
46
|
this.abortController = createAbortController(this.processManager)
|
|
43
47
|
this.projectName = projectName
|
|
44
48
|
const basePath =
|
|
@@ -96,6 +96,7 @@ export class MedusaProjectCreator
|
|
|
96
96
|
factBoxOptions: this.factBoxOptions,
|
|
97
97
|
verbose: this.options.verbose,
|
|
98
98
|
processManager: this.processManager,
|
|
99
|
+
version: this.options.version,
|
|
99
100
|
})
|
|
100
101
|
}
|
|
101
102
|
} catch (e) {
|
|
@@ -153,6 +154,8 @@ export class MedusaProjectCreator
|
|
|
153
154
|
nextjsDirectory: this.nextjsDirectory,
|
|
154
155
|
client: this.client,
|
|
155
156
|
verbose: this.options.verbose,
|
|
157
|
+
packageManager: this.packageManager,
|
|
158
|
+
version: this.options.version,
|
|
156
159
|
})
|
|
157
160
|
} finally {
|
|
158
161
|
await this.client?.end()
|
|
@@ -214,18 +217,19 @@ export class MedusaProjectCreator
|
|
|
214
217
|
}
|
|
215
218
|
|
|
216
219
|
protected showSuccessMessage(): void {
|
|
220
|
+
const commandStr = this.packageManager.getCommandStr(`dev`)
|
|
217
221
|
logMessage({
|
|
218
222
|
message: boxen(
|
|
219
223
|
chalk.green(
|
|
220
224
|
`Change to the \`${
|
|
221
225
|
this.projectName
|
|
222
|
-
}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa
|
|
226
|
+
}\` directory to explore your Medusa project.${EOL}${EOL}Start your Medusa application again with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}${
|
|
223
227
|
this.inviteToken
|
|
224
|
-
? `After you start the Medusa
|
|
228
|
+
? `After you start the Medusa application, you can create an admin user with the URL http://localhost:9000/app/invite?token=${this.inviteToken}&first_run=true${EOL}${EOL}`
|
|
225
229
|
: ""
|
|
226
230
|
}${
|
|
227
231
|
this.nextjsDirectory?.length
|
|
228
|
-
? `The Next.js Starter
|
|
232
|
+
? `The Next.js Starter Storefront was installed in the \`${this.nextjsDirectory}\` directory. Change to that directory and start it with the following command:${EOL}${EOL}${commandStr}${EOL}${EOL}`
|
|
229
233
|
: ""
|
|
230
234
|
}Check out the Medusa documentation to start your development:${EOL}${EOL}https://docs.medusajs.com/${EOL}${EOL}Star us on GitHub if you like what we're building:${EOL}${EOL}https://github.com/medusajs/medusa/stargazers`
|
|
231
235
|
),
|
|
@@ -57,6 +57,16 @@ export class ProjectCreatorFactory {
|
|
|
57
57
|
type: "warn",
|
|
58
58
|
})
|
|
59
59
|
askProjectName = true
|
|
60
|
+
} else if (args[0].includes(".")) {
|
|
61
|
+
// We don't allow projects to have a dot in the name, as this causes issues for
|
|
62
|
+
// for MikroORM path resolutions.
|
|
63
|
+
logMessage({
|
|
64
|
+
message: `Project names cannot contain a dot (.) character. Please enter a different ${
|
|
65
|
+
isPlugin ? "plugin" : "project"
|
|
66
|
+
} name.`,
|
|
67
|
+
type: "error",
|
|
68
|
+
})
|
|
69
|
+
askProjectName = true
|
|
60
70
|
}
|
|
61
71
|
}
|
|
62
72
|
|
|
@@ -80,6 +90,14 @@ async function askForProjectName(
|
|
|
80
90
|
return slugify(input).toLowerCase()
|
|
81
91
|
},
|
|
82
92
|
validate: (input) => {
|
|
93
|
+
// We don't allow projects to have a dot in the name, as this causes issues for
|
|
94
|
+
// for MikroORM path resolutions.
|
|
95
|
+
if (input.includes(".")) {
|
|
96
|
+
return `Project names cannot contain a dot (.) character. Please enter a different ${
|
|
97
|
+
isPlugin ? "plugin" : "project"
|
|
98
|
+
} name.`
|
|
99
|
+
}
|
|
100
|
+
|
|
83
101
|
if (!input.length) {
|
|
84
102
|
return `Please enter a ${isPlugin ? "plugin" : "project"} name`
|
|
85
103
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "fs"
|
|
2
|
+
|
|
3
|
+
export function updatePackageVersions(
|
|
4
|
+
packageJsonOrPath: string | Record<string, any>,
|
|
5
|
+
version: string,
|
|
6
|
+
{ applyChanges = false }: { applyChanges?: boolean } = {}
|
|
7
|
+
) {
|
|
8
|
+
const packageJson =
|
|
9
|
+
typeof packageJsonOrPath === "string"
|
|
10
|
+
? JSON.parse(readFileSync(packageJsonOrPath, "utf-8"))
|
|
11
|
+
: packageJsonOrPath
|
|
12
|
+
|
|
13
|
+
if (packageJson.dependencies) {
|
|
14
|
+
for (const dependency of Object.keys(packageJson.dependencies)) {
|
|
15
|
+
if (dependency.startsWith("@medusajs/")) {
|
|
16
|
+
packageJson.dependencies[dependency] = version
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (packageJson.devDependencies) {
|
|
21
|
+
for (const dependency of Object.keys(packageJson.devDependencies)) {
|
|
22
|
+
if (dependency.startsWith("@medusajs/")) {
|
|
23
|
+
packageJson.devDependencies[dependency] = version
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (applyChanges && typeof packageJsonOrPath === "string") {
|
|
29
|
+
writeFileSync(packageJsonOrPath, JSON.stringify(packageJson, null, 2))
|
|
30
|
+
}
|
|
31
|
+
}
|