create-bcp-app 0.1.1
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/LICENSE +21 -0
- package/README.md +23 -0
- package/bin/create-bcp-app.mjs +177 -0
- package/package.json +29 -0
- package/src/index.mjs +405 -0
- package/template/.env.example +2 -0
- package/template/README.md +23 -0
- package/template/app/api/hello/route.ts +6 -0
- package/template/app/layout.tsx +47 -0
- package/template/app/page.tsx +37 -0
- package/template/bcp.config.ts +37 -0
- package/template/gitignore +9 -0
- package/template/tsconfig.json +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 chidchanun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# create-bcp-app
|
|
2
|
+
|
|
3
|
+
Create a new BCP Framework project.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx create-bcp-app my-app
|
|
7
|
+
cd my-app
|
|
8
|
+
npm run dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Options
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
--no-install Create files without running npm install
|
|
15
|
+
--bcp <specifier> Override dependencies.bcp
|
|
16
|
+
-h, --help Show help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The `--bcp` option is primarily useful for prerelease and local package testing, for example:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx create-bcp-app my-app --bcp file:../bcp-0.1.0.tgz
|
|
23
|
+
```
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
createBcpApp,
|
|
7
|
+
} from "../src/index.mjs";
|
|
8
|
+
|
|
9
|
+
const args =
|
|
10
|
+
process.argv.slice(2);
|
|
11
|
+
|
|
12
|
+
if (
|
|
13
|
+
args.includes("--help") ||
|
|
14
|
+
args.includes("-h")
|
|
15
|
+
) {
|
|
16
|
+
printHelp();
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let projectDirectory =
|
|
21
|
+
null;
|
|
22
|
+
let install =
|
|
23
|
+
true;
|
|
24
|
+
let bcpPackage =
|
|
25
|
+
undefined;
|
|
26
|
+
|
|
27
|
+
for (
|
|
28
|
+
let index = 0;
|
|
29
|
+
index < args.length;
|
|
30
|
+
index++
|
|
31
|
+
) {
|
|
32
|
+
const value =
|
|
33
|
+
args[index];
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
value === "--no-install"
|
|
37
|
+
) {
|
|
38
|
+
install =
|
|
39
|
+
false;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
value === "--bcp"
|
|
45
|
+
) {
|
|
46
|
+
const nextValue =
|
|
47
|
+
args[
|
|
48
|
+
index + 1
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
if (!nextValue) {
|
|
52
|
+
fail(
|
|
53
|
+
"--bcp requires a package specifier."
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bcpPackage =
|
|
58
|
+
nextValue;
|
|
59
|
+
index++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (
|
|
64
|
+
value.startsWith("-")
|
|
65
|
+
) {
|
|
66
|
+
fail(
|
|
67
|
+
`Unknown option: ${value}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (
|
|
72
|
+
projectDirectory !==
|
|
73
|
+
null
|
|
74
|
+
) {
|
|
75
|
+
fail(
|
|
76
|
+
"Only one project directory may be provided."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
projectDirectory =
|
|
81
|
+
value;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!projectDirectory) {
|
|
85
|
+
printHelp();
|
|
86
|
+
process.exitCode =
|
|
87
|
+
1;
|
|
88
|
+
} else {
|
|
89
|
+
try {
|
|
90
|
+
const result =
|
|
91
|
+
await createBcpApp({
|
|
92
|
+
projectDirectory,
|
|
93
|
+
install,
|
|
94
|
+
bcpPackage,
|
|
95
|
+
packageManager:
|
|
96
|
+
"npm",
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const relative =
|
|
100
|
+
path.relative(
|
|
101
|
+
process.cwd(),
|
|
102
|
+
result.targetDirectory
|
|
103
|
+
) || ".";
|
|
104
|
+
|
|
105
|
+
console.log("");
|
|
106
|
+
console.log(
|
|
107
|
+
`Created BCP app: ${result.projectName}`
|
|
108
|
+
);
|
|
109
|
+
console.log(
|
|
110
|
+
`Location: ${result.targetDirectory}`
|
|
111
|
+
);
|
|
112
|
+
console.log("");
|
|
113
|
+
console.log(
|
|
114
|
+
"Next steps:"
|
|
115
|
+
);
|
|
116
|
+
console.log(
|
|
117
|
+
` cd ${quoteIfNeeded(relative)}`
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (!install) {
|
|
121
|
+
console.log(
|
|
122
|
+
" npm install"
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
console.log(
|
|
127
|
+
" npm run dev"
|
|
128
|
+
);
|
|
129
|
+
console.log("");
|
|
130
|
+
} catch (error) {
|
|
131
|
+
fail(
|
|
132
|
+
error instanceof Error
|
|
133
|
+
? error.message
|
|
134
|
+
: String(error)
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function printHelp() {
|
|
140
|
+
console.log(`
|
|
141
|
+
create-bcp-app
|
|
142
|
+
|
|
143
|
+
Usage:
|
|
144
|
+
npx create-bcp-app <project-name> [options]
|
|
145
|
+
|
|
146
|
+
Options:
|
|
147
|
+
--no-install Create files without running npm install
|
|
148
|
+
--bcp <specifier> Override the package specifier stored under dependencies.bcp
|
|
149
|
+
-h, --help Show this help message
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
npx create-bcp-app my-app
|
|
153
|
+
npx create-bcp-app my-app --no-install
|
|
154
|
+
npx create-bcp-app my-app --bcp file:../bcp-0.1.0.tgz
|
|
155
|
+
`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function quoteIfNeeded(
|
|
159
|
+
value
|
|
160
|
+
) {
|
|
161
|
+
return /\s/.test(
|
|
162
|
+
value
|
|
163
|
+
)
|
|
164
|
+
? JSON.stringify(
|
|
165
|
+
value
|
|
166
|
+
)
|
|
167
|
+
: value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function fail(
|
|
171
|
+
message
|
|
172
|
+
) {
|
|
173
|
+
console.error(
|
|
174
|
+
`create-bcp-app: ${message}`
|
|
175
|
+
);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-bcp-app",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Create a new BCP Framework application.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-bcp-app": "bin/create-bcp-app.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"src",
|
|
13
|
+
"template",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=24.11.0"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/chidchanun/bcp-freamwork.git",
|
|
23
|
+
"directory": "create-bcp-app"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"bcpFrameworkPackage": "@chidchanun/bcp"
|
|
29
|
+
}
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
spawn,
|
|
5
|
+
} from "node:child_process";
|
|
6
|
+
import {
|
|
7
|
+
fileURLToPath,
|
|
8
|
+
} from "node:url";
|
|
9
|
+
|
|
10
|
+
const packageRoot =
|
|
11
|
+
path.resolve(
|
|
12
|
+
path.dirname(
|
|
13
|
+
fileURLToPath(
|
|
14
|
+
import.meta.url
|
|
15
|
+
)
|
|
16
|
+
),
|
|
17
|
+
".."
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export async function createBcpApp(
|
|
21
|
+
options
|
|
22
|
+
) {
|
|
23
|
+
const targetDirectory =
|
|
24
|
+
path.resolve(
|
|
25
|
+
options.projectDirectory
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const projectName =
|
|
29
|
+
validateProjectName(
|
|
30
|
+
path.basename(
|
|
31
|
+
targetDirectory
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
ensureTargetDirectory(
|
|
36
|
+
targetDirectory
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const templateDirectory =
|
|
40
|
+
path.join(
|
|
41
|
+
packageRoot,
|
|
42
|
+
"template"
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
copyTemplate(
|
|
46
|
+
templateDirectory,
|
|
47
|
+
targetDirectory
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const packageMetadata =
|
|
51
|
+
readPackageMetadata();
|
|
52
|
+
|
|
53
|
+
const packageSpecifier =
|
|
54
|
+
options.bcpPackage ??
|
|
55
|
+
createDefaultBcpPackageSpecifier(
|
|
56
|
+
packageMetadata.frameworkPackage,
|
|
57
|
+
packageMetadata.version
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const packageJson = {
|
|
61
|
+
name:
|
|
62
|
+
projectName,
|
|
63
|
+
version:
|
|
64
|
+
"0.1.0",
|
|
65
|
+
private:
|
|
66
|
+
true,
|
|
67
|
+
type:
|
|
68
|
+
"module",
|
|
69
|
+
scripts: {
|
|
70
|
+
dev:
|
|
71
|
+
"bcp dev",
|
|
72
|
+
build:
|
|
73
|
+
"bcp build",
|
|
74
|
+
start:
|
|
75
|
+
"bcp start",
|
|
76
|
+
routes:
|
|
77
|
+
"bcp routes",
|
|
78
|
+
typecheck:
|
|
79
|
+
"tsc --noEmit",
|
|
80
|
+
},
|
|
81
|
+
dependencies: {
|
|
82
|
+
bcp:
|
|
83
|
+
packageSpecifier,
|
|
84
|
+
react:
|
|
85
|
+
"^19.2.8",
|
|
86
|
+
"react-dom":
|
|
87
|
+
"^19.2.8",
|
|
88
|
+
},
|
|
89
|
+
devDependencies: {
|
|
90
|
+
"@types/node":
|
|
91
|
+
"^24.13.3",
|
|
92
|
+
"@types/react":
|
|
93
|
+
"^19.2.18",
|
|
94
|
+
"@types/react-dom":
|
|
95
|
+
"^19.2.4",
|
|
96
|
+
typescript:
|
|
97
|
+
"^5.9.3",
|
|
98
|
+
},
|
|
99
|
+
engines: {
|
|
100
|
+
node:
|
|
101
|
+
">=24.11.0",
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
fs.writeFileSync(
|
|
106
|
+
path.join(
|
|
107
|
+
targetDirectory,
|
|
108
|
+
"package.json"
|
|
109
|
+
),
|
|
110
|
+
`${JSON.stringify(
|
|
111
|
+
packageJson,
|
|
112
|
+
null,
|
|
113
|
+
2
|
|
114
|
+
)}\n`,
|
|
115
|
+
"utf8"
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
if (
|
|
119
|
+
options.install !== false
|
|
120
|
+
) {
|
|
121
|
+
await runInstall(
|
|
122
|
+
targetDirectory,
|
|
123
|
+
options.packageManager ??
|
|
124
|
+
"npm"
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
targetDirectory,
|
|
130
|
+
projectName,
|
|
131
|
+
packageSpecifier,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function validateProjectName(
|
|
136
|
+
value
|
|
137
|
+
) {
|
|
138
|
+
const name =
|
|
139
|
+
String(
|
|
140
|
+
value ?? ""
|
|
141
|
+
).trim();
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
!name ||
|
|
145
|
+
name === "." ||
|
|
146
|
+
name === ".."
|
|
147
|
+
) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
"Project name is required."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
name !==
|
|
155
|
+
name.toLowerCase()
|
|
156
|
+
) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
"Project name must use lowercase characters."
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (
|
|
163
|
+
!/^[a-z0-9][a-z0-9._-]*$/.test(
|
|
164
|
+
name
|
|
165
|
+
)
|
|
166
|
+
) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
"Project name may contain lowercase letters, numbers, dots, underscores and hyphens."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (
|
|
173
|
+
name === "node_modules" ||
|
|
174
|
+
name === "favicon.ico"
|
|
175
|
+
) {
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Project name "${name}" is reserved.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return name;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function ensureTargetDirectory(
|
|
185
|
+
targetDirectory
|
|
186
|
+
) {
|
|
187
|
+
if (
|
|
188
|
+
fs.existsSync(
|
|
189
|
+
targetDirectory
|
|
190
|
+
)
|
|
191
|
+
) {
|
|
192
|
+
const entries =
|
|
193
|
+
fs.readdirSync(
|
|
194
|
+
targetDirectory
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (
|
|
198
|
+
entries.length > 0
|
|
199
|
+
) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Target directory is not empty: ${targetDirectory}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
fs.mkdirSync(
|
|
209
|
+
targetDirectory,
|
|
210
|
+
{
|
|
211
|
+
recursive: true,
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function copyTemplate(
|
|
217
|
+
sourceDirectory,
|
|
218
|
+
targetDirectory
|
|
219
|
+
) {
|
|
220
|
+
fs.cpSync(
|
|
221
|
+
sourceDirectory,
|
|
222
|
+
targetDirectory,
|
|
223
|
+
{
|
|
224
|
+
recursive: true,
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const gitignoreTemplate =
|
|
229
|
+
path.join(
|
|
230
|
+
targetDirectory,
|
|
231
|
+
"gitignore"
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (
|
|
235
|
+
fs.existsSync(
|
|
236
|
+
gitignoreTemplate
|
|
237
|
+
)
|
|
238
|
+
) {
|
|
239
|
+
fs.renameSync(
|
|
240
|
+
gitignoreTemplate,
|
|
241
|
+
path.join(
|
|
242
|
+
targetDirectory,
|
|
243
|
+
".gitignore"
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function readPackageMetadata() {
|
|
250
|
+
const packageJson =
|
|
251
|
+
JSON.parse(
|
|
252
|
+
fs.readFileSync(
|
|
253
|
+
path.join(
|
|
254
|
+
packageRoot,
|
|
255
|
+
"package.json"
|
|
256
|
+
),
|
|
257
|
+
"utf8"
|
|
258
|
+
)
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
if (
|
|
262
|
+
typeof packageJson.version !==
|
|
263
|
+
"string" ||
|
|
264
|
+
packageJson.version.trim() ===
|
|
265
|
+
""
|
|
266
|
+
) {
|
|
267
|
+
throw new Error(
|
|
268
|
+
"create-bcp-app package version is missing."
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const frameworkPackage =
|
|
273
|
+
typeof packageJson.bcpFrameworkPackage ===
|
|
274
|
+
"string" &&
|
|
275
|
+
packageJson.bcpFrameworkPackage.trim() !==
|
|
276
|
+
""
|
|
277
|
+
? packageJson.bcpFrameworkPackage.trim()
|
|
278
|
+
: "bcp";
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
version:
|
|
282
|
+
packageJson.version,
|
|
283
|
+
frameworkPackage,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function createDefaultBcpPackageSpecifier(
|
|
288
|
+
frameworkPackage,
|
|
289
|
+
version
|
|
290
|
+
) {
|
|
291
|
+
if (
|
|
292
|
+
frameworkPackage === "bcp"
|
|
293
|
+
) {
|
|
294
|
+
return `^${version}`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return `npm:${frameworkPackage}@^${version}`;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function runInstall(
|
|
301
|
+
targetDirectory,
|
|
302
|
+
packageManager
|
|
303
|
+
) {
|
|
304
|
+
if (
|
|
305
|
+
packageManager !== "npm"
|
|
306
|
+
) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
`Unsupported package manager: ${packageManager}. Only npm is supported in this release.`
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const invocation =
|
|
313
|
+
resolveNpmInvocation([
|
|
314
|
+
"install",
|
|
315
|
+
]);
|
|
316
|
+
|
|
317
|
+
return new Promise(
|
|
318
|
+
(
|
|
319
|
+
resolve,
|
|
320
|
+
reject
|
|
321
|
+
) => {
|
|
322
|
+
const child =
|
|
323
|
+
spawn(
|
|
324
|
+
invocation.command,
|
|
325
|
+
invocation.args,
|
|
326
|
+
{
|
|
327
|
+
cwd:
|
|
328
|
+
targetDirectory,
|
|
329
|
+
stdio:
|
|
330
|
+
"inherit",
|
|
331
|
+
env:
|
|
332
|
+
process.env,
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
child.once(
|
|
337
|
+
"error",
|
|
338
|
+
reject
|
|
339
|
+
);
|
|
340
|
+
child.once(
|
|
341
|
+
"exit",
|
|
342
|
+
(
|
|
343
|
+
code,
|
|
344
|
+
signal
|
|
345
|
+
) => {
|
|
346
|
+
if (
|
|
347
|
+
code === 0
|
|
348
|
+
) {
|
|
349
|
+
resolve();
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
reject(
|
|
354
|
+
new Error(
|
|
355
|
+
signal
|
|
356
|
+
? `npm install stopped by ${signal}.`
|
|
357
|
+
: `npm install exited with code ${code ?? 1}.`
|
|
358
|
+
)
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function resolveNpmInvocation(
|
|
367
|
+
args
|
|
368
|
+
) {
|
|
369
|
+
const npmExecPath =
|
|
370
|
+
process.env.npm_execpath;
|
|
371
|
+
|
|
372
|
+
if (npmExecPath) {
|
|
373
|
+
return {
|
|
374
|
+
command:
|
|
375
|
+
process.execPath,
|
|
376
|
+
args: [
|
|
377
|
+
npmExecPath,
|
|
378
|
+
...args,
|
|
379
|
+
],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (
|
|
384
|
+
process.platform === "win32"
|
|
385
|
+
) {
|
|
386
|
+
return {
|
|
387
|
+
command:
|
|
388
|
+
process.env.ComSpec ??
|
|
389
|
+
"cmd.exe",
|
|
390
|
+
args: [
|
|
391
|
+
"/d",
|
|
392
|
+
"/s",
|
|
393
|
+
"/c",
|
|
394
|
+
"npm",
|
|
395
|
+
...args,
|
|
396
|
+
],
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
command:
|
|
402
|
+
"npm",
|
|
403
|
+
args,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# BCP App
|
|
2
|
+
|
|
3
|
+
This project was created with `create-bcp-app`.
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Open `http://localhost:3000`.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run dev
|
|
17
|
+
npm run routes
|
|
18
|
+
npm run typecheck
|
|
19
|
+
npm run build
|
|
20
|
+
npm start
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The production build is written to `.bcp-framework/build` and runs as a standalone Node.js server.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ReactNode,
|
|
3
|
+
} from "react";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Link,
|
|
7
|
+
type Metadata,
|
|
8
|
+
} from "bcp";
|
|
9
|
+
|
|
10
|
+
export const metadata:
|
|
11
|
+
Metadata = {
|
|
12
|
+
title:
|
|
13
|
+
"BCP App",
|
|
14
|
+
description:
|
|
15
|
+
"Created with BCP Framework.",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default function RootLayout(
|
|
19
|
+
{
|
|
20
|
+
children,
|
|
21
|
+
}: {
|
|
22
|
+
children:
|
|
23
|
+
ReactNode;
|
|
24
|
+
}
|
|
25
|
+
) {
|
|
26
|
+
return (
|
|
27
|
+
<div>
|
|
28
|
+
<header>
|
|
29
|
+
<strong>
|
|
30
|
+
BCP App
|
|
31
|
+
</strong>
|
|
32
|
+
|
|
33
|
+
{" · "}
|
|
34
|
+
|
|
35
|
+
<Link href="/">
|
|
36
|
+
Home
|
|
37
|
+
</Link>
|
|
38
|
+
</header>
|
|
39
|
+
|
|
40
|
+
<hr />
|
|
41
|
+
|
|
42
|
+
<main>
|
|
43
|
+
{children}
|
|
44
|
+
</main>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Metadata,
|
|
3
|
+
} from "bcp";
|
|
4
|
+
|
|
5
|
+
export const metadata:
|
|
6
|
+
Metadata = {
|
|
7
|
+
title:
|
|
8
|
+
"Home | BCP App",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default function HomePage() {
|
|
12
|
+
return (
|
|
13
|
+
<section>
|
|
14
|
+
<h1>
|
|
15
|
+
Welcome to BCP Framework
|
|
16
|
+
</h1>
|
|
17
|
+
|
|
18
|
+
<p>
|
|
19
|
+
Edit
|
|
20
|
+
{" "}
|
|
21
|
+
<code>
|
|
22
|
+
app/page.tsx
|
|
23
|
+
</code>
|
|
24
|
+
{" "}
|
|
25
|
+
to get started.
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<p>
|
|
29
|
+
API example:
|
|
30
|
+
{" "}
|
|
31
|
+
<a href="/api/hello">
|
|
32
|
+
/api/hello
|
|
33
|
+
</a>
|
|
34
|
+
</p>
|
|
35
|
+
</section>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineConfig,
|
|
3
|
+
} from "bcp/config";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
server: {
|
|
7
|
+
port: 3000,
|
|
8
|
+
hostname:
|
|
9
|
+
"localhost",
|
|
10
|
+
bodyLimit:
|
|
11
|
+
1024 * 1024,
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
compression: true,
|
|
15
|
+
|
|
16
|
+
build: {
|
|
17
|
+
minify: true,
|
|
18
|
+
sourceMaps: false,
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
cache: {
|
|
22
|
+
response: true,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
security: {
|
|
26
|
+
poweredByHeader:
|
|
27
|
+
false,
|
|
28
|
+
contentSecurityPolicy:
|
|
29
|
+
false,
|
|
30
|
+
frameOptions:
|
|
31
|
+
"SAMEORIGIN",
|
|
32
|
+
referrerPolicy:
|
|
33
|
+
"strict-origin-when-cross-origin",
|
|
34
|
+
permissionsPolicy:
|
|
35
|
+
"camera=(), microphone=(), geolocation=()",
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"allowSyntheticDefaultImports": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"types": [
|
|
13
|
+
"node",
|
|
14
|
+
"react",
|
|
15
|
+
"react-dom"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"app/**/*.ts",
|
|
20
|
+
"app/**/*.tsx",
|
|
21
|
+
"bcp.config.ts"
|
|
22
|
+
],
|
|
23
|
+
"exclude": [
|
|
24
|
+
"node_modules",
|
|
25
|
+
".bcp-framework"
|
|
26
|
+
]
|
|
27
|
+
}
|