create-ec-app 0.0.5 → 0.0.6
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/index.js +139 -88
- package/dist/index.js.map +1 -1
- package/dist/libFunctions.d.ts +42 -0
- package/dist/libFunctions.d.ts.map +1 -0
- package/dist/libFunctions.js +121 -0
- package/dist/libFunctions.js.map +1 -0
- package/package.json +54 -59
- package/README.md +0 -207
- package/bin/index.js +0 -2
- package/dist/creators/mobile.d.ts +0 -2
- package/dist/creators/mobile.d.ts.map +0 -1
- package/dist/creators/mobile.js +0 -244
- package/dist/creators/mobile.js.map +0 -1
- package/dist/creators/portal.d.ts +0 -2
- package/dist/creators/portal.d.ts.map +0 -1
- package/dist/creators/portal.js +0 -1005
- package/dist/creators/portal.js.map +0 -1
- package/dist/creators/powerpages.d.ts +0 -2
- package/dist/creators/powerpages.d.ts.map +0 -1
- package/dist/creators/powerpages.js +0 -755
- package/dist/creators/powerpages.js.map +0 -1
- package/dist/creators/webresource.d.ts +0 -2
- package/dist/creators/webresource.d.ts.map +0 -1
- package/dist/creators/webresource.js +0 -705
- package/dist/creators/webresource.js.map +0 -1
- package/dist/readmes/mobile.md +0 -42
- package/dist/readmes/portal.md +0 -161
- package/dist/readmes/powerpages.md +0 -108
- package/dist/readmes/webresource.md +0 -260
package/dist/index.js
CHANGED
|
@@ -1,95 +1,146 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
name
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
projectName = newProjectName;
|
|
25
|
-
}
|
|
26
|
-
// Prompt for application type
|
|
27
|
-
const appTypes = [
|
|
28
|
-
{
|
|
29
|
-
name: "Webresource App",
|
|
30
|
-
value: "webresource",
|
|
31
|
-
description: "React app for Dynamics 365 webresources with Vite, optional Kendo UI, and Tailwind"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: "Portal App",
|
|
35
|
-
value: "portal",
|
|
36
|
-
description: "Next.js app for customer portals with authentication and Dynamics integration"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "Power Pages App",
|
|
40
|
-
value: "powerpages",
|
|
41
|
-
description: "React SPA for Power Pages with authentication context and data services"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
name: "Mobile App",
|
|
45
|
-
value: "mobile",
|
|
46
|
-
description: "React Native Expo app with TypeScript and NativeWind"
|
|
47
|
-
}
|
|
48
|
-
];
|
|
49
|
-
const { appType } = await inquirer.prompt([
|
|
50
|
-
{
|
|
51
|
-
type: "list",
|
|
52
|
-
name: "appType",
|
|
53
|
-
message: "What type of application would you like to create?",
|
|
54
|
-
choices: appTypes.map(type => ({
|
|
55
|
-
name: `${type.name}\n ${chalk.gray(type.description)}`,
|
|
56
|
-
value: type.value,
|
|
57
|
-
short: type.name
|
|
58
|
-
})),
|
|
59
|
-
pageSize: 10
|
|
2
|
+
import path, { dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { cancel, intro, isCancel, log, outro, select, spinner, text, } from "@clack/prompts";
|
|
5
|
+
import fs from "fs-extra";
|
|
6
|
+
import { applyLayer, replaceTokensRecursively } from "./libFunctions.js";
|
|
7
|
+
const { execSync } = await import("node:child_process");
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
async function main() {
|
|
11
|
+
intro("Create EC App");
|
|
12
|
+
const name = await text({
|
|
13
|
+
message: "Project name",
|
|
14
|
+
placeholder: "my-app",
|
|
15
|
+
validate(value) {
|
|
16
|
+
if (value.length === 0)
|
|
17
|
+
return "Project name cannot be empty";
|
|
18
|
+
if (value.toLocaleLowerCase() !== value)
|
|
19
|
+
return "Project name must be lowercase";
|
|
20
|
+
if (/\s/.test(value))
|
|
21
|
+
return "Project name cannot contain spaces";
|
|
22
|
+
if (/[^a-z0-9-_]/.test(value))
|
|
23
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
60
24
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
25
|
+
});
|
|
26
|
+
if (isCancel(name)) {
|
|
27
|
+
cancel("Operation cancelled.");
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
const projectName = String(name).trim();
|
|
31
|
+
log.step(`Creating project: ${projectName}`);
|
|
32
|
+
const target = await select({
|
|
33
|
+
message: "What are you building?",
|
|
34
|
+
options: [
|
|
35
|
+
{ label: "Web Resource", value: "webresource" },
|
|
36
|
+
{ label: "Portal (WIP)", value: "portal" },
|
|
37
|
+
{ label: "Static Web App", value: "swa" },
|
|
38
|
+
{ label: "Power Pages", value: "power-pages" },
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
if (isCancel(target)) {
|
|
42
|
+
cancel("Operation cancelled.");
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
log.step(`Selected target: ${target}`);
|
|
46
|
+
const uiType = await select({
|
|
47
|
+
message: "What UI library do you want to use?",
|
|
48
|
+
options: [
|
|
49
|
+
{ label: "Kendo UI", value: "kendo" },
|
|
50
|
+
{ label: "Shadcn/UI", value: "shadcn-ui" },
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
if (isCancel(uiType)) {
|
|
54
|
+
cancel("Operation cancelled.");
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
const shouldRunNpmInstall = await select({
|
|
58
|
+
message: "Do you want to install dependencies?",
|
|
59
|
+
options: [
|
|
60
|
+
{ label: "Yes", value: { run: true } },
|
|
61
|
+
{ label: "No", value: { run: false } },
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
if (isCancel(shouldRunNpmInstall)) {
|
|
65
|
+
cancel("Operation cancelled.");
|
|
66
|
+
process.exit(0);
|
|
80
67
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
68
|
+
const projectDir = path.join(process.cwd(), projectName);
|
|
69
|
+
const templatesRoot = path.join(__dirname, "..", "templates");
|
|
70
|
+
const baseDir = path.join(templatesRoot, "base");
|
|
71
|
+
const targetDir = path.join(templatesRoot, "targets", target);
|
|
72
|
+
const uiDir = path.join(templatesRoot, "ui", uiType);
|
|
73
|
+
await fs.copy(baseDir, projectDir);
|
|
74
|
+
if (fs.existsSync(targetDir)) {
|
|
75
|
+
await applyLayer(targetDir, projectDir);
|
|
87
76
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
77
|
+
if (fs.existsSync(uiDir)) {
|
|
78
|
+
await applyLayer(uiDir, projectDir);
|
|
79
|
+
}
|
|
80
|
+
await replaceTokensRecursively(projectDir, {
|
|
81
|
+
APP_NAME: projectName,
|
|
82
|
+
TARGET: target,
|
|
83
|
+
UI: uiType,
|
|
84
|
+
});
|
|
85
|
+
//WARN: This is a special case fix for having AuthContext in Kendo for Power Pages
|
|
86
|
+
if (target === "power-pages" && uiType === "kendo") {
|
|
87
|
+
const mainTsxPath = path.join(projectDir, "src", "main.tsx");
|
|
88
|
+
await fs.writeFile(mainTsxPath, POWER_PAGES_KENDO_MAIN_TSX, "utf-8");
|
|
89
|
+
}
|
|
90
|
+
if (shouldRunNpmInstall.run) {
|
|
91
|
+
const s = spinner();
|
|
92
|
+
s.start("Running npm install...");
|
|
93
|
+
const { execSync } = await import("node:child_process");
|
|
94
|
+
execSync("npm install", { cwd: projectDir, stdio: "inherit" });
|
|
95
|
+
s.stop("Dependencies installed.");
|
|
96
|
+
}
|
|
97
|
+
const sGit = spinner();
|
|
98
|
+
sGit.start("Initializing git repository...");
|
|
99
|
+
execSync("git init", { cwd: projectDir, stdio: "ignore" });
|
|
100
|
+
execSync("git add .", { cwd: projectDir, stdio: "ignore" });
|
|
101
|
+
execSync('git commit -m "Initial commit"', {
|
|
102
|
+
cwd: projectDir,
|
|
103
|
+
stdio: "ignore",
|
|
104
|
+
});
|
|
105
|
+
sGit.stop("Git repository initialized.");
|
|
106
|
+
outro(`Scaffolded ${projectName} as ${target} with ${uiType}. Next steps: 'git remote origin add <url>'`);
|
|
107
|
+
}
|
|
108
|
+
main().catch((err) => {
|
|
109
|
+
console.error(err);
|
|
93
110
|
process.exit(1);
|
|
94
111
|
});
|
|
112
|
+
// NOTE: Constants
|
|
113
|
+
const POWER_PAGES_KENDO_MAIN_TSX = `import { StrictMode } from "react";
|
|
114
|
+
import { createRoot } from "react-dom/client";
|
|
115
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
116
|
+
import "@progress/kendo-theme-fluent/dist/all.css";
|
|
117
|
+
import "./index.css";
|
|
118
|
+
import App from "./App.tsx";
|
|
119
|
+
|
|
120
|
+
import { AuthProvider } from "./context/AuthContext.tsx";
|
|
121
|
+
|
|
122
|
+
const queryClient = new QueryClient({
|
|
123
|
+
defaultOptions: {
|
|
124
|
+
queries: {
|
|
125
|
+
refetchOnWindowFocus: false,
|
|
126
|
+
retry: 3,
|
|
127
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
128
|
+
},
|
|
129
|
+
mutations: {
|
|
130
|
+
retry: 1,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const root = createRoot(document.getElementById("root")!);
|
|
136
|
+
|
|
137
|
+
root.render(
|
|
138
|
+
<StrictMode>
|
|
139
|
+
<AuthProvider>
|
|
140
|
+
<QueryClientProvider client={queryClient}>
|
|
141
|
+
<App />
|
|
142
|
+
</QueryClientProvider>
|
|
143
|
+
</AuthProvider>
|
|
144
|
+
</StrictMode>
|
|
145
|
+
);`;
|
|
95
146
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Applies a template later onto an existing base project
|
|
3
|
+
* @param { string } layerDir - the base directory of the layer to patch
|
|
4
|
+
* @param { string } projectDir - the base directory of the files to be patched
|
|
5
|
+
* */
|
|
6
|
+
export declare function applyLayer(layerDir: string, projectDir: string): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Safely reads a JSON file if it exists.
|
|
9
|
+
*
|
|
10
|
+
* If the file does not exist, returns `undefined` instead of throwing.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} filePath - Absolute path to the JSON file.
|
|
13
|
+
* @returns {Promise<any | undefined>} The parsed JSON object or `undefined` if the file does not exist.
|
|
14
|
+
*/
|
|
15
|
+
export declare function readJsonIfExists(filePath: string): Promise<any | undefined>;
|
|
16
|
+
/**
|
|
17
|
+
* Merges two JSON objects with special handling for dependency-style keys.
|
|
18
|
+
*
|
|
19
|
+
* Shallow merges the root object, then deep-merges the following keys:
|
|
20
|
+
* - dependencies
|
|
21
|
+
* - devDependencies
|
|
22
|
+
* - peerDependencies
|
|
23
|
+
* - scripts
|
|
24
|
+
*
|
|
25
|
+
* Patch values always override base values on conflicts.
|
|
26
|
+
*
|
|
27
|
+
* @param {any} base - The base JSON object (from the base template).
|
|
28
|
+
* @param {any} patch - The patch JSON object (from a layer).
|
|
29
|
+
* @returns {any} The merged JSON result.
|
|
30
|
+
*/
|
|
31
|
+
export declare function mergeJson(base: any, patch: any): any;
|
|
32
|
+
/**
|
|
33
|
+
* Recursively replaces {{TOKEN}} placeholders in all text files under a directory.
|
|
34
|
+
*
|
|
35
|
+
* Traverses the directory tree depth-first. Each file is treated as UTF-8 text.
|
|
36
|
+
* If a file cannot be read as text (binary), it is skipped silently.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} rootDir - Root directory to begin token replacement.
|
|
39
|
+
* @param {Record<string, string>} tokens - Key/value pairs used for replacement.
|
|
40
|
+
*/
|
|
41
|
+
export declare function replaceTokensRecursively(rootDir: string, tokens: Record<string, string>): Promise<void>;
|
|
42
|
+
//# sourceMappingURL=libFunctions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libFunctions.d.ts","sourceRoot":"","sources":["../src/libFunctions.ts"],"names":[],"mappings":"AAGA;;;;KAIK;AACL,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBA6CpE;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACrC,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC,CAK1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,GAAG,GAAG,CAoBpD;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,iBA4B9B"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
/**
|
|
4
|
+
* Applies a template later onto an existing base project
|
|
5
|
+
* @param { string } layerDir - the base directory of the layer to patch
|
|
6
|
+
* @param { string } projectDir - the base directory of the files to be patched
|
|
7
|
+
* */
|
|
8
|
+
export async function applyLayer(layerDir, projectDir) {
|
|
9
|
+
const entries = await fs.readdir(layerDir, { withFileTypes: true });
|
|
10
|
+
for (const entry of entries) {
|
|
11
|
+
const layerPath = path.join(layerDir, entry.name);
|
|
12
|
+
const relPath = path.relative(layerDir, layerPath);
|
|
13
|
+
if (entry.isDirectory()) {
|
|
14
|
+
await applyLayer(layerPath, path.join(projectDir, entry.name));
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (entry.name.endsWith(".patch.json")) {
|
|
18
|
+
const targetRel = relPath.replace(/\.patch\.json$/, ".json");
|
|
19
|
+
const targetPath = path.join(projectDir, targetRel);
|
|
20
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
21
|
+
const baseJson = (await readJsonIfExists(targetPath)) ?? {};
|
|
22
|
+
const patchJson = await fs.readJson(layerPath);
|
|
23
|
+
const merged = mergeJson(baseJson, patchJson);
|
|
24
|
+
await fs.writeJson(targetPath, merged, { spaces: 2 });
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (/\.(patch\.ts|patch\.tsx|patch\.js|patch\.jsx|patch\.css)$/.test(entry.name)) {
|
|
28
|
+
const targetRel = relPath.replace(".patch.", ".");
|
|
29
|
+
const targetPath = path.join(projectDir, targetRel);
|
|
30
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
31
|
+
await fs.copy(layerPath, targetPath);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const targetPath = path.join(projectDir, relPath);
|
|
35
|
+
await fs.ensureDir(path.dirname(targetPath));
|
|
36
|
+
await fs.copy(layerPath, targetPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Safely reads a JSON file if it exists.
|
|
41
|
+
*
|
|
42
|
+
* If the file does not exist, returns `undefined` instead of throwing.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} filePath - Absolute path to the JSON file.
|
|
45
|
+
* @returns {Promise<any | undefined>} The parsed JSON object or `undefined` if the file does not exist.
|
|
46
|
+
*/
|
|
47
|
+
export async function readJsonIfExists(filePath) {
|
|
48
|
+
if (!(await fs.pathExists(filePath))) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return fs.readJson(filePath);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Merges two JSON objects with special handling for dependency-style keys.
|
|
55
|
+
*
|
|
56
|
+
* Shallow merges the root object, then deep-merges the following keys:
|
|
57
|
+
* - dependencies
|
|
58
|
+
* - devDependencies
|
|
59
|
+
* - peerDependencies
|
|
60
|
+
* - scripts
|
|
61
|
+
*
|
|
62
|
+
* Patch values always override base values on conflicts.
|
|
63
|
+
*
|
|
64
|
+
* @param {any} base - The base JSON object (from the base template).
|
|
65
|
+
* @param {any} patch - The patch JSON object (from a layer).
|
|
66
|
+
* @returns {any} The merged JSON result.
|
|
67
|
+
*/
|
|
68
|
+
export function mergeJson(base, patch) {
|
|
69
|
+
const result = { ...base, ...patch };
|
|
70
|
+
const mergeKeys = [
|
|
71
|
+
"dependencies",
|
|
72
|
+
"devDependencies",
|
|
73
|
+
"peerDependencies",
|
|
74
|
+
"scripts",
|
|
75
|
+
];
|
|
76
|
+
for (const key of mergeKeys) {
|
|
77
|
+
if (base?.[key] || patch?.[key]) {
|
|
78
|
+
result[key] = {
|
|
79
|
+
...(base?.[key] ?? {}),
|
|
80
|
+
...(patch?.[key] ?? {}),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Recursively replaces {{TOKEN}} placeholders in all text files under a directory.
|
|
88
|
+
*
|
|
89
|
+
* Traverses the directory tree depth-first. Each file is treated as UTF-8 text.
|
|
90
|
+
* If a file cannot be read as text (binary), it is skipped silently.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} rootDir - Root directory to begin token replacement.
|
|
93
|
+
* @param {Record<string, string>} tokens - Key/value pairs used for replacement.
|
|
94
|
+
*/
|
|
95
|
+
export async function replaceTokensRecursively(rootDir, tokens) {
|
|
96
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true });
|
|
97
|
+
for (const entry of entries) {
|
|
98
|
+
const fullPath = path.join(rootDir, entry.name);
|
|
99
|
+
if (entry.isDirectory()) {
|
|
100
|
+
await replaceTokensRecursively(fullPath, tokens);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
let content;
|
|
104
|
+
try {
|
|
105
|
+
content = await fs.readFile(fullPath, "utf8");
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
let updated = content;
|
|
111
|
+
for (const [key, value] of Object.entries(tokens)) {
|
|
112
|
+
const pattern = new RegExp(`{{${key}}}`, "g");
|
|
113
|
+
updated = updated.replace(pattern, value);
|
|
114
|
+
}
|
|
115
|
+
if (updated !== content) {
|
|
116
|
+
await fs.writeFile(fullPath, updated, "utf8");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=libFunctions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"libFunctions.js","sourceRoot":"","sources":["../src/libFunctions.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,60 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"bugs": {
|
|
57
|
-
"url": "https://github.com/Enterprisecloud-Pty-Ltd/create-ec-app/issues"
|
|
58
|
-
},
|
|
59
|
-
"homepage": "https://github.com/Enterprisecloud-Pty-Ltd/create-ec-app#readme"
|
|
60
|
-
}
|
|
2
|
+
"name": "create-ec-app",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"description": "Unified CLI tool to create different types of EC applications: Webresource, Portal, Power Pages",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-ec-app": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "tsx src/index.ts",
|
|
10
|
+
"build": "tsc -p tsconfig.json",
|
|
11
|
+
"test": "node bin/index.js test-app",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react",
|
|
16
|
+
"vite",
|
|
17
|
+
"kendo",
|
|
18
|
+
"tailwind",
|
|
19
|
+
"cli",
|
|
20
|
+
"powerpages",
|
|
21
|
+
"portal",
|
|
22
|
+
"webresource",
|
|
23
|
+
"dynamics",
|
|
24
|
+
"ec"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22.0.0"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/**/*",
|
|
31
|
+
"bin/**/*"
|
|
32
|
+
],
|
|
33
|
+
"author": "Schalk Conradie",
|
|
34
|
+
"type": "module",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@clack/prompts": "^0.11.0",
|
|
37
|
+
"fs-extra": "^11.3.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/fs-extra": "^11.0.4",
|
|
41
|
+
"@types/node": "^24.10.1",
|
|
42
|
+
"ts-node": "^10.9.2",
|
|
43
|
+
"tsx": "^4.21.0",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/Enterprisecloud-Pty-Ltd/create-ec-app.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/Enterprisecloud-Pty-Ltd/create-ec-app/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/Enterprisecloud-Pty-Ltd/create-ec-app#readme"
|
|
54
|
+
}
|
|
55
|
+
|