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

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.17 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',
@@ -417871,6 +417871,7 @@ Address the errors and return the fixed code.`;
417871
417871
  switch (event.type) {
417872
417872
  case USER_SENT_PROMPT: {
417873
417873
  const { request, peer } = event;
417874
+ params.signals.emit("generationStarted");
417874
417875
  const initialElementIds = clark.context.initialElementIds ?? Object.keys(params.sourceTrackerInterface.getElementToFilePathMap() ?? {});
417875
417876
  clark.updateContext((context2) => ({
417876
417877
  ...context2,
@@ -431924,6 +431925,9 @@ function getPageFolder(rootPath, pageName) {
431924
431925
  function getPageFilePath(rootPath, pageName) {
431925
431926
  return path21.join(getPageFolder(rootPath, pageName), "index.tsx");
431926
431927
  }
431928
+ function isPageFilePath(filePath) {
431929
+ return /pages\/.*\/index\.tsx/.test(filePath);
431930
+ }
431927
431931
 
431928
431932
  // ../../../vite-plugin-file-sync/dist/traverse.js
431929
431933
  init_cjs_shims();
@@ -433797,6 +433801,87 @@ function addLegacyCustomComponentVariables(path55, tracker) {
433797
433801
  });
433798
433802
  }
433799
433803
 
433804
+ // ../../../vite-plugin-file-sync/dist/operations/operation-processor.js
433805
+ init_cjs_shims();
433806
+ var OperationProcessor = class {
433807
+ config;
433808
+ operationQueue;
433809
+ pendingOperations = [];
433810
+ batchTimer = null;
433811
+ _enabled = true;
433812
+ constructor(config2 = {}) {
433813
+ this.config = {
433814
+ batchWindowMs: 50,
433815
+ maxBatchSize: 100,
433816
+ ...config2
433817
+ };
433818
+ this.operationQueue = new OperationQueue();
433819
+ }
433820
+ async addOperation(operation) {
433821
+ const timestamp2 = Date.now();
433822
+ const id2 = `operation-${timestamp2}-${Math.random()}`;
433823
+ const fullOperation = {
433824
+ ...operation,
433825
+ id: id2,
433826
+ timestamp: timestamp2
433827
+ };
433828
+ if (!this._enabled || fullOperation.priority) {
433829
+ return this.processOperations([fullOperation]);
433830
+ }
433831
+ this.pendingOperations.push(fullOperation);
433832
+ if (this.pendingOperations.length >= this.config.maxBatchSize) {
433833
+ return this.flush();
433834
+ }
433835
+ this.resetBatchTimer();
433836
+ }
433837
+ async flush() {
433838
+ if (this.pendingOperations.length === 0) {
433839
+ return;
433840
+ }
433841
+ const operations = [...this.pendingOperations];
433842
+ this.pendingOperations = [];
433843
+ this.clearBatchTimer();
433844
+ return this.operationQueue.enqueue(() => this.processOperations(operations));
433845
+ }
433846
+ disable() {
433847
+ this.setEnabled(false);
433848
+ }
433849
+ enable() {
433850
+ this.setEnabled(true);
433851
+ }
433852
+ setEnabled(enabled) {
433853
+ const wasEnabled = this._enabled;
433854
+ this._enabled = enabled;
433855
+ if (!enabled && wasEnabled && this.pendingOperations.length > 0) {
433856
+ this.flush().catch((error) => {
433857
+ console.error("Error flushing operations on priority mode enable:", error);
433858
+ });
433859
+ }
433860
+ }
433861
+ async processOperations(operations) {
433862
+ if (operations.length === 0) {
433863
+ return;
433864
+ }
433865
+ for (const operation of operations) {
433866
+ await operation.execute();
433867
+ }
433868
+ }
433869
+ resetBatchTimer() {
433870
+ this.clearBatchTimer();
433871
+ this.batchTimer = setTimeout(() => {
433872
+ this.flush().catch((error) => {
433873
+ console.error("Error flushing operations on timer:", error);
433874
+ });
433875
+ }, this.config.batchWindowMs);
433876
+ }
433877
+ clearBatchTimer() {
433878
+ if (this.batchTimer) {
433879
+ clearTimeout(this.batchTimer);
433880
+ this.batchTimer = null;
433881
+ }
433882
+ }
433883
+ };
433884
+
433800
433885
  // ../../../vite-plugin-file-sync/dist/parsing/bindings.js
433801
433886
  init_cjs_shims();
433802
433887
  var localBindingKinds = /* @__PURE__ */ new Set(["local", "param", "var", "const", "let"]);
@@ -435896,6 +435981,7 @@ var SourceTracker = class {
435896
435981
  const extension = path26.extname(fileName);
435897
435982
  if (extension !== ".ts" && extension !== ".tsx")
435898
435983
  return;
435984
+ const existingFile = fileName in this.fileToMeta;
435899
435985
  try {
435900
435986
  const astMap = this.parseJsxFromEntrypoint({
435901
435987
  files: [{ fileName, code: fileContents }]
@@ -435918,7 +436004,19 @@ var SourceTracker = class {
435918
436004
  delete this.elementToLocation[key2];
435919
436005
  delete this.elementToFilePath[key2];
435920
436006
  });
435921
- const changedFiles = this.sbScopeManager.resetScope(fileName);
436007
+ let changedFiles = [];
436008
+ if (existingFile) {
436009
+ changedFiles = this.sbScopeManager.resetScope(fileName);
436010
+ } else {
436011
+ this.sbScopeManager.parseScopes({
436012
+ [fileName]: {
436013
+ code: fileContents,
436014
+ ast,
436015
+ imports: extractImportsFromAst(ast)
436016
+ }
436017
+ });
436018
+ changedFiles.push(fileName);
436019
+ }
435922
436020
  if (!fileName.endsWith(SCOPE_FILE)) {
435923
436021
  const { idMap } = supplementElementIds({
435924
436022
  fileName,
@@ -436044,7 +436142,7 @@ var SourceTracker = class {
436044
436142
  });
436045
436143
  return scopeDefinition.id;
436046
436144
  };
436047
- deleteApi = async ({ pageName, apiName }) => {
436145
+ deleteApi = ({ pageName, apiName }) => {
436048
436146
  const { scopeDefinition, filePath: scopeFilePath } = this.sbScopeManager.getScopeDefinitionAndFilePathByNameOrId({
436049
436147
  identifier: pageName,
436050
436148
  type: "name"
@@ -436076,24 +436174,24 @@ var SourceTracker = class {
436076
436174
  });
436077
436175
  return scopeDefinition.id;
436078
436176
  };
436079
- addEntity = async ({ scopeId, entity }) => {
436177
+ addEntity = ({ scopeId, entity }) => {
436080
436178
  const changedFiles = this.sbScopeManager.addScopeEntity(scopeId, entity);
436081
436179
  changedFiles.forEach((file) => {
436082
436180
  this.changedFiles.add(file);
436083
436181
  });
436084
436182
  };
436085
- updateEntity = async (payload) => {
436183
+ updateEntity = (payload) => {
436086
436184
  const changedFile = this.sbScopeManager.updateScopeEntity(payload);
436087
436185
  this.changedFiles.add(changedFile);
436088
436186
  };
436089
- deleteEntity = async ({ entityId }) => {
436187
+ deleteEntity = ({ entityId }) => {
436090
436188
  const { changedFiles, deletedEntitiesNames } = this.sbScopeManager.deleteScopeEntity(entityId);
436091
436189
  changedFiles.forEach((file) => {
436092
436190
  this.changedFiles.add(file);
436093
436191
  });
436094
436192
  return deletedEntitiesNames[0];
436095
436193
  };
436096
- renameEntity = async ({ entityId, oldName, newName, scopeName }) => {
436194
+ renameEntity = ({ entityId, oldName, newName, scopeName }) => {
436097
436195
  const { changedFiles, scopeFile } = this.sbScopeManager.renameScopeEntity({
436098
436196
  entityId,
436099
436197
  newName,
@@ -436124,7 +436222,7 @@ var SourceTracker = class {
436124
436222
  }
436125
436223
  };
436126
436224
  // THEMING
436127
- updateTheme = async ({ themeFilePath, theme }) => {
436225
+ updateTheme = ({ themeFilePath, theme }) => {
436128
436226
  const ast = this.getCurrentFiles()[themeFilePath]?.ast;
436129
436227
  if (!ast) {
436130
436228
  throw new Error("File not found in source tracker " + path26);
@@ -436137,7 +436235,7 @@ var SourceTracker = class {
436137
436235
  throw e;
436138
436236
  }
436139
436237
  };
436140
- addElement = async ({ parentElement, tagName, properties, children, id: id2, scopeName }) => {
436238
+ addElement = ({ parentElement, tagName, properties, children, id: id2, scopeName }) => {
436141
436239
  const logger3 = getLogger();
436142
436240
  const parentOpeningElementPath = this.getElementToLocation(parentElement.source.id);
436143
436241
  const parentFilepath = this.getElementToFilePath(parentElement.source.id);
@@ -436281,7 +436379,7 @@ var SourceTracker = class {
436281
436379
  throw new Error("Error updating source tracker during add" + e.message);
436282
436380
  }
436283
436381
  };
436284
- deleteElement = async ({ source: source2, scopeName }) => {
436382
+ deleteElement = ({ source: source2, scopeName }) => {
436285
436383
  const logger3 = getLogger();
436286
436384
  let openingTag = this.getElementToLocation(source2.id);
436287
436385
  if (!openingTag) {
@@ -436440,13 +436538,13 @@ var SourceTracker = class {
436440
436538
  element.node.closingElement = import_types24.default.jsxClosingElement(import_types24.default.jsxIdentifier(getTagName(openingElement.node.name) ?? ""));
436441
436539
  }
436442
436540
  };
436443
- setProperty = async ({ source: source2, property, info }) => {
436444
- await this.setProperties({
436541
+ setProperty = ({ source: source2, property, info }) => {
436542
+ this.setProperties({
436445
436543
  source: source2,
436446
436544
  changes: { [property]: info }
436447
436545
  });
436448
436546
  };
436449
- setProperties = async ({ source: source2, changes }) => {
436547
+ setProperties = ({ source: source2, changes }) => {
436450
436548
  const logger3 = getLogger();
436451
436549
  if (Object.keys(changes).length === 0)
436452
436550
  return;
@@ -436672,12 +436770,13 @@ var SUPPORTED_FILETYPES = [
436672
436770
  }
436673
436771
  ];
436674
436772
  var APP_THEME_FILE_NAME = "appTheme.ts";
436675
- var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436773
+ var FileSystemManager = class extends import_shared32.TracedEventEmitter {
436676
436774
  rootDir;
436677
436775
  tsFiles = {};
436678
436776
  apiFiles = {};
436679
436777
  sourceTracker;
436680
436778
  fsOperationQueue;
436779
+ operationProcessor;
436681
436780
  generationNumberSequence;
436682
436781
  routes = {};
436683
436782
  watcher;
@@ -436690,6 +436789,11 @@ var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436690
436789
  this.fsOperationQueue = fsOperationQueue;
436691
436790
  this.generationNumberSequence = generationNumberSequence;
436692
436791
  this._tracer = tracer2;
436792
+ this.operationProcessor = new OperationProcessor({
436793
+ batchWindowMs: 50,
436794
+ maxBatchSize: 100
436795
+ });
436796
+ this.operationProcessor.disable();
436693
436797
  applyErrorHandling(this, {
436694
436798
  watch: { operation: "editing from code" },
436695
436799
  handleCreatePage: { operation: "creating a page" },
@@ -436836,132 +436940,193 @@ var FileSyncManager = class extends import_shared32.TracedEventEmitter {
436836
436940
  this.updateApi(content2, path55);
436837
436941
  }
436838
436942
  });
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);
436943
+ watcher.on("all", this.handleFileChange);
436944
+ }
436945
+ enableOperationsQueue() {
436946
+ this.operationProcessor.enable();
436947
+ }
436948
+ disableOperationsQueue() {
436949
+ this.operationProcessor.disable();
436950
+ }
436951
+ async flushOperations() {
436952
+ await this.operationProcessor.flush();
436953
+ }
436954
+ handleFileChange = async (event, filePath) => {
436955
+ const logger3 = getLogger();
436956
+ logger3.info(`File changed: ${filePath}, event: ${event}`);
436957
+ const rootPath = this.rootDir;
436958
+ if (!rootPath) {
436959
+ throw new Error("Root directory not set");
436960
+ }
436961
+ if (event === "addDir" || event === "unlinkDir") {
436962
+ return;
436963
+ }
436964
+ const routePath = path27.join(rootPath, ROUTES_FILE);
436965
+ const fileType = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
436966
+ if (!fileType || !filePath.startsWith(rootPath)) {
436967
+ return;
436968
+ }
436969
+ switch (event) {
436970
+ case "add": {
436971
+ const data = await readFile6(filePath);
436972
+ if (typeof data !== "string")
436973
+ return;
436974
+ const isPage = isPageFilePath(filePath);
436975
+ if (isPage) {
436976
+ void this.operationProcessor.addOperation({
436977
+ metadata: {
436978
+ filePath
436979
+ },
436980
+ execute: async () => {
436981
+ const file = await readFile6(filePath);
436982
+ if (!file) {
436983
+ logger3.error(`Failed to read file: ${filePath}`);
436984
+ return;
436985
+ }
436986
+ if (!(filePath in this.tsFiles)) {
436987
+ this.tsFiles[filePath] = file;
436988
+ this.handleNonVisualChangeByDeletingIds(filePath, file);
436989
+ this.emit("addPage", filePath);
436990
+ }
436860
436991
  }
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;
436992
+ });
436993
+ } else {
436994
+ void this.operationProcessor.addOperation({
436995
+ metadata: {
436996
+ filePath
436997
+ },
436998
+ execute: async () => {
436999
+ switch (fileType.type) {
437000
+ case "api":
437001
+ case "python-api-step":
437002
+ case "js-api-step": {
437003
+ await this.processApiUpdates(filePath, fileType);
437004
+ break;
437005
+ }
437006
+ }
436868
437007
  }
436869
- }
436870
- break;
437008
+ });
436871
437009
  }
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);
437010
+ break;
437011
+ }
437012
+ case "change": {
437013
+ if (filePath === routePath) {
437014
+ void this.operationProcessor.addOperation({
437015
+ metadata: {
437016
+ filePath
437017
+ },
437018
+ priority: true,
437019
+ execute: async () => {
437020
+ try {
437021
+ const data = JSON.parse(await readFile6(filePath) ?? "{}");
437022
+ if (!isEqual_default(this.routes, data)) {
437023
+ this.routes = data;
437024
+ this.emit("routesChanged", this.routes);
436902
437025
  }
437026
+ } catch (e) {
437027
+ logger3.error("Error parsing routes file", getErrorMeta(e));
436903
437028
  }
436904
- break;
436905
- case "api":
436906
- case "python-api-step":
436907
- case "js-api-step":
436908
- {
436909
- await this.processApiUpdates(filePath, fileType);
437029
+ }
437030
+ });
437031
+ return;
437032
+ } else {
437033
+ void this.operationProcessor.addOperation({
437034
+ metadata: {
437035
+ filePath
437036
+ },
437037
+ execute: async () => {
437038
+ const fileType2 = SUPPORTED_FILETYPES.find((f) => filePath.endsWith(f.extension));
437039
+ if (!fileType2 || !filePath.startsWith(rootPath)) {
437040
+ return;
436910
437041
  }
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
437042
+ const data = await readFile6(filePath);
437043
+ if (typeof data !== "string")
437044
+ return;
437045
+ switch (fileType2.type) {
437046
+ case "tsx":
437047
+ case "scope":
437048
+ {
437049
+ if (!(filePath in this.tsFiles && this.tsFiles[filePath] === data)) {
437050
+ logger3.info(`File changed: ${filePath} updating AST tracker`);
437051
+ this.tsFiles[filePath] = data;
437052
+ this.handleNonVisualChangeByDeletingIds(filePath, data);
437053
+ this.emit("fileChanged", filePath, data, true);
437054
+ } else {
437055
+ logger3.info(`File unchanged from last tracked state: ${filePath}`);
437056
+ this.emit("fileChanged", filePath, data, false);
437057
+ }
437058
+ }
437059
+ break;
437060
+ case "api":
437061
+ case "python-api-step":
437062
+ case "js-api-step":
437063
+ {
437064
+ await this.processApiUpdates(filePath, fileType2);
437065
+ }
437066
+ break;
436934
437067
  }
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;
437068
+ }
437069
+ });
436943
437070
  }
437071
+ break;
436944
437072
  }
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);
437073
+ case "unlink": {
437074
+ if (filePath in this.tsFiles) {
437075
+ void this.operationProcessor.addOperation({
437076
+ metadata: {
437077
+ filePath
437078
+ },
437079
+ execute: async () => {
437080
+ await this.deleteTsFile(filePath);
437081
+ }
436953
437082
  });
436954
- break;
436955
- default:
436956
- this.fsOperationQueue.enqueue(async () => {
436957
- void handleFileChange(event, filePath);
437083
+ } else if (filePath in this.apiFiles) {
437084
+ void this.operationProcessor.addOperation({
437085
+ metadata: {
437086
+ filePath
437087
+ },
437088
+ execute: async () => {
437089
+ await this.deleteApiFile(filePath);
437090
+ }
436958
437091
  });
437092
+ }
437093
+ break;
436959
437094
  }
436960
- });
436961
- }
437095
+ }
437096
+ };
436962
437097
  getApiFiles() {
436963
437098
  return this.formatApisToClientApis(this.apiFiles);
436964
437099
  }
437100
+ async deleteTsFile(filePath) {
437101
+ delete this.tsFiles[filePath];
437102
+ this.sourceTracker?.removeFile(filePath);
437103
+ if (isPageFilePath(filePath)) {
437104
+ this.emit("deletePage", filePath);
437105
+ }
437106
+ }
437107
+ async deleteApiFile(filePath) {
437108
+ const api = this.apiFiles[filePath];
437109
+ if (!api) {
437110
+ return;
437111
+ }
437112
+ delete this.apiFiles[filePath];
437113
+ this.sourceTracker?.deleteApi({
437114
+ pageName: api.pageName,
437115
+ apiName: api.apiPb.metadata.name
437116
+ });
437117
+ const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
437118
+ await this.writeChanges(changes);
437119
+ const scopeId = this.sourceTracker?.getScopeDefinitionForPage(api.pageName)?.id;
437120
+ this.emit("apiManualDelete", {
437121
+ api: {
437122
+ id: getClientApiId(api.apiPb.metadata.name, api.pageName),
437123
+ apiName: api.apiPb.metadata.name,
437124
+ // TODO(saksham): get pagename more defensively
437125
+ pageName: getPageName2(filePath),
437126
+ scopeId
437127
+ }
437128
+ });
437129
+ }
436965
437130
  getTsFilePaths() {
436966
437131
  return Object.keys(this.tsFiles);
436967
437132
  }
@@ -437169,11 +437334,11 @@ export default registerPage(Page, { name: "${name18}" });
437169
437334
  handleReparent = async (payload, writeFile9 = true) => {
437170
437335
  const { from, to, changedProps, transaction } = payload;
437171
437336
  this.trackTransaction(transaction?.id);
437172
- await this.sourceTracker?.setProperties({
437337
+ this.sourceTracker?.setProperties({
437173
437338
  source: from.source,
437174
437339
  changes: changedProps ?? {}
437175
437340
  });
437176
- await this.sourceTracker?.moveElement({
437341
+ this.sourceTracker?.moveElement({
437177
437342
  from,
437178
437343
  to
437179
437344
  });
@@ -437187,7 +437352,7 @@ export default registerPage(Page, { name: "${name18}" });
437187
437352
  };
437188
437353
  handleCreateComponent = async (payload, writeFile9 = true) => {
437189
437354
  this.trackTransaction(payload.transaction?.id);
437190
- const sourceId = await this.sourceTracker?.addElement(payload);
437355
+ const sourceId = this.sourceTracker?.addElement(payload);
437191
437356
  if (writeFile9) {
437192
437357
  const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
437193
437358
  await this.writeChanges(changes ?? [], (fileName) => {
@@ -437201,7 +437366,7 @@ export default registerPage(Page, { name: "${name18}" });
437201
437366
  const { elements, transaction } = payload;
437202
437367
  this.trackTransaction(transaction?.id);
437203
437368
  for (const element of elements) {
437204
- await this.sourceTracker?.deleteElement({
437369
+ this.sourceTracker?.deleteElement({
437205
437370
  source: element.source,
437206
437371
  scopeName: element.scopeName
437207
437372
  });
@@ -437217,7 +437382,7 @@ export default registerPage(Page, { name: "${name18}" });
437217
437382
  handleSetProperty = async (payload, writeFile9 = true) => {
437218
437383
  const { element: { source: source2 }, property, value: value2, transaction } = payload;
437219
437384
  this.trackTransaction(transaction?.id);
437220
- await this.sourceTracker?.setProperty({
437385
+ this.sourceTracker?.setProperty({
437221
437386
  source: source2,
437222
437387
  property,
437223
437388
  info: value2
@@ -437232,7 +437397,7 @@ export default registerPage(Page, { name: "${name18}" });
437232
437397
  handleSetProperties = async (payload, writeFile9 = true) => {
437233
437398
  const { element: { source: source2 }, properties, transaction } = payload;
437234
437399
  this.trackTransaction(transaction?.id);
437235
- await this.sourceTracker?.setProperties({
437400
+ this.sourceTracker?.setProperties({
437236
437401
  source: source2,
437237
437402
  changes: properties
437238
437403
  });
@@ -437362,7 +437527,7 @@ export default registerPage(Page, { name: "${name18}" });
437362
437527
  await fs12.rmdir(apiDir, { recursive: true });
437363
437528
  }
437364
437529
  delete this.apiFiles[apiFilePath];
437365
- const scopeId = await this.sourceTracker.deleteApi({
437530
+ const scopeId = this.sourceTracker.deleteApi({
437366
437531
  pageName,
437367
437532
  apiName
437368
437533
  });
@@ -437456,7 +437621,7 @@ export default registerPage(Page, { name: "${name18}" });
437456
437621
  }));
437457
437622
  };
437458
437623
  handleAddEntity = async (payload) => {
437459
- await this.sourceTracker?.addEntity({
437624
+ this.sourceTracker?.addEntity({
437460
437625
  scopeId: payload.scopeId,
437461
437626
  entity: {
437462
437627
  type: payload.type,
@@ -437470,7 +437635,7 @@ export default registerPage(Page, { name: "${name18}" });
437470
437635
  });
437471
437636
  };
437472
437637
  handleUpdateEntity = async (payload) => {
437473
- await this.sourceTracker?.updateEntity({
437638
+ this.sourceTracker?.updateEntity({
437474
437639
  entityId: payload.entityId,
437475
437640
  updates: payload.updates
437476
437641
  });
@@ -437480,7 +437645,7 @@ export default registerPage(Page, { name: "${name18}" });
437480
437645
  });
437481
437646
  };
437482
437647
  handleDeleteEntity = async (payload) => {
437483
- const deletedEntityName = await this.sourceTracker?.deleteEntity({
437648
+ const deletedEntityName = this.sourceTracker?.deleteEntity({
437484
437649
  entityId: payload.entityId
437485
437650
  });
437486
437651
  const changes = await this.sourceTracker?.getAndFlushChanges() ?? [];
@@ -437496,7 +437661,7 @@ export default registerPage(Page, { name: "${name18}" });
437496
437661
  throw new Error("Root directory not set");
437497
437662
  }
437498
437663
  const filePath = path27.join(this.rootDir, APP_THEME_FILE_NAME);
437499
- await this.sourceTracker?.updateTheme({
437664
+ this.sourceTracker?.updateTheme({
437500
437665
  themeFilePath: filePath,
437501
437666
  theme
437502
437667
  });
@@ -437532,7 +437697,7 @@ export default registerPage(Page, { name: "${name18}" });
437532
437697
  };
437533
437698
  handleRenameEntity = async (payload) => {
437534
437699
  const { elementId, newName, oldName, scopeName } = payload;
437535
- await this.sourceTracker?.renameEntity({
437700
+ this.sourceTracker?.renameEntity({
437536
437701
  entityId: elementId,
437537
437702
  oldName,
437538
437703
  newName,
@@ -438217,7 +438382,7 @@ var fileSyncVitePlugin = (pluginParams, options9) => {
438217
438382
  const aiService = pluginParams.aiService;
438218
438383
  const fsOperationQueue = pluginParams.fsOperationQueue;
438219
438384
  const httpServer2 = pluginParams.httpServer;
438220
- const fileSyncManager = new FileSyncManager(fsOperationQueue, generationNumberSequence, pluginParams.tracer);
438385
+ const fileSyncManager = new FileSystemManager(fsOperationQueue, generationNumberSequence, pluginParams.tracer);
438221
438386
  if (syncService) {
438222
438387
  syncService.generationNumberSequence = generationNumberSequence;
438223
438388
  }
@@ -438630,7 +438795,12 @@ var fileSyncVitePlugin = (pluginParams, options9) => {
438630
438795
  return socket.call.aiSetDraftState({ hasDraft });
438631
438796
  });
438632
438797
  });
438633
- aiService.on("generationCompleted", (hasDraft) => {
438798
+ aiService.on("generationStarted", () => {
438799
+ fileSyncManager.enableOperationsQueue();
438800
+ });
438801
+ aiService.on("generationCompleted", async (hasDraft) => {
438802
+ fileSyncManager.disableOperationsQueue();
438803
+ await fileSyncManager.flushOperations();
438634
438804
  if (hasDraft) {
438635
438805
  logger3.info("Requesting full reload to render AI draft");
438636
438806
  server.ws.send({
@@ -442607,7 +442777,7 @@ var import_util30 = __toESM(require_dist3(), 1);
442607
442777
  // ../sdk/package.json
442608
442778
  var package_default = {
442609
442779
  name: "@superblocksteam/sdk",
442610
- version: "2.0.6-next.16",
442780
+ version: "2.0.6-next.17",
442611
442781
  type: "module",
442612
442782
  description: "Superblocks JS SDK",
442613
442783
  homepage: "https://www.superblocks.com",
@@ -442648,11 +442818,11 @@ var package_default = {
442648
442818
  "@opentelemetry/semantic-conventions": "^1.28.0",
442649
442819
  "@rollup/wasm-node": "^4.35.0",
442650
442820
  "@superblocksteam/bucketeer-sdk": "0.5.0",
442651
- "@superblocksteam/library": "2.0.6-next.16",
442652
- "@superblocksteam/library-shared": "2.0.6-next.16",
442821
+ "@superblocksteam/library": "2.0.6-next.17",
442822
+ "@superblocksteam/library-shared": "2.0.6-next.17",
442653
442823
  "@superblocksteam/shared": "0.9198.0",
442654
- "@superblocksteam/util": "2.0.6-next.16",
442655
- "@superblocksteam/vite-plugin-file-sync": "2.0.6-next.16",
442824
+ "@superblocksteam/util": "2.0.6-next.17",
442825
+ "@superblocksteam/vite-plugin-file-sync": "2.0.6-next.17",
442656
442826
  "@vitejs/plugin-react": "^4.3.4",
442657
442827
  axios: "^1.4.0",
442658
442828
  chokidar: "^4.0.3",
@@ -450223,7 +450393,8 @@ async function startVite({ app, httpServer: httpServer2, root: root2, mode, port
450223
450393
  };
450224
450394
  const isCustomBuildEnabled2 = await isCustomComponentsEnabled();
450225
450395
  const customFolder = path37.join(root2, "custom");
450226
- const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.6-next.16";
450396
+ const draftsFolder = path37.join(root2, ".superblocks");
450397
+ const cdnUrl = "https://assets-cdn.superblocks.com/library/2.0.6-next.17";
450227
450398
  const env3 = loadEnv(mode, root2, "");
450228
450399
  const hmrPort = await getFreePort();
450229
450400
  const hmrOptions = {
@@ -450254,10 +450425,7 @@ async function startVite({ app, httpServer: httpServer2, root: root2, mode, port
450254
450425
  server: {
450255
450426
  middlewareMode: true,
450256
450427
  watch: {
450257
- ignored: [
450258
- `${customFolder}/**/*`,
450259
- `${root2}/.superblocks/{generations,drafts}/**/*`
450260
- ]
450428
+ ignored: [`${customFolder}/**/*`, `${draftsFolder}/**/*`]
450261
450429
  },
450262
450430
  hmr: hmrOptions,
450263
450431
  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.17"
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.17",
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.17",
46
46
  "@superblocksteam/shared": "0.9198.0",
47
- "@superblocksteam/util": "2.0.6-next.16",
47
+ "@superblocksteam/util": "2.0.6-next.17",
48
48
  "@types/babel__core": "^7.20.0",
49
49
  "@types/chai": "^4",
50
50
  "@types/fs-extra": "^11.0.1",