@kapeta/local-cluster-service 0.70.1 → 0.70.3

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/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.70.3](https://github.com/kapetacom/local-cluster-service/compare/v0.70.2...v0.70.3) (2024-09-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * better dedupe of refs ([48f676e](https://github.com/kapetacom/local-cluster-service/commit/48f676e0f6780580c2b77cdb8e6f3336f6633e77))
7
+ * match full pattern in lazy check ([5b5e9d7](https://github.com/kapetacom/local-cluster-service/commit/5b5e9d7cfaf3e6e9b3eacf378e90362e99433d86))
8
+
9
+ ## [0.70.2](https://github.com/kapetacom/local-cluster-service/compare/v0.70.1...v0.70.2) (2024-09-09)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * Wait for last ([#237](https://github.com/kapetacom/local-cluster-service/issues/237)) ([071bf9e](https://github.com/kapetacom/local-cluster-service/commit/071bf9ea19cb5d5393d7f895c2131311b38325b6))
15
+
1
16
  ## [0.70.1](https://github.com/kapetacom/local-cluster-service/compare/v0.70.0...v0.70.1) (2024-09-09)
2
17
 
3
18
 
@@ -44,6 +44,7 @@ export declare class PageQueue extends EventEmitter {
44
44
  private addPageGenerator;
45
45
  cancel(): void;
46
46
  wait(): Promise<void>;
47
+ get length(): number;
47
48
  private addImagePrompt;
48
49
  }
49
50
  export declare class PageGenerator extends EventEmitter {
@@ -104,7 +104,7 @@ class PageQueue extends node_events_1.EventEmitter {
104
104
  generator.on('page_refs', async ({ event, references }) => {
105
105
  try {
106
106
  const matchesExistingPages = (url) => {
107
- return [...this.pages.keys()].some((path) => new RegExp(path.replaceAll('/*', '/[^/]+')).test(url));
107
+ return [...this.pages.keys()].some((path) => new RegExp(`^${path.replaceAll('/*', '/[^/]+')}$`).test(url.replace(/\?.*$/gi, '')));
108
108
  };
109
109
  const initialPrompts = [];
110
110
  const resourcePromises = references.map(async (reference) => {
@@ -125,16 +125,16 @@ class PageQueue extends node_events_1.EventEmitter {
125
125
  case 'javascript':
126
126
  //console.log('Ignoring reference', reference);
127
127
  break;
128
- case 'html':
129
- //console.log('Adding page generator for', reference);
130
- if (matchesExistingPages(reference.url)) {
128
+ case 'html': {
129
+ const normalizedPath = (0, page_utils_1.normalizePath)(reference.url);
130
+ if (matchesExistingPages(normalizedPath)) {
131
131
  break;
132
132
  }
133
- this.pages.set(reference.url, reference.description);
133
+ this.pages.set(normalizedPath, reference.description);
134
134
  initialPrompts.push({
135
135
  name: reference.name,
136
136
  title: reference.title,
137
- path: reference.url,
137
+ path: normalizedPath,
138
138
  method: 'GET',
139
139
  storage_prefix: this.systemId + '_',
140
140
  prompt: `Implement a page for ${reference.name} at ${reference.url} with the following description: ${reference.description}.\n` +
@@ -145,6 +145,7 @@ class PageQueue extends node_events_1.EventEmitter {
145
145
  theme: this.theme,
146
146
  });
147
147
  break;
148
+ }
148
149
  }
149
150
  });
150
151
  // Wait for resources to be generated
@@ -186,8 +187,13 @@ class PageQueue extends node_events_1.EventEmitter {
186
187
  this.eventQueue.cancel();
187
188
  }
188
189
  async wait() {
189
- await this.eventQueue.wait();
190
- await this.queue.wait();
190
+ while (!this.eventQueue.empty || !this.queue.empty) {
191
+ await this.eventQueue.wait();
192
+ await this.queue.wait();
193
+ }
194
+ }
195
+ get length() {
196
+ return this.queue.length + this.eventQueue.length;
191
197
  }
192
198
  async addImagePrompt(prompt) {
193
199
  if (this.images.has(prompt.url)) {
@@ -20,4 +20,6 @@ export declare class PromiseQueue {
20
20
  private next;
21
21
  cancel(): void;
22
22
  wait(): Promise<void>;
23
+ get empty(): boolean;
24
+ get length(): number;
23
25
  }
@@ -83,8 +83,15 @@ class PromiseQueue {
83
83
  }
84
84
  async wait() {
85
85
  while (this.queue.length > 0 || this.active.length > 0) {
86
- await Promise.all(this.active);
86
+ await Promise.allSettled(this.active);
87
+ this.next();
87
88
  }
88
89
  }
90
+ get empty() {
91
+ return this.queue.length === 0 && this.active.length === 0;
92
+ }
93
+ get length() {
94
+ return this.queue.length + this.active.length;
95
+ }
89
96
  }
90
97
  exports.PromiseQueue = PromiseQueue;
@@ -7,6 +7,7 @@ import { Response } from 'express';
7
7
  import { ConversationItem } from './stream';
8
8
  import { ImagePrompt } from './PageGenerator';
9
9
  export declare const SystemIdHeader = "System-Id";
10
+ export declare function normalizePath(path: string): string;
10
11
  export declare function writePageToDisk(systemId: string, event: StormEventPage): Promise<{
11
12
  path: string;
12
13
  }>;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.getSystemBaseDir = exports.hasPageOnDisk = exports.writeImageToDisk = exports.writeAssetToDisk = exports.writePageToDisk = exports.SystemIdHeader = void 0;
6
+ exports.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.getSystemBaseDir = exports.hasPageOnDisk = exports.writeImageToDisk = exports.writeAssetToDisk = exports.writePageToDisk = exports.normalizePath = exports.SystemIdHeader = void 0;
7
7
  const node_os_1 = __importDefault(require("node:os"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
@@ -14,6 +14,7 @@ function normalizePath(path) {
14
14
  .replace(/:[a-z][a-z_]*\b/gi, '*')
15
15
  .replace(/\{[a-z-.]+}/gi, '*');
16
16
  }
17
+ exports.normalizePath = normalizePath;
17
18
  async function writePageToDisk(systemId, event) {
18
19
  const baseDir = getSystemBaseDir(systemId);
19
20
  const filePath = getFilePath(event.payload.method);
@@ -420,7 +420,9 @@ router.post('/ui/edit', async (req, res) => {
420
420
  const promises = [];
421
421
  queue.on('page', (data) => {
422
422
  if (systemId) {
423
- promises.push(sendPageEvent(systemId, data, res));
423
+ const promise = sendPageEvent(systemId, data, res);
424
+ promises.push(promise);
425
+ return promise;
424
426
  }
425
427
  });
426
428
  queue.on('event', (data) => {
@@ -44,6 +44,7 @@ export declare class PageQueue extends EventEmitter {
44
44
  private addPageGenerator;
45
45
  cancel(): void;
46
46
  wait(): Promise<void>;
47
+ get length(): number;
47
48
  private addImagePrompt;
48
49
  }
49
50
  export declare class PageGenerator extends EventEmitter {
@@ -104,7 +104,7 @@ class PageQueue extends node_events_1.EventEmitter {
104
104
  generator.on('page_refs', async ({ event, references }) => {
105
105
  try {
106
106
  const matchesExistingPages = (url) => {
107
- return [...this.pages.keys()].some((path) => new RegExp(path.replaceAll('/*', '/[^/]+')).test(url));
107
+ return [...this.pages.keys()].some((path) => new RegExp(`^${path.replaceAll('/*', '/[^/]+')}$`).test(url.replace(/\?.*$/gi, '')));
108
108
  };
109
109
  const initialPrompts = [];
110
110
  const resourcePromises = references.map(async (reference) => {
@@ -125,16 +125,16 @@ class PageQueue extends node_events_1.EventEmitter {
125
125
  case 'javascript':
126
126
  //console.log('Ignoring reference', reference);
127
127
  break;
128
- case 'html':
129
- //console.log('Adding page generator for', reference);
130
- if (matchesExistingPages(reference.url)) {
128
+ case 'html': {
129
+ const normalizedPath = (0, page_utils_1.normalizePath)(reference.url);
130
+ if (matchesExistingPages(normalizedPath)) {
131
131
  break;
132
132
  }
133
- this.pages.set(reference.url, reference.description);
133
+ this.pages.set(normalizedPath, reference.description);
134
134
  initialPrompts.push({
135
135
  name: reference.name,
136
136
  title: reference.title,
137
- path: reference.url,
137
+ path: normalizedPath,
138
138
  method: 'GET',
139
139
  storage_prefix: this.systemId + '_',
140
140
  prompt: `Implement a page for ${reference.name} at ${reference.url} with the following description: ${reference.description}.\n` +
@@ -145,6 +145,7 @@ class PageQueue extends node_events_1.EventEmitter {
145
145
  theme: this.theme,
146
146
  });
147
147
  break;
148
+ }
148
149
  }
149
150
  });
150
151
  // Wait for resources to be generated
@@ -186,8 +187,13 @@ class PageQueue extends node_events_1.EventEmitter {
186
187
  this.eventQueue.cancel();
187
188
  }
188
189
  async wait() {
189
- await this.eventQueue.wait();
190
- await this.queue.wait();
190
+ while (!this.eventQueue.empty || !this.queue.empty) {
191
+ await this.eventQueue.wait();
192
+ await this.queue.wait();
193
+ }
194
+ }
195
+ get length() {
196
+ return this.queue.length + this.eventQueue.length;
191
197
  }
192
198
  async addImagePrompt(prompt) {
193
199
  if (this.images.has(prompt.url)) {
@@ -20,4 +20,6 @@ export declare class PromiseQueue {
20
20
  private next;
21
21
  cancel(): void;
22
22
  wait(): Promise<void>;
23
+ get empty(): boolean;
24
+ get length(): number;
23
25
  }
@@ -83,8 +83,15 @@ class PromiseQueue {
83
83
  }
84
84
  async wait() {
85
85
  while (this.queue.length > 0 || this.active.length > 0) {
86
- await Promise.all(this.active);
86
+ await Promise.allSettled(this.active);
87
+ this.next();
87
88
  }
88
89
  }
90
+ get empty() {
91
+ return this.queue.length === 0 && this.active.length === 0;
92
+ }
93
+ get length() {
94
+ return this.queue.length + this.active.length;
95
+ }
89
96
  }
90
97
  exports.PromiseQueue = PromiseQueue;
@@ -7,6 +7,7 @@ import { Response } from 'express';
7
7
  import { ConversationItem } from './stream';
8
8
  import { ImagePrompt } from './PageGenerator';
9
9
  export declare const SystemIdHeader = "System-Id";
10
+ export declare function normalizePath(path: string): string;
10
11
  export declare function writePageToDisk(systemId: string, event: StormEventPage): Promise<{
11
12
  path: string;
12
13
  }>;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.getSystemBaseDir = exports.hasPageOnDisk = exports.writeImageToDisk = exports.writeAssetToDisk = exports.writePageToDisk = exports.SystemIdHeader = void 0;
6
+ exports.writeConversationToFile = exports.readConversationFromFile = exports.readPageFromDisk = exports.readPageFromDiskAsString = exports.resolveReadPath = exports.getSystemBaseDir = exports.hasPageOnDisk = exports.writeImageToDisk = exports.writeAssetToDisk = exports.writePageToDisk = exports.normalizePath = exports.SystemIdHeader = void 0;
7
7
  const node_os_1 = __importDefault(require("node:os"));
8
8
  const path_1 = __importDefault(require("path"));
9
9
  const fs_extra_1 = __importDefault(require("fs-extra"));
@@ -14,6 +14,7 @@ function normalizePath(path) {
14
14
  .replace(/:[a-z][a-z_]*\b/gi, '*')
15
15
  .replace(/\{[a-z-.]+}/gi, '*');
16
16
  }
17
+ exports.normalizePath = normalizePath;
17
18
  async function writePageToDisk(systemId, event) {
18
19
  const baseDir = getSystemBaseDir(systemId);
19
20
  const filePath = getFilePath(event.payload.method);
@@ -420,7 +420,9 @@ router.post('/ui/edit', async (req, res) => {
420
420
  const promises = [];
421
421
  queue.on('page', (data) => {
422
422
  if (systemId) {
423
- promises.push(sendPageEvent(systemId, data, res));
423
+ const promise = sendPageEvent(systemId, data, res);
424
+ promises.push(promise);
425
+ return promise;
424
426
  }
425
427
  });
426
428
  queue.on('event', (data) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kapeta/local-cluster-service",
3
- "version": "0.70.1",
3
+ "version": "0.70.3",
4
4
  "description": "Manages configuration, ports and service discovery for locally running Kapeta systems",
5
5
  "type": "commonjs",
6
6
  "exports": {
@@ -8,7 +8,7 @@ import { stormClient, UIPagePrompt } from './stormClient';
8
8
  import { ReferenceClassification, StormEvent, StormEventPage, StormImage, UIShell } from './events';
9
9
  import { EventEmitter } from 'node:events';
10
10
  import { PromiseQueue } from './PromiseQueue';
11
- import { hasPageOnDisk } from './page-utils';
11
+ import { hasPageOnDisk, normalizePath } from './page-utils';
12
12
 
13
13
  export interface ImagePrompt {
14
14
  name: string;
@@ -137,7 +137,9 @@ export class PageQueue extends EventEmitter {
137
137
  generator.on('page_refs', async ({ event, references }) => {
138
138
  try {
139
139
  const matchesExistingPages = (url: string) => {
140
- return [...this.pages.keys()].some((path) => new RegExp(path.replaceAll('/*', '/[^/]+')).test(url));
140
+ return [...this.pages.keys()].some((path) =>
141
+ new RegExp(`^${path.replaceAll('/*', '/[^/]+')}$`).test(url.replace(/\?.*$/gi, ''))
142
+ );
141
143
  };
142
144
  const initialPrompts: InitialPrompt[] = [];
143
145
  const resourcePromises = references.map(async (reference) => {
@@ -161,17 +163,17 @@ export class PageQueue extends EventEmitter {
161
163
  case 'javascript':
162
164
  //console.log('Ignoring reference', reference);
163
165
  break;
164
- case 'html':
165
- //console.log('Adding page generator for', reference);
166
- if (matchesExistingPages(reference.url)) {
166
+ case 'html': {
167
+ const normalizedPath = normalizePath(reference.url);
168
+ if (matchesExistingPages(normalizedPath)) {
167
169
  break;
168
170
  }
169
- this.pages.set(reference.url, reference.description);
171
+ this.pages.set(normalizedPath, reference.description);
170
172
 
171
173
  initialPrompts.push({
172
174
  name: reference.name,
173
175
  title: reference.title,
174
- path: reference.url,
176
+ path: normalizedPath,
175
177
  method: 'GET',
176
178
  storage_prefix: this.systemId + '_',
177
179
  prompt:
@@ -183,6 +185,7 @@ export class PageQueue extends EventEmitter {
183
185
  theme: this.theme,
184
186
  });
185
187
  break;
188
+ }
186
189
  }
187
190
  });
188
191
 
@@ -227,8 +230,14 @@ export class PageQueue extends EventEmitter {
227
230
  }
228
231
 
229
232
  public async wait() {
230
- await this.eventQueue.wait();
231
- await this.queue.wait();
233
+ while (!this.eventQueue.empty || !this.queue.empty) {
234
+ await this.eventQueue.wait();
235
+ await this.queue.wait();
236
+ }
237
+ }
238
+
239
+ public get length() {
240
+ return this.queue.length + this.eventQueue.length;
232
241
  }
233
242
 
234
243
  private async addImagePrompt(prompt: ImagePrompt) {
@@ -114,7 +114,16 @@ export class PromiseQueue {
114
114
 
115
115
  public async wait() {
116
116
  while (this.queue.length > 0 || this.active.length > 0) {
117
- await Promise.all(this.active);
117
+ await Promise.allSettled(this.active);
118
+ this.next();
118
119
  }
119
120
  }
121
+
122
+ public get empty() {
123
+ return this.queue.length === 0 && this.active.length === 0;
124
+ }
125
+
126
+ public get length() {
127
+ return this.queue.length + this.active.length;
128
+ }
120
129
  }
@@ -15,7 +15,7 @@ import { ImagePrompt } from './PageGenerator';
15
15
 
16
16
  export const SystemIdHeader = 'System-Id';
17
17
 
18
- function normalizePath(path: string) {
18
+ export function normalizePath(path: string) {
19
19
  return path
20
20
  .replace(/\?.*$/gi, '')
21
21
  .replace(/:[a-z][a-z_]*\b/gi, '*')
@@ -519,7 +519,9 @@ router.post('/ui/edit', async (req: KapetaBodyRequest, res: Response) => {
519
519
 
520
520
  queue.on('page', (data) => {
521
521
  if (systemId) {
522
- promises.push(sendPageEvent(systemId, data, res));
522
+ const promise = sendPageEvent(systemId, data, res);
523
+ promises.push(promise);
524
+ return promise;
523
525
  }
524
526
  });
525
527