extension-create 2.2.1 → 3.1.0-next.10
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 +11 -16
- package/dist/lib/find-manifest-json.d.ts +1 -0
- package/dist/lib/messages.d.ts +1 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/module.js +127 -59
- package/package.json +32 -30
- package/dist/test-template-init/README.md +0 -47
- package/dist/test-template-init/images/extension_48.png +0 -0
- package/dist/test-template-init/index.js +0 -1
- package/dist/test-template-init/manifest.json +0 -11
- package/dist/test-template-init/package.json +0 -22
- package/dist/test-template-init/public/logo.png +0 -0
- package/dist/test-template-init/screenshot.png +0 -0
package/README.md
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
[npm-version-image]: https://img.shields.io/npm/v/extension-create.svg?color=0971fe
|
|
2
2
|
[npm-version-url]: https://www.npmjs.com/package/extension-create
|
|
3
|
-
[downloads-image]: https://img.shields.io/npm/dm/extension-create.svg?color=
|
|
4
|
-
[downloads-url]: https://npmjs.
|
|
5
|
-
[
|
|
6
|
-
[
|
|
3
|
+
[npm-downloads-image]: https://img.shields.io/npm/dm/extension-create.svg?color=0971fe
|
|
4
|
+
[npm-downloads-url]: https://www.npmjs.com/package/extension-create
|
|
5
|
+
[action-image]: https://github.com/extension-js/create/actions/workflows/ci.yml/badge.svg?branch=main
|
|
6
|
+
[action-url]: https://github.com/extension-js/create/actions/workflows/ci.yml
|
|
7
7
|
|
|
8
|
-
[![
|
|
8
|
+
[![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![CI][action-image]][action-url]
|
|
9
9
|
|
|
10
10
|
# extension-create
|
|
11
11
|
|
|
12
|
-
The standalone extension creation engine
|
|
12
|
+
The standalone extension creation engine for Extension.js.
|
|
13
|
+
Use it to scaffold a new extension project from a template.
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
Install the package using your preferred package manager:
|
|
15
|
+
## Install
|
|
17
16
|
|
|
18
17
|
```bash
|
|
19
18
|
npm install extension-create
|
|
20
|
-
# or
|
|
21
|
-
pnpm add extension-create
|
|
22
|
-
# or
|
|
23
|
-
yarn add extension-create
|
|
24
19
|
```
|
|
25
20
|
|
|
26
|
-
##
|
|
21
|
+
## Usage
|
|
27
22
|
|
|
28
23
|
Create a new extension with a single function call:
|
|
29
24
|
|
|
@@ -42,7 +37,7 @@ await extensionCreate('my-react-extension', {
|
|
|
42
37
|
})
|
|
43
38
|
```
|
|
44
39
|
|
|
45
|
-
## API
|
|
40
|
+
## API reference
|
|
46
41
|
|
|
47
42
|
### `extensionCreate(projectName, options)`
|
|
48
43
|
|
|
@@ -58,7 +53,7 @@ Creates a new extension project with the specified configuration.
|
|
|
58
53
|
|
|
59
54
|
## Templates
|
|
60
55
|
|
|
61
|
-
Templates are sourced from the public
|
|
56
|
+
Templates are sourced from the public examples repository. Browse the catalog in the [Extension.js examples](https://github.com/extension-js/examples) and reference templates by name (for example, `content`, `content-react`, `content-vue`).
|
|
62
57
|
|
|
63
58
|
## License
|
|
64
59
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findManifestJsonPath(projectPath: string): Promise<string>;
|
package/dist/lib/messages.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare function destinationNotWriteable(workingDir: string): string;
|
|
|
2
2
|
export declare function directoryHasConflicts(projectPath: string, conflictingFiles: string[]): Promise<string>;
|
|
3
3
|
export declare function noProjectName(): string;
|
|
4
4
|
export declare function noUrlAllowed(): string;
|
|
5
|
-
export declare function successfullInstall(projectPath: string, projectName: string): Promise<string>;
|
|
5
|
+
export declare function successfullInstall(projectPath: string, projectName: string, depsInstalled: boolean): Promise<string>;
|
|
6
6
|
export declare function startingNewExtension(projectName: string): string;
|
|
7
7
|
export declare function checkingIfPathIsWriteable(): string;
|
|
8
8
|
export declare function scanningPossiblyConflictingFiles(): string;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare namespace NodeJS {
|
|
|
5
5
|
EXTENSION_PUBLIC_BROWSER: 'chrome' | 'edge' | 'firefox' | 'chromium-based' | 'gecko-based';
|
|
6
6
|
EXTENSION_PUBLIC_MODE: 'development' | 'production';
|
|
7
7
|
EXTENSION_PUBLIC_DESCRIPTION_TEXT: string;
|
|
8
|
-
|
|
8
|
+
EXTENSION_PUBLIC_LLM_API_KEY: string;
|
|
9
9
|
EXTENSION_ENV: 'development' | 'production';
|
|
10
10
|
}
|
|
11
11
|
}
|
package/dist/module.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const __rslib_import_meta_url__ = /*#__PURE__*/ function() {
|
|
3
|
-
return
|
|
3
|
+
return "u" < typeof document ? new (require('url'.replace('', ''))).URL('file:' + __filename).href : document.currentScript && document.currentScript.src || new URL('main.js', document.baseURI).href;
|
|
4
4
|
}();
|
|
5
5
|
var __webpack_require__ = {};
|
|
6
6
|
(()=>{
|
|
@@ -25,7 +25,7 @@ var __webpack_require__ = {};
|
|
|
25
25
|
})();
|
|
26
26
|
(()=>{
|
|
27
27
|
__webpack_require__.r = (exports1)=>{
|
|
28
|
-
if (
|
|
28
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
29
29
|
value: 'Module'
|
|
30
30
|
});
|
|
31
31
|
Object.defineProperty(exports1, '__esModule', {
|
|
@@ -45,30 +45,30 @@ var external_pintor_default = /*#__PURE__*/ __webpack_require__.n(external_pinto
|
|
|
45
45
|
const external_package_manager_detector_namespaceObject = require("package-manager-detector");
|
|
46
46
|
function destinationNotWriteable(workingDir) {
|
|
47
47
|
const workingDirFolder = external_path_namespaceObject.basename(workingDir);
|
|
48
|
-
return `${external_pintor_default().red('
|
|
48
|
+
return `${external_pintor_default().red('Error')} Couldn't write to the destination directory.\n${external_pintor_default().red('Next step: choose a writable path or update folder permissions.')}\n${external_pintor_default().red('Path')} ${external_pintor_default().underline(workingDirFolder)}`;
|
|
49
49
|
}
|
|
50
50
|
async function directoryHasConflicts(projectPath, conflictingFiles) {
|
|
51
51
|
const projectName = external_path_namespaceObject.basename(projectPath);
|
|
52
|
-
let message = `
|
|
52
|
+
let message = `Conflicting files found in ${external_pintor_default().blue(projectName)}.\n\n`;
|
|
53
53
|
for (const file of conflictingFiles){
|
|
54
54
|
const stats = await external_fs_namespaceObject.promises.lstat(external_path_namespaceObject.join(projectPath, file));
|
|
55
55
|
message += stats.isDirectory() ? ` ${external_pintor_default().yellow('-')} ${external_pintor_default().yellow(file)}\n` : ` ${external_pintor_default().yellow('-')} ${external_pintor_default().yellow(file)}\n`;
|
|
56
56
|
}
|
|
57
|
-
message += `\n${external_pintor_default().red('
|
|
57
|
+
message += `\n${external_pintor_default().red('Next step: remove or rename the files above, or choose a different directory name.')}\n\nPath: ${external_pintor_default().underline(projectPath)}`;
|
|
58
58
|
return message;
|
|
59
59
|
}
|
|
60
60
|
function noProjectName() {
|
|
61
|
-
return `${external_pintor_default().red('
|
|
61
|
+
return `${external_pintor_default().red('Error')} Project name is required.\nNext step: provide a project name (for example, ${external_pintor_default().blue('my-extension')}) or run ${external_pintor_default().blue('--help')} for usage.`;
|
|
62
62
|
}
|
|
63
63
|
function noUrlAllowed() {
|
|
64
|
-
return `${external_pintor_default().red('
|
|
64
|
+
return `${external_pintor_default().red('Error')} URLs are not allowed as a project path.\nNext step: provide a project name or a local directory path.`;
|
|
65
65
|
}
|
|
66
|
-
async function successfullInstall(projectPath, projectName) {
|
|
66
|
+
async function successfullInstall(projectPath, projectName, depsInstalled) {
|
|
67
67
|
const relativePath = external_path_namespaceObject.relative(process.cwd(), projectPath);
|
|
68
68
|
const pm = await (0, external_package_manager_detector_namespaceObject.detect)();
|
|
69
69
|
let command = 'npm run';
|
|
70
70
|
let installCmd = 'npm install';
|
|
71
|
-
switch(
|
|
71
|
+
switch(pm?.name){
|
|
72
72
|
case 'yarn':
|
|
73
73
|
command = 'yarn dev';
|
|
74
74
|
installCmd = 'yarn';
|
|
@@ -87,86 +87,88 @@ async function successfullInstall(projectPath, projectName) {
|
|
|
87
87
|
installCmd = 'pnpm install';
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
const steps = depsInstalled ? ` 1. ${external_pintor_default().blue('cd')} ${external_pintor_default().underline(relativePath)}\n 2. ${external_pintor_default().blue(command)} (runs a fresh browser profile with your extension loaded)\n` : ` 1. ${external_pintor_default().blue('cd')} ${external_pintor_default().underline(relativePath)}\n 2. ${external_pintor_default().blue(installCmd)}\n 3. ${external_pintor_default().blue(command)} (runs a fresh browser profile with your extension loaded)\n`;
|
|
91
|
+
const depsNote = depsInstalled ? `\n${external_pintor_default().gray('Dependencies installed. You can start developing now.')}\n` : '\n';
|
|
92
|
+
return `${external_pintor_default().green('Created')} ${external_pintor_default().blue(projectName)}\n\nNext steps:\n\n` + steps + depsNote;
|
|
91
93
|
}
|
|
92
94
|
function startingNewExtension(projectName) {
|
|
93
|
-
return
|
|
95
|
+
return `Creating ${external_pintor_default().blue(projectName)}...`;
|
|
94
96
|
}
|
|
95
97
|
function checkingIfPathIsWriteable() {
|
|
96
|
-
return
|
|
98
|
+
return 'Checking if the destination path is writable...';
|
|
97
99
|
}
|
|
98
100
|
function scanningPossiblyConflictingFiles() {
|
|
99
|
-
return
|
|
101
|
+
return 'Scanning for conflicting files...';
|
|
100
102
|
}
|
|
101
103
|
function createDirectoryError(projectName, error) {
|
|
102
|
-
return `${external_pintor_default().red('
|
|
104
|
+
return `${external_pintor_default().red('Error')} Couldn't create directory ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check the path and permissions, then try again.')}`;
|
|
103
105
|
}
|
|
104
106
|
function writingTypeDefinitions(projectName) {
|
|
105
|
-
return
|
|
107
|
+
return `Writing type definitions for ${external_pintor_default().blue(projectName)}...`;
|
|
106
108
|
}
|
|
107
109
|
function writingTypeDefinitionsError(error) {
|
|
108
|
-
return `${external_pintor_default().red('
|
|
110
|
+
return `${external_pintor_default().red('Error')} Couldn't write the extension type definitions.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check file permissions, then try again.')}`;
|
|
109
111
|
}
|
|
110
112
|
function installingFromTemplate(projectName, templateName) {
|
|
111
|
-
if ('init' === templateName) return
|
|
112
|
-
return
|
|
113
|
+
if ('init' === templateName) return `Installing ${external_pintor_default().blue(projectName)}...`;
|
|
114
|
+
return `Installing ${external_pintor_default().blue(projectName)} from template ${external_pintor_default().yellow(templateName)}...`;
|
|
113
115
|
}
|
|
114
116
|
function installingFromTemplateError(projectName, template, error) {
|
|
115
|
-
return `${external_pintor_default().red('
|
|
117
|
+
return `${external_pintor_default().red('Error')} Couldn't find template ${external_pintor_default().yellow(template)} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: choose a valid template name or URL.')}`;
|
|
116
118
|
}
|
|
117
119
|
function initializingGitForRepository(projectName) {
|
|
118
|
-
return
|
|
120
|
+
return `Initializing git repository for ${external_pintor_default().blue(projectName)}...`;
|
|
119
121
|
}
|
|
120
122
|
function initializingGitForRepositoryFailed(gitCommand, gitArgs, code) {
|
|
121
|
-
return `${external_pintor_default().red('
|
|
123
|
+
return `${external_pintor_default().red('Error')} Command ${external_pintor_default().yellow(gitCommand)} ${external_pintor_default().yellow(gitArgs.join(' '))} failed.\n${external_pintor_default().red(`Exit code: ${external_pintor_default().yellow(String(code))}`)}\n${external_pintor_default().red('Next step: run the command manually to inspect the error.')}`;
|
|
122
124
|
}
|
|
123
125
|
function initializingGitForRepositoryProcessError(projectName, error) {
|
|
124
|
-
return `${external_pintor_default().red('
|
|
126
|
+
return `${external_pintor_default().red('Error')} Child process failed while initializing ${external_pintor_default().yellow('git')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error?.message || error))}\n${external_pintor_default().red('Next step: retry initialization or create the repository manually.')}`;
|
|
125
127
|
}
|
|
126
128
|
function initializingGitForRepositoryError(projectName, error) {
|
|
127
|
-
return `${external_pintor_default().red('
|
|
129
|
+
return `${external_pintor_default().red('Error')} Couldn't initialize ${external_pintor_default().yellow('git')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error?.message || error))}\n${external_pintor_default().red('Next step: retry initialization or create the repository manually.')}`;
|
|
128
130
|
}
|
|
129
131
|
function installingDependencies() {
|
|
130
|
-
return
|
|
132
|
+
return 'Installing dependencies (this may take a moment)...';
|
|
131
133
|
}
|
|
132
134
|
function installingDependenciesFailed(gitCommand, gitArgs, code) {
|
|
133
|
-
return `${external_pintor_default().red('
|
|
135
|
+
return `${external_pintor_default().red('Error')} Command ${external_pintor_default().yellow(gitCommand)} ${external_pintor_default().yellow(gitArgs.join(' '))} failed.\n${external_pintor_default().red(`Exit code: ${external_pintor_default().yellow(String(code))}`)}\n${external_pintor_default().red('Next step: run the command manually to inspect the error.')}`;
|
|
134
136
|
}
|
|
135
137
|
function installingDependenciesProcessError(projectName, error) {
|
|
136
|
-
return `${external_pintor_default().red('
|
|
138
|
+
return `${external_pintor_default().red('Error')} Child process failed while installing dependencies for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: run the install command manually to inspect the error.')}`;
|
|
137
139
|
}
|
|
138
140
|
function cantInstallDependencies(projectName, error) {
|
|
139
|
-
return `${external_pintor_default().red('
|
|
141
|
+
return `${external_pintor_default().red('Error')} Couldn't install dependencies for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error?.message || error))}\n${external_pintor_default().red('Next step: check your package manager settings, then try again.')}`;
|
|
140
142
|
}
|
|
141
143
|
function writingPackageJsonMetadata() {
|
|
142
|
-
return
|
|
144
|
+
return `Writing ${external_pintor_default().yellow('package.json')}...`;
|
|
143
145
|
}
|
|
144
146
|
function writingPackageJsonMetadataError(projectName, error) {
|
|
145
|
-
return `${external_pintor_default().red('
|
|
147
|
+
return `${external_pintor_default().red('Error')} Couldn't write ${external_pintor_default().yellow('package.json')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check file permissions, then try again.')}`;
|
|
146
148
|
}
|
|
147
149
|
function writingManifestJsonMetadata() {
|
|
148
|
-
return
|
|
150
|
+
return `Writing ${external_pintor_default().yellow('manifest.json')}...`;
|
|
149
151
|
}
|
|
150
152
|
function writingManifestJsonMetadataError(projectName, error) {
|
|
151
|
-
return `${external_pintor_default().red('
|
|
153
|
+
return `${external_pintor_default().red('Error')} Couldn't write ${external_pintor_default().yellow('manifest.json')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check file permissions, then try again.')}`;
|
|
152
154
|
}
|
|
153
155
|
function writingReadmeMetaData() {
|
|
154
|
-
return
|
|
156
|
+
return `Writing ${external_pintor_default().yellow('README.md')}...`;
|
|
155
157
|
}
|
|
156
158
|
function writingGitIgnore() {
|
|
157
|
-
return
|
|
159
|
+
return `Writing ${external_pintor_default().yellow('.gitignore')}...`;
|
|
158
160
|
}
|
|
159
161
|
function writingReadmeMetaDataEError(projectName, error) {
|
|
160
|
-
return `${external_pintor_default().red('
|
|
162
|
+
return `${external_pintor_default().red('Error')} Couldn't write ${external_pintor_default().yellow('README.md')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check file permissions, then try again.')}`;
|
|
161
163
|
}
|
|
162
164
|
function folderExists(projectName) {
|
|
163
|
-
return
|
|
165
|
+
return `Ensuring ${external_pintor_default().blue(projectName)} exists...`;
|
|
164
166
|
}
|
|
165
167
|
function writingDirectoryError(error) {
|
|
166
|
-
return `${external_pintor_default().red('
|
|
168
|
+
return `${external_pintor_default().red('Error')} Couldn't check directory writability.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check the path and permissions, then try again.')}`;
|
|
167
169
|
}
|
|
168
170
|
function cantSetupBuiltInTests(projectName, error) {
|
|
169
|
-
return `${external_pintor_default().red('
|
|
171
|
+
return `${external_pintor_default().red('Error')} Couldn't set up built-in tests for ${external_pintor_default().yellow(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: run the setup step again or skip tests.')}`;
|
|
170
172
|
}
|
|
171
173
|
const promises_namespaceObject = require("fs/promises");
|
|
172
174
|
const external_url_namespaceObject = require("url");
|
|
@@ -225,7 +227,7 @@ async function getInstallCommand() {
|
|
|
225
227
|
if (process.env.npm_config_user_agent) {
|
|
226
228
|
if (process.env.npm_config_user_agent.includes('pnpm')) return 'pnpm';
|
|
227
229
|
}
|
|
228
|
-
switch(
|
|
230
|
+
switch(pm?.name){
|
|
229
231
|
case 'yarn':
|
|
230
232
|
command = 'yarn';
|
|
231
233
|
break;
|
|
@@ -296,7 +298,6 @@ var external_go_git_it_default = /*#__PURE__*/ __webpack_require__.n(external_go
|
|
|
296
298
|
const import_external_template_filename = (0, external_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__);
|
|
297
299
|
const import_external_template_dirname = external_path_namespaceObject.dirname(import_external_template_filename);
|
|
298
300
|
async function importExternalTemplate(projectPath, projectName, template) {
|
|
299
|
-
external_path_namespaceObject.dirname(projectPath);
|
|
300
301
|
const templateName = external_path_namespaceObject.basename(template);
|
|
301
302
|
const examplesUrl = 'https://github.com/extension-js/examples/tree/main/examples';
|
|
302
303
|
const templateUrl = `${examplesUrl}/${template}`;
|
|
@@ -306,7 +307,24 @@ async function importExternalTemplate(projectPath, projectName, template) {
|
|
|
306
307
|
});
|
|
307
308
|
if ('development' === process.env.EXTENSION_ENV) {
|
|
308
309
|
console.log(installingFromTemplate(projectName, template));
|
|
309
|
-
|
|
310
|
+
async function findTemplatesRoot(startDir) {
|
|
311
|
+
let current = startDir;
|
|
312
|
+
const maxDepth = 6;
|
|
313
|
+
for(let i = 0; i < maxDepth; i++){
|
|
314
|
+
const candidate = external_path_namespaceObject.join(current, 'templates');
|
|
315
|
+
try {
|
|
316
|
+
const stats = await promises_namespaceObject.stat(candidate);
|
|
317
|
+
if (stats.isDirectory()) return candidate;
|
|
318
|
+
} catch {}
|
|
319
|
+
const parent = external_path_namespaceObject.dirname(current);
|
|
320
|
+
if (parent === current) break;
|
|
321
|
+
current = parent;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const localTemplatesRoot = await findTemplatesRoot(import_external_template_dirname);
|
|
325
|
+
if (!localTemplatesRoot) throw new Error('Local templates directory not found');
|
|
326
|
+
const localTemplateName = 'init' === templateName ? "javascript" : templateName;
|
|
327
|
+
const localTemplatePath = external_path_namespaceObject.join(localTemplatesRoot, localTemplateName);
|
|
310
328
|
await copyDirectoryWithSymlinks(localTemplatePath, projectPath);
|
|
311
329
|
} else {
|
|
312
330
|
const tempRoot = await promises_namespaceObject.mkdtemp(external_path_namespaceObject.join(external_os_namespaceObject.tmpdir(), 'extension-js-create-'));
|
|
@@ -320,8 +338,7 @@ async function importExternalTemplate(projectPath, projectName, template) {
|
|
|
320
338
|
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
321
339
|
const originalStderrWrite = process.stderr.write.bind(process.stderr);
|
|
322
340
|
const shouldFilter = (chunk)=>{
|
|
323
|
-
|
|
324
|
-
const s = 'string' == typeof chunk ? chunk : (null == chunk ? void 0 : null == (_chunk_toString = chunk.toString) ? void 0 : _chunk_toString.call(chunk)) ?? '';
|
|
341
|
+
const s = 'string' == typeof chunk ? chunk : chunk?.toString?.() ?? '';
|
|
325
342
|
if (!s) return false;
|
|
326
343
|
return /Using git version/i.test(s) || /GitHub API rate limit reached, continuing without connectivity check/i.test(s);
|
|
327
344
|
};
|
|
@@ -353,7 +370,7 @@ async function importExternalTemplate(projectPath, projectName, template) {
|
|
|
353
370
|
responseType: 'arraybuffer',
|
|
354
371
|
maxRedirects: 5
|
|
355
372
|
});
|
|
356
|
-
const contentType = String(
|
|
373
|
+
const contentType = String(headers?.['content-type'] || '');
|
|
357
374
|
const looksZip = /zip|octet-stream/i.test(contentType) || template.toLowerCase().endsWith('.zip');
|
|
358
375
|
if (!looksZip) throw new Error(`Remote template does not appear to be a ZIP archive: ${template}`);
|
|
359
376
|
const zip = new (external_adm_zip_default())(Buffer.from(data));
|
|
@@ -377,7 +394,9 @@ async function importExternalTemplate(projectPath, projectName, template) {
|
|
|
377
394
|
const extensionJsPackageJsonScripts = {
|
|
378
395
|
dev: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension dev' : 'extension dev',
|
|
379
396
|
start: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension start' : 'extension start',
|
|
380
|
-
build: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension build' : 'extension build'
|
|
397
|
+
build: 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension build' : 'extension build',
|
|
398
|
+
'build:firefox': 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension build --browser firefox' : 'extension build --browser firefox',
|
|
399
|
+
'build:edge': 'development' === process.env.EXTENSION_ENV ? 'node node_modules/extension build --browser edge' : 'extension build --browser edge'
|
|
381
400
|
};
|
|
382
401
|
async function overridePackageJson(projectPath, projectName, { template, cliVersion }) {
|
|
383
402
|
const templatePath = getTemplatePath(process.cwd());
|
|
@@ -461,21 +480,62 @@ async function installDependencies(projectPath, projectName) {
|
|
|
461
480
|
throw error;
|
|
462
481
|
}
|
|
463
482
|
}
|
|
483
|
+
const manifestSearchMaxDepth = 3;
|
|
484
|
+
const ignoredManifestDirs = new Set([
|
|
485
|
+
'node_modules',
|
|
486
|
+
'.git'
|
|
487
|
+
]);
|
|
488
|
+
async function findManifestJsonPath(projectPath) {
|
|
489
|
+
const candidates = [
|
|
490
|
+
external_path_namespaceObject.join(projectPath, 'manifest.json'),
|
|
491
|
+
external_path_namespaceObject.join(projectPath, 'src', 'manifest.json'),
|
|
492
|
+
external_path_namespaceObject.join(projectPath, 'extension', 'manifest.json'),
|
|
493
|
+
external_path_namespaceObject.join(projectPath, 'extension', 'src', 'manifest.json')
|
|
494
|
+
];
|
|
495
|
+
for (const candidate of candidates)try {
|
|
496
|
+
await external_fs_namespaceObject.promises.access(candidate);
|
|
497
|
+
return candidate;
|
|
498
|
+
} catch {}
|
|
499
|
+
const queue = [
|
|
500
|
+
{
|
|
501
|
+
dir: projectPath,
|
|
502
|
+
depth: 0
|
|
503
|
+
}
|
|
504
|
+
];
|
|
505
|
+
while(queue.length > 0){
|
|
506
|
+
const current = queue.shift();
|
|
507
|
+
if (!current) continue;
|
|
508
|
+
let entries;
|
|
509
|
+
try {
|
|
510
|
+
entries = await external_fs_namespaceObject.promises.readdir(current.dir, {
|
|
511
|
+
withFileTypes: true
|
|
512
|
+
});
|
|
513
|
+
} catch {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
for (const entry of entries){
|
|
517
|
+
if (entry.isFile() && 'manifest.json' === entry.name) return external_path_namespaceObject.join(current.dir, entry.name);
|
|
518
|
+
if (entry.isDirectory() && current.depth < manifestSearchMaxDepth && !ignoredManifestDirs.has(entry.name)) queue.push({
|
|
519
|
+
dir: external_path_namespaceObject.join(current.dir, entry.name),
|
|
520
|
+
depth: current.depth + 1
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
throw new Error(`Could not locate manifest.json under ${projectPath}. Checked common paths and searched up to depth ${manifestSearchMaxDepth}.`);
|
|
525
|
+
}
|
|
464
526
|
async function writeReadmeFile(projectPath, projectName) {
|
|
465
527
|
try {
|
|
466
528
|
await promises_namespaceObject.access(external_path_namespaceObject.join(projectPath, 'README.md'));
|
|
467
529
|
return;
|
|
468
530
|
} catch {}
|
|
469
531
|
const initTemplateReadme = `
|
|
470
|
-
<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>
|
|
532
|
+
<a href="https://extension.js.org" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/Powered%20by%20%7C%20Extension.js-0971fe" alt="Powered by Extension.js" align="right" /></a>
|
|
471
533
|
|
|
472
534
|
# [projectName]
|
|
473
535
|
|
|
474
536
|
> [templateDescription]
|
|
475
537
|
|
|
476
|
-
|
|
477
|
-
describe for an audience of developers looking to use the example. Avoid jargon and
|
|
478
|
-
use simple language.
|
|
538
|
+
This project was created with Extension.js. Use the commands below to run and build it.
|
|
479
539
|
|
|
480
540
|
## Installation
|
|
481
541
|
|
|
@@ -489,18 +549,26 @@ npm install
|
|
|
489
549
|
|
|
490
550
|
### dev
|
|
491
551
|
|
|
492
|
-
Run the extension in development mode.
|
|
552
|
+
Run the extension in development mode. You can target a specific browser using the
|
|
553
|
+
\`--browser <browser>\` flag. Supported values: \`chrome\`, \`firefox\`, \`edge\`.
|
|
493
554
|
|
|
494
555
|
\`\`\`bash
|
|
495
|
-
[runCommand] dev
|
|
556
|
+
[runCommand] dev --browser chrome
|
|
557
|
+
# or
|
|
558
|
+
[runCommand] dev --browser firefox
|
|
559
|
+
# or
|
|
560
|
+
[runCommand] dev --browser edge
|
|
496
561
|
\`\`\`
|
|
497
562
|
|
|
498
563
|
### build
|
|
499
564
|
|
|
500
|
-
Build the extension for production.
|
|
565
|
+
Build the extension for production. Use \`--browser <browser>\` to select a target.
|
|
501
566
|
|
|
502
567
|
\`\`\`bash
|
|
503
|
-
[runCommand] build
|
|
568
|
+
[runCommand] build (defaults to Chrome)
|
|
569
|
+
# or use convenience scripts
|
|
570
|
+
[runCommand] build:firefox (Firefox)
|
|
571
|
+
[runCommand] build:edge (Edge)
|
|
504
572
|
\`\`\`
|
|
505
573
|
|
|
506
574
|
### Preview
|
|
@@ -513,10 +581,10 @@ Preview the extension in the browser.
|
|
|
513
581
|
|
|
514
582
|
## Learn more
|
|
515
583
|
|
|
516
|
-
Learn more
|
|
584
|
+
Learn more in the [Extension.js docs](https://extension.js.org).
|
|
517
585
|
`;
|
|
518
586
|
const installCommand = await getInstallCommand();
|
|
519
|
-
const manifestJsonPath =
|
|
587
|
+
const manifestJsonPath = await findManifestJsonPath(projectPath);
|
|
520
588
|
const manifestJson = JSON.parse(await promises_namespaceObject.readFile(manifestJsonPath, 'utf-8'));
|
|
521
589
|
const readmeFileEdited = initTemplateReadme.replaceAll('[projectName]', projectName).replaceAll("[templateDescription]", manifestJson.description).replaceAll('[runCommand]', installCommand);
|
|
522
590
|
try {
|
|
@@ -531,7 +599,7 @@ Learn more about this and other examples at @https://extension.js.org/
|
|
|
531
599
|
}
|
|
532
600
|
}
|
|
533
601
|
async function writeManifestJson(projectPath, projectName) {
|
|
534
|
-
const manifestJsonPath =
|
|
602
|
+
const manifestJsonPath = await findManifestJsonPath(projectPath);
|
|
535
603
|
const manifestJsonContent = await promises_namespaceObject.readFile(manifestJsonPath);
|
|
536
604
|
const manifestJson = JSON.parse(manifestJsonContent.toString());
|
|
537
605
|
const manifestMetadata = {
|
|
@@ -541,7 +609,7 @@ async function writeManifestJson(projectPath, projectName) {
|
|
|
541
609
|
};
|
|
542
610
|
try {
|
|
543
611
|
console.log(writingManifestJsonMetadata());
|
|
544
|
-
await promises_namespaceObject.writeFile(
|
|
612
|
+
await promises_namespaceObject.writeFile(manifestJsonPath, JSON.stringify(manifestMetadata, null, 2));
|
|
545
613
|
} catch (error) {
|
|
546
614
|
console.error(writingManifestJsonMetadataError(projectName, error));
|
|
547
615
|
throw error;
|
|
@@ -693,7 +761,7 @@ async function extensionCreate(projectNameInput, { cliVersion, template = 'init'
|
|
|
693
761
|
await writeGitignore(projectPath);
|
|
694
762
|
await setupBuiltInTests(projectPath, projectName);
|
|
695
763
|
if (isTypeScriptTemplate(template)) await generateExtensionTypes(projectPath, projectName);
|
|
696
|
-
const successfulInstall = await successfullInstall(projectPath, projectName);
|
|
764
|
+
const successfulInstall = await successfullInstall(projectPath, projectName, Boolean(install));
|
|
697
765
|
console.log(successfulInstall);
|
|
698
766
|
} catch (error) {
|
|
699
767
|
console.error(error);
|
|
@@ -701,9 +769,9 @@ async function extensionCreate(projectNameInput, { cliVersion, template = 'init'
|
|
|
701
769
|
}
|
|
702
770
|
}
|
|
703
771
|
exports.extensionCreate = __webpack_exports__.extensionCreate;
|
|
704
|
-
for(var
|
|
772
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
705
773
|
"extensionCreate"
|
|
706
|
-
].indexOf(
|
|
774
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
707
775
|
Object.defineProperty(exports, '__esModule', {
|
|
708
776
|
value: true
|
|
709
777
|
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"license": "MIT",
|
|
3
|
+
"packageManager": "pnpm@10.28.0",
|
|
3
4
|
"repository": {
|
|
4
5
|
"type": "git",
|
|
5
|
-
"url": "https://github.com/extension-js/
|
|
6
|
+
"url": "https://github.com/extension-js/extension.js.git"
|
|
6
7
|
},
|
|
7
8
|
"engines": {
|
|
8
9
|
"node": ">=18"
|
|
9
10
|
},
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
13
|
+
"development": "./module.ts",
|
|
12
14
|
"types": "./dist/module.d.ts",
|
|
13
15
|
"import": "./dist/module.js",
|
|
14
16
|
"require": "./dist/module.js"
|
|
@@ -20,7 +22,7 @@
|
|
|
20
22
|
"dist"
|
|
21
23
|
],
|
|
22
24
|
"name": "extension-create",
|
|
23
|
-
"version": "
|
|
25
|
+
"version": "3.1.0-next.10",
|
|
24
26
|
"description": "The standalone extension creation engine for Extension.js",
|
|
25
27
|
"author": {
|
|
26
28
|
"name": "Cezar Augusto",
|
|
@@ -32,6 +34,16 @@
|
|
|
32
34
|
"registry": "https://registry.npmjs.org",
|
|
33
35
|
"tag": "latest"
|
|
34
36
|
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"clean": "rm -rf dist",
|
|
39
|
+
"watch": "rslib build --watch",
|
|
40
|
+
"compile": "rslib build",
|
|
41
|
+
"format": "prettier --write \"**/*.{ts,tsx,md,js,json}\"",
|
|
42
|
+
"lint": "eslint .",
|
|
43
|
+
"pretest:create": "pnpm compile",
|
|
44
|
+
"test:create": "vitest run",
|
|
45
|
+
"test:coverage": "vitest run --coverage"
|
|
46
|
+
},
|
|
35
47
|
"keywords": [
|
|
36
48
|
"webextension",
|
|
37
49
|
"browser-extension",
|
|
@@ -55,40 +67,30 @@
|
|
|
55
67
|
"edge-extension"
|
|
56
68
|
],
|
|
57
69
|
"dependencies": {
|
|
58
|
-
"adm-zip": "^0.5.
|
|
59
|
-
"axios": "^1.
|
|
70
|
+
"adm-zip": "^0.5.16",
|
|
71
|
+
"axios": "^1.13.2",
|
|
60
72
|
"cross-spawn": "^7.0.6",
|
|
61
|
-
"go-git-it": "^5.0.
|
|
62
|
-
"package-manager-detector": "^
|
|
73
|
+
"go-git-it": "^5.0.3",
|
|
74
|
+
"package-manager-detector": "^1.6.0",
|
|
63
75
|
"pintor": "0.3.0",
|
|
64
76
|
"tiny-glob": "^0.2.9"
|
|
65
77
|
},
|
|
66
78
|
"devDependencies": {
|
|
67
|
-
"@changesets/cli": "^2.29.
|
|
68
|
-
"@eslint/js": "^9.
|
|
69
|
-
"@rslib/core": "^0.
|
|
70
|
-
"@types/adm-zip": "^0.5.
|
|
71
|
-
"@types/chrome": "^0.
|
|
79
|
+
"@changesets/cli": "^2.29.8",
|
|
80
|
+
"@eslint/js": "^9.39.2",
|
|
81
|
+
"@rslib/core": "^0.19.2",
|
|
82
|
+
"@types/adm-zip": "^0.5.7",
|
|
83
|
+
"@types/chrome": "^0.1.33",
|
|
72
84
|
"@types/cross-spawn": "^6.0.6",
|
|
73
|
-
"@types/node": "^
|
|
74
|
-
"@types/webextension-polyfill": "0.12.
|
|
75
|
-
"@vitest/coverage-v8": "^
|
|
76
|
-
"eslint": "^9.
|
|
77
|
-
"globals": "^
|
|
78
|
-
"prettier": "^3.
|
|
85
|
+
"@types/node": "^25.0.9",
|
|
86
|
+
"@types/webextension-polyfill": "0.12.4",
|
|
87
|
+
"@vitest/coverage-v8": "^4.0.17",
|
|
88
|
+
"eslint": "^9.39.2",
|
|
89
|
+
"globals": "^17.0.0",
|
|
90
|
+
"prettier": "^3.8.0",
|
|
79
91
|
"tsconfig": "*",
|
|
80
|
-
"typescript": "5.
|
|
81
|
-
"vitest": "^
|
|
92
|
+
"typescript": "5.9.3",
|
|
93
|
+
"vitest": "^4.0.17",
|
|
82
94
|
"webextension-polyfill": "^0.12.0"
|
|
83
|
-
},
|
|
84
|
-
"scripts": {
|
|
85
|
-
"clean": "rm -rf dist",
|
|
86
|
-
"watch": "rslib build --watch",
|
|
87
|
-
"compile": "rslib build",
|
|
88
|
-
"format": "prettier --write \"**/*.{ts,tsx,md,js,json}\"",
|
|
89
|
-
"lint": "eslint .",
|
|
90
|
-
"pretest:create": "pnpm compile",
|
|
91
|
-
"test:create": "vitest run",
|
|
92
|
-
"test:coverage": "vitest run --coverage"
|
|
93
95
|
}
|
|
94
|
-
}
|
|
96
|
+
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<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>
|
|
2
|
-
|
|
3
|
-
# init
|
|
4
|
-
|
|
5
|
-
> A basic browser extension example built with Extension.js. Perfect starting point for developers learning browser extension development with modern tooling.
|
|
6
|
-
|
|
7
|
-
What this example does in the scope of a browser extension. The description should
|
|
8
|
-
describe for an audience of developers looking to use the example. Avoid jargon and
|
|
9
|
-
use simple language.
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
npx extension@latest create <project-name> --template init
|
|
15
|
-
cd <project-name>
|
|
16
|
-
npm install
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Commands
|
|
20
|
-
|
|
21
|
-
### dev
|
|
22
|
-
|
|
23
|
-
Run the extension in development mode.
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
npx extension@latest dev
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
### build
|
|
30
|
-
|
|
31
|
-
Build the extension for production.
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
npx extension@latest build
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Preview
|
|
38
|
-
|
|
39
|
-
Preview the extension in the browser.
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npx extension@latest preview
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Learn more
|
|
46
|
-
|
|
47
|
-
Learn more about this and other examples at @https://extension.js.org/
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
console.log('test')
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json.schemastore.org/chrome-manifest.json",
|
|
3
|
-
"manifest_version": 3,
|
|
4
|
-
"version": "0.0.1",
|
|
5
|
-
"name": "test-template-init",
|
|
6
|
-
"description": "A basic browser extension example built with Extension.js. Perfect starting point for developers learning browser extension development with modern tooling.",
|
|
7
|
-
"icons": {
|
|
8
|
-
"48": "images/extension_48.png"
|
|
9
|
-
},
|
|
10
|
-
"author": "Your Name"
|
|
11
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"private": true,
|
|
3
|
-
"name": "test-template-init",
|
|
4
|
-
"description": "A basic browser extension example built with Extension.js. Perfect starting point for developers learning browser extension development with modern tooling.",
|
|
5
|
-
"version": "0.0.1",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"author": {
|
|
9
|
-
"name": "Your Name",
|
|
10
|
-
"email": "your@email.com",
|
|
11
|
-
"url": "https://yourwebsite.com"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"dev": "extension dev",
|
|
15
|
-
"start": "extension start",
|
|
16
|
-
"build": "extension build"
|
|
17
|
-
},
|
|
18
|
-
"dependencies": {},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"extension": "^undefined"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
Binary file
|
|
Binary file
|