lucid-package 0.0.48 → 0.0.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucid-package",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -12,4 +12,4 @@ export declare function watchEditorExtension(name: string, isInternalTesting: bo
12
12
  * @param extensionNames The names of the editor extensions
13
13
  * @param quiet If true, will only show errors in output
14
14
  */
15
- export declare function debugEditorExtension(extensionNames: string[], quiet?: boolean): Promise<void>;
15
+ export declare function debugEditorExtension(extensionNames: string[], quiet?: boolean, pickAnyPort?: boolean): Promise<void>;
@@ -88,7 +88,8 @@ exports.watchEditorExtension = watchEditorExtension;
88
88
  * @param extensionNames The names of the editor extensions
89
89
  * @param quiet If true, will only show errors in output
90
90
  */
91
- async function debugEditorExtension(extensionNames, quiet = false) {
91
+ async function debugEditorExtension(extensionNames, quiet = false, pickAnyPort = false) {
92
+ let port = 9900;
92
93
  await Promise.all(extensionNames.map(async (name) => {
93
94
  const child = child_process.spawn(`${process.argv[0]} ${process.argv[1]} watch-editor-extension ${name} ${quiet ? '--quiet ' : ''}`, {
94
95
  stdio: 'inherit',
@@ -127,11 +128,11 @@ async function debugEditorExtension(extensionNames, quiet = false) {
127
128
  app.get(['/editorextension', '/editorextension/:name'], async (req, res) => {
128
129
  var _a;
129
130
  const name = (_a = req.params['name']) !== null && _a !== void 0 ? _a : extensionNames[0];
130
- const rawExtension = await getRawEditorExtension(name);
131
+ const rawExtension = await getRawEditorExtension(name, port);
131
132
  res.send(rawExtension);
132
133
  });
133
134
  app.get('/editorextensions', async (req, res) => {
134
- res.send(await Promise.all(extensionNames.map((name) => getRawEditorExtension(name))));
135
+ res.send(await Promise.all(extensionNames.map((name) => getRawEditorExtension(name, port))));
135
136
  });
136
137
  app.get('/settings', async (req, res) => {
137
138
  var _a;
@@ -167,10 +168,25 @@ async function debugEditorExtension(extensionNames, quiet = false) {
167
168
  res.sendStatus(404);
168
169
  }
169
170
  });
170
- app.listen(9900, 'localhost', () => {
171
- console.log('Listening at http://localhost:9900/extension.js');
172
- });
173
- (0, shapelibrary_1.debugShapeLibraries)();
171
+ const listen = () => {
172
+ app.listen(port, 'localhost', () => {
173
+ console.log('Listening at http://localhost:' + port + '/extension.js');
174
+ (0, shapelibrary_1.debugShapeLibraries)(undefined, pickAnyPort);
175
+ }).on('error', (err) => {
176
+ if (err.code === 'EADDRINUSE') {
177
+ if (pickAnyPort && port < 15000) {
178
+ port++;
179
+ listen();
180
+ }
181
+ else {
182
+ console.error('Failed to listen for extension');
183
+ console.error(err);
184
+ process.exit(1);
185
+ }
186
+ }
187
+ });
188
+ };
189
+ listen();
174
190
  }
175
191
  exports.debugEditorExtension = debugEditorExtension;
176
192
  async function getExtensionManifest(name) {
@@ -202,7 +218,7 @@ async function getExtensionCodeDirectoryNameFromCodePath(codePath) {
202
218
  }
203
219
  return undefined;
204
220
  }
205
- async function getRawEditorExtension(name) {
221
+ async function getRawEditorExtension(name, port) {
206
222
  var _a, _b, _c;
207
223
  const { manifest, extensionManifest } = await getExtensionManifest(name);
208
224
  const codePath = extensionManifest === null || extensionManifest === void 0 ? void 0 : extensionManifest['codePath'];
@@ -219,7 +235,7 @@ async function getRawEditorExtension(name) {
219
235
  title: (_c = extensionManifest === null || extensionManifest === void 0 ? void 0 : extensionManifest['title']) !== null && _c !== void 0 ? _c : 'Local dev extension',
220
236
  products: products,
221
237
  scopes: extensionManifest === null || extensionManifest === void 0 ? void 0 : extensionManifest['scopes'],
222
- codeUrl: `http://localhost:9900/editorextension/${directory}/extension.js`,
238
+ codeUrl: `http://localhost:${port}/editorextension/${directory}/extension.js`,
223
239
  };
224
240
  }
225
241
  function getExtensionProducts(product, products) {
package/src/index.js CHANGED
@@ -62,6 +62,11 @@ class LucidSuiteExtensionCLI {
62
62
  action: 'store_true',
63
63
  help: argparse_1.SUPPRESS,
64
64
  });
65
+ testExtensionParser.add_argument('--anyport', {
66
+ default: false,
67
+ action: 'store_true',
68
+ help: argparse_1.SUPPRESS,
69
+ });
65
70
  const watchExtensionParser = subparsers.add_parser('watch-editor-extension', {
66
71
  help: 'Compile an editor extension in debug mode',
67
72
  });
@@ -151,7 +156,7 @@ class LucidSuiteExtensionCLI {
151
156
  break;
152
157
  case 'test-editor-extension':
153
158
  if ((0, package_1.currentlyInPackage)()) {
154
- await (0, editorextension_1.debugEditorExtension)(parsed['name'], parsed['quiet']);
159
+ await (0, editorextension_1.debugEditorExtension)(parsed['name'], parsed['quiet'], parsed['anyport']);
155
160
  }
156
161
  else {
157
162
  console.error('Not currently in a Lucid extension package folder');
package/src/package.js CHANGED
@@ -4,6 +4,7 @@ exports.writePackage = exports.updateAllExtensionSDK = exports.modifyManifest =
4
4
  const fsOld = require("fs");
5
5
  const fs = require("fs/promises");
6
6
  const JSZip = require("jszip");
7
+ const lucid_extension_sdk_1 = require("lucid-extension-sdk");
7
8
  const editorextension_1 = require("./editorextension");
8
9
  const filesystemutil_1 = require("./filesystemutil");
9
10
  const packagemanifest_1 = require("./packagemanifest");
@@ -19,6 +20,7 @@ function currentlyInPackage() {
19
20
  }
20
21
  exports.currentlyInPackage = currentlyInPackage;
21
22
  const allScopes = new Set(['DOWNLOAD', 'NETWORK', 'READ', 'SHOW_MODAL', 'CUSTOM_UI', 'WRITE']);
23
+ const uuidRegex = /^[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}$/i;
22
24
  async function modifyManifest(callback, manifestOverrideEnv) {
23
25
  const manifest = await (0, packagemanifest_1.readManifest)(manifestOverrideEnv);
24
26
  await callback(manifest);
@@ -43,6 +45,9 @@ async function writePackage(quiet = false, manifestOverrideEnv) {
43
45
  const zip = new JSZip();
44
46
  //Increment the patch number automatically on each build
45
47
  await modifyManifest(async (manifest) => {
48
+ if (manifest['id'] !== undefined && (!(0, lucid_extension_sdk_1.isString)(manifest['id']) || !uuidRegex.test(manifest['id']))) {
49
+ throw new Error('manifest.json: If "id" is specified, must be a UUID matching the package ID from the Lucid developer portal');
50
+ }
46
51
  const parts = manifest['version'].split('.');
47
52
  parts[parts.length - 1] = String(parseInt(parts[parts.length - 1], 10) + 1);
48
53
  manifest['version'] = parts.join('.');
@@ -10,14 +10,10 @@ var SettingType;
10
10
  SettingType["STRING"] = "string";
11
11
  })(SettingType = exports.SettingType || (exports.SettingType = {}));
12
12
  const versionRegex = /^\d+\.\d+\.\d+$/;
13
- const uuidRegex = /^[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}$/i;
14
13
  function validateManifestOrThrow(manifest) {
15
14
  if (!(0, lucid_extension_sdk_1.isObject)(manifest)) {
16
15
  throw new Error('manifest.json must be a valid JSON object');
17
16
  }
18
- if (manifest['id'] !== undefined && (!(0, lucid_extension_sdk_1.isString)(manifest['id']) || !uuidRegex.test(manifest['id']))) {
19
- throw new Error('manifest.json: If "id" is specified, must be a UUID matching the package ID from the Lucid developer portal');
20
- }
21
17
  if (!(0, lucid_extension_sdk_1.isString)(manifest['version']) || !versionRegex.test(manifest['version'])) {
22
18
  throw new Error('manifest.json: "version" must be a string in the format <major>.<minor>.<patch>');
23
19
  }
@@ -1,4 +1,4 @@
1
1
  export declare function createEmptyShapeLibrary(name: string): Promise<void>;
2
- export declare function getShapeListJson(name: string, packagePath: string): Promise<string>;
2
+ export declare function getShapeListJson(name: string, packagePath: string, port?: number): Promise<string>;
3
3
  export declare function buildShapeLibrary(name: string): Promise<void>;
4
- export declare function debugShapeLibraries(packagePath?: string): Promise<void>;
4
+ export declare function debugShapeLibraries(packagePath?: string, pickAnyPort?: boolean): Promise<void>;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.debugShapeLibraries = exports.buildShapeLibrary = exports.getShapeListJson = exports.createEmptyShapeLibrary = void 0;
4
4
  const express = require("express");
5
5
  const fs = require("fs/promises");
6
- const http = require("http");
7
6
  const JSZip = require("jszip");
8
7
  const path = require("path");
9
8
  const filesystemutil_1 = require("./filesystemutil");
@@ -37,7 +36,7 @@ const defaultNameMap = new Map([
37
36
  ]);
38
37
  //Produce JSON equivalent to the document service's
39
38
  // /shapeLibraries/:name/shapes endpoint
40
- async function getShapeListJson(name, packagePath) {
39
+ async function getShapeListJson(name, packagePath, port = 9901) {
41
40
  const packageManifest = await (0, packagemanifest_1.readManifest)('local', packagePath + '/');
42
41
  const rawManifest = await fs.readFile(packagePath + `/shapelibraries/${name}/library.manifest`);
43
42
  const manifest = hjson.parse(rawManifest.toString());
@@ -101,7 +100,7 @@ async function getShapeListJson(name, packagePath) {
101
100
  }
102
101
  else if (imageMap[key]['type'] == 'file') {
103
102
  finalImageMap[key] =
104
- 'http://localhost:9901/shapeLibraries/' +
103
+ `http://localhost:${port}/shapeLibraries/` +
105
104
  encodeURIComponent(name) +
106
105
  '/images/' +
107
106
  encodeURIComponent(imageMap[key]['path']);
@@ -121,8 +120,8 @@ async function getShapeListJson(name, packagePath) {
121
120
  'name': shapeManifest['name'],
122
121
  'order': index,
123
122
  'properties': JSON.stringify(properties),
124
- 'shapeLibrary': 'http://localhost:9901/shapeLibraries/' + encodeURIComponent(name),
125
- 'uri': `http://localhost:9901/shapeLibraries/${encodeURIComponent(name)}/shapes/${encodeURIComponent(shapeName)}`,
123
+ 'shapeLibrary': `http://localhost:${port}/shapeLibraries/` + encodeURIComponent(name),
124
+ 'uri': `http://localhost:${port}/shapeLibraries/${encodeURIComponent(name)}/shapes/${encodeURIComponent(shapeName)}`,
126
125
  };
127
126
  })));
128
127
  }
@@ -139,7 +138,12 @@ async function buildShapeLibrary(name) {
139
138
  }
140
139
  }
141
140
  else {
142
- zip.file(source.replace(`shapelibraries/${name}/`, ''), await fs.readFile(source));
141
+ /**
142
+ * On Windows machines '\' is used as the file separator. To ensure that we correctly zip files on Windows
143
+ * machines we replace '\' with '/'.
144
+ */
145
+ const normalizedSource = path.sep === '\\' ? source.replace(/\\/g, '/') : source;
146
+ zip.file(normalizedSource.replace(`shapelibraries/${name}/`, ''), await fs.readFile(source));
143
147
  }
144
148
  };
145
149
  await addToZip(`shapelibraries/${name}`);
@@ -148,7 +152,8 @@ async function buildShapeLibrary(name) {
148
152
  await fs.writeFile(`shapelibraries/${name}.lcsz`, zipBytes);
149
153
  }
150
154
  exports.buildShapeLibrary = buildShapeLibrary;
151
- async function debugShapeLibraries(packagePath = '.') {
155
+ async function debugShapeLibraries(packagePath = '.', pickAnyPort = false) {
156
+ let port = 9901;
152
157
  const app = express();
153
158
  app.use((req, res, next) => {
154
159
  res.header('Access-Control-Allow-Origin', '*');
@@ -167,7 +172,7 @@ async function debugShapeLibraries(packagePath = '.') {
167
172
  const libraryDefinitionContent = await fs.readFile(packagePath + '/shapelibraries/' + libraryManifest['name'] + '/library.manifest');
168
173
  const libraryDefinition = JSON.parse(libraryDefinitionContent.toString());
169
174
  return {
170
- 'uri': 'http://localhost:9901/shapeLibraries/' +
175
+ 'uri': `http://localhost:${port}/shapeLibraries/` +
171
176
  encodeURIComponent(libraryManifest['name']) +
172
177
  '?version=' +
173
178
  shapeLibraryVersion,
@@ -176,7 +181,7 @@ async function debugShapeLibraries(packagePath = '.') {
176
181
  'name': libraryDefinition['name'],
177
182
  'size': 0,
178
183
  'accountId': 0,
179
- 'shapes': 'http://localhost:9901/shapeLibraries/' +
184
+ 'shapes': `http://localhost:${port}/shapeLibraries/` +
180
185
  encodeURIComponent(libraryManifest['name']) +
181
186
  '/shapes',
182
187
  'shared': false,
@@ -188,7 +193,7 @@ async function debugShapeLibraries(packagePath = '.') {
188
193
  });
189
194
  app.get('/shapeLibraries/:libraryName/shapes', async (req, res) => {
190
195
  //Find all the shapes in the given shape library, and produce JSON for the client
191
- res.send(await getShapeListJson(req.params.libraryName, packagePath));
196
+ res.send(await getShapeListJson(req.params.libraryName, packagePath, port));
192
197
  });
193
198
  app.get('/shapeLibraries/:libraryName/images/:image', async (req, res) => {
194
199
  const oldcwd = process.cwd();
@@ -200,21 +205,36 @@ async function debugShapeLibraries(packagePath = '.') {
200
205
  process.chdir(oldcwd);
201
206
  });
202
207
  app.get('/shapeLibraries/');
203
- const server = http.createServer(app);
204
- //Watch for any shape library changes, and inform watchers that they need to refresh them.
205
- const wss = new ws.Server({ server, path: '/shapeLibraries/changes' });
206
- const sockets = [];
207
- wss.on('connection', (ws) => {
208
- sockets.push(ws);
209
- });
210
- chokidar.watch(packagePath + '/shapelibraries').on('all', () => {
211
- shapeLibraryVersion = Date.now();
212
- for (const socket of sockets) {
213
- socket.send('refresh');
214
- }
215
- });
216
- server.listen(9901, 'localhost', () => {
217
- console.log('Listening at http://localhost:9901/shapeLibraries');
218
- });
208
+ const listen = () => {
209
+ const server = app.listen(port, 'localhost', () => {
210
+ console.log('Listening at http://localhost:' + port + '/shapeLibraries');
211
+ //Watch for any shape library changes, and inform watchers that they need to refresh them.
212
+ const wss = new ws.Server({ server, path: '/shapeLibraries/changes' });
213
+ const sockets = [];
214
+ wss.on('connection', (ws) => {
215
+ sockets.push(ws);
216
+ });
217
+ chokidar.watch(packagePath + '/shapelibraries').on('all', () => {
218
+ shapeLibraryVersion = Date.now();
219
+ for (const socket of sockets) {
220
+ socket.send('refresh');
221
+ }
222
+ });
223
+ });
224
+ server.on('error', (err) => {
225
+ if (err.code === 'EADDRINUSE') {
226
+ if (pickAnyPort && port < 15000) {
227
+ port++;
228
+ listen();
229
+ }
230
+ else {
231
+ console.error('Failed to listen for shapes');
232
+ console.error(err);
233
+ process.exit(1);
234
+ }
235
+ }
236
+ });
237
+ };
238
+ listen();
219
239
  }
220
240
  exports.debugShapeLibraries = debugShapeLibraries;