lucid-package 0.0.128 → 0.0.129

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.
Files changed (35) hide show
  1. package/package.json +3 -3
  2. package/src/angularframeworkutils.d.ts +2 -1
  3. package/src/angularframeworkutils.js +8 -5
  4. package/src/dataconnector.d.ts +2 -1
  5. package/src/dataconnector.js +3 -3
  6. package/src/editorextension.d.ts +6 -5
  7. package/src/editorextension.js +14 -13
  8. package/src/filesystemutil.d.ts +16 -3
  9. package/src/filesystemutil.js +40 -8
  10. package/src/index.js +41 -12
  11. package/src/installationutil.d.ts +16 -3
  12. package/src/installationutil.js +34 -8
  13. package/src/package.d.ts +5 -3
  14. package/src/package.js +30 -11
  15. package/src/reactframeworkutils.d.ts +2 -1
  16. package/src/reactframeworkutils.js +8 -5
  17. package/src/shapelibrary.js +2 -2
  18. package/templates/dataconnector/package-lock.json +103 -15
  19. package/templates/dataconnector/pnpm-lock.yaml +1163 -0
  20. package/templates/dataconnector/pnpm-workspace.yaml +1 -0
  21. package/templates/dataconnector/tsconfig.json +1 -0
  22. package/templates/editorextension/angular/skeleton/pnpm-lock.yaml +847 -0
  23. package/templates/editorextension/angular/skeleton/pnpm-workspace.yaml +1 -0
  24. package/templates/editorextension/angular/skeleton/tsconfig.json +1 -0
  25. package/templates/editorextension/angular/skeleton/webpack.config.js +4 -4
  26. package/templates/editorextension/react/skeleton/pnpm-lock.yaml +847 -0
  27. package/templates/editorextension/react/skeleton/pnpm-workspace.yaml +1 -0
  28. package/templates/editorextension/react/skeleton/tsconfig.json +1 -0
  29. package/templates/editorextension/react/skeleton/webpack.config.js +4 -4
  30. package/templates/editorextension/vanilla/pnpm-lock.yaml +847 -0
  31. package/templates/editorextension/vanilla/pnpm-workspace.yaml +1 -0
  32. package/templates/editorextension/vanilla/tsconfig.json +1 -0
  33. package/templates/package/package.json +9 -9
  34. package/templates/package/pnpm-lock.yaml +9 -0
  35. package/templates/package/pnpm-workspace.yaml +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucid-package",
3
- "version": "0.0.128",
3
+ "version": "0.0.129",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -14,8 +14,8 @@
14
14
  "@types/express": "^4.17.13",
15
15
  "@types/node": "^16.11.11",
16
16
  "@types/webpack": "^5.28.5",
17
- "prettier": "file:../../cake/node_modules/prettier",
18
- "prettier-plugin-organize-imports": "file:../../cake/node_modules/prettier-plugin-organize-imports"
17
+ "prettier": "catalog:",
18
+ "prettier-plugin-organize-imports": "catalog:"
19
19
  },
