@superblocksteam/cli 2.0.6-next.16 → 2.0.6-next.18

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 CHANGED
@@ -14,7 +14,7 @@ $ npm install -g @superblocksteam/cli
14
14
  $ superblocks COMMAND
15
15
  running command...
16
16
  $ superblocks (--version)
17
- @superblocksteam/cli/2.0.6-next.16 linux-x64 node-v20.19.0
17
+ @superblocksteam/cli/2.0.6-next.18 linux-x64 node-v20.19.0
18
18
  $ superblocks --help [COMMAND]
19
19
  USAGE
20
20
  $ superblocks COMMAND
package/dist/index.js CHANGED
@@ -413073,7 +413073,7 @@ init_cjs_shims();
413073
413073
  var templates = {
413074
413074
  "api-builder-to-yaml": {
413075
413075
  "bootstrap.mjs": 'import { register } from "node:module";\nimport { pathToFileURL } from "node:url";\n\nregister("./shim-loader.mjs", pathToFileURL("./"));\n',
413076
- "package.json": '{\n "type": "module",\n "dependencies": {\n "acorn": "^8.14.0",\n "prettier": "^3.5.3",\n "yaml": "^2.7.1"\n },\n "devDependencies": {\n "@types/node": "^22.15.18",\n "@typescript-eslint/parser": "^8.17.0",\n "eslint": "^9.26.0",\n "typescript": "^5.8.3",\n "vitest": "^3.0.9"\n }\n}',
413076
+ "package.json": '{\n "type": "module",\n "dependencies": {\n "acorn": "^8.14.0",\n "prettier": "^3.5.3",\n "yaml": "^2.7.1"\n },\n "devDependencies": {\n "@types/node": "^22.15.18",\n "@typescript-eslint/parser": "^8.17.0",\n "eslint": "^9.26.0",\n "typescript": "^5.8.3",\n "vitest": "^3.2.0"\n }\n}\n',
413077
413077
  "shim-loader.mjs": 'import path from "path";\nimport { pathToFileURL } from "url";\n\nconst overrideMap = {\n "@superblocksteam/library": "./dist/superblocks-library-shim/index.js",\n};\n\nexport async function resolve(specifier, context, nextResolve) {\n if (overrideMap[specifier]) {\n const fullPath = path.resolve(overrideMap[specifier]);\n return {\n shortCircuit: true,\n url: pathToFileURL(fullPath).href,\n };\n }\n\n return nextResolve(specifier, context);\n}\n',
413078
413078
  "src/do-eval-to-sdk.ts": 'import fs from "fs";\nimport path from "path";\nimport { fileURLToPath } from "url";\n\n// finds all JavaScript files in the `dist/apis-to-transform` directory,\n// imports each module, converts its JSON representation to SDK,\n// and outputs a JSON map with filenames as keys and SDK content as values.\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n const apisDir = path.resolve(__dirname, "./to-sdk");\n\n const files = fs.readdirSync(apisDir);\n\n const jsFiles = files.filter(\n (file) => file.endsWith(".js") && file !== "__template__.js",\n );\n\n const results: Record<string, string> = {};\n\n for (const jsFile of jsFiles) {\n const filePath = path.join(apisDir, jsFile);\n const absolutePath = path.resolve(filePath);\n\n try {\n const fileUrl = new URL(`file://${absolutePath}`);\n const module = await import(fileUrl.href);\n\n const defaultExport = module.default;\n\n if (defaultExport && typeof defaultExport.toSDK === "function") {\n const sdkData = await defaultExport.toSDK();\n\n results[jsFile] = sdkData;\n } else {\n console.warn(`${jsFile}: Default export doesn\'t have a toSDK method`);\n }\n } catch (error) {\n console.error(`Error processing ${jsFile}:`, error);\n }\n }\n\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error("Error:", error);\n process.exit(1);\n});\n',
413079
413079
  "src/do-eval-to-yaml.ts": 'import fs from "fs";\nimport path from "path";\nimport { fileURLToPath } from "url";\nimport yaml from "yaml";\n\n// finds all JavaScript files in the `dist/apis-to-transform` directory,\n// imports each module, converts its JSON representation to YAML,\n// and outputs a JSON map with filenames as keys and YAML content as values.\n\nasync function main() {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n const apisDir = path.resolve(__dirname, "./to-yaml");\n\n const files = fs.readdirSync(apisDir);\n\n const jsFiles = files.filter((file) => file.endsWith(".js"));\n\n const results: Record<string, string> = {};\n\n for (const jsFile of jsFiles) {\n const filePath = path.join(apisDir, jsFile);\n const absolutePath = path.resolve(filePath);\n\n try {\n const fileUrl = new URL(`file://${absolutePath}`);\n const module = await import(fileUrl.href);\n\n const defaultExport = module.default;\n\n if (defaultExport && typeof defaultExport.toJSON === "function") {\n const jsonData = await defaultExport.toJSON();\n\n const yamlContent = yaml.stringify(jsonData);\n\n results[jsFile] = yamlContent;\n } else {\n console.warn(`${jsFile}: Default export doesn\'t have a toJSON method`);\n }\n } catch (error) {\n console.error(`Error processing ${jsFile}:`, error);\n }\n }\n\n console.log(JSON.stringify(results, null, 2));\n}\n\nmain().catch((error) => {\n console.error("Error:", error);\n process.exit(1);\n});\n',
@@ -413290,6 +413290,7 @@ var Paths;
413290
413290
  })(Paths || (Paths = {}));
