extension-create 2.0.1 → 2.1.2
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/README.md +24 -4
- package/dist/lib/messages.d.ts +31 -0
- package/dist/lib/types.d.ts +26 -0
- package/dist/lib/utils.d.ts +8 -0
- package/dist/module.d.ts +2 -4
- package/dist/module.js +672 -34
- package/dist/rslib.config.d.ts +2 -0
- package/dist/steps/create-directory.d.ts +1 -0
- package/dist/steps/generate-extension-types.d.ts +1 -0
- package/dist/steps/import-external-template.d.ts +1 -0
- package/dist/steps/import-local-template.d.ts +1 -0
- package/dist/steps/initialize-git-repository.d.ts +1 -0
- package/dist/steps/install-dependencies.d.ts +1 -0
- package/dist/steps/setup-built-in-tests.d.ts +1 -0
- package/dist/steps/write-gitignore.d.ts +1 -0
- package/dist/steps/write-manifest-json.d.ts +1 -0
- package/dist/steps/write-package-json.d.ts +6 -0
- package/dist/steps/write-readme-file.d.ts +1 -0
- package/dist/vitest.config.d.ts +2 -0
- package/package.json +52 -16
- package/dist/template/README.md +0 -35
- package/dist/template/manifest.json +0 -7
- package/dist/template/package.json +0 -17
package/README.md
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
|
+
[npm-version-image]: https://img.shields.io/npm/v/extension-create.svg?color=0971fe
|
|
2
|
+
[npm-version-url]: https://www.npmjs.com/package/extension-create
|
|
3
|
+
[downloads-image]: https://img.shields.io/npm/dm/extension-create.svg?color=2ecc40
|
|
4
|
+
[downloads-url]: https://npmjs.org/package/extension-create
|
|
5
|
+
[empowering-image]: https://img.shields.io/badge/Empowering-Extension.js-0971fe
|
|
6
|
+
[empowering-url]: https://extension.js.org
|
|
7
|
+
|
|
8
|
+
[![Empowering][empowering-image]][empowering-url] [![Version][npm-version-image]][npm-version-url] [![Downloads][downloads-image]][downloads-url]
|
|
9
|
+
|
|
1
10
|
# extension-create
|
|
2
11
|
|
|
3
|
-
>
|
|
12
|
+
> Scaffold a new [Extension.js](https://extension.js.org) project from a template.
|
|
13
|
+
|
|
14
|
+
This package implements the logic Extension.js uses to scaffold a new extension project from a selected template.
|
|
15
|
+
It performs, in order:
|
|
4
16
|
|
|
5
|
-
|
|
17
|
+
- Create or reuse the target directory (and fail on conflicting files)
|
|
18
|
+
- Import the selected template (local in dev, remote via Git in prod)
|
|
19
|
+
- Write `package.json` metadata and add Extension.js scripts
|
|
20
|
+
- Write `manifest.json` metadata
|
|
21
|
+
- Initialize a Git repository
|
|
22
|
+
- Write a `.gitignore`
|
|
23
|
+
- Remove template-only test files
|
|
24
|
+
- If the template is TypeScript-based, generate `extension-env.d.ts`
|
|
6
25
|
|
|
7
26
|
## Installation
|
|
8
27
|
|
|
@@ -19,8 +38,9 @@ async function createNewExtension () {
|
|
|
19
38
|
await extensionCreate(
|
|
20
39
|
projectName: /* string (required) */,
|
|
21
40
|
{
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
template: 'init', // or any template name (see /examples)
|
|
42
|
+
install: false, // optionally run the package manager install step
|
|
43
|
+
cliVersion: '2.x' // used to pin the CLI when not in dev mode
|
|
24
44
|
}
|
|
25
45
|
)
|
|
26
46
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare function destinationNotWriteable(workingDir: string): string;
|
|
2
|
+
export declare function directoryHasConflicts(projectPath: string, conflictingFiles: string[]): Promise<string>;
|
|
3
|
+
export declare function noProjectName(): string;
|
|
4
|
+
export declare function noUrlAllowed(): string;
|
|
5
|
+
export declare function successfullInstall(projectPath: string, projectName: string): Promise<string>;
|
|
6
|
+
export declare function startingNewExtension(projectName: string): string;
|
|
7
|
+
export declare function checkingIfPathIsWriteable(): string;
|
|
8
|
+
export declare function scanningPossiblyConflictingFiles(): string;
|
|
9
|
+
export declare function createDirectoryError(projectName: string, error: any): string;
|
|
10
|
+
export declare function writingTypeDefinitions(projectName: string): string;
|
|
11
|
+
export declare function writingTypeDefinitionsError(error: any): string;
|
|
12
|
+
export declare function installingFromTemplate(projectName: string, templateName: string): string;
|
|
13
|
+
export declare function installingFromTemplateError(projectName: string, template: string, error: any): string;
|
|
14
|
+
export declare function initializingGitForRepository(projectName: string): string;
|
|
15
|
+
export declare function initializingGitForRepositoryFailed(gitCommand: string, gitArgs: string[], code: number | null): string;
|
|
16
|
+
export declare function initializingGitForRepositoryProcessError(projectName: string, error: any): string;
|
|
17
|
+
export declare function initializingGitForRepositoryError(projectName: string, error: any): string;
|
|
18
|
+
export declare function installingDependencies(): string;
|
|
19
|
+
export declare function installingDependenciesFailed(gitCommand: string, gitArgs: string[], code: number | null): string;
|
|
20
|
+
export declare function installingDependenciesProcessError(projectName: string, error: any): string;
|
|
21
|
+
export declare function cantInstallDependencies(projectName: string, error: any): string;
|
|
22
|
+
export declare function writingPackageJsonMetadata(): string;
|
|
23
|
+
export declare function writingPackageJsonMetadataError(projectName: string, error: any): string;
|
|
24
|
+
export declare function writingManifestJsonMetadata(): string;
|
|
25
|
+
export declare function writingManifestJsonMetadataError(projectName: string, error: any): string;
|
|
26
|
+
export declare function writingReadmeMetaData(): string;
|
|
27
|
+
export declare function writingGitIgnore(): string;
|
|
28
|
+
export declare function writingReadmeMetaDataEError(projectName: string, error: any): string;
|
|
29
|
+
export declare function folderExists(projectName: string): string;
|
|
30
|
+
export declare function writingDirectoryError(error: any): string;
|
|
31
|
+
export declare function cantSetupBuiltInTests(projectName: string, error: any): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
declare namespace NodeJS {
|
|
2
|
+
interface ProcessEnv {
|
|
3
|
+
EXTENSION_BROWSER: 'chrome' | 'edge' | 'firefox' | 'chromium-based' | 'gecko-based';
|
|
4
|
+
EXTENSION_MODE: 'development' | 'production';
|
|
5
|
+
EXTENSION_PUBLIC_BROWSER: 'chrome' | 'edge' | 'firefox' | 'chromium-based' | 'gecko-based';
|
|
6
|
+
EXTENSION_PUBLIC_MODE: 'development' | 'production';
|
|
7
|
+
EXTENSION_PUBLIC_DESCRIPTION_TEXT: string;
|
|
8
|
+
EXTENSION_PUBLIC_OPENAI_API_KEY: string;
|
|
9
|
+
EXTENSION_ENV: 'development' | 'production';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
interface ImportMetaEnv {
|
|
13
|
+
EXTENSION_BROWSER: NodeJS.ProcessEnv['EXTENSION_BROWSER'];
|
|
14
|
+
EXTENSION_MODE: NodeJS.ProcessEnv['EXTENSION_MODE'];
|
|
15
|
+
EXTENSION_PUBLIC_BROWSER: NodeJS.ProcessEnv['EXTENSION_BROWSER'];
|
|
16
|
+
EXTENSION_PUBLIC_MODE: NodeJS.ProcessEnv['EXTENSION_MODE'];
|
|
17
|
+
[key: string]: string | undefined;
|
|
18
|
+
}
|
|
19
|
+
interface ImportMeta {
|
|
20
|
+
readonly env: ImportMetaEnv;
|
|
21
|
+
readonly webpackHot?: {
|
|
22
|
+
accept: (module?: string | string[], callback?: () => void) => void;
|
|
23
|
+
dispose: (callback: () => void) => void;
|
|
24
|
+
};
|
|
25
|
+
url: string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function copyDirectory(source: string, destination: string): Promise<void[]>;
|
|
2
|
+
export declare function copyDirectoryWithSymlinks(source: string, destination: string): Promise<void>;
|
|
3
|
+
export declare function moveDirectoryContents(source: string, destination: string): Promise<void>;
|
|
4
|
+
export declare function getInstallCommand(): Promise<string>;
|
|
5
|
+
export declare function getTemplatePath(workingDir: string): string;
|
|
6
|
+
export declare function isDirectoryWriteable(directory: string, projectName: string): Promise<boolean>;
|
|
7
|
+
export declare function isExternalTemplate(_templateName: string): boolean;
|
|
8
|
+
export declare function isTypeScriptTemplate(templateName: string): boolean;
|
package/dist/module.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
interface CreateOptions {
|
|
1
|
+
export interface CreateOptions {
|
|
2
2
|
template: string;
|
|
3
3
|
install?: boolean;
|
|
4
4
|
cliVersion?: string;
|
|
5
5
|
}
|
|
6
|
-
declare function extensionCreate(projectNameInput: string | undefined, { cliVersion, template, install }: CreateOptions): Promise<void>;
|
|
7
|
-
|
|
8
|
-
export { type CreateOptions, extensionCreate };
|
|
6
|
+
export declare function extensionCreate(projectNameInput: string | undefined, { cliVersion, template, install }: CreateOptions): Promise<void>;
|
package/dist/module.js
CHANGED
|
@@ -1,39 +1,677 @@
|
|
|
1
|
-
"use strict";
|
|
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
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
|
|
3
|
+
return 'undefined' == typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
|
|
4
|
+
}();
|
|
5
|
+
var __webpack_require__ = {};
|
|
6
|
+
(()=>{
|
|
7
|
+
__webpack_require__.n = (module)=>{
|
|
8
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
9
|
+
__webpack_require__.d(getter, {
|
|
10
|
+
a: getter
|
|
11
|
+
});
|
|
12
|
+
return getter;
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
17
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: definition[key]
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
})();
|
|
23
|
+
(()=>{
|
|
24
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
25
|
+
})();
|
|
26
|
+
(()=>{
|
|
27
|
+
__webpack_require__.r = (exports1)=>{
|
|
28
|
+
if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
29
|
+
value: 'Module'
|
|
30
|
+
});
|
|
31
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
32
|
+
value: true
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __webpack_exports__ = {};
|
|
37
|
+
__webpack_require__.r(__webpack_exports__);
|
|
38
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
39
|
+
extensionCreate: ()=>extensionCreate
|
|
40
|
+
});
|
|
41
|
+
const external_path_namespaceObject = require("path");
|
|
42
|
+
const external_fs_namespaceObject = require("fs");
|
|
43
|
+
const external_pintor_namespaceObject = require("pintor");
|
|
44
|
+
var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pintor_namespaceObject);
|
|
45
|
+
const external_package_manager_detector_namespaceObject = require("package-manager-detector");
|
|
46
|
+
function destinationNotWriteable(workingDir) {
|
|
47
|
+
const workingDirFolder = external_path_namespaceObject.basename(workingDir);
|
|
48
|
+
return `${external_pintor_default().red('ERROR')} Failed to write in the destination directory.\n${external_pintor_default().red('Path is not writable. Ensure you have write permissions for this folder.')}\n${external_pintor_default().red('NOT WRITEABLE')} ${external_pintor_default().underline(workingDirFolder)}`;
|
|
49
|
+
}
|
|
50
|
+
async function directoryHasConflicts(projectPath, conflictingFiles) {
|
|
51
|
+
const projectName = external_path_namespaceObject.basename(projectPath);
|
|
52
|
+
let message = `Conflict! Path to ${external_pintor_default().yellow(projectName)} includes conflicting files.\n`;
|
|
53
|
+
for (const file of conflictingFiles){
|
|
54
|
+
const stats = await external_fs_namespaceObject.promises.lstat(external_path_namespaceObject.join(projectPath, file));
|
|
55
|
+
message += stats.isDirectory() ? `${external_pintor_default().gray('-')} ${external_pintor_default().yellow(file)}\n` : `${external_pintor_default().gray('-')} ${external_pintor_default().yellow(file)}\n`;
|
|
56
|
+
}
|
|
57
|
+
message += `${external_pintor_default().red('You need to either rename/remove the files listed above, or choose a new directory name for your extension.')}\nPath to conflicting directory: ${external_pintor_default().underline(projectPath)}`;
|
|
58
|
+
return message;
|
|
59
|
+
}
|
|
60
|
+
function noProjectName() {
|
|
61
|
+
return `${external_pintor_default().red('ERROR')} You need to provide an extension name to create one. See ${external_pintor_default().blue('--help')} for command info.`;
|
|
62
|
+
}
|
|
63
|
+
function noUrlAllowed() {
|
|
64
|
+
return `${external_pintor_default().red('ERROR')} URLs are not allowed as a project path. Either write a name or a path to a local folder.`;
|
|
65
|
+
}
|
|
66
|
+
async function successfullInstall(projectPath, projectName) {
|
|
67
|
+
const relativePath = external_path_namespaceObject.relative(process.cwd(), projectPath);
|
|
68
|
+
const pm = await (0, external_package_manager_detector_namespaceObject.detect)();
|
|
69
|
+
let command = 'npm run';
|
|
70
|
+
let installCmd = 'npm install';
|
|
71
|
+
switch(null == pm ? void 0 : pm.name){
|
|
72
|
+
case 'yarn':
|
|
73
|
+
command = 'yarn dev';
|
|
74
|
+
installCmd = 'yarn';
|
|
75
|
+
break;
|
|
76
|
+
case 'pnpm':
|
|
77
|
+
command = 'pnpm dev';
|
|
78
|
+
installCmd = 'pnpm install';
|
|
79
|
+
break;
|
|
80
|
+
default:
|
|
81
|
+
command = 'npm run dev';
|
|
82
|
+
installCmd = 'npm install';
|
|
83
|
+
}
|
|
84
|
+
if (process.env.npm_config_user_agent) {
|
|
85
|
+
if (process.env.npm_config_user_agent.includes('pnpm')) {
|
|
86
|
+
command = 'pnpm dev';
|
|
87
|
+
installCmd = 'pnpm install';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return `\u{1F9E9} - ${external_pintor_default().green('Success!')} Extension ${external_pintor_default().yellow(projectName)} created.\nNow ${external_pintor_default().blue('cd')} ${external_pintor_default().underline(relativePath)}\n${external_pintor_default().blue(installCmd)} to install dependencies\n${external_pintor_default().blue(command)} to open a new browser instance\nwith your extension installed, loaded, and enabled for development.\n${external_pintor_default().green('You are ready')}. Time to hack on your extension!`;
|
|
91
|
+
}
|
|
92
|
+
function startingNewExtension(projectName) {
|
|
93
|
+
return `\u{1F423} - Starting a new browser extension named ${external_pintor_default().yellow(projectName)}...`;
|
|
94
|
+
}
|
|
95
|
+
function checkingIfPathIsWriteable() {
|
|
96
|
+
return `\u{1F91E} - Checking if destination path is writeable...`;
|
|
97
|
+
}
|
|
98
|
+
function scanningPossiblyConflictingFiles() {
|
|
99
|
+
return "\uD83D\uDD0E - Scanning for potential conflicting files...";
|
|
100
|
+
}
|
|
101
|
+
function createDirectoryError(projectName, error) {
|
|
102
|
+
return `${external_pintor_default().red('ERROR')} Can't create directory ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
103
|
+
}
|
|
104
|
+
function writingTypeDefinitions(projectName) {
|
|
105
|
+
return `\u{1F537} - Writing type definitions for ${external_pintor_default().yellow(projectName)}...`;
|
|
106
|
+
}
|
|
107
|
+
function writingTypeDefinitionsError(error) {
|
|
108
|
+
return `${external_pintor_default().red('ERROR')} Failed to write the extension type definition.\n${external_pintor_default().red(String(error))}`;
|
|
109
|
+
}
|
|
110
|
+
function installingFromTemplate(projectName, templateName) {
|
|
111
|
+
if ('init' === templateName) return `\u{1F9F0} - Installing ${external_pintor_default().yellow(projectName)}...`;
|
|
112
|
+
return `\u{1F9F0} - Installing ${external_pintor_default().yellow(projectName)} from template ${external_pintor_default().yellow(templateName)}...`;
|
|
113
|
+
}
|
|
114
|
+
function installingFromTemplateError(projectName, template, error) {
|
|
115
|
+
return `${external_pintor_default().red('ERROR')} Can't find template ${external_pintor_default().yellow(template)} for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
116
|
+
}
|
|
117
|
+
function initializingGitForRepository(projectName) {
|
|
118
|
+
return `\u{1F332} - Initializing git repository for ${external_pintor_default().yellow(projectName)}...`;
|
|
119
|
+
}
|
|
120
|
+
function initializingGitForRepositoryFailed(gitCommand, gitArgs, code) {
|
|
121
|
+
return `${external_pintor_default().red('ERROR')} Command ${external_pintor_default().gray(gitCommand)} ${external_pintor_default().gray(gitArgs.join(' '))} failed.\n${external_pintor_default().red(`exit code ${external_pintor_default().gray(String(code))}`)}`;
|
|
122
|
+
}
|
|
123
|
+
function initializingGitForRepositoryProcessError(projectName, error) {
|
|
124
|
+
return `${external_pintor_default().red('ERROR')} Child process error: Can't initialize ${external_pintor_default().gray('git')} for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String((null == error ? void 0 : error.message) || error))}`;
|
|
125
|
+
}
|
|
126
|
+
function initializingGitForRepositoryError(projectName, error) {
|
|
127
|
+
return `${external_pintor_default().red('ERROR')} Can't initialize ${external_pintor_default().gray('git')} for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String((null == error ? void 0 : error.message) || error))}`;
|
|
128
|
+
}
|
|
129
|
+
function installingDependencies() {
|
|
130
|
+
return "\uD83D\uDEE0 - Installing dependencies... (takes a moment)";
|
|
131
|
+
}
|
|
132
|
+
function installingDependenciesFailed(gitCommand, gitArgs, code) {
|
|
133
|
+
return `${external_pintor_default().red('ERROR')} Command ${external_pintor_default().gray(gitCommand)} ${external_pintor_default().gray(gitArgs.join(' '))} failed.\n${external_pintor_default().red(`exit code ${external_pintor_default().gray(String(code))}`)}`;
|
|
134
|
+
}
|
|
135
|
+
function installingDependenciesProcessError(projectName, error) {
|
|
136
|
+
return `${external_pintor_default().red('ERROR')} Child process error: Can't install dependencies for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
137
|
+
}
|
|
138
|
+
function cantInstallDependencies(projectName, error) {
|
|
139
|
+
return `${external_pintor_default().red('ERROR')} Can't install dependencies for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String((null == error ? void 0 : error.message) || error))}`;
|
|
140
|
+
}
|
|
141
|
+
function writingPackageJsonMetadata() {
|
|
142
|
+
return `\u{1F4DD} - Writing ${external_pintor_default().yellow('package.json')} metadata...`;
|
|
143
|
+
}
|
|
144
|
+
function writingPackageJsonMetadataError(projectName, error) {
|
|
145
|
+
return `${external_pintor_default().red('ERROR')} Can't write ${external_pintor_default().yellow('package.json')} for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
146
|
+
}
|
|
147
|
+
function writingManifestJsonMetadata() {
|
|
148
|
+
return `\u{1F4DC} - Writing ${external_pintor_default().yellow('manifest.json')} metadata...`;
|
|
149
|
+
}
|
|
150
|
+
function writingManifestJsonMetadataError(projectName, error) {
|
|
151
|
+
return `${external_pintor_default().red('ERROR')} Can't write ${external_pintor_default().yellow('manifest.json')} for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
152
|
+
}
|
|
153
|
+
function writingReadmeMetaData() {
|
|
154
|
+
return `\u{1F4C4} - Writing ${external_pintor_default().yellow('README.md')} metadata...`;
|
|
155
|
+
}
|
|
156
|
+
function writingGitIgnore() {
|
|
157
|
+
return `\u{1F648} - Writing ${external_pintor_default().yellow('.gitignore')} lines...`;
|
|
158
|
+
}
|
|
159
|
+
function writingReadmeMetaDataEError(projectName, error) {
|
|
160
|
+
return `${external_pintor_default().red('ERROR')} Can't write the ${external_pintor_default().yellow('README.md')} file for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
161
|
+
}
|
|
162
|
+
function folderExists(projectName) {
|
|
163
|
+
return `\u{1F91D} - Ensuring ${external_pintor_default().yellow(projectName)} folder exists...`;
|
|
164
|
+
}
|
|
165
|
+
function writingDirectoryError(error) {
|
|
166
|
+
return `${external_pintor_default().red('ERROR')} Error while checking directory writability.\n${external_pintor_default().red(String(error))}`;
|
|
167
|
+
}
|
|
168
|
+
function cantSetupBuiltInTests(projectName, error) {
|
|
169
|
+
return `${external_pintor_default().red('ERROR')} Can't setup built-in tests for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}`;
|
|
170
|
+
}
|
|
171
|
+
const promises_namespaceObject = require("fs/promises");
|
|
172
|
+
const external_url_namespaceObject = require("url");
|
|
173
|
+
const utils_filename = (0, external_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__);
|
|
174
|
+
const utils_dirname = external_path_namespaceObject.dirname(utils_filename);
|
|
175
|
+
async function copyDirectoryWithSymlinks(source, destination) {
|
|
176
|
+
const entries = await promises_namespaceObject.readdir(source, {
|
|
177
|
+
withFileTypes: true
|
|
178
|
+
});
|
|
179
|
+
await promises_namespaceObject.mkdir(destination, {
|
|
180
|
+
recursive: true
|
|
181
|
+
});
|
|
182
|
+
for (const entry of entries){
|
|
183
|
+
const sourcePath = external_path_namespaceObject.join(source, entry.name);
|
|
184
|
+
const destPath = external_path_namespaceObject.join(destination, entry.name);
|
|
185
|
+
if (entry.isDirectory()) await copyDirectoryWithSymlinks(sourcePath, destPath);
|
|
186
|
+
else if (entry.isSymbolicLink()) {
|
|
187
|
+
const target = await promises_namespaceObject.readlink(sourcePath);
|
|
188
|
+
await promises_namespaceObject.symlink(target, destPath);
|
|
189
|
+
} else await promises_namespaceObject.copyFile(sourcePath, destPath);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function moveDirectoryContents(source, destination) {
|
|
193
|
+
await promises_namespaceObject.mkdir(destination, {
|
|
194
|
+
recursive: true
|
|
195
|
+
});
|
|
196
|
+
const entries = await promises_namespaceObject.readdir(source, {
|
|
197
|
+
withFileTypes: true
|
|
198
|
+
});
|
|
199
|
+
for (const entry of entries){
|
|
200
|
+
const sourcePath = external_path_namespaceObject.join(source, entry.name);
|
|
201
|
+
const destPath = external_path_namespaceObject.join(destination, entry.name);
|
|
202
|
+
if (entry.isDirectory()) await moveDirectoryContents(sourcePath, destPath);
|
|
203
|
+
else if (entry.isSymbolicLink()) {
|
|
204
|
+
const target = await promises_namespaceObject.readlink(sourcePath);
|
|
205
|
+
await promises_namespaceObject.symlink(target, destPath);
|
|
206
|
+
} else await promises_namespaceObject.rename(sourcePath, destPath);
|
|
207
|
+
}
|
|
208
|
+
await promises_namespaceObject.rm(source, {
|
|
209
|
+
recursive: true,
|
|
210
|
+
force: true
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
async function getInstallCommand() {
|
|
214
|
+
const pm = await (0, external_package_manager_detector_namespaceObject.detect)();
|
|
215
|
+
let command = 'npm';
|
|
216
|
+
if (process.env.npm_config_user_agent) {
|
|
217
|
+
if (process.env.npm_config_user_agent.includes('pnpm')) return 'pnpm';
|
|
218
|
+
}
|
|
219
|
+
switch(null == pm ? void 0 : pm.name){
|
|
220
|
+
case 'yarn':
|
|
221
|
+
command = 'yarn';
|
|
222
|
+
break;
|
|
223
|
+
case 'pnpm':
|
|
224
|
+
command = 'pnpm';
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
command = 'npm';
|
|
228
|
+
}
|
|
229
|
+
return command;
|
|
230
|
+
}
|
|
231
|
+
function getTemplatePath(workingDir) {
|
|
232
|
+
const templatesDir = external_path_namespaceObject.resolve(utils_dirname, '..', 'template');
|
|
233
|
+
return external_path_namespaceObject.resolve(workingDir, templatesDir);
|
|
234
|
+
}
|
|
235
|
+
async function isDirectoryWriteable(directory, projectName) {
|
|
236
|
+
try {
|
|
237
|
+
console.log(folderExists(projectName));
|
|
238
|
+
await promises_namespaceObject.mkdir(directory, {
|
|
239
|
+
recursive: true
|
|
240
|
+
});
|
|
241
|
+
return true;
|
|
242
|
+
} catch (err) {
|
|
243
|
+
console.log(writingDirectoryError(err));
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function isExternalTemplate(_templateName) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
function isTypeScriptTemplate(templateName) {
|
|
251
|
+
return templateName.includes("typescript") || templateName.includes('react') || templateName.includes('preact') || templateName.includes('svelte') || templateName.includes('solid');
|
|
252
|
+
}
|
|
253
|
+
const allowlist = [
|
|
254
|
+
'LICENSE',
|
|
255
|
+
'node_modules'
|
|
256
|
+
];
|
|
257
|
+
async function createDirectory(projectPath, projectName) {
|
|
258
|
+
console.log(startingNewExtension(projectName));
|
|
259
|
+
try {
|
|
260
|
+
const isCurrentDirWriteable = await isDirectoryWriteable(projectPath, projectName);
|
|
261
|
+
console.log(checkingIfPathIsWriteable());
|
|
262
|
+
if (!isCurrentDirWriteable) {
|
|
263
|
+
console.error(destinationNotWriteable(projectPath));
|
|
264
|
+
throw new Error(destinationNotWriteable(projectPath));
|
|
265
|
+
}
|
|
266
|
+
const currentDir = await promises_namespaceObject.readdir(projectPath);
|
|
267
|
+
console.log(scanningPossiblyConflictingFiles());
|
|
268
|
+
const conflictingFiles = await Promise.all(currentDir.filter((file)=>!file.startsWith('.')).filter((file)=>!file.endsWith('.log')).filter((file)=>!allowlist.includes(file)).map(async (file)=>{
|
|
269
|
+
const stats = await promises_namespaceObject.lstat(external_path_namespaceObject.join(projectPath, file));
|
|
270
|
+
return stats.isDirectory() ? `${file}/` : `${file}`;
|
|
271
|
+
}));
|
|
272
|
+
if (conflictingFiles.length > 0) {
|
|
273
|
+
const conflictMessage = await directoryHasConflicts(projectPath, conflictingFiles);
|
|
274
|
+
throw new Error(conflictMessage);
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.error(createDirectoryError(projectName, error));
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const external_os_namespaceObject = require("os");
|
|
282
|
+
const external_axios_namespaceObject = require("axios");
|
|
283
|
+
var external_axios_default = /*#__PURE__*/ __webpack_require__.n(external_axios_namespaceObject);
|
|
284
|
+
const external_adm_zip_namespaceObject = require("adm-zip");
|
|
285
|
+
var external_adm_zip_default = /*#__PURE__*/ __webpack_require__.n(external_adm_zip_namespaceObject);
|
|
286
|
+
const external_go_git_it_namespaceObject = require("go-git-it");
|
|
287
|
+
var external_go_git_it_default = /*#__PURE__*/ __webpack_require__.n(external_go_git_it_namespaceObject);
|
|
288
|
+
const import_external_template_filename = (0, external_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__);
|
|
289
|
+
const import_external_template_dirname = external_path_namespaceObject.dirname(import_external_template_filename);
|
|
290
|
+
async function importExternalTemplate(projectPath, projectName, template) {
|
|
291
|
+
external_path_namespaceObject.dirname(projectPath);
|
|
292
|
+
const templateName = external_path_namespaceObject.basename(template);
|
|
293
|
+
const examplesUrl = 'https://github.com/extension-js/examples/tree/main/examples';
|
|
294
|
+
const templateUrl = `${examplesUrl}/${template}`;
|
|
295
|
+
try {
|
|
296
|
+
await promises_namespaceObject.mkdir(projectPath, {
|
|
297
|
+
recursive: true
|
|
298
|
+
});
|
|
299
|
+
if ('development' === process.env.EXTENSION_ENV) {
|
|
300
|
+
console.log(installingFromTemplate(projectName, template));
|
|
301
|
+
const localTemplatePath = external_path_namespaceObject.join(import_external_template_dirname, '..', '..', '..', 'examples', templateName);
|
|
302
|
+
await copyDirectoryWithSymlinks(localTemplatePath, projectPath);
|
|
303
|
+
} else {
|
|
304
|
+
const tempRoot = await promises_namespaceObject.mkdtemp(external_path_namespaceObject.join(external_os_namespaceObject.tmpdir(), 'extension-js-create-'));
|
|
305
|
+
const tempPath = external_path_namespaceObject.join(tempRoot, projectName + '-temp');
|
|
306
|
+
await promises_namespaceObject.mkdir(tempPath, {
|
|
307
|
+
recursive: true
|
|
308
|
+
});
|
|
309
|
+
const isHttp = /^https?:\/\//i.test(template);
|
|
310
|
+
const isGithub = /^https?:\/\/github.com\//i.test(template);
|
|
311
|
+
if (isGithub) {
|
|
312
|
+
await external_go_git_it_default()(template, tempPath, installingFromTemplate(projectName, templateName));
|
|
313
|
+
const candidates = await promises_namespaceObject.readdir(tempPath, {
|
|
314
|
+
withFileTypes: true
|
|
315
|
+
});
|
|
316
|
+
const preferred = candidates.find((d)=>d.isDirectory() && d.name === templateName);
|
|
317
|
+
const srcPath = preferred ? external_path_namespaceObject.join(tempPath, templateName) : tempPath;
|
|
318
|
+
await moveDirectoryContents(srcPath, projectPath);
|
|
319
|
+
} else if (isHttp) {
|
|
320
|
+
const { data, headers } = await external_axios_default().get(template, {
|
|
321
|
+
responseType: 'arraybuffer',
|
|
322
|
+
maxRedirects: 5
|
|
323
|
+
});
|
|
324
|
+
const contentType = String((null == headers ? void 0 : headers['content-type']) || '');
|
|
325
|
+
const looksZip = /zip|octet-stream/i.test(contentType) || template.toLowerCase().endsWith('.zip');
|
|
326
|
+
if (!looksZip) throw new Error(`Remote template does not appear to be a ZIP archive: ${template}`);
|
|
327
|
+
const zip = new (external_adm_zip_default())(Buffer.from(data));
|
|
328
|
+
zip.extractAllTo(tempPath, true);
|
|
329
|
+
await moveDirectoryContents(tempPath, projectPath);
|
|
330
|
+
} else {
|
|
331
|
+
await external_go_git_it_default()(templateUrl, tempPath, installingFromTemplate(projectName, templateName));
|
|
332
|
+
const srcPath = external_path_namespaceObject.join(tempPath, templateName);
|
|
333
|
+
await moveDirectoryContents(srcPath, projectPath);
|
|
334
|
+
}
|
|
335
|
+
await promises_namespaceObject.rm(tempRoot, {
|
|
336
|
+
recursive: true,
|
|
337
|
+
force: true
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
} catch (error) {
|
|
341
|
+
console.error(installingFromTemplateError(projectName, templateName, error));
|
|
342
|
+
throw error;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const extensionJsPackageJsonScripts = {
|
|
346
|
+
dev: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension dev' : 'extension dev',
|
|
347
|
+
start: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension start' : 'extension start',
|
|
348
|
+
build: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension build' : 'extension build'
|
|
349
|
+
};
|
|
350
|
+
async function overridePackageJson(projectPath, projectName, { template, cliVersion }) {
|
|
351
|
+
const templatePath = getTemplatePath(process.cwd());
|
|
352
|
+
const candidatePath = isExternalTemplate(template) ? external_path_namespaceObject.join(projectPath, 'package.json') : external_path_namespaceObject.join(templatePath, 'package.json');
|
|
353
|
+
let packageJson = {};
|
|
354
|
+
try {
|
|
355
|
+
const packageJsonContent = await promises_namespaceObject.readFile(candidatePath);
|
|
356
|
+
packageJson = JSON.parse(packageJsonContent.toString());
|
|
357
|
+
} catch {
|
|
358
|
+
packageJson = {
|
|
359
|
+
name: external_path_namespaceObject.basename(projectPath),
|
|
360
|
+
private: true,
|
|
361
|
+
scripts: {},
|
|
362
|
+
dependencies: {},
|
|
363
|
+
devDependencies: {}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
packageJson.scripts = packageJson.scripts || {};
|
|
367
|
+
packageJson.dependencies = packageJson.dependencies || {};
|
|
368
|
+
packageJson.devDependencies = {
|
|
369
|
+
...packageJson.devDependencies || {},
|
|
370
|
+
extension: 'development' === process.env.EXTENSION_ENV ? '*' : `^${cliVersion}`
|
|
371
|
+
};
|
|
372
|
+
const packageMetadata = {
|
|
373
|
+
...packageJson,
|
|
374
|
+
name: external_path_namespaceObject.basename(projectPath),
|
|
375
|
+
private: true,
|
|
376
|
+
scripts: {
|
|
377
|
+
...packageJson.scripts,
|
|
378
|
+
...extensionJsPackageJsonScripts
|
|
379
|
+
},
|
|
380
|
+
dependencies: packageJson.dependencies,
|
|
381
|
+
devDependencies: packageJson.devDependencies,
|
|
382
|
+
author: {
|
|
383
|
+
name: 'Your Name',
|
|
384
|
+
email: 'your@email.com',
|
|
385
|
+
url: 'https://yourwebsite.com'
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
try {
|
|
389
|
+
console.log(writingPackageJsonMetadata());
|
|
390
|
+
await promises_namespaceObject.writeFile(external_path_namespaceObject.join(projectPath, 'package.json'), JSON.stringify(packageMetadata, null, 2));
|
|
391
|
+
} catch (error) {
|
|
392
|
+
console.error(writingPackageJsonMetadataError(projectName, error));
|
|
393
|
+
throw error;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
const external_cross_spawn_namespaceObject = require("cross-spawn");
|
|
397
|
+
function getInstallArgs() {
|
|
398
|
+
return [
|
|
399
|
+
'install',
|
|
400
|
+
'--silent'
|
|
401
|
+
];
|
|
402
|
+
}
|
|
403
|
+
async function installDependencies(projectPath, projectName) {
|
|
404
|
+
const nodeModulesPath = external_path_namespaceObject.join(projectPath, 'node_modules');
|
|
405
|
+
const command = await getInstallCommand();
|
|
406
|
+
const dependenciesArgs = getInstallArgs();
|
|
407
|
+
console.log(installingDependencies());
|
|
408
|
+
try {
|
|
409
|
+
await external_fs_namespaceObject.promises.mkdir(nodeModulesPath, {
|
|
410
|
+
recursive: true
|
|
411
|
+
});
|
|
412
|
+
const stdio = 'development' === process.env.EXTENSION_ENV ? 'inherit' : 'ignore';
|
|
413
|
+
const child = (0, external_cross_spawn_namespaceObject.spawn)(command, dependenciesArgs, {
|
|
414
|
+
stdio,
|
|
415
|
+
cwd: projectPath
|
|
416
|
+
});
|
|
417
|
+
await new Promise((resolve, reject)=>{
|
|
418
|
+
child.on('close', (code)=>{
|
|
419
|
+
if (0 !== code) reject(new Error(installingDependenciesFailed(command, dependenciesArgs, code)));
|
|
420
|
+
else resolve();
|
|
421
|
+
});
|
|
422
|
+
child.on('error', (error)=>{
|
|
423
|
+
console.error(installingDependenciesProcessError(projectName, error));
|
|
424
|
+
reject(error);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
} catch (error) {
|
|
428
|
+
console.error(cantInstallDependencies(projectName, error));
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async function writeReadmeFile(projectPath, projectName) {
|
|
433
|
+
try {
|
|
434
|
+
await promises_namespaceObject.access(external_path_namespaceObject.join(projectPath, 'README.md'));
|
|
435
|
+
return;
|
|
436
|
+
} catch {}
|
|
437
|
+
const initTemplateReadme = `
|
|
438
|
+
<a href="https://extension.js.org" target="_blank"><img src="https://img.shields.io/badge/Powered%20by%20%7C%20Extension.js-0971fe" alt="Powered by Extension.js" align="right" /></a>
|
|
439
|
+
|
|
440
|
+
# [projectName]
|
|
441
|
+
|
|
442
|
+
> [templateDescription]
|
|
443
|
+
|
|
444
|
+
What this example does in the scope of a browser extension. The description should
|
|
445
|
+
describe for an audience of developers looking to use the example. Avoid jargon and
|
|
446
|
+
use simple language.
|
|
447
|
+
|
|
448
|
+
## Installation
|
|
449
|
+
|
|
450
|
+
\`\`\`bash
|
|
451
|
+
[runCommand] create <project-name> --template init
|
|
452
|
+
cd <project-name>
|
|
453
|
+
npm install
|
|
454
|
+
\`\`\`
|
|
455
|
+
|
|
456
|
+
## Commands
|
|
457
|
+
|
|
458
|
+
### dev
|
|
459
|
+
|
|
460
|
+
Run the extension in development mode.
|
|
461
|
+
|
|
462
|
+
\`\`\`bash
|
|
463
|
+
[runCommand] dev
|
|
464
|
+
\`\`\`
|
|
465
|
+
|
|
466
|
+
### build
|
|
467
|
+
|
|
468
|
+
Build the extension for production.
|
|
469
|
+
|
|
470
|
+
\`\`\`bash
|
|
471
|
+
[runCommand] build
|
|
472
|
+
\`\`\`
|
|
473
|
+
|
|
474
|
+
### Preview
|
|
475
|
+
|
|
476
|
+
Preview the extension in the browser.
|
|
477
|
+
|
|
478
|
+
\`\`\`bash
|
|
479
|
+
[runCommand] preview
|
|
480
|
+
\`\`\`
|
|
481
|
+
|
|
482
|
+
## Learn more
|
|
483
|
+
|
|
484
|
+
Learn more about this and other examples at @https://extension.js.org/
|
|
485
|
+
`;
|
|
486
|
+
const installCommand = await getInstallCommand();
|
|
487
|
+
const manifestJsonPath = external_path_namespaceObject.join(projectPath, 'manifest.json');
|
|
488
|
+
const manifestJson = JSON.parse(await promises_namespaceObject.readFile(manifestJsonPath, 'utf-8'));
|
|
489
|
+
const readmeFileEdited = initTemplateReadme.replaceAll('[projectName]', projectName).replaceAll("[templateDescription]", manifestJson.description).replaceAll('[runCommand]', installCommand);
|
|
490
|
+
try {
|
|
491
|
+
console.log(writingReadmeMetaData());
|
|
492
|
+
await promises_namespaceObject.mkdir(projectPath, {
|
|
493
|
+
recursive: true
|
|
494
|
+
});
|
|
495
|
+
await promises_namespaceObject.writeFile(external_path_namespaceObject.join(projectPath, 'README.md'), readmeFileEdited);
|
|
496
|
+
} catch (error) {
|
|
497
|
+
console.error(writingReadmeMetaDataEError(projectName, error));
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
async function writeManifestJson(projectPath, projectName) {
|
|
502
|
+
const manifestJsonPath = external_path_namespaceObject.join(projectPath, 'manifest.json');
|
|
503
|
+
const manifestJsonContent = await promises_namespaceObject.readFile(manifestJsonPath);
|
|
504
|
+
const manifestJson = JSON.parse(manifestJsonContent.toString());
|
|
505
|
+
const manifestMetadata = {
|
|
506
|
+
...manifestJson,
|
|
507
|
+
name: external_path_namespaceObject.basename(projectPath),
|
|
508
|
+
author: 'Your Name'
|
|
509
|
+
};
|
|
510
|
+
try {
|
|
511
|
+
console.log(writingManifestJsonMetadata());
|
|
512
|
+
await promises_namespaceObject.writeFile(external_path_namespaceObject.join(projectPath, 'manifest.json'), JSON.stringify(manifestMetadata, null, 2));
|
|
513
|
+
} catch (error) {
|
|
514
|
+
console.error(writingManifestJsonMetadataError(projectName, error));
|
|
515
|
+
throw error;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async function generateExtensionTypes(projectPath, projectName) {
|
|
519
|
+
const extensionEnvFile = external_path_namespaceObject.join(projectPath, 'extension-env.d.ts');
|
|
520
|
+
const typePath = 'extension';
|
|
521
|
+
const fileContent = `\
|
|
522
|
+
// Required Extension.js types for TypeScript projects.
|
|
30
523
|
// This file is auto-generated and should not be excluded.
|
|
31
524
|
// If you need additional types, consider creating a new *.d.ts file and
|
|
32
525
|
// referencing it in the "include" array of your tsconfig.json file.
|
|
33
526
|
// See https://www.typescriptlang.org/tsconfig#include for more information.
|
|
34
|
-
/// <reference types="${
|
|
527
|
+
/// <reference types="${typePath}/types" />
|
|
35
528
|
|
|
36
|
-
// Polyfill types for browser.* APIs
|
|
37
|
-
/// <reference types="${
|
|
38
|
-
`;
|
|
39
|
-
|
|
529
|
+
// Polyfill types for browser.* APIs
|
|
530
|
+
/// <reference types="${typePath}/types/polyfill" />
|
|
531
|
+
`;
|
|
532
|
+
try {
|
|
533
|
+
await promises_namespaceObject.mkdir(projectPath, {
|
|
534
|
+
recursive: true
|
|
535
|
+
});
|
|
536
|
+
console.log(writingTypeDefinitions(projectName));
|
|
537
|
+
await promises_namespaceObject.writeFile(extensionEnvFile, fileContent);
|
|
538
|
+
} catch (error) {
|
|
539
|
+
console.error(writingTypeDefinitionsError(error));
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const globalDependencies = [
|
|
544
|
+
'',
|
|
545
|
+
'# dependencies',
|
|
546
|
+
'node_modules'
|
|
547
|
+
];
|
|
548
|
+
const globalTesting = [
|
|
549
|
+
'',
|
|
550
|
+
'# testing',
|
|
551
|
+
'coverage'
|
|
552
|
+
];
|
|
553
|
+
const globalProduction = [
|
|
554
|
+
'',
|
|
555
|
+
'# production',
|
|
556
|
+
'dist'
|
|
557
|
+
];
|
|
558
|
+
const globalMisc = [
|
|
559
|
+
'',
|
|
560
|
+
'# misc',
|
|
561
|
+
'.DS_Store'
|
|
562
|
+
];
|
|
563
|
+
const envFiles = [
|
|
564
|
+
'',
|
|
565
|
+
'# local env files',
|
|
566
|
+
'.env.local',
|
|
567
|
+
'.env.development.local',
|
|
568
|
+
'.env.test.local',
|
|
569
|
+
'.env.production.local'
|
|
570
|
+
];
|
|
571
|
+
const debugFiles = [
|
|
572
|
+
'',
|
|
573
|
+
'# debug files',
|
|
574
|
+
'npm-debug.log*',
|
|
575
|
+
'yarn-debug.log*',
|
|
576
|
+
'yarn-error.log*'
|
|
577
|
+
];
|
|
578
|
+
const globalLines = [
|
|
579
|
+
'# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.',
|
|
580
|
+
...globalDependencies,
|
|
581
|
+
...globalTesting,
|
|
582
|
+
...globalProduction,
|
|
583
|
+
...globalMisc,
|
|
584
|
+
...envFiles,
|
|
585
|
+
...debugFiles
|
|
586
|
+
];
|
|
587
|
+
async function writeGitignore(projectPath) {
|
|
588
|
+
const gitIgnorePath = external_path_namespaceObject.join(projectPath, '.gitignore');
|
|
589
|
+
const fileHandle = await promises_namespaceObject.open(gitIgnorePath, 'a+').catch((err)=>{
|
|
590
|
+
console.error(err);
|
|
591
|
+
throw err;
|
|
592
|
+
});
|
|
593
|
+
const paths = new Set();
|
|
594
|
+
for await (let line of fileHandle.readLines({
|
|
595
|
+
autoClose: false
|
|
596
|
+
})){
|
|
597
|
+
line = line.trim();
|
|
598
|
+
if (0 !== line.length) paths.add(line);
|
|
599
|
+
}
|
|
600
|
+
const linesToAdd = globalLines.filter((line)=>!paths.has(line));
|
|
601
|
+
while('' === linesToAdd[linesToAdd.length - 1])linesToAdd.pop();
|
|
602
|
+
console.log(writingGitIgnore());
|
|
603
|
+
await fileHandle.appendFile(linesToAdd.join('\n')).catch((err)=>{
|
|
604
|
+
console.error(err);
|
|
605
|
+
throw err;
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
async function initializeGitRepository(projectPath, projectName) {
|
|
609
|
+
const gitCommand = 'git';
|
|
610
|
+
const gitArgs = [
|
|
611
|
+
'init',
|
|
612
|
+
'--quiet'
|
|
613
|
+
];
|
|
614
|
+
console.log(initializingGitForRepository(projectName));
|
|
615
|
+
try {
|
|
616
|
+
const stdio = 'development' === process.env.EXTENSION_ENV ? 'inherit' : 'ignore';
|
|
617
|
+
const child = (0, external_cross_spawn_namespaceObject.spawn)(gitCommand, gitArgs, {
|
|
618
|
+
stdio,
|
|
619
|
+
cwd: projectPath
|
|
620
|
+
});
|
|
621
|
+
await new Promise((resolve, reject)=>{
|
|
622
|
+
child.on('close', (code)=>{
|
|
623
|
+
if (0 !== code) reject(new Error(initializingGitForRepositoryFailed(gitCommand, gitArgs, code)));
|
|
624
|
+
else resolve();
|
|
625
|
+
});
|
|
626
|
+
child.on('error', (error)=>{
|
|
627
|
+
console.error(initializingGitForRepositoryProcessError(projectName, error));
|
|
628
|
+
reject(error);
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
} catch (error) {
|
|
632
|
+
console.error(initializingGitForRepositoryError(projectName, error));
|
|
633
|
+
throw error;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
async function setupBuiltInTests(projectPath, projectName) {
|
|
637
|
+
try {
|
|
638
|
+
const testSpecPath = external_path_namespaceObject.join(projectPath, 'tests', 'templates.spec.ts');
|
|
639
|
+
if (external_fs_namespaceObject.existsSync(testSpecPath)) external_fs_namespaceObject.unlinkSync(testSpecPath);
|
|
640
|
+
} catch (error) {
|
|
641
|
+
console.error(cantSetupBuiltInTests(projectName, error));
|
|
642
|
+
throw error;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
async function extensionCreate(projectNameInput, { cliVersion, template = 'init', install = false }) {
|
|
646
|
+
if (!projectNameInput) throw new Error(noProjectName());
|
|
647
|
+
if (projectNameInput.startsWith('http')) throw new Error(noUrlAllowed());
|
|
648
|
+
const projectPath = external_path_namespaceObject.isAbsolute(projectNameInput) ? projectNameInput : external_path_namespaceObject.join(process.cwd(), projectNameInput);
|
|
649
|
+
const projectName = external_path_namespaceObject.basename(projectPath);
|
|
650
|
+
try {
|
|
651
|
+
await createDirectory(projectPath, projectName);
|
|
652
|
+
await importExternalTemplate(projectPath, projectName, template);
|
|
653
|
+
await overridePackageJson(projectPath, projectName, {
|
|
654
|
+
template,
|
|
655
|
+
cliVersion
|
|
656
|
+
});
|
|
657
|
+
if (install) await installDependencies(projectPath, projectName);
|
|
658
|
+
await writeReadmeFile(projectPath, projectName);
|
|
659
|
+
await writeManifestJson(projectPath, projectName);
|
|
660
|
+
await initializeGitRepository(projectPath, projectName);
|
|
661
|
+
await writeGitignore(projectPath);
|
|
662
|
+
await setupBuiltInTests(projectPath, projectName);
|
|
663
|
+
if (isTypeScriptTemplate(template)) await generateExtensionTypes(projectPath, projectName);
|
|
664
|
+
const successfulInstall = await successfullInstall(projectPath, projectName);
|
|
665
|
+
console.log(successfulInstall);
|
|
666
|
+
} catch (error) {
|
|
667
|
+
console.error(error);
|
|
668
|
+
throw error;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
exports.extensionCreate = __webpack_exports__.extensionCreate;
|
|
672
|
+
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
673
|
+
"extensionCreate"
|
|
674
|
+
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
675
|
+
Object.defineProperty(exports, '__esModule', {
|
|
676
|
+
value: true
|
|
677
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createDirectory(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateExtensionTypes(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function importExternalTemplate(projectPath: string, projectName: string, template: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function importLocalTemplate(projectPath: string, projectName: string, template: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initializeGitRepository(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function installDependencies(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupBuiltInTests(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function writeGitignore(projectPath: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function writeManifestJson(projectPath: string, projectName: string): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function writeReadmeFile(projectPath: string, projectName: string): Promise<void>;
|
package/package.json
CHANGED
|
@@ -8,42 +8,78 @@
|
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=18"
|
|
10
10
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/module.d.ts",
|
|
14
|
+
"import": "./dist/module.js",
|
|
15
|
+
"require": "./dist/module.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
14
18
|
"main": "./dist/module.js",
|
|
15
19
|
"types": "./dist/module.d.ts",
|
|
16
20
|
"files": [
|
|
17
21
|
"dist"
|
|
18
22
|
],
|
|
23
|
+
"name": "extension-create",
|
|
24
|
+
"version": "2.1.2",
|
|
25
|
+
"description": "The create step of Extension.js",
|
|
19
26
|
"author": {
|
|
20
27
|
"name": "Cezar Augusto",
|
|
21
28
|
"email": "boss@cezaraugusto.net",
|
|
22
29
|
"url": "https://cezaraugusto.com"
|
|
23
30
|
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public",
|
|
33
|
+
"registry": "https://registry.npmjs.org",
|
|
34
|
+
"tag": "latest"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"webextension",
|
|
38
|
+
"browser-extension",
|
|
39
|
+
"manifest-v3",
|
|
40
|
+
"mv3",
|
|
41
|
+
"cross-browser",
|
|
42
|
+
"scaffold",
|
|
43
|
+
"generator",
|
|
44
|
+
"project-generator",
|
|
45
|
+
"create-extension",
|
|
46
|
+
"create-browser-extension",
|
|
47
|
+
"starter-template",
|
|
48
|
+
"template",
|
|
49
|
+
"templates",
|
|
50
|
+
"starter-kit",
|
|
51
|
+
"boilerplate",
|
|
52
|
+
"init",
|
|
53
|
+
"bootstrap",
|
|
54
|
+
"chrome-extension",
|
|
55
|
+
"firefox-extension",
|
|
56
|
+
"edge-extension"
|
|
57
|
+
],
|
|
24
58
|
"dependencies": {
|
|
25
|
-
"
|
|
26
|
-
"
|
|
59
|
+
"adm-zip": "^0.5.12",
|
|
60
|
+
"axios": "^1.7.2",
|
|
27
61
|
"cross-spawn": "^7.0.6",
|
|
28
|
-
"go-git-it": "
|
|
29
|
-
"package-manager-detector": "^0.2.7"
|
|
62
|
+
"go-git-it": "^5.0.0",
|
|
63
|
+
"package-manager-detector": "^0.2.7",
|
|
64
|
+
"pintor": "0.3.0",
|
|
65
|
+
"tiny-glob": "^0.2.9"
|
|
30
66
|
},
|
|
31
67
|
"devDependencies": {
|
|
68
|
+
"@rslib/core": "^0.6.9",
|
|
32
69
|
"@types/cross-spawn": "^6.0.6",
|
|
33
70
|
"@types/node": "^22.10.1",
|
|
34
|
-
"@
|
|
71
|
+
"@vitest/coverage-v8": "3.2.2",
|
|
35
72
|
"globals": "^15.13.0",
|
|
36
|
-
"jest": "^29.7.0",
|
|
37
|
-
"ts-jest": "^29.2.5",
|
|
38
73
|
"tsconfig": "*",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
74
|
+
"typescript": "5.7.2",
|
|
75
|
+
"vitest": "3.2.2"
|
|
41
76
|
},
|
|
42
77
|
"scripts": {
|
|
43
78
|
"clean": "rm -rf dist",
|
|
44
|
-
"watch": "
|
|
45
|
-
"compile": "
|
|
46
|
-
"
|
|
47
|
-
"test:create": "
|
|
79
|
+
"watch": "rslib build --watch",
|
|
80
|
+
"compile": "rslib build",
|
|
81
|
+
"pretest:create": "pnpm compile",
|
|
82
|
+
"test:create": "vitest run",
|
|
83
|
+
"test:coverage": "vitest run --coverage"
|
|
48
84
|
}
|
|
49
85
|
}
|
package/dist/template/README.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# [projectName]
|
|
2
|
-
|
|
3
|
-
> [templateDescription]
|
|
4
|
-
|
|
5
|
-
## Available Scripts
|
|
6
|
-
|
|
7
|
-
In the project directory, you can run the following scripts:
|
|
8
|
-
|
|
9
|
-
### [runCommand] dev
|
|
10
|
-
|
|
11
|
-
**Development Mode**: This command runs your extension in development mode. It will launch a new browser instance with your extension loaded. The page will automatically reload whenever you make changes to your code, allowing for a smooth development experience.
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
[runCommand] dev
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### [runCommand] start
|
|
18
|
-
|
|
19
|
-
**Production Preview**: This command runs your extension in production mode. It will launch a new browser instance with your extension loaded, simulating the environment and behavior of your extension as it will appear once published.
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
[runCommand] start
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### [runCommand] build
|
|
26
|
-
|
|
27
|
-
**Build for Production**: This command builds your extension for production. It optimizes and bundles your extension, preparing it for deployment to the target browser's store.
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
[runCommand] build
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Learn More
|
|
34
|
-
|
|
35
|
-
To learn more about creating cross-browser extensions with Extension.js, visit the [official documentation](https://extension.js.org).
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"license": "MIT",
|
|
3
|
-
"repository": {
|
|
4
|
-
"type": "git",
|
|
5
|
-
"url": "https://github.com/extension-js/extension.git",
|
|
6
|
-
"directory": "examples/init"
|
|
7
|
-
},
|
|
8
|
-
"name": "init",
|
|
9
|
-
"description": "An Extension.js example.",
|
|
10
|
-
"version": "0.0.1",
|
|
11
|
-
"keywords": [
|
|
12
|
-
"extension",
|
|
13
|
-
"browser-extension",
|
|
14
|
-
"web-extension",
|
|
15
|
-
"template"
|
|
16
|
-
]
|
|
17
|
-
}
|