20
20
  "publishConfig": {
21
21
  "access": "public"
@@ -1 +1,2 @@
1
- export declare function createAngularEditorExtension(name: string, isInternal: boolean, skipSDKDependency: boolean): Promise<void>;
1
+ import { PackageManagerOptions } from './installationutil';
2
+ export declare function createAngularEditorExtension(name: string, isInternal: boolean, packageManagerOptions: PackageManagerOptions, skipSDKDependency: boolean): Promise<void>;
@@ -8,14 +8,17 @@ const installationutil_1 = require("./installationutil");
8
8
  const package_1 = require("./package");
9
9
  const theme_1 = require("./theme");
10
10
  const ANGULAR_PROJECT_NAME = 'angular-app';
11
- async function createAngularEditorExtension(name, isInternal, skipSDKDependency) {
12
- await (0, editorextension_1.createEditorExtension)(name, isInternal, skipSDKDependency, path.join('angular', 'skeleton'), [
11
+ async function createAngularEditorExtension(name, isInternal, packageManagerOptions, skipSDKDependency) {
12
+ await (0, editorextension_1.createEditorExtension)(name, isInternal, packageManagerOptions, skipSDKDependency, path.join('angular', 'skeleton'), [
13
13
  'webpack-shell-plugin-next',
14
14
  ]);
15
15
  const angularEditorExtensionTargetFolder = path.join(process.cwd(), ANGULAR_PROJECT_NAME);
16
16
  console.log((0, theme_1.success)('Creating Angular project in ' + angularEditorExtensionTargetFolder));
17
- (0, installationutil_1.installAngularProject)(ANGULAR_PROJECT_NAME);
18
- const webpackConfig = (await fs.readFile('webpack.config.js', 'utf8')).replace('<<dynamicname>>', ANGULAR_PROJECT_NAME);
17
+ (0, installationutil_1.installAngularProject)(ANGULAR_PROJECT_NAME, packageManagerOptions);
18
+ const angularBuildCommand = `${packageManagerOptions.packageManagerPath} exec -- ./node_modules/@angular/cli build`;
19
+ const webpackConfig = (await fs.readFile('webpack.config.js', 'utf8'))
20
+ .replace('<<dynamicname>>', ANGULAR_PROJECT_NAME)
21
+ .replace('<<angularbuildcommand>>', angularBuildCommand);
19
22
  const extensionTemplateCode = (await fs.readFile(path.join('src', 'extension.ts'), 'utf8')).replace('<<dynamicname>>', ANGULAR_PROJECT_NAME);
20
23
  await fs.writeFile(path.join(process.cwd(), 'webpack.config.js'), webpackConfig);
21
24
  await fs.writeFile(path.join('src', 'extension.ts'), extensionTemplateCode);
@@ -24,5 +27,5 @@ async function createAngularEditorExtension(name, isInternal, skipSDKDependency)
24
27
  packageJson.name = ANGULAR_PROJECT_NAME;
25
28
  await fs.writeFile('package.json', JSON.stringify(packageJson, null, 4));
26
29
  console.log('Installing Angular dependencies');
27
- (0, installationutil_1.installDependenciesIfNeeded)(isInternal, skipSDKDependency);
30
+ (0, installationutil_1.installDependenciesIfNeeded)(isInternal, packageManagerOptions, skipSDKDependency);
28
31
  }
@@ -1 +1,2 @@
1
- export declare function createDataConnector(name: string, isInternal: boolean, skipSDKDependency: boolean): Promise<void>;
1
+ import { PackageManagerOptions } from './installationutil';
2
+ export declare function createDataConnector(name: string, isInternal: boolean, packageManagerOptions: PackageManagerOptions, skipSDKDependency: boolean): Promise<void>;
@@ -6,11 +6,11 @@ const filesystemutil_1 = require("./filesystemutil");
6
6
  const installationutil_1 = require("./installationutil");
7
7
  const package_1 = require("./package");
8
8
  const theme_1 = require("./theme");
9
- async function createDataConnector(name, isInternal, skipSDKDependency) {
9
+ async function createDataConnector(name, isInternal, packageManagerOptions, skipSDKDependency) {
10
10
  console.log((0, theme_1.success)('Creating data connector in dataconnectors/' + name));
11
11
  const source = path.join(__dirname, '..', 'templates', 'dataconnector');
12
12
  const targetFolder = path.join('dataconnectors', name);
13
- (0, filesystemutil_1.copyFolderRecursiveSync)(source, targetFolder);
13
+ (0, filesystemutil_1.copyFolderRecursiveSync)(source, targetFolder, (0, filesystemutil_1.getPackageManagerExcludePaths)(source, packageManagerOptions.mode));
14
14
  await (0, package_1.modifyManifest)((manifest) => {
15
15
  if (!manifest['dataConnectors']) {
16
16
  manifest['dataConnectors'] = [];
@@ -24,5 +24,5 @@ async function createDataConnector(name, isInternal, skipSDKDependency) {
24
24
  });
25
25
  console.log(`Installing dependencies`);
26
26
  process.chdir(targetFolder);
27
- (0, installationutil_1.installDependenciesIfNeeded)(isInternal, skipSDKDependency);
27
+ (0, installationutil_1.installDependenciesIfNeeded)(isInternal, packageManagerOptions, skipSDKDependency);
28
28
  }
@@ -1,14 +1,15 @@
1
1
  import { Compiler } from 'webpack';
2
- export declare function createEditorExtension(name: string, isInternal: boolean, skipSDKDependency: boolean, source?: string, deps?: string[]): Promise<void>;
3
- export declare function buildEditorExtension(name: string, isInternal: boolean, quiet?: boolean, skipSdkDependency?: boolean): Promise<void>;
4
- export declare function updateExtensionSDK(name: string): Promise<void>;
2
+ import { PackageManagerOptions } from './installationutil';
3
+ export declare function createEditorExtension(name: string, isInternal: boolean, packageManagerOptions: PackageManagerOptions, skipSDKDependency: boolean, source?: string, deps?: string[]): Promise<void>;
4
+ export declare function buildEditorExtension(name: string, isInternal: boolean, packageManagerOptions: PackageManagerOptions, quiet?: boolean, skipSdkDependency?: boolean): Promise<void>;
5
+ export declare function updateExtensionSDK(name: string, packageManagerOptions: PackageManagerOptions): Promise<void>;
5
6
  /**
6
7
  * Uses webpack to watch for changes in the editor extension
7
8
  * @param name The editor extension name
8
9
  * @param quiet If true, will only show errors in output
9
10
  * @param ignoreNodeModules If true, while serving, will not autoreload on changes to node_modules files
10
11
  */
11
- export declare function watchEditorExtension(name: string, isInternal: boolean, quiet?: boolean, ignoreNodeModules?: boolean): Promise<{
12
+ export declare function watchEditorExtension(name: string, isInternal: boolean, packageManagerOptions: PackageManagerOptions, quiet?: boolean, ignoreNodeModules?: boolean): Promise<{
12
13
  name: string;
13
14
  compiler: Compiler;
14
15
  }>;
@@ -18,5 +19,5 @@ export declare function watchEditorExtension(name: string, isInternal: boolean,
18
19
  * @param quiet If true, will only show errors in output
19
20
  * @param watchIgnoreNodeModules If true, while serving, will not autoreload on changes to node_modules files
20
21
  */
21
- export declare function debugEditorExtension(extensionNames: string[], isInternal: boolean, quiet?: boolean, pickAnyPort?: boolean, watchIgnoreNodeModules?: boolean): Promise<void>;
22
+ export declare function debugEditorExtension(extensionNames: string[], isInternal: boolean, packageManagerOptions: PackageManagerOptions, quiet?: boolean, pickAnyPort?: boolean, watchIgnoreNodeModules?: boolean): Promise<void>;
22
23
  export declare function getAllExtensionNames(): Promise<string[]>;
@@ -24,12 +24,12 @@ const webpack = require('webpack');
24
24
  const WebPackCLI = require('webpack-cli');
25
25
  const ws = require('ws');
26
26
  const chokidar = require('chokidar');
27
- async function createEditorExtension(name, isInternal, skipSDKDependency, source = 'vanilla', deps = []) {
27
+ async function createEditorExtension(name, isInternal, packageManagerOptions, skipSDKDependency, source = 'vanilla', deps = []) {
28
28
  const editorExtensionSource = path.join(__dirname, '..', 'templates', 'editorextension', source);
29
29
  const editorExtensionTargetFolder = path.join('editorextensions', name);
30
- const codePath = path.join('editorextensions', name, 'bin', 'extension.js');
30
+ const codePath = path.posix.join('editorextensions', name, 'bin', 'extension.js');
31
31
  console.log((0, theme_1.success)('Creating empty editor extension in ' + editorExtensionTargetFolder));
32
- (0, filesystemutil_1.copyFolderRecursiveSync)(editorExtensionSource, editorExtensionTargetFolder);
32
+ (0, filesystemutil_1.copyFolderRecursiveSync)(editorExtensionSource, editorExtensionTargetFolder, (0, filesystemutil_1.getPackageManagerExcludePaths)(editorExtensionSource, packageManagerOptions.mode));
33
33
  // Angular and React extensions will automatically create the `public` folder,
34
34
  // during the webpack build
35
35
  if (source === 'vanilla') {
@@ -51,20 +51,20 @@ async function createEditorExtension(name, isInternal, skipSDKDependency, source
51
51
  });
52
52
  console.log(`Installing dependencies`);
53
53
  process.chdir(editorExtensionTargetFolder);
54
- (0, installationutil_1.installDependenciesIfNeeded)(isInternal, skipSDKDependency, deps);
54
+ (0, installationutil_1.installDependenciesIfNeeded)(isInternal, packageManagerOptions, skipSDKDependency, deps);
55
55
  }
56
- async function buildEditorExtension(name, isInternal, quiet = false, skipSdkDependency = false) {
56
+ async function buildEditorExtension(name, isInternal, packageManagerOptions, quiet = false, skipSdkDependency = false) {
57
57
  const extensionCodePath = path.join('editorextensions', await getExtensionCodeDirectoryName(name));
58
58
  process.chdir(extensionCodePath);
59
- (0, installationutil_1.installDependenciesIfNeeded)(isInternal, skipSdkDependency);
59
+ (0, installationutil_1.installDependenciesIfNeeded)(isInternal, packageManagerOptions, skipSdkDependency);
60
60
  const cli = new WebPackCLI();
61
61
  await cli.run(['node', 'webpack', '--mode', 'production', ...(quiet ? ['--stats', 'errors-only'] : [])]);
62
62
  }
63
- async function updateExtensionSDK(name) {
63
+ async function updateExtensionSDK(name, packageManagerOptions) {
64
64
  const extensionCodePath = path.join('editorextensions', await getExtensionCodeDirectoryName(name));
65
65
  process.chdir(extensionCodePath);
66
66
  console.log((0, theme_1.success)('Installing latest SDK in extension ' + name));
67
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)('npm install lucid-extension-sdk@latest').toString());
67
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`"${packageManagerOptions.packageManagerPath}" add lucid-extension-sdk@latest`).toString());
68
68
  }
69
69
  /**
70
70
  * Uses webpack to watch for changes in the editor extension
@@ -72,11 +72,11 @@ async function updateExtensionSDK(name) {
72
72
  * @param quiet If true, will only show errors in output
73
73
  * @param ignoreNodeModules If true, while serving, will not autoreload on changes to node_modules files
74
74
  */
75
- async function watchEditorExtension(name, isInternal, quiet = false, ignoreNodeModules = false) {
75
+ async function watchEditorExtension(name, isInternal, packageManagerOptions, quiet = false, ignoreNodeModules = false) {
76
76
  const originalDirectory = process.cwd();
77
77
  const extensionCodePath = path.join('editorextensions', await getExtensionCodeDirectoryName(name));
78
78
  process.chdir(extensionCodePath);
79
- (0, installationutil_1.installDependenciesIfNeeded)(isInternal);
79
+ (0, installationutil_1.installDependenciesIfNeeded)(isInternal, packageManagerOptions);
80
80
  const webpackConfigExport = require(path.resolve('webpack.config.js'));
81
81
  // For backwards compatibility, we need to support extensions where the webpack config is a fuction or an object
82
82
  const webpackConfig = typeof webpackConfigExport == 'function' ? webpackConfigExport({ environment: 'dev' }) : webpackConfigExport;
@@ -115,8 +115,8 @@ async function watchEditorExtension(name, isInternal, quiet = false, ignoreNodeM
115
115
  * @param quiet If true, will only show errors in output
116
116
  * @param watchIgnoreNodeModules If true, while serving, will not autoreload on changes to node_modules files
117
117
  */
118
- async function debugEditorExtension(extensionNames, isInternal, quiet = false, pickAnyPort = false, watchIgnoreNodeModules = false) {
119
- const watchers = await Promise.all(extensionNames.map(async (name) => watchEditorExtension(name, isInternal, quiet, watchIgnoreNodeModules)));
118
+ async function debugEditorExtension(extensionNames, isInternal, packageManagerOptions, quiet = false, pickAnyPort = false, watchIgnoreNodeModules = false) {
119
+ const watchers = await Promise.all(extensionNames.map(async (name) => watchEditorExtension(name, isInternal, packageManagerOptions, quiet, watchIgnoreNodeModules)));
120
120
  const app = express();
121
121
  const initialPortToTry = 9900;
122
122
  // The actual port number (that the server serves from)can change, depending on anyport behavior.
@@ -307,7 +307,8 @@ async function getExtensionCodeDirectoryName(name) {
307
307
  * extensionName.
308
308
  */
309
309
  async function getExtensionCodeDirectoryNameFromCodePath(codePath) {
310
- const parts = codePath.split(path.sep) ?? [];
310
+ const normalizedPath = (0, filesystemutil_1.getNormalizedZipPath)(codePath);
311
+ const parts = normalizedPath.split(path.posix.sep) ?? [];
311
312
  if (parts[0] === 'editorextensions' && parts[1]) {
312
313
  return `${parts[1]}`;
313
314
  }
@@ -1,7 +1,20 @@
1
+ import { PackageManagerMode } from './installationutil';
2
+ /**
3
+ * Returns the paths of package manager files to exclude when copying templates.
4
+ * @param sourceDir The source directory containing the template files
5
+ * @param mode Which package manager is being used
6
+ */
7
+ export declare function getPackageManagerExcludePaths(sourceDir: string, mode: PackageManagerMode): string[];
1
8
  export declare function copyFileSync(source: string, target: string): void;
2
- export declare function copyFolderRecursiveSync(source: string, targetFolder: string): void;
3
9
  /**
4
- * On Windows machines '\' is used as the file separator. To ensure that we correctly zip files on Windows
5
- * machines we replace '\' with '/'.
10
+ * Copies a folder recursively, optionally excluding specified paths.
11
+ * @param source Source directory path
12
+ * @param targetFolder Target directory path
13
+ * @param excludePaths Array of paths to exclude (will be resolved to absolute paths)
14
+ */
15
+ export declare function copyFolderRecursiveSync(source: string, targetFolder: string, excludePaths?: string[]): void;
16
+ /**
17
+ * On Windows machines '\' is used as the file separator. To ensure that we correctly zip files
18
+ * and handle manifests generated on Windows, we always replace '\' with '/'.
6
19
  */
7
20
  export declare function getNormalizedZipPath(rawPath: string): string;
@@ -1,10 +1,26 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPackageManagerExcludePaths = getPackageManagerExcludePaths;
3
4
  exports.copyFileSync = copyFileSync;
4
5
  exports.copyFolderRecursiveSync = copyFolderRecursiveSync;
5
6
  exports.getNormalizedZipPath = getNormalizedZipPath;
6
7
  const fs = require("fs");
7
8
  const path = require("path");
9
+ const installationutil_1 = require("./installationutil");
10
+ /**
11
+ * Returns the paths of package manager files to exclude when copying templates.
12
+ * @param sourceDir The source directory containing the template files
13
+ * @param mode Which package manager is being used
14
+ */
15
+ function getPackageManagerExcludePaths(sourceDir, mode) {
16
+ if (mode === installationutil_1.PackageManagerMode.Pnpm) {
17
+ return [path.join(sourceDir, 'package-lock.json')];
18
+ }
19
+ else {
20
+ // npm mode
21
+ return [path.join(sourceDir, 'pnpm-lock.yaml'), path.join(sourceDir, 'pnpm-workspace.yaml')];
22
+ }
23
+ }
8
24
  function copyFileSync(source, target) {
9
25
  var targetFile = target;
10
26
  // If target is a directory, a new file with the same name will be created
@@ -15,19 +31,24 @@ function copyFileSync(source, target) {
15
31
  }
16
32
  fs.writeFileSync(targetFile, fs.readFileSync(source));
17
33
  }
18
- function copyFolderRecursiveSync(source, targetFolder) {
19
- var files = [];
34
+ /**
35
+ * Internal implementation that uses a pre-resolved Set of exclude paths.
36
+ */
37
+ function copyFolderRecursiveSyncImpl(source, targetFolder, excludePaths) {
20
38
  // Check if folder needs to be created or integrated
21
39
  if (!fs.existsSync(targetFolder)) {
22
40
  fs.mkdirSync(targetFolder, { recursive: true });
23
41
  }
24
42
  // Copy
25
43
  if (fs.lstatSync(source).isDirectory()) {
26
- files = fs.readdirSync(source);
44
+ const files = fs.readdirSync(source);
27
45
  files.forEach((file) => {
28
- var curSource = path.join(source, file);
46
+ const curSource = path.join(source, file);
47
+ if (excludePaths.has(fs.realpathSync(curSource))) {
48
+ return;
49
+ }
29
50
  if (fs.lstatSync(curSource).isDirectory()) {
30
- copyFolderRecursiveSync(curSource, path.join(targetFolder, file));
51
+ copyFolderRecursiveSyncImpl(curSource, path.join(targetFolder, file), excludePaths);
31
52
  }
32
53
  else {
33
54
  copyFileSync(curSource, targetFolder);
@@ -36,9 +57,20 @@ function copyFolderRecursiveSync(source, targetFolder) {
36
57
  }
37
58
  }
38
59
  /**
39
- * On Windows machines '\' is used as the file separator. To ensure that we correctly zip files on Windows
40
- * machines we replace '\' with '/'.
60
+ * Copies a folder recursively, optionally excluding specified paths.
61
+ * @param source Source directory path
62
+ * @param targetFolder Target directory path
63
+ * @param excludePaths Array of paths to exclude (will be resolved to absolute paths)
64
+ */
65
+ function copyFolderRecursiveSync(source, targetFolder, excludePaths = []) {
66
+ // Resolve all exclude paths once upfront, filtering out paths that don't exist
67
+ const resolvedExcludes = new Set(excludePaths.filter((p) => fs.existsSync(p)).map((p) => fs.realpathSync(p)));
68
+ copyFolderRecursiveSyncImpl(source, targetFolder, resolvedExcludes);
69
+ }
70
+ /**
71
+ * On Windows machines '\' is used as the file separator. To ensure that we correctly zip files
72
+ * and handle manifests generated on Windows, we always replace '\' with '/'.
41
73
  */
42
74
  function getNormalizedZipPath(rawPath) {
43
- return path.sep === '\\' ? rawPath.replace(/\\/g, '/') : rawPath;
75
+ return rawPath.replace(/\\/g, '/');
44
76
  }
package/src/index.js CHANGED
@@ -6,6 +6,7 @@ const angularframeworkutils_1 = require("./angularframeworkutils");
6
6
  const dataconnector_1 = require("./dataconnector");
7
7
  const editorextension_1 = require("./editorextension");
8
8
  const interactive = require("./interactibilityutil");
9
+ const installationutil_1 = require("./installationutil");
9
10
  const package_1 = require("./package");
10
11
  const reactframeworkutils_1 = require("./reactframeworkutils");
11
12
  const shapelibrary_1 = require("./shapelibrary");
@@ -28,6 +29,17 @@ class LucidSuiteExtensionCLI {
28
29
  type: 'str',
29
30
  help: argparse_1.SUPPRESS,
30
31
  });
32
+ parser.add_argument('--mode', {
33
+ type: 'str',
34
+ choices: ['pnpm', 'npm'],
35
+ default: 'npm',
36
+ help: 'Package manager to use (default: npm)',
37
+ });
38
+ parser.add_argument('--package-manager-path', {
39
+ type: 'str',
40
+ metavar: 'PATH',
41
+ help: 'Explicit path to the package manager binary. If not provided, assumes the package manager is available on the PATH.',
42
+ });
31
43
  const subparsers = parser.add_subparsers({ dest: 'command' });
32
44
  const createParser = subparsers.add_parser('create', {
33
45
  help: 'Create a new Lucid extension package in a new directory',
@@ -148,6 +160,23 @@ class LucidSuiteExtensionCLI {
148
160
  // If we've spawned a child process recursively calling a new lucid-package target,
149
161
  // as long as it's originally triggered by Bazel then we're still using Bazel flows.
150
162
  process.env['BAZEL_TARGET'];
163
+ // Convert mode string to enum
164
+ let mode;
165
+ if (parsed['mode'] === 'pnpm') {
166
+ mode = installationutil_1.PackageManagerMode.Pnpm;
167
+ }
168
+ else if (parsed['mode'] === 'npm') {
169
+ mode = installationutil_1.PackageManagerMode.Npm;
170
+ }
171
+ else {
172
+ throw new Error(`Unknown package manager mode: ${parsed['mode']}`);
173
+ }
174
+ // If --package-manager-path is set, use it as the package manager command.
175
+ // Otherwise, use the mode string (pnpm or npm) and assume it's available on the PATH.
176
+ const packageManagerOptions = {
177
+ mode,
178
+ packageManagerPath: parsed['package_manager_path'] ?? parsed['mode'],
179
+ };
151
180
  let isChdir = !!parsed['chdir'];
152
181
  if (isChdir) {
153
182
  if (parsed['project']) {
@@ -165,7 +194,7 @@ class LucidSuiteExtensionCLI {
165
194
  if (parsed['name'] == null) {
166
195
  parsed['name'] = await interactive.inputPrompt('Please enter the name of the Lucid Package');
167
196
  }
168
- await (0, package_1.createEmptyPackage)(parsed['name']);
197
+ await (0, package_1.createEmptyPackage)(parsed['name'], packageManagerOptions);
169
198
  const options = ['Editor Extension', 'Shape Library', 'Data Connector'];
170
199
  const choices = await interactive.multiSelect('Select components to add to package (can select none or more than one)', options);
171
200
  const packagePath = path.join(process.cwd(), parsed['name']);
@@ -180,17 +209,17 @@ class LucidSuiteExtensionCLI {
180
209
  const choice = await interactive.selectPrompt('Please select a framework', options);
181
210
  switch (choice) {
182
211
  case 0:
183
- await (0, angularframeworkutils_1.createAngularEditorExtension)(editorExtensionName, isInternal, false);
212
+ await (0, angularframeworkutils_1.createAngularEditorExtension)(editorExtensionName, isInternal, packageManagerOptions, false);
184
213
  break;
185
214
  case 1:
186
215
  const options = ['Javascript', 'Typescript'];
187
216
  const choice = await interactive.selectPrompt('Please select flavor', options);
188
- await (0, reactframeworkutils_1.createReactEditorExtension)(editorExtensionName, options[choice], isInternal, false);
217
+ await (0, reactframeworkutils_1.createReactEditorExtension)(editorExtensionName, options[choice], isInternal, packageManagerOptions, false);
189
218
  break;
190
219
  }
191
220
  }
192
221
  else {
193
- await (0, editorextension_1.createEditorExtension)(editorExtensionName, isInternal, false);
222
+ await (0, editorextension_1.createEditorExtension)(editorExtensionName, isInternal, packageManagerOptions, false);
194
223
  }
195
224
  break;
196
225
  case 1:
@@ -201,7 +230,7 @@ class LucidSuiteExtensionCLI {
201
230
  case 2:
202
231
  process.chdir(packagePath);
203
232
  const dataConnectorName = await interactive.inputPrompt('Please enter the name of the data connector');
204
- await (0, dataconnector_1.createDataConnector)(dataConnectorName, isInternal, false);
233
+ await (0, dataconnector_1.createDataConnector)(dataConnectorName, isInternal, packageManagerOptions, false);
205
234
  break;
206
235
  }
207
236
  }
@@ -214,16 +243,16 @@ class LucidSuiteExtensionCLI {
214
243
  else {
215
244
  switch (parsed['command']) {
216
245
  case 'bundle':
217
- await (0, package_1.writePackage)(parsed['quiet'], parsed['env'], parsed['skip_sdk']);
246
+ await (0, package_1.writePackage)(packageManagerOptions, parsed['quiet'], parsed['env'], parsed['skip_sdk']);
218
247
  break;
219
248
  case 'update-sdk':
220
- await (0, package_1.updateAllExtensionSDK)();
249
+ await (0, package_1.updateAllExtensionSDK)(packageManagerOptions);
221
250
  break;
222
251
  case 'create-editor-extension':
223
- await (0, editorextension_1.createEditorExtension)(parsed['name'], isInternal, parsed['skip_sdk']);
252
+ await (0, editorextension_1.createEditorExtension)(parsed['name'], isInternal, packageManagerOptions, parsed['skip_sdk']);
224
253
  break;
225
254
  case 'build-editor-extension':
226
- await (0, editorextension_1.buildEditorExtension)(parsed['name'], isInternal, parsed['quiet'], parsed['skip_sdk']);
255
+ await (0, editorextension_1.buildEditorExtension)(parsed['name'], isInternal, packageManagerOptions, parsed['quiet'], parsed['skip_sdk']);
227
256
  break;
228
257
  case 'create-shape-library':
229
258
  await (0, shapelibrary_1.createEmptyShapeLibrary)(parsed['name']);
@@ -239,7 +268,7 @@ class LucidSuiteExtensionCLI {
239
268
  await (0, shapelibrary_1.createImageShapeLibrary)(parsed['name'], parsed['path'], config);
240
269
  break;
241
270
  case 'create-data-connector':
242
- await (0, dataconnector_1.createDataConnector)(parsed['name'], isInternal, parsed['skip_sdk']);
271
+ await (0, dataconnector_1.createDataConnector)(parsed['name'], isInternal, packageManagerOptions, parsed['skip_sdk']);
243
272
  break;
244
273
  case 'test-shape-libraries':
245
274
  await (0, shapelibrary_1.debugShapeLibraries)();
@@ -248,10 +277,10 @@ class LucidSuiteExtensionCLI {
248
277
  if (parsed['name'].length === 0) {
249
278
  parsed['name'] = await (0, editorextension_1.getAllExtensionNames)();
250
279
  }
251
- await (0, editorextension_1.debugEditorExtension)(parsed['name'], isInternal, parsed['quiet'], parsed['anyport'], parsed['watch_ignore_node_modules']);
280
+ await (0, editorextension_1.debugEditorExtension)(parsed['name'], isInternal, packageManagerOptions, parsed['quiet'], parsed['anyport'], parsed['watch_ignore_node_modules']);
252
281
  break;
253
282
  case 'watch-editor-extension':
254
- await (0, editorextension_1.watchEditorExtension)(parsed['name'], isInternal, parsed['quiet']);
283
+ await (0, editorextension_1.watchEditorExtension)(parsed['name'], isInternal, packageManagerOptions, parsed['quiet']);
255
284
  break;
256
285
  default:
257
286
  parser.print_help();
@@ -1,3 +1,16 @@
1
- export declare function installDependenciesIfNeeded(isInternal: boolean, skipSDKDependency?: boolean, additionalDependencies?: string[]): void;
2
- export declare function installReactProject(reactProjectName: string, typescript: boolean): void;
3
- export declare function installAngularProject(angularProjectName: string): void;
1
+ export declare enum PackageManagerMode {
2
+ Pnpm = "pnpm",
3
+ Npm = "npm"
4
+ }
5
+ export interface PackageManagerOptions {
6
+ /** Which package manager to use. */
7
+ mode: PackageManagerMode;
8
+ /**
9
+ * Path to the package manager binary. If a path is not provided, the package manager is assumed to be on the PATH,
10
+ * , i.e., this is set to "pnpm" or "npm" and that command is assumed to be available on the PATH.
11
+ */
12
+ packageManagerPath: string;
13
+ }
14
+ export declare function installDependenciesIfNeeded(isInternal: boolean, packageManagerOptions: PackageManagerOptions, skipSDKDependency?: boolean, additionalDependencies?: string[]): void;
15
+ export declare function installReactProject(reactProjectName: string, typescript: boolean, packageManagerOptions: PackageManagerOptions): void;
16
+ export declare function installAngularProject(angularProjectName: string, packageManagerOptions: PackageManagerOptions): void;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PackageManagerMode = void 0;
3
4
  exports.installDependenciesIfNeeded = installDependenciesIfNeeded;
4
5
  exports.installReactProject = installReactProject;
5
6
  exports.installAngularProject = installAngularProject;
@@ -7,9 +8,33 @@ const oldFs = require("fs");
7
8
  const path = require("path");
8
9
  const shellutil_1 = require("./shellutil");
9
10
  const theme_1 = require("./theme");
10
- function installDependenciesIfNeeded(isInternal, skipSDKDependency = false, additionalDependencies = []) {
11
+ var PackageManagerMode;
12
+ (function (PackageManagerMode) {
13
+ PackageManagerMode["Pnpm"] = "pnpm";
14
+ PackageManagerMode["Npm"] = "npm";
15
+ })(PackageManagerMode || (exports.PackageManagerMode = PackageManagerMode = {}));
16
+ /**
17
+ * Get the install command for installing dependencies from a lockfile.
18
+ */
19
+ function getInstallCommand(options) {
20
+ if (options.mode === PackageManagerMode.Pnpm) {
21
+ return `"${options.packageManagerPath}" --silent install --frozen-lockfile`;
22
+ }
23
+ else {
24
+ // npm mode
25
+ return `"${options.packageManagerPath}" --silent ci`;
26
+ }
27
+ }
28
+ /**
29
+ * Get the command for adding a package as a dependency.
30
+ */
31
+ function getAddCommand(options, packages, silent = false) {
32
+ const silentFlag = silent ? '--silent' : '';
33
+ return `"${options.packageManagerPath}" ${silentFlag} add ${packages.join(' ')}`;
34
+ }
35
+ function installDependenciesIfNeeded(isInternal, packageManagerOptions, skipSDKDependency = false, additionalDependencies = []) {
11
36
  if (!oldFs.existsSync('node_modules')) {
12
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)('npm ci --silent').toString());
37
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(getInstallCommand(packageManagerOptions)).toString());
13
38
  }
14
39
  const sdkDir = path.join('node_modules', 'lucid-extension-sdk');
15
40
  if (isInternal) {
@@ -20,15 +45,16 @@ function installDependenciesIfNeeded(isInternal, skipSDKDependency = false, addi
20
45
  // Otherwise, install the NPM version of the SDK directly. If you would like to opt out of this you can use the
21
46
  // `--skip-sdk` CLI flag.
22
47
  console.log((0, theme_1.success)('Adding dependency on SDK'));
23
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)('npm install --save lucid-extension-sdk').toString());
48
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(getAddCommand(packageManagerOptions, ['lucid-extension-sdk'])).toString());
24
49
  }
25
50
  if (additionalDependencies.length) {
26
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`npm install --silent ${additionalDependencies.reduce((acc, current) => `${acc} ${current}`, '')}`).toString());
51
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(getAddCommand(packageManagerOptions, additionalDependencies, true)).toString());
27
52
  }
28
53
  }
29
- function installReactProject(reactProjectName, typescript) {
30
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`npm install create-react-app && npx create-react-app ${reactProjectName} ${typescript ? '--template typescript' : ''}`).toString());
54
+ function installReactProject(reactProjectName, typescript, packageManagerOptions) {
55
+ const templateArg = typescript ? '--template typescript' : '';
56
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`"${packageManagerOptions.packageManagerPath}" add create-react-app && "${packageManagerOptions.packageManagerPath}" exec -- create-react-app ${reactProjectName} ${templateArg}`).toString());
31
57
  }
32
- function installAngularProject(angularProjectName) {
33
- console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`npm install @angular/cli && npx ng new ${angularProjectName}`).toString());
58
+ function installAngularProject(angularProjectName, packageManagerOptions) {
59
+ console.log((0, shellutil_1.execSyncLoggingOutputOnError)(`"${packageManagerOptions.packageManagerPath}" add @angular/cli && "${packageManagerOptions.packageManagerPath}" exec -- ng new ${angularProjectName}`).toString());
34
60
  }
package/src/package.d.ts CHANGED
@@ -1,11 +1,13 @@
1
+ import { PackageManagerOptions } from './installationutil';
1
2
  import { PackageManifest } from './packagemanifest';
2
- export declare function createEmptyPackage(root: string): Promise<void>;
3
+ export declare function createEmptyPackage(root: string, packageManagerOptions: PackageManagerOptions): Promise<void>;
3
4
  export declare function currentlyInPackage(): boolean;
4
5
  export declare function readJson(path: string): Promise<any>;
5
6
  export declare function modifyManifest(callback: (manifest: PackageManifest) => void | Promise<void>, manifestOverrideEnv?: string): Promise<void>;
6
- export declare function updateAllExtensionSDK(): Promise<void>;
7
+ export declare function updateAllExtensionSDK(packageManagerOptions: PackageManagerOptions): Promise<void>;
7
8
  /**
8
9
  *
10
+ * @param packageManagerOptions Options for which package manager to use (npm or pnpm)
9
11
  * @param manifestOverrideEnv The environment definine what manifest to read from. `manifest.env.json`
10
12
  */
11
- export declare function writePackage(quiet?: boolean, manifestOverrideEnv?: string, skipSdkDependency?: boolean): Promise<void>;
13
+ export declare function writePackage(packageManagerOptions: PackageManagerOptions, quiet?: boolean, manifestOverrideEnv?: string, skipSdkDependency?: boolean): Promise<void>;
package/src/package.js CHANGED
@@ -13,15 +13,23 @@ const lucid_extension_sdk_1 = require("lucid-extension-sdk");
13
13
  const path = require("path");
14
14
  const editorextension_1 = require("./editorextension");
15
15
  const filesystemutil_1 = require("./filesystemutil");
16
+ const installationutil_1 = require("./installationutil");
16
17
  const packagemanifest_1 = require("./packagemanifest");
17
18
  const shapelibrary_1 = require("./shapelibrary");
18
19
  const shellutil_1 = require("./shellutil");
19
20
  const theme_1 = require("./theme");
20
21
  const ziputil_1 = require("./ziputil");
21
- async function createEmptyPackage(root) {
22
+ async function createEmptyPackage(root, packageManagerOptions) {
22
23
  console.log((0, theme_1.success)('Creating Lucid Suite package in ' + root));
23
24
  const source = path.join(__dirname, '..', 'templates', 'package');
24
- (0, filesystemutil_1.copyFolderRecursiveSync)(source, root);
25
+ (0, filesystemutil_1.copyFolderRecursiveSync)(source, root, (0, filesystemutil_1.getPackageManagerExcludePaths)(source, packageManagerOptions.mode));
26
+ // For npm mode, modify package.json to use npm exec instead of pnpm dlx
27
+ if (packageManagerOptions.mode === installationutil_1.PackageManagerMode.Npm) {
28
+ const packageJsonPath = path.join(root, 'package.json');
29
+ let content = fsOld.readFileSync(packageJsonPath, 'utf8');
30
+ content = content.replace(/pnpm dlx/g, 'npm exec --');
31
+ fsOld.writeFileSync(packageJsonPath, content);
32
+ }
25
33
  }
26
34
  function currentlyInPackage() {
27
35
  return ((fsOld.existsSync('editorextensions') || fsOld.existsSync('shapelibraries')) &&
@@ -47,20 +55,22 @@ async function modifyManifest(callback, manifestOverrideEnv) {
47
55
  await callback(manifest);
48
56
  await fs.writeFile('manifest.json', JSON.stringify(manifest, undefined, 2));
49
57
  }
50
- async function updateAllExtensionSDK() {
58
+ async function updateAllExtensionSDK(packageManagerOptions) {
51
59
  const manifest = await (0, packagemanifest_1.readManifest)();
52
60
  for (const extension of manifest['extensions'] || []) {
53
- const parts = extension['codePath'].split(path.sep);
61
+ const codePath = (0, filesystemutil_1.getNormalizedZipPath)(extension['codePath']);
62
+ const parts = codePath.split(path.posix.sep);
54
63
  if (parts[0] === 'editorextensions') {
55
- await (0, editorextension_1.updateExtensionSDK)(parts[1]);
64
+ await (0, editorextension_1.updateExtensionSDK)(parts[1], packageManagerOptions);
56
65
  }
57
66
  }
58
67
  }
59
68
  /**
60
69
  *
70
+ * @param packageManagerOptions Options for which package manager to use (npm or pnpm)
61
71
  * @param manifestOverrideEnv The environment definine what manifest to read from. `manifest.env.json`
62
72
  */
63
- async function writePackage(quiet = false, manifestOverrideEnv, skipSdkDependency = false) {
73
+ async function writePackage(packageManagerOptions, quiet = false, manifestOverrideEnv, skipSdkDependency = false) {
64
74
  const zip = new JSZip();
65
75
  const quietableConsoleLog = (...data) => {
66
76
  if (!quiet) {
@@ -86,7 +96,9 @@ async function writePackage(quiet = false, manifestOverrideEnv, skipSdkDependenc
86
96
  .join(', ')}`);
87
97
  process.exit(1);
88
98
  }
89
- const parts = extension['codePath'].split(path.sep);
99
+ const codePath = (0, filesystemutil_1.getNormalizedZipPath)(extension['codePath']);
100
+ extension['codePath'] = codePath;
101
+ const parts = codePath.split(path.posix.sep);
90
102
  if (parts[0] === 'editorextensions') {
91
103
  //Can't just call the method, as the WebpackCLI class does process.exit(2) :facepalm:
92
104
  quietableConsoleLog((0, theme_1.success)(`Compiling editor extension ${parts[1]}`));
@@ -95,7 +107,12 @@ async function writePackage(quiet = false, manifestOverrideEnv, skipSdkDependenc
95
107
  process.argv[0] +
96
108
  '" "' +
97
109
  process.argv[1] +
98
- '" build-editor-extension ' +
110
+ '" ' +
111
+ // --mode and --package-manager-path are global args, so they need to go before
112
+ // build-editor-extension (but after the script path)
113
+ `--mode ${packageManagerOptions.mode} ` +
114
+ `--package-manager-path "${packageManagerOptions.packageManagerPath}" ` +
115
+ 'build-editor-extension ' +
99
116
  (quiet ? '--quiet ' : '') +
100
117
  (skipSdkDependency ? '--skip-sdk ' : '') +
101
118
  '"' +
@@ -104,16 +121,18 @@ async function writePackage(quiet = false, manifestOverrideEnv, skipSdkDependenc
104
121
  quietableConsoleLog(cmd);
105
122
  quietableConsoleLog((0, shellutil_1.execSyncLoggingOutputOnError)(cmd, (quiet = quiet)).toString());
106
123
  }
107
- (0, ziputil_1.jsZipFileDeterministic)(zip, extension['codePath'], await fs.readFile(extension['codePath']));
124
+ (0, ziputil_1.jsZipFileDeterministic)(zip, codePath, await fs.readFile(codePath));
108
125
  }
109
126
  //Do the same for each shape library
110
127
  for (const library of manifest['shapeLibraries'] || []) {
111
- const parts = library['lcszPath'].split(path.sep);
128
+ const lcszPath = (0, filesystemutil_1.getNormalizedZipPath)(library['lcszPath']);
129
+ library['lcszPath'] = lcszPath;
130
+ const parts = lcszPath.split(path.posix.sep);
112
131
  if (parts[0] === 'shapelibraries') {
113
132
  quietableConsoleLog((0, theme_1.success)(`Building shape library ${parts[1]}`));
114
133
  await (0, shapelibrary_1.buildShapeLibrary)(parts[1].replace('.lcsz', ''), quiet);
115
134
  }
116
- (0, ziputil_1.jsZipFileDeterministic)(zip, library['lcszPath'], await fs.readFile(library['lcszPath']));
135
+ (0, ziputil_1.jsZipFileDeterministic)(zip, lcszPath, await fs.readFile(lcszPath));
117
136
  }
118
137
  //Add any static resources
119
138
  const checkDirForResources = async (directory, zipDirectory) => {