413291
413291
  var LOG_SYSTEM_PROMPT = false;
413292
413292
  var SAVE_LLM_GENERATION_STEPS = false;
413293
+ var SAVE_RAW_LLM_RESPONSE = false;
413293
413294
 
413294
413295
  // ../../../vite-plugin-file-sync/dist/ai-service/integrations/from-prompt-context.js
413295
413296
  init_cjs_shims();
@@ -417871,6 +417872,7 @@ Address the errors and return the fixed code.`;
417871
417872
  switch (event.type) {
417872
417873
  case USER_SENT_PROMPT: {
417873
417874
  const { request, peer } = event;
417875
+ params.signals.emit("generationStarted");
417874
417876
  const initialElementIds = clark.context.initialElementIds ?? Object.keys(params.sourceTrackerInterface.getElementToFilePathMap() ?? {});
417875
417877
  clark.updateContext((context2) => ({
417876
417878
  ...context2,
@@ -424480,6 +424482,7 @@ var doLLMGenerating = (clark, { anthropicProvider, appShell, artifactProcessor,
424480
424482
  let artifactChunk = null;
424481
424483
  let stepId = null;
424482
424484
  const flushedAfterArtifacts = [];
424485
+ let rawLLMResponse = "";
424483
424486
  const resultBuffer = new BoltResultBuffer({
424484
424487
  onTypeChange: async (type2) => {
424485
424488
  switch (type2) {
@@ -424589,6 +424592,9 @@ var doLLMGenerating = (clark, { anthropicProvider, appShell, artifactProcessor,
424589
424592
  for await (const chunk of fullStream) {
424590
424593
  switch (chunk.type) {
424591
424594
  case "text-delta":
424595
+ if (SAVE_LLM_GENERATION_STEPS) {
424596
+ rawLLMResponse += chunk.textDelta;
424597
+ }
424592
424598
  resultBuffer.add(chunk.textDelta);
424593
424599
  resultBuffer.maybeFlush();
424594
424600
  break;
@@ -424659,6 +424665,19 @@ var doLLMGenerating = (clark, { anthropicProvider, appShell, artifactProcessor,
424659
424665
  }
424660
424666
  }
424661
424667
  resultBuffer.maybeFlush(true);
424668
+ if (SAVE_RAW_LLM_RESPONSE && rawLLMResponse.length > 0) {
424669
+ try {
424670
+ logger3.debug(`[ai-service] Raw LLM response length: ${rawLLMResponse.length} characters`);
424671
+ void appShell.saveGeneratedArtifact({
424672
+ type: "file",
424673
+ filePath: "raw-llm-response.txt",
424674
+ content: rawLLMResponse
424675
+ }, stepId ?? "unknown-step-id", clark.context.runTimestamp ?? "unknown-run-timestamp");
424676
+ logger3.info(`[ai-service] Raw LLM response saved to debug folder`);
424677
+ } catch (error) {
424678
+ logger3.error("[ai-service] Failed to save raw LLM response:", getErrorMeta(error));
424679
+ }
424680
+ }
424662
424681
  }
424663
424682
  }
424664
424683
  };
@@ -431924,6 +431943,9 @@ function getPageFolder(rootPath, pageName) {
431924
431943
  function getPageFilePath(rootPath, pageName) {
431925
431944
  return path21.join(getPageFolder(rootPath, pageName), "index.tsx");
431926
431945
  }
431946
+ function isPageFilePath(filePath) {
431947
+ return /pages\/.*\/index\.tsx/.test(filePath);
431948
+ }
431927
431949
 
431928
431950
  // ../../../vite-plugin-file-sync/dist/traverse.js
431929
431951
  init_cjs_shims();
@@ -433797,6 +433819,87 @@ function addLegacyCustomComponentVariables(path55, tracker) {
433797
433819
  });
433798
433820
  }
433799
433821
 
433822
+ // ../../../vite-plugin-file-sync/dist/operations/operation-processor.js
433823
+ init_cjs_shims();
433824
+ var OperationProcessor = class {
433825
+ config;
433826
+ operationQueue;
433827
+ pendingOperations = [];
433828
+ batchTimer = null;
433829
+ _enabled = true;
433830
+ constructor(config2 = {}) {
433831
+ this.config = {
433832
+ batchWindowMs: 50,
433833
+ maxBatchSize: 100,
433834
+ ...config2
433835
+ };
433836
+ this.operationQueue = new OperationQueue();
433837
+ }
433838
+ async addOperation(operation) {
433839
+ const timestamp2 = Date.now();
433840
+ const id2 = `operation-${timestamp2}-${Math.random()}`;
433841
+ const fullOperation = {
433842
+ ...operation,
433843
+ id: id2,
433844
+ timestamp: timestamp2
433845
+ };
433846
+ if (!this._enabled || fullOperation.priority) {
433847
+ return this.processOperations([fullOperation]);
433848
+ }
433849
+ this.pendingOperations.push(fullOperation);
433850
+ if (this.pendingOperations.length >= this.config.maxBatchSize) {
433851
+ return this.flush();
433852
+ }
433853
+ this.resetBatchTimer();
433854
+ }
433855
+ async flush() {
433856
+ if (this.pendingOperations.length === 0) {
433857
+ return;
433858
+ }
433859
+ const operations = [...this.pendingOperations];
433860
+ this.pendingOperations = [];
433861
+ this.clearBatchTimer();
433862
+ return this.operationQueue.enqueue(() => this.processOperations(operations));
433863
+ }
433864
+ disable() {
433865
+ this.setEnabled(false);
433866
+ }
433867
+ enable() {
433868
+ this.setEnabled(true);
433869
+ }
433870
+ setEnabled(enabled) {
433871
+ const wasEnabled = this._enabled;
433872
+ this._enabled = enabled;
433873
+ if (!enabled && wasEnabled && this.pendingOperations.length > 0) {
433874
+ this.flush().catch((error) => {
433875
+ console.error("Error flushing operations on priority mode enable:", error);
433876
+ });
433877
+ }
433878
+ }
433879
+ async processOperations(operations) {
433880
+ if (operations.length === 0) {
433881
+ return;
433882
+ }
433883
+ for (const operation of operations) {
433884
+ await operation.execute();
433885
+ }
433886
+ }
433887
+ resetBatchTimer() {
433888
+ this.clearBatchTimer();
433889
+ this.batchTimer = setTimeout(() => {
433890
+ this.flush().catch((error) => {
433891
+ console.error("Error flushing operations on timer:", error);
433892
+ });
433893
+ }, this.config.batchWindowMs);
433894
+ }
433895
+ clearBatchTimer() {
433896
+ if (this.batchTimer) {
433897
+ clearTimeout(this.batchTimer);
433898
+ this.batchTimer = null;
433899
+ }
433900
+ }
433901
+ };
433902
+
433800
433903
  // ../../../vite-plugin-file-sync/dist/parsing/bindings.js
433801
433904
  init_cjs_shims();
433802
433905
  var localBindingKinds = /* @__PURE__ */ new Set(["local", "param", "var", "const", "let"]);
@@ -435896,6 +435999,7 @@ var SourceTracker = class {
435896
435999
  const extension = path26.extname(fileName);
435897
436000
  if (extension !== ".ts" && extension !== ".tsx")
435898
436001
  return;
436002
+ const existingFile = fileName in this.fileToMeta;
435899
436003
  try {
435900
436004
  const astMap = this.parseJsxFromEntrypoint({
435901
436005
  files: [{ fileName, code: fileContents }]
@@ -435918,7 +436022,19 @@ var SourceTracker = class {
435918
436022
  delete this.elementToLocation[key2];
435919
436023
  delete this.elementToFilePath[key2];
435920
436024
  });
435921
- const changedFiles = this.sbScopeManager.resetScope(fileName);
436025
+ let changedFiles = [];
436026
+ if (existingFile) {
436027
+ changedFiles = this.sbScopeManager.resetScope(fileName);
436028
+ } else {
436029
+ this.sbScopeManager.parseScopes({
436030
+ [fileName]: {
436031
+ code: fileContents,
436032
+ ast,
436033
+ imports: extractImportsFromAst(ast)
436034
+ }
436035
+ });
436036
+ changedFiles.push(fileName);
436037
+ }
435922
436038
  if (!fileName.endsWith(SCOPE_FILE)) {
435923
436039
  const { idMap } = supplementElementIds({
435924
436040
  fileName,
@@ -436044,7 +436160,7 @@ var SourceTracker = class {
436044
436160
  });
436045
436161
  return scopeDefinition.id;
436046
436162
  };
436047
- deleteApi = async ({ pageName, apiName }) => {
436163
+ deleteApi = ({ pageName, apiName }) => {
436048
436164
  const { scopeDefinition, filePath: scopeFilePath } = this.sbScopeManager.getScopeDefinitionAndFilePathByNameOrId({
436049
436165
  identifier: pageName,
436050
436166
  type: "name"
@@ -436076,24 +436192,24 @@ var SourceTracker = class {
436076
436192
  });
436077
436193
  return scopeDefinition.id;
436078
436194
  };
436079
- addEntity = async ({ scopeId, entity }) => {
436195
+ addEntity = ({ scopeId, entity }) => {
436080
436196
  const changedFiles = this.sbScopeManager.addScopeEntity(scopeId, entity);
436081
436197
  changedFiles.forEach((file) => {
436082
436198
  this.changedFiles.add(file);
436083
436199
  });
436084
436200
  };
436085
- updateEntity = async (payload) => {
436201
+ updateEntity = (payload) => {
436086
436202
  const changedFile = this.sbScopeManager.updateScopeEntity(payload);
436087
436203
  this.changedFiles.add(changedFile);
436088
436204
  };
436089
- deleteEntity = async ({ entityId }) => {
436205
+ deleteEntity = ({ entityId }) => {
436090
436206
  const { changedFiles, deletedEntitiesNames } = this.sbScopeManager.deleteScopeEntity(entityId);
436091
436207
  changedFiles.forEach((file) => {
436092
436208
  this.changedFiles.add(file);
436093
436209
  });
436094
436210
  return deletedEntitiesNames[0];
436095
436211
  };
436096
- renameEntity = async ({ entityId, oldName, newName, scopeName }) => {
436212
+ renameEntity = ({ entityId, oldName, newName, scopeName }) => {
436097
436213
  const { changedFiles, scopeFile } = this.sbScopeManager.renameScopeEntity({
436098
436214
  entityId,
436099
436215
  newName,
@@ -436124,7 +436240,7 @@ var SourceTracker = class {
436124
436240
  }
436125
436241
  };
436126
436242
  // THEMING
436127
- updateTheme = async ({ themeFilePath, theme }) => {
436243
+ updateTheme = ({ themeFilePath, theme }) => {
436128
436244
  const ast = this.getCurrentFiles()[themeFilePath]?.ast;
436129
436245
  if (!ast) {
436130
436246
  throw new Error("File not found in source tracker " + path26);
@@ -436137,7 +436253,7 @@ var SourceTracker = class {
436137
436253
  throw e;
436138
436254
  }
436139
436255
  };
436140
- addElement = async ({ parentElement, tagName, properties, children, id: id2, scopeName }) => {
436256
+ addElement = ({ parentElement, tagName, properties, children, id: id2, scopeName }) => {
436141
436257
  const logger3 = getLogger();
436142
436258
  const parentOpeningElementPath = this.getElementToLocation(parentElement.source.id);
436143
436259
  const parentFilepath = this.getElementToFilePath(parentElement.source.id);
@@ -436281,7 +436397,7 @@ var SourceTracker = class {
436281
436397
  throw new Error("Error updating source tracker during add" + e.message);
436282
436398
  }
436283
436399
  };
436284
- deleteElement = async ({ source: source2, scopeName }) => {
436400
+ deleteElement = ({ source: source2, scopeName }) => {
436285
436401
  const logger3 = getLogger();
436286
436402
  let openingTag = this.getElementToLocation(source2.id);
436287
436403
  if (!openingTag) {
@@ -436440,13 +436556,13 @@ var SourceTracker = class {
436440
436556
  element.node.closingElement = import_types24.default.jsxClosingElement(import_types24.default.jsxIdentifier(getTagName(openingElement.node.name) ?? ""));
436441
436557
  }
436442
436558
  };
436443
- setProperty = async ({ source: source2, property, info }) => {
436444
- await this.setProperties({
436559
+ setProperty = ({ source: source2, property, info }) => {
436560
+ this.setProperties({
436445
436561
  source: source2,
436446
436562
  changes: { [property]: info }
436447
436563
  });
436448
436564
  };
436449
- setProperties = async ({ source: source2, changes }) => {
436565
+ setProperties = ({ source: source2, changes }) => {
436450
436566
  const logger3 = getLogger();
436451
436567
  if (Object.keys(changes).length === 0)
436452
436568
  return;
@@ -436672,12 +436788,13 @@ var SUPPORTED_FILETYPES = [
436672
436788
  }
436673
436789
  ];
436674
436790
  var APP_THEME_FILE_NAME = "appTheme.ts";
436675
- var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436791
+ var FileSystemManager = class extends import_shared32.TracedEventEmitter {
436676
436792
  rootDir;
436677
436793
  tsFiles = {};
436678
436794
  apiFiles = {};
436679
436795
  sourceTracker;
436680
436796
  fsOperationQueue;
436797
+ operationProcessor;
436681
436798
  generationNumberSequence;
436682
436799
  routes = {};
436683
436800
  watcher;
@@ -436690,6 +436807,11 @@ var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436690
436807
  this.fsOperationQueue = fsOperationQueue;
436691
436808
  this.generationNumberSequence = generationNumberSequence;
436692
436809
  this._tracer = tracer2;
436810
+ this.operationProcessor = new OperationProcessor({
436811
+ batchWindowMs: 50,
436812
+ maxBatchSize: 100
436813
+ });
436814
+ this.operationProcessor.disable();
436693
436815
  applyErrorHandling(this, {
436694
436816
  watch: { operation: "editing from code" },
436695
436817
  handleCreatePage: { operation: "creating a page" },
@@ -436836,132 +436958,193 @@ var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436836
436958
  this.updateApi(content2, path55);
436837
436959
  }
436838
436960
  });
436839
- const handleFileChange = async (event, filePath) => {
436840
- logger3.info(`File changed: ${filePath}, event: ${event}`);
436841
- switch (event) {
436842
- case "add": {
436843
- const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
436844
- if (!fileType || !filePath.startsWith(rootPath)) {
436845
- return;
436846
- }
436847
- const data = await readFile6(filePath);
436848
- if (typeof data !== "string")
436849
- return;
436850
- if (/pages\/.*\/index\.tsx/.test(filePath)) {
436851
- const file = await readFile6(filePath);
436852
- if (!file) {
436853
- logger3.error(`Failed to read file: ${filePath}`);
436854
- return;
436855
- }
436856
- if (!(filePath in this.tsFiles)) {
436857
- this.tsFiles[filePath] = file;
436858
- this.handleNonVisualChangeByDeletingIds(filePath, file);
436859
- this.emit("addPage", filePath);
436961
+ watcher.on("all", this.handleFileChange);
436962
+ }
436963
+ enableOperationsQueue() {
436964
+ this.operationProcessor.enable();
436965
+ }
436966
+ disableOperationsQueue() {
436967
+ this.operationProcessor.disable();
436968
+ }
436969
+ async flushOperations() {
436970
+ await this.operationProcessor.flush();
436971
+ }
436972
+ handleFileChange = async (event, filePath) => {
436973
+ const logger3 = getLogger();
436974
+ logger3.info(`File changed: ${filePath}, event: ${event}`);
436975
+ const rootPath = this.rootDir;
436976
+ if (!rootPath) {
436977
+ throw new Error("Root directory not set");
436978
+ }
436979
+ if (event === "addDir" || event === "unlinkDir") {
436980
+ return;
436981
+ }
436982
+ const routePath = path27.join(rootPath, ROUTES_FILE);
436983
+ const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
436984
+ if (!fileType || !filePath.startsWith(rootPath)) {
436985
+ return;
436986
+ }
436987
+ switch (event) {
436988
+ case "add": {
436989
+ const data = await readFile6(filePath);
436990
+ if (typeof data !== "string")
436991
+ return;
436992
+ const isPage = isPageFilePath(filePath);
436993
+ if (isPage) {
436994
+ void this.operationProcessor.addOperation({
436995
+ metadata: {
436996
+ filePath
436997
+ },
436998
+ execute: async () => {
436999
+ const file = await readFile6(filePath);
437000
+ if (!file) {
437001
+ logger3.error(`Failed to read file: ${filePath}`);
437002
+ return;
437003
+ }
437004
+ if (!(filePath in this.tsFiles)) {
437005
+ this.tsFiles[filePath] = file;
437006
+ this.handleNonVisualChangeByDeletingIds(filePath, file);
437007
+ this.emit("addPage", filePath);
437008
+ }
436860
437009
  }
436861
- }
436862
- switch (fileType.type) {
436863
- case "api":
436864
- case "python-api-step":
436865
- case "js-api-step": {
436866
- await this.processApiUpdates(filePath, fileType);
436867
- break;
437010
+ });
437011
+ } else {
437012
+ void this.operationProcessor.addOperation({
437013
+ metadata: {
437014
+ filePath
437015
+ },
437016
+ execute: async () => {
437017
+ switch (fileType.type) {
437018
+ case "api":
437019
+ case "python-api-step":
437020
+ case "js-api-step": {
437021
+ await this.processApiUpdates(filePath, fileType);
437022
+ break;
437023
+ }
437024
+ }
436868
437025
  }
436869
- }
436870
- break;
437026
+ });
436871
437027
  }
436872
- case "change": {
436873
- if (filePath === routePath) {
436874
- const data2 = await readFile6(filePath);
436875
- try {
436876
- this.routes = JSON.parse(data2);
436877
- this.emit("routesChanged", this.routes);
436878
- } catch (e) {
436879
- logger3.error("Error parsing routes file", getErrorMeta(e));
436880
- }
436881
- return;
436882
- }
436883
- const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
436884
- if (!fileType || !filePath.startsWith(rootPath)) {
436885
- return;
436886
- }
436887
- const data = await readFile6(filePath);
436888
- if (typeof data !== "string")
436889
- return;
436890
- switch (fileType.type) {
436891
- case "tsx":
436892
- case "scope":
436893
- {
436894
- if (!(filePath in this.tsFiles && this.tsFiles[filePath] === data)) {
436895
- logger3.info(`File changed: ${filePath} updating AST tracker`);
436896
- this.tsFiles[filePath] = data;
436897
- this.handleNonVisualChangeByDeletingIds(filePath, data);
436898
- this.emit("fileChanged", filePath, data, true);
436899
- } else {
436900
- logger3.info(`File unchanged from last tracked state: ${filePath}`);
436901
- this.emit("fileChanged", filePath, data, false);
437028
+ break;
437029
+ }
437030
+ case "change": {
437031
+ if (filePath === routePath) {
437032
+ void this.operationProcessor.addOperation({
437033
+ metadata: {
437034
+ filePath
437035
+ },
437036
+ priority: true,
437037
+ execute: async () => {
437038
+ try {
437039
+ const data = JSON.parse(await readFile6(filePath) ?? "{}");
437040
+ if (!isEqual_default(this.routes, data)) {
437041
+ this.routes = data;
437042
+ this.emit("routesChanged", this.routes);
436902
437043
  }
437044
+ } catch (e) {
437045
+ logger3.error("Error parsing routes file", getErrorMeta(e));
436903
437046
  }
436904
- break;
436905
- case "api":
436906
- case "python-api-step":
436907
- case "js-api-step":
436908
- {
436909
- await this.processApiUpdates(filePath, fileType);
437047
+ }
437048
+ });
437049
+ return;
437050
+ } else {
437051
+ void this.operationProcessor.addOperation({
437052
+ metadata: {
437053
+ filePath
437054
+ },
437055
+ execute: async () => {
437056
+ const fileType2 = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
437057
+ if (!fileType2 || !filePath.startsWith(rootPath)) {
437058
+ return;
436910
437059
  }
436911
- break;
436912
- }
436913
- break;
436914
- }
436915
- case "unlink": {
436916
- if (filePath in this.apiFiles) {
436917
- const api = this.apiFiles[filePath];
436918
- delete this.apiFiles[filePath];
436919
- if (!api || !this.sourceTracker)
436920
- break;
436921
- const scopeId = await this.sourceTracker.deleteApi({
436922
- pageName: api.pageName,
436923
- apiName: api.apiPb.metadata.name
436924
- });
436925
- const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
436926
- await this.writeChanges(changes);
436927
- this.emit("apiManualDelete", {
436928
- api: {
436929
- id: getClientApiId(api.apiPb.metadata.name, api.pageName),
436930
- apiName: api.apiPb.metadata.name,
436931
- // TODO(saksham): get pagename more defensively
436932
- pageName: getPageName2(filePath),
436933
- scopeId
437060
+ const data = await readFile6(filePath);
437061
+ if (typeof data !== "string")
437062
+ return;
437063
+ switch (fileType2.type) {
437064
+ case "tsx":
437065
+ case "scope":
437066
+ {
437067
+ if (!(filePath in this.tsFiles && this.tsFiles[filePath] === data)) {
437068
+ logger3.info(`File changed: ${filePath} updating AST tracker`);
437069
+ this.tsFiles[filePath] = data;
437070
+ this.handleNonVisualChangeByDeletingIds(filePath, data);
437071
+ this.emit("fileChanged", filePath, data, true);
437072
+ } else {
437073
+ logger3.info(`File unchanged from last tracked state: ${filePath}`);
437074
+ this.emit("fileChanged", filePath, data, false);
437075
+ }
437076
+ }
437077
+ break;
437078
+ case "api":
437079
+ case "python-api-step":
437080
+ case "js-api-step":
437081
+ {
437082
+ await this.processApiUpdates(filePath, fileType2);
437083
+ }
437084
+ break;
436934
437085
  }
436935
- });
436936
- }
436937
- if (filePath in this.tsFiles) {
436938
- delete this.tsFiles[filePath];
436939
- this.sourceTracker?.removeFile(filePath);
436940
- this.emit("deletePage", filePath);
436941
- }
436942
- break;
437086
+ }
437087
+ });
436943
437088
  }
437089
+ break;
436944
437090
  }
436945
- };
436946
- watcher.on("all", async (event, filePath) => {
436947
- const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
436948
- switch (fileType?.type) {
436949
- case "tsx":
436950
- case "scope":
436951
- this.fsOperationQueue.enqueue(async () => {
436952
- return await handleFileChange(event, filePath);
437091
+ case "unlink": {
437092
+ if (filePath in this.tsFiles) {
437093
+ void this.operationProcessor.addOperation({
437094
+ metadata: {
437095
+ filePath
437096
+ },
437097
+ execute: async () => {
437098
+ await this.deleteTsFile(filePath);
437099
+ }
436953
437100
  });
436954
- break;
436955
- default:
436956
- this.fsOperationQueue.enqueue(async () => {
436957
- void handleFileChange(event, filePath);
437101
+ } else if (filePath in this.apiFiles) {
437102
+ void this.operationProcessor.addOperation({
437103
+ metadata: {
437104
+ filePath
437105
+ },
437106
+ execute: async () => {
437107
+ await this.deleteApiFile(filePath);
437108
+ }
436958
437109
  });
437110
+ }
437111
+ break;
436959
437112
  }
436960
- });
436961
- }
437113
+ }
437114
+ };
436962
437115
  getApiFiles() {
436963
437116
  return this.formatApisToClientApis(this.apiFiles);
436964
437117
  }
437118
+ async deleteTsFile(filePath) {
437119
+ delete this.tsFiles[filePath];
437120
+ this.sourceTracker?.removeFile(filePath);
437121
+ if (isPageFilePath(filePath)) {
437122
+ this.emit("deletePage", filePath);
437123
+ }
437124
+ }
437125
+ async deleteApiFile(filePath) {
437126
+ const api = this.apiFiles[filePath];
437127
+ if (!api) {
437128
+ return;
437129
+ }
437130
+ delete this.apiFiles[filePath];
437131
+ this.sourceTracker?.deleteApi({
437132
+ pageName: api.pageName,
437133
+ apiName: api.apiPb.metadata.name
437134
+ });
437135
+ const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
437136
+ await this.writeChanges(changes);
437137
+ const scopeId = this.sourceTracker?.getScopeDefinitionForPage(api.pageName)?.id;
437138
+ this.emit("apiManualDelete", {
437139
+ api: {
437140
+ id: getClientApiId(api.apiPb.metadata.name, api.pageName),
437141
+ apiName: api.apiPb.metadata.name,
437142
+ // TODO(saksham): get pagename more defensively
437143
+ pageName: getPageName2(filePath),
437144
+ scopeId
437145
+ }
437146
+ });
437147
+ }
436965
437148
  getTsFilePaths() {
436966
437149
  return Object.keys(this.tsFiles);
436967
437150
  }
@@ -437169,11 +437352,11 @@ export default registerPage(Page, { name: "${name18}" });
437169
437352
  handleReparent = async (payload, writeFile9 = true) => {
437170
437353
  const { from, to, changedProps, transaction } = payload;
437171
437354
  this.trackTransaction(transaction?.id);
437172
- await this.sourceTracker?.setProperties({
437355
+ this.sourceTracker?.setProperties({
437173
437356
  source: from.source,
437174
437357
  changes: changedProps ?? {}
437175
437358
  });
437176
- await this.sourceTracker?.moveElement({
437359
+ this.sourceTracker?.moveElement({
437177
437360
  from,
437178
437361
  to
437179
437362
  });
@@ -437187,7 +437370,7 @@ export default registerPage(Page, { name: "${name18}" });
437187
437370
  };
437188
437371
  handleCreateComponent = async (payload, writeFile9 = true) => {
437189
437372
  this.trackTransaction(payload.transaction?.id);
437190
- const sourceId = await this.sourceTracker?.addElement(payload);
437373
+ const sourceId = this.sourceTracker?.addElement(payload);
437191
437374
  if (writeFile9) {
437192
437375
  const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
437193
437376
  await this.writeChanges(changes ?? [], (fileName) => {
@@ -437201,7 +437384,7 @@ export default registerPage(Page, { name: "${name18}" });
437201
437384
  const { elements, transaction } = payload;
437202
437385
  this.trackTransaction(transaction?.id);
437203
437386
  for (const element of elements) {
437204
- await this.sourceTracker?.deleteElement({
437387
+ this.sourceTracker?.deleteElement({
437205
437388
  source: element.source,
437206
437389
  scopeName: element.scopeName
437207
437390
  });
@@ -437217,7 +437400,7 @@ export default registerPage(Page, { name: "${name18}" });
437217
437400
  handleSetProperty = async (payload, writeFile9 = true) => {
437218
437401
  const { element: { source: source2 }, property, value: value2, transaction } = payload;
437219
437402
  this.trackTransaction(transaction?.id);
437220
- await this.sourceTracker?.setProperty({
437403
+ this.sourceTracker?.setProperty({
437221
437404
  source: source2,
437222
437405
  property,
437223
437406
  info: value2
@@ -437232,7 +437415,7 @@ export default registerPage(Page, { name: "${name18}" });
437232
437415
  handleSetProperties = async (payload, writeFile9 = true) => {
437233
437416
  const { element: { source: source2 }, properties, transaction } = payload;
437234
437417
  this.trackTransaction(transaction?.id);
437235
- await this.sourceTracker?.setProperties({
437418
+ this.sourceTracker?.setProperties({
437236
437419
  source: source2,
437237
437420
  changes: properties
437238
437421
  });
@@ -437362,7 +437545,7 @@ export default registerPage(Page, { name: "${name18}" });
437362
437545
  await fs12.rmdir(apiDir, { recursive: true });
437363
437546
  }
437364
437547
  delete this.apiFiles[apiFilePath];
437365
- const scopeId = await this.sourceTracker.deleteApi({
437548
+ const scopeId = this.sourceTracker.deleteApi({
437366
437549
  pageName,
437367
437550
  apiName
437368
437551
  });
@@ -437456,7 +437639,7 @@ export default registerPage(Page, { name: "${name18}" });
437456
437639
  }));
437457
437640
  };
437458
437641
  handleAddEntity = async (payload) => {
437459
- await this.sourceTracker?.addEntity({
437642
+ this.sourceTracker?.addEntity({
437460
437643
  scopeId: payload.scopeId,
437461
437644
  entity: {
437462
437645
  type: payload.type,
@@ -437470,7 +437653,7 @@ export default registerPage(Page, { name: "${name18}" });
437470
437653
  });
437471
437654
  };
437472
437655
  handleUpdateEntity = async (payload) => {
437473
- await this.sourceTracker?.updateEntity({
437656
+ this.sourceTracker?.updateEntity({
437474
437657
  entityId: payload.entityId,
437475
437658
  updates: payload.updates
437476
437659
  });
@@ -437480,7 +437663,7 @@ export default registerPage(Page, { name: "${name18}" });
437480
437663
  });
437481
437664
  };
437482
437665
  handleDeleteEntity = async (payload) => {
437483
- const deletedEntityName = await this.sourceTracker?.deleteEntity({
437666
+ const deletedEntityName = this.sourceTracker?.deleteEntity({
437484
437667
  entityId: payload.entityId
437485
437668
  });
437486
437669
  const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
@@ -437496,7 +437679,7 @@ export default registerPage(Page, { name: "${name18}" });
437496
437679
  throw new Error("Root directory not set");
437497
437680
  }
437498
437681
  const filePath = path27.join(this.rootDir, APP_THEME_FILE_NAME);
437499
- await this.sourceTracker?.updateTheme({
437682
+ this.sourceTracker?.updateTheme({
437500
437683
  themeFilePath: filePath,
437501
437684
  theme
437502
437685
  });
@@ -437532,7 +437715,7 @@ export default registerPage(Page, { name: "${name18}" });
437532
437715
  };
437533
437716
  handleRenameEntity = async (payload) => {
437534
437717
  const { elementId, newName, oldName, scopeName } = payload;
437535
- await this.sourceTracker?.renameEntity({
437718
+ this.sourceTracker?.renameEntity({
437536
437719
  entityId: elementId,
437537
437720
  oldName,
437538
437721
  newName,
@@ -438217,7 +438400,7 @@ var fileSyncVitePlugin = (pluginParams, options9) => {
438217
438400
  const aiService = pluginParams.aiService;
438218
438401
  const fsOperationQueue = pluginParams.fsOperationQueue;
438219
438402
  const httpServer2 = pluginParams.httpServer;
438220
- const fileSyncManager = new FileSyncManager(fsOperationQueue, generationNumberSequence, pluginParams.tracer);
438403
+ const fileSyncManager = new FileSystemManager(fsOperationQueue, generationNumberSequence, pluginParams.tracer);
438221
438404
  if (syncService) {
438222
438405
  syncService.generationNumberSequence = generationNumberSequence;
438223
438406
  }
@@ -438630,7 +438813,12 @@ var fileSyncVitePlugin = (pluginParams, options9) => {
438630
438813
  return socket.call.aiSetDraftState({ hasDraft });
438631
438814
  });
438632
438815
  });
438633
- aiService.on("generationCompleted", (hasDraft) => {
438816
+ aiService.on("generationStarted", () => {
438817
+ fileSyncManager.enableOperationsQueue();
438818
+ });
438819
+ aiService.on("generationCompleted", async (hasDraft) => {
438820
+ fileSyncManager.disableOperationsQueue();
438821
+ await fileSyncManager.flushOperations();
438634
438822
  if (hasDraft) {
438635
438823
  logger3.info("Requesting full reload to render AI draft");
438636
438824
  server.ws.send({
@@ -442607,7 +442795,7 @@ var import_util30 = __toESM(require_dist3(), 1);
442607
442795
  // ../sdk/package.json
442608
442796
  var package_default = {
442609
442797
  name: "@superblocksteam/sdk",
442610
- version: "2.0.6-next.16",
442798
+ version: "2.0.6-next.18",
442611
442799
  type: "module",
442612
442800
  description: "Superblocks JS SDK",
442613
442801
  homepage: "https://www.superblocks.com",
@@ -442648,11 +442836,11 @@ var package_default = {
442648
442836
  "@opentelemetry/semantic-conventions": "^1.28.0",
442649
442837
  "@rollup/wasm-node": "^4.35.0",
442650
442838
  "@superblocksteam/bucketeer-sdk": "0.5.0",
442651
- "@superblocksteam/library": "2.0.6-next.16",
442652
- "@superblocksteam/library-shared": "2.0.6-next.16",
442839
+ "@superblocksteam/library": "2.0.6-next.18",
442840
+ "@superblocksteam/library-shared": "2.0.6-next.18",
442653
442841
  "@superblocksteam/shared": "0.9198.0",
442654
- "@superblocksteam/util": "2.0.6-next.16",
442655
- "@superblocksteam/vite-plugin-file-sync": "2.0.6-next.16",
442842
+ "@superblocksteam/util": "2.0.6-next.18",
442843
+ "@superblocksteam/vite-plugin-file-sync": "2.0.6-next.18",
442656
442844
  "@vitejs/plugin-react": "^4.3.4",
442657
442845
  axios: "^1.4.0",
442658
442846
  chokidar: "^4.0.3",
@@ -450223,7 +450411,8 @@ async function startVite({ app, httpServer: httpServer2, root: root2, mode, port
450223
450411
  };
450224
450412
  const isCustomBuildEnabled2 = await isCustomComponentsEnabled();
450225
450413
  const customFolder = path37.join(root2, "custom");
450226
- const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.6-next.16";
450414
+ const draftsFolder = path37.join(root2, ".superblocks");
450415
+ const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.6-next.18";
450227
450416
  const env3 = loadEnv(mode, root2, "");
450228
450417
  const hmrPort = await getFreePort();
450229
450418
  const hmrOptions = {
@@ -450254,10 +450443,7 @@ async function startVite({ app, httpServer: httpServer2, root: root2, mode, port
450254
450443
  server: {
450255
450444
  middlewareMode: true,
450256
450445
  watch: {
450257
- ignored: [
450258
- `${customFolder}/**/*`,
450259
- `${root2}/.superblocks/{generations,drafts}/**/*`
450260
- ]
450446
+ ignored: [`${customFolder}/**/*`, `${draftsFolder}/**/*`]
450261
450447
  },
450262
450448
  hmr: hmrOptions,
450263
450449
  cors: {
@@ -585,5 +585,5 @@
585
585
  "strict": true
586
586
  }
587
587
  },
588
- "version": "2.0.6-next.16"
588
+ "version": "2.0.6-next.18"
589
589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/cli",
3
- "version": "2.0.6-next.16",
3
+ "version": "2.0.6-next.18",
4
4
  "type": "module",
5
5
  "description": "Official Superblocks CLI",
6
6
  "homepage": "https://www.superblocks.com",
@@ -42,9 +42,9 @@
42
42
  "devDependencies": {
43
43
  "@eslint/js": "^9.16.0",
44
44
  "@oclif/test": "^4.1.11",
45
- "@superblocksteam/sdk": "2.0.6-next.16",
45
+ "@superblocksteam/sdk": "2.0.6-next.18",
46
46
  "@superblocksteam/shared": "0.9198.0",
47
- "@superblocksteam/util": "2.0.6-next.16",
47
+ "@superblocksteam/util": "2.0.6-next.18",
48
48
  "@types/babel__core": "^7.20.0",
49
49
  "@types/chai": "^4",
50
50
  "@types/fs-extra": "^11.0.1",