@vedangiitb/qwintly-core 1.3.12 → 1.3.14

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/dist/core.d.ts CHANGED
@@ -36,6 +36,7 @@ export declare class QwintlyCore {
36
36
  private readonly statusRepo;
37
37
  private readonly ctxRepo;
38
38
  private readonly redisStatusPublisher;
39
+ private readonly projectOpsRepo;
39
40
  constructor(options: QwintlyCoreOptions);
40
41
  runAiFlow(initialContents: any[], tools: Tool[], handlers: Record<string, ToolHandler>, maxSteps: number, terminalToolNames: string[]): Promise<ToolLoopResult>;
41
42
  streamLog(message: string, eventType: EventType, displayedSummary?: boolean): Promise<void>;
@@ -44,5 +45,6 @@ export declare class QwintlyCore {
44
45
  buildPlannerIdx(): Promise<PlannerIndex>;
45
46
  buildCodegenIdx(): Promise<CodegenIndex>;
46
47
  buildValidatorIdx(): Promise<ValidatorIndex>;
48
+ syncEditOps(genId: string, workspace: string): Promise<boolean>;
47
49
  }
48
50
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAGL,WAAW,EACX,cAAc,EACf,MAAM,iCAAiC,CAAC;AAUzC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAIhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAiBF,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,OAAO,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoB;gBAE7C,OAAO,EAAE,kBAAkB;IAuD1B,SAAS,CACpB,eAAe,EAAE,GAAG,EAAE,EACtB,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,cAAc,CAAC;IAwBb,SAAS,CACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,IAAI,CAAC;IA2BH,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC;YAQ1C,UAAU;IAMX,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;CAG1D"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,IAAI,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAGL,WAAW,EACX,cAAc,EACf,MAAM,iCAAiC,CAAC;AAazC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,cAAc,EACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAGhE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAiBF,qBAAa,WAAW;IACtB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,SAAgB,IAAI,EAAE,OAAO,CAAC;IAE9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAoB;IACzD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;gBAE1C,OAAO,EAAE,kBAAkB;IA2D1B,SAAS,CACpB,eAAe,EAAE,GAAG,EAAE,EACtB,KAAK,EAAE,IAAI,EAAE,EACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,GAC1B,OAAO,CAAC,cAAc,CAAC;IAwBb,SAAS,CACpB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,EACpB,gBAAgB,GAAE,OAAe,GAChC,OAAO,CAAC,IAAI,CAAC;IA2BH,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC;YAQ1C,UAAU;IAMX,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAIxC,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;IAI5C,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAY7E"}
package/dist/core.js CHANGED
@@ -9,8 +9,10 @@ import { statusService } from "./logging/genStatus.service.js";
9
9
  import { SendStatusToRedis } from "./logging/redis.service.js";
10
10
  import { ContextRepository } from "./repository/context.repository.js";
11
11
  import { GenStatusRepository } from "./repository/genStatus.repository.js";
12
- import { assertNonEmptyString } from "./utils/utils.js";
12
+ import { ProjectOpsRepository } from "./repository/projectOperations.repository.js";
13
+ import { applyOperations } from "./services/syncEditOps.service.js";
13
14
  import { initializeToolCallsRepository } from "./services/toolcallPersist.service.js";
15
+ import { assertNonEmptyString } from "./utils/utils.js";
14
16
  export class QwintlyCore {
15
17
  constructor(options) {
16
18
  assertNonEmptyString(options.chatId, "chatId");
@@ -38,6 +40,7 @@ export class QwintlyCore {
38
40
  }
39
41
  this.statusRepo = new GenStatusRepository(options.supabase.endpoint, options.supabase.secret);
40
42
  this.ctxRepo = new ContextRepository(options.supabase.endpoint, options.supabase.secret);
43
+ this.projectOpsRepo = new ProjectOpsRepository(options.supabase.endpoint, options.supabase.secret);
41
44
  this.redisStatusPublisher = new SendStatusToRedis(options.upstash.url, options.upstash.token);
42
45
  initializeToolCallsRepository(options.supabase.endpoint, options.supabase.secret, options.sessionId);
43
46
  console.log(`QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`);
@@ -94,5 +97,19 @@ export class QwintlyCore {
94
97
  async buildValidatorIdx() {
95
98
  return this.buildIndex(buildValidatorIndex);
96
99
  }
100
+ async syncEditOps(genId, workspace) {
101
+ if (!genId)
102
+ return false;
103
+ const projectOpsRepo = this.projectOpsRepo;
104
+ const ops = await projectOpsRepo.fetchProjectOperations(genId);
105
+ if (!ops || ops.length === 0)
106
+ return false;
107
+ const appliedIds = await applyOperations(ops, workspace);
108
+ if (appliedIds.length > 0) {
109
+ await projectOpsRepo.markOperationsApplied(appliedIds);
110
+ }
111
+ const isModified = appliedIds.length > 0;
112
+ return isModified;
113
+ }
97
114
  }
98
115
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport { getClient } from \"./ai/generate/generateClient.js\";\nimport {\n runToolLoop,\n RunToolLoopOptions,\n ToolHandler,\n ToolLoopResult,\n} from \"./ai/toolLoop/toolLoopRunner.js\";\nimport { initUnsplash } from \"./image/unsplash.service.js\";\nimport { buildCodegenIndex } from \"./indexer/codegenIndex.js\";\nimport { buildPlannerIndex } from \"./indexer/plannerIndex.js\";\nimport { computeProjectInfo } from \"./indexer/projectInfoIndex.js\";\nimport { buildValidatorIndex } from \"./indexer/validatorIndex.js\";\nimport { statusService } from \"./logging/genStatus.service.js\";\nimport { SendStatusToRedis } from \"./logging/redis.service.js\";\nimport { ContextRepository } from \"./repository/context.repository.js\";\nimport { GenStatusRepository } from \"./repository/genStatus.repository.js\";\nimport { EventType, GenStep } from \"./types/events.js\";\nimport {\n CodegenIndex,\n PlannerIndex,\n ValidatorIndex,\n} from \"./types/index/index.types.js\";\nimport type { ProjectInfo } from \"./types/projectInfo.types.js\";\nimport { assertNonEmptyString } from \"./utils/utils.js\";\nimport { initializeToolCallsRepository } from \"./services/toolcallPersist.service.js\";\n\nexport type QwintlyCoreOptions = {\n chatId: string;\n sessionId: string;\n workspacePath: string;\n source: string;\n step: GenStep;\n supabase: { endpoint: string; secret: string };\n upstash: { url: string; token: string };\n unsplash: { url: string; accessKey: string };\n gemini?: { apiKey: string; model?: string };\n};\n\ntype AiResponseOptions = {\n tools?: Tool[];\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\ntype AiClient = {\n aiResponse: (\n request: unknown,\n options?: AiResponseOptions,\n ) => Promise<{\n functionCalls?: any[];\n text?: string;\n }>;\n};\n\nexport class QwintlyCore {\n public readonly chatId: string;\n public readonly sessionId: string;\n public readonly workspacePath: string;\n public readonly source: string;\n public readonly step: GenStep;\n\n private readonly aiClient?: AiClient;\n private readonly statusRepo: GenStatusRepository;\n private readonly ctxRepo: ContextRepository;\n private readonly redisStatusPublisher: SendStatusToRedis;\n\n constructor(options: QwintlyCoreOptions) {\n assertNonEmptyString(options.chatId, \"chatId\");\n assertNonEmptyString(options.sessionId, \"sessionId\");\n assertNonEmptyString(options.workspacePath, \"workspacePath\");\n assertNonEmptyString(options.source, \"source\");\n assertNonEmptyString(options.step, \"step\");\n assertNonEmptyString(options.supabase?.endpoint, \"supabase.endpoint\");\n assertNonEmptyString(options.supabase?.secret, \"supabase.secret\");\n assertNonEmptyString(options.upstash?.url, \"upstash.url\");\n assertNonEmptyString(options.upstash?.token, \"upstash.token\");\n\n this.chatId = options.chatId;\n this.sessionId = options.sessionId;\n this.workspacePath = options.workspacePath;\n this.source = options.source;\n this.step = options.step;\n\n if (options.unsplash?.url && options.unsplash?.accessKey) {\n initUnsplash({\n url: options.unsplash.url,\n accessKey: options.unsplash.accessKey,\n });\n }\n\n if (options.gemini?.apiKey) {\n this.aiClient = getClient(\n \"gemini\",\n options.gemini.apiKey,\n options.gemini.model,\n ) as AiClient;\n }\n\n this.statusRepo = new GenStatusRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.ctxRepo = new ContextRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.redisStatusPublisher = new SendStatusToRedis(\n options.upstash.url,\n options.upstash.token,\n );\n initializeToolCallsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n options.sessionId,\n );\n\n console.log(\n `QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`,\n );\n }\n\n public async runAiFlow(\n initialContents: any[],\n tools: Tool[],\n handlers: Record<string, ToolHandler>,\n maxSteps: number,\n terminalToolNames: string[],\n ): Promise<ToolLoopResult> {\n if (!this.aiClient) {\n throw new Error(\n \"AI client not initialized. Please provide 'gemini' config to use runAiFlow.\",\n );\n }\n const toolLoopOptions: RunToolLoopOptions = {\n initialContents: initialContents,\n tools: tools,\n handlers: handlers,\n maxSteps: maxSteps,\n terminalToolNames: terminalToolNames,\n aiCall: (request, options) =>\n this.aiClient!.aiResponse(request, {\n tools: options.tools,\n toolCallingMode: options.toolCallingMode,\n }),\n logger: this.streamLog.bind(this),\n };\n\n const result = await runToolLoop(toolLoopOptions);\n return result;\n }\n\n public async streamLog(\n message: string,\n eventType: EventType,\n displayedSummary: boolean = false,\n ): Promise<void> {\n try {\n assertNonEmptyString(message, \"message\");\n await statusService(\n this.chatId,\n this.sessionId,\n eventType,\n this.step,\n message,\n this.source,\n {\n repository: {\n persist: this.statusRepo.persistStatusMessage.bind(this.statusRepo),\n },\n publisher: {\n publish: this.redisStatusPublisher.sendStatusToRedis.bind(\n this.redisStatusPublisher,\n ),\n },\n },\n displayedSummary,\n );\n } catch (error) {\n console.error(error);\n }\n }\n\n public async buildProjectInfoIdx(): Promise<ProjectInfo> {\n const projectInfo = await computeProjectInfo(this.workspacePath);\n\n await this.ctxRepo.updateProjectInfo(this.chatId, projectInfo);\n\n return projectInfo;\n }\n\n private async buildIndex<T>(\n builder: (path: string) => Promise<T>,\n ): Promise<T> {\n return builder(this.workspacePath);\n }\n\n public async buildPlannerIdx(): Promise<PlannerIndex> {\n return this.buildIndex(buildPlannerIndex);\n }\n\n public async buildCodegenIdx(): Promise<CodegenIndex> {\n return this.buildIndex(buildCodegenIndex);\n }\n\n public async buildValidatorIdx(): Promise<ValidatorIndex> {\n return this.buildIndex(buildValidatorIndex);\n }\n}\n"]}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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","sourcesContent":["import { FunctionCallingConfigMode, Tool } from \"@google/genai\";\nimport { getClient } from \"./ai/generate/generateClient.js\";\nimport {\n runToolLoop,\n RunToolLoopOptions,\n ToolHandler,\n ToolLoopResult,\n} from \"./ai/toolLoop/toolLoopRunner.js\";\nimport { initUnsplash } from \"./image/unsplash.service.js\";\nimport { buildCodegenIndex } from \"./indexer/codegenIndex.js\";\nimport { buildPlannerIndex } from \"./indexer/plannerIndex.js\";\nimport { computeProjectInfo } from \"./indexer/projectInfoIndex.js\";\nimport { buildValidatorIndex } from \"./indexer/validatorIndex.js\";\nimport { statusService } from \"./logging/genStatus.service.js\";\nimport { SendStatusToRedis } from \"./logging/redis.service.js\";\nimport { ContextRepository } from \"./repository/context.repository.js\";\nimport { GenStatusRepository } from \"./repository/genStatus.repository.js\";\nimport { ProjectOpsRepository } from \"./repository/projectOperations.repository.js\";\nimport { applyOperations } from \"./services/syncEditOps.service.js\";\nimport { initializeToolCallsRepository } from \"./services/toolcallPersist.service.js\";\nimport { EventType, GenStep } from \"./types/events.js\";\nimport {\n CodegenIndex,\n PlannerIndex,\n ValidatorIndex,\n} from \"./types/index/index.types.js\";\nimport type { ProjectInfo } from \"./types/projectInfo.types.js\";\nimport { assertNonEmptyString } from \"./utils/utils.js\";\n\nexport type QwintlyCoreOptions = {\n chatId: string;\n sessionId: string;\n workspacePath: string;\n source: string;\n step: GenStep;\n supabase: { endpoint: string; secret: string };\n upstash: { url: string; token: string };\n unsplash: { url: string; accessKey: string };\n gemini?: { apiKey: string; model?: string };\n};\n\ntype AiResponseOptions = {\n tools?: Tool[];\n toolCallingMode?: FunctionCallingConfigMode;\n};\n\ntype AiClient = {\n aiResponse: (\n request: unknown,\n options?: AiResponseOptions,\n ) => Promise<{\n functionCalls?: any[];\n text?: string;\n }>;\n};\n\nexport class QwintlyCore {\n public readonly chatId: string;\n public readonly sessionId: string;\n public readonly workspacePath: string;\n public readonly source: string;\n public readonly step: GenStep;\n\n private readonly aiClient?: AiClient;\n private readonly statusRepo: GenStatusRepository;\n private readonly ctxRepo: ContextRepository;\n private readonly redisStatusPublisher: SendStatusToRedis;\n private readonly projectOpsRepo: ProjectOpsRepository;\n\n constructor(options: QwintlyCoreOptions) {\n assertNonEmptyString(options.chatId, \"chatId\");\n assertNonEmptyString(options.sessionId, \"sessionId\");\n assertNonEmptyString(options.workspacePath, \"workspacePath\");\n assertNonEmptyString(options.source, \"source\");\n assertNonEmptyString(options.step, \"step\");\n assertNonEmptyString(options.supabase?.endpoint, \"supabase.endpoint\");\n assertNonEmptyString(options.supabase?.secret, \"supabase.secret\");\n assertNonEmptyString(options.upstash?.url, \"upstash.url\");\n assertNonEmptyString(options.upstash?.token, \"upstash.token\");\n\n this.chatId = options.chatId;\n this.sessionId = options.sessionId;\n this.workspacePath = options.workspacePath;\n this.source = options.source;\n this.step = options.step;\n\n if (options.unsplash?.url && options.unsplash?.accessKey) {\n initUnsplash({\n url: options.unsplash.url,\n accessKey: options.unsplash.accessKey,\n });\n }\n\n if (options.gemini?.apiKey) {\n this.aiClient = getClient(\n \"gemini\",\n options.gemini.apiKey,\n options.gemini.model,\n ) as AiClient;\n }\n\n this.statusRepo = new GenStatusRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.ctxRepo = new ContextRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.projectOpsRepo = new ProjectOpsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n );\n this.redisStatusPublisher = new SendStatusToRedis(\n options.upstash.url,\n options.upstash.token,\n );\n initializeToolCallsRepository(\n options.supabase.endpoint,\n options.supabase.secret,\n options.sessionId,\n );\n\n console.log(\n `QwintlyCore initialized (chatId=${this.chatId}, sessionId=${this.sessionId})`,\n );\n }\n\n public async runAiFlow(\n initialContents: any[],\n tools: Tool[],\n handlers: Record<string, ToolHandler>,\n maxSteps: number,\n terminalToolNames: string[],\n ): Promise<ToolLoopResult> {\n if (!this.aiClient) {\n throw new Error(\n \"AI client not initialized. Please provide 'gemini' config to use runAiFlow.\",\n );\n }\n const toolLoopOptions: RunToolLoopOptions = {\n initialContents: initialContents,\n tools: tools,\n handlers: handlers,\n maxSteps: maxSteps,\n terminalToolNames: terminalToolNames,\n aiCall: (request, options) =>\n this.aiClient!.aiResponse(request, {\n tools: options.tools,\n toolCallingMode: options.toolCallingMode,\n }),\n logger: this.streamLog.bind(this),\n };\n\n const result = await runToolLoop(toolLoopOptions);\n return result;\n }\n\n public async streamLog(\n message: string,\n eventType: EventType,\n displayedSummary: boolean = false,\n ): Promise<void> {\n try {\n assertNonEmptyString(message, \"message\");\n await statusService(\n this.chatId,\n this.sessionId,\n eventType,\n this.step,\n message,\n this.source,\n {\n repository: {\n persist: this.statusRepo.persistStatusMessage.bind(this.statusRepo),\n },\n publisher: {\n publish: this.redisStatusPublisher.sendStatusToRedis.bind(\n this.redisStatusPublisher,\n ),\n },\n },\n displayedSummary,\n );\n } catch (error) {\n console.error(error);\n }\n }\n\n public async buildProjectInfoIdx(): Promise<ProjectInfo> {\n const projectInfo = await computeProjectInfo(this.workspacePath);\n\n await this.ctxRepo.updateProjectInfo(this.chatId, projectInfo);\n\n return projectInfo;\n }\n\n private async buildIndex<T>(\n builder: (path: string) => Promise<T>,\n ): Promise<T> {\n return builder(this.workspacePath);\n }\n\n public async buildPlannerIdx(): Promise<PlannerIndex> {\n return this.buildIndex(buildPlannerIndex);\n }\n\n public async buildCodegenIdx(): Promise<CodegenIndex> {\n return this.buildIndex(buildCodegenIndex);\n }\n\n public async buildValidatorIdx(): Promise<ValidatorIndex> {\n return this.buildIndex(buildValidatorIndex);\n }\n\n public async syncEditOps(genId: string, workspace: string): Promise<boolean> {\n if (!genId) return false;\n const projectOpsRepo = this.projectOpsRepo;\n const ops = await projectOpsRepo.fetchProjectOperations(genId);\n if (!ops || ops.length === 0) return false;\n const appliedIds = await applyOperations(ops, workspace);\n if (appliedIds.length > 0) {\n await projectOpsRepo.markOperationsApplied(appliedIds);\n }\n const isModified = appliedIds.length > 0;\n return isModified;\n }\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import { DBRepository } from "./repository.js";
2
+ export declare class ProjectOpsRepository extends DBRepository {
3
+ fetchProjectOperations(genId: string): Promise<any>;
4
+ markOperationsApplied(ids: string[]): Promise<void>;
5
+ }
6
+ //# sourceMappingURL=projectOperations.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectOperations.repository.d.ts","sourceRoot":"","sources":["../../src/repository/projectOperations.repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,qBAAa,oBAAqB,SAAQ,YAAY;IAM9C,sBAAsB,CAAC,KAAK,EAAE,MAAM;IAiBpC,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE;CAY1C"}
@@ -0,0 +1,35 @@
1
+ import { DBRepository } from "./repository.js";
2
+ export class ProjectOpsRepository extends DBRepository {
3
+ /*
4
+ * Table: project_operations
5
+ * Use: Fetch queued project operations
6
+ */
7
+ async fetchProjectOperations(genId) {
8
+ const supabase = this.client;
9
+ const { data, error } = await supabase
10
+ .from("project_operations")
11
+ .select("id, operation, route")
12
+ .eq("gen_id", genId)
13
+ .eq("status", "queued")
14
+ .order("created_at", { ascending: true });
15
+ if (error)
16
+ throw error;
17
+ return data;
18
+ }
19
+ /*
20
+ * Table: project_operations
21
+ * Use: Update project operation status
22
+ */
23
+ async markOperationsApplied(ids) {
24
+ if (!Array.isArray(ids) || ids.length === 0)
25
+ return;
26
+ const supabase = this.client;
27
+ const { error } = await supabase
28
+ .from("project_operations")
29
+ .update({ status: "applied" })
30
+ .in("id", ids);
31
+ if (error)
32
+ throw error;
33
+ }
34
+ }
35
+ //# sourceMappingURL=projectOperations.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectOperations.repository.js","sourceRoot":"","sources":["../../src/repository/projectOperations.repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD;;;OAGG;IAEH,KAAK,CAAC,sBAAsB,CAAC,KAAa;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAE7B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ;aACnC,IAAI,CAAC,oBAAoB,CAAC;aAC1B,MAAM,CAAC,sBAAsB,CAAC;aAC9B,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;aACnB,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;aACtB,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,qBAAqB,CAAC,GAAa;QACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEpD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ;aAC7B,IAAI,CAAC,oBAAoB,CAAC;aAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;aAC7B,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAEjB,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC;IACzB,CAAC;CAEF","sourcesContent":["import { DBRepository } from \"./repository.js\";\r\n\r\nexport class ProjectOpsRepository extends DBRepository {\n /*\r\n * Table: project_operations\r\n * Use: Fetch queued project operations\r\n */\r\n\r\n async fetchProjectOperations(genId: string) {\n const supabase = this.client;\r\n\r\n const { data, error } = await supabase\r\n .from(\"project_operations\")\r\n .select(\"id, operation, route\")\r\n .eq(\"gen_id\", genId)\r\n .eq(\"status\", \"queued\")\r\n .order(\"created_at\", { ascending: true });\r\n if (error) throw error;\n return data;\n }\n\n /*\n * Table: project_operations\n * Use: Update project operation status\n */\n async markOperationsApplied(ids: string[]) {\n if (!Array.isArray(ids) || ids.length === 0) return;\n\n const supabase = this.client;\n const { error } = await supabase\n .from(\"project_operations\")\n .update({ status: \"applied\" })\n .in(\"id\", ids);\n\n if (error) throw error;\n }\n\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const applyOperations: (ops: any, workspace: string) => Promise<string[]>;
2
+ //# sourceMappingURL=syncEditOps.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncEditOps.service.d.ts","sourceRoot":"","sources":["../../src/services/syncEditOps.service.ts"],"names":[],"mappings":"AA0HA,eAAO,MAAM,eAAe,GAC1B,KAAK,GAAG,EACR,WAAW,MAAM,KAChB,OAAO,CAAC,MAAM,EAAE,CAuHlB,CAAC"}
@@ -0,0 +1,221 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ async function pathExists(p) {
4
+ try {
5
+ await fs.stat(p);
6
+ return true;
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ function isRouteGroupSegment(segment) {
13
+ return segment.startsWith("(") && segment.endsWith(")");
14
+ }
15
+ function routeFromAppDir(appRoot, dirAbsPath) {
16
+ const rel = path.relative(appRoot, dirAbsPath);
17
+ if (!rel || rel === ".")
18
+ return "/";
19
+ const parts = rel
20
+ .split(path.sep)
21
+ .filter(Boolean)
22
+ .filter((seg) => {
23
+ if (isRouteGroupSegment(seg))
24
+ return false;
25
+ if (seg.startsWith("@"))
26
+ return false; // parallel routes
27
+ return true;
28
+ });
29
+ return `/${parts.join("/")}`;
30
+ }
31
+ async function walkDirs(rootAbs) {
32
+ const dirs = [];
33
+ const queue = [rootAbs];
34
+ while (queue.length) {
35
+ const current = queue.shift();
36
+ dirs.push(current);
37
+ const entries = await fs.readdir(current, { withFileTypes: true });
38
+ for (const entry of entries) {
39
+ if (!entry.isDirectory())
40
+ continue;
41
+ queue.push(path.join(current, entry.name));
42
+ }
43
+ }
44
+ return dirs;
45
+ }
46
+ async function readJsonFile(filePath) {
47
+ const raw = await fs.readFile(filePath, "utf-8");
48
+ return JSON.parse(raw);
49
+ }
50
+ async function writeJsonFile(filePath, value) {
51
+ const out = `${JSON.stringify(value, null, 2)}\n`;
52
+ await fs.writeFile(filePath, out, "utf-8");
53
+ }
54
+ function findElementById(elements, id) {
55
+ for (const element of elements) {
56
+ if (!element || typeof element !== "object")
57
+ continue;
58
+ if (element.id === id)
59
+ return { element, parent: null };
60
+ const children = element.children;
61
+ if (Array.isArray(children) && children.length) {
62
+ const found = findElementById(children, id);
63
+ if (found)
64
+ return { element: found.element, parent: element };
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ function removeElementById(elements, id) {
70
+ for (let i = 0; i < elements.length; i++) {
71
+ const el = elements[i];
72
+ if (!el || typeof el !== "object")
73
+ continue;
74
+ if (el.id === id) {
75
+ elements.splice(i, 1);
76
+ return true;
77
+ }
78
+ if (Array.isArray(el.children) && el.children.length) {
79
+ const removed = removeElementById(el.children, id);
80
+ if (removed)
81
+ return true;
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ function normalizeOps(value) {
87
+ if (!value)
88
+ return [];
89
+ if (Array.isArray(value))
90
+ return value;
91
+ if (typeof value === "string") {
92
+ try {
93
+ const parsed = JSON.parse(value);
94
+ return Array.isArray(parsed) ? parsed : [];
95
+ }
96
+ catch {
97
+ return [];
98
+ }
99
+ }
100
+ return [];
101
+ }
102
+ function normalizeRoute(value) {
103
+ if (typeof value !== "string")
104
+ return "";
105
+ const trimmed = value.trim();
106
+ if (!trimmed)
107
+ return "";
108
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
109
+ }
110
+ export const applyOperations = async (ops, workspace) => {
111
+ const appRoot = path.join(workspace, "app");
112
+ if (!(await pathExists(appRoot)))
113
+ return [];
114
+ const rows = Array.isArray(ops) ? ops : [];
115
+ if (rows.length === 0)
116
+ return [];
117
+ // Map route -> pageConfig.json path
118
+ const routeToConfigPath = new Map();
119
+ const allDirs = await walkDirs(appRoot);
120
+ for (const dirAbs of allDirs) {
121
+ const pageTsx = path.join(dirAbs, "page.tsx");
122
+ const pageConfigJson = path.join(dirAbs, "pageConfig.json");
123
+ const hasPage = await pathExists(pageTsx);
124
+ const hasConfig = await pathExists(pageConfigJson);
125
+ if (!hasPage || !hasConfig)
126
+ continue;
127
+ const routeKey = routeFromAppDir(appRoot, dirAbs);
128
+ routeToConfigPath.set(routeKey, pageConfigJson);
129
+ }
130
+ // Group ops per route so we only read/write each config once.
131
+ const opsByRoute = new Map();
132
+ for (const row of rows) {
133
+ if (!row || typeof row !== "object")
134
+ continue;
135
+ const rowId = typeof row.id === "string" ? row.id : "";
136
+ if (!rowId)
137
+ continue;
138
+ const route = normalizeRoute(row.route);
139
+ if (!route)
140
+ continue;
141
+ const list = normalizeOps(row.operation);
142
+ if (list.length === 0)
143
+ continue;
144
+ const existing = opsByRoute.get(route) ?? [];
145
+ existing.push({ rowId, ops: list });
146
+ opsByRoute.set(route, existing);
147
+ }
148
+ const appliedIds = new Set();
149
+ for (const [route, entries] of opsByRoute) {
150
+ const configPath = routeToConfigPath.get(route);
151
+ if (!configPath)
152
+ continue;
153
+ let config;
154
+ try {
155
+ config = await readJsonFile(configPath);
156
+ }
157
+ catch {
158
+ continue;
159
+ }
160
+ if (!config || typeof config !== "object")
161
+ continue;
162
+ if (!Array.isArray(config.elements))
163
+ continue;
164
+ let changed = false;
165
+ for (const entry of entries) {
166
+ let rowChanged = false;
167
+ for (const op of entry.ops) {
168
+ if (!op || typeof op !== "object")
169
+ continue;
170
+ const kind = op.kind;
171
+ if (kind === "text") {
172
+ const id = op.id;
173
+ const newText = op.newText;
174
+ if (typeof id !== "string" || typeof newText !== "string")
175
+ continue;
176
+ const found = findElementById(config.elements, id);
177
+ if (!found)
178
+ continue;
179
+ found.element.props = {
180
+ ...(found.element.props ?? {}),
181
+ text: newText,
182
+ };
183
+ changed = true;
184
+ rowChanged = true;
185
+ continue;
186
+ }
187
+ if (kind === "delete") {
188
+ const id = op.id;
189
+ const parentId = op.parentId;
190
+ if (typeof id !== "string")
191
+ continue;
192
+ if (typeof parentId === "string" && parentId) {
193
+ const parent = findElementById(config.elements, parentId)?.element;
194
+ if (parent?.children && Array.isArray(parent.children)) {
195
+ const before = parent.children.length;
196
+ parent.children = parent.children.filter((child) => child?.id !== id);
197
+ if (parent.children.length !== before) {
198
+ changed = true;
199
+ rowChanged = true;
200
+ }
201
+ continue;
202
+ }
203
+ }
204
+ // Fallback: locate and remove by id anywhere in the tree (including top-level).
205
+ if (removeElementById(config.elements, id)) {
206
+ changed = true;
207
+ rowChanged = true;
208
+ }
209
+ }
210
+ }
211
+ if (rowChanged) {
212
+ appliedIds.add(entry.rowId);
213
+ }
214
+ }
215
+ if (changed) {
216
+ await writeJsonFile(configPath, config);
217
+ }
218
+ }
219
+ return [...appliedIds];
220
+ };
221
+ //# sourceMappingURL=syncEditOps.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncEditOps.service.js","sourceRoot":"","sources":["../../src/services/syncEditOps.service.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { BuilderElement } from \"../types/elements.js\";\nimport { ProjectOp, ProjectOperationRow } from \"../types/projectOps.types.js\";\nimport { PageConfig } from \"../types/snapshot.js\";\n\nasync function pathExists(p: string) {\n try {\n await fs.stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isRouteGroupSegment(segment: string) {\n return segment.startsWith(\"(\") && segment.endsWith(\")\");\n}\n\nfunction routeFromAppDir(appRoot: string, dirAbsPath: string) {\n const rel = path.relative(appRoot, dirAbsPath);\n if (!rel || rel === \".\") return \"/\";\n\n const parts = rel\n .split(path.sep)\n .filter(Boolean)\n .filter((seg) => {\n if (isRouteGroupSegment(seg)) return false;\n if (seg.startsWith(\"@\")) return false; // parallel routes\n return true;\n });\n\n return `/${parts.join(\"/\")}`;\n}\n\nasync function walkDirs(rootAbs: string): Promise<string[]> {\n const dirs: string[] = [];\n const queue: string[] = [rootAbs];\n\n while (queue.length) {\n const current = queue.shift()!;\n dirs.push(current);\n\n const entries = await fs.readdir(current, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n queue.push(path.join(current, entry.name));\n }\n }\n\n return dirs;\n}\n\nasync function readJsonFile<T>(filePath: string): Promise<T> {\n const raw = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n}\n\nasync function writeJsonFile(filePath: string, value: unknown) {\n const out = `${JSON.stringify(value, null, 2)}\\n`;\n await fs.writeFile(filePath, out, \"utf-8\");\n}\n\nfunction findElementById(\n elements: BuilderElement[],\n id: string,\n): { element: BuilderElement; parent: BuilderElement | null } | null {\n for (const element of elements) {\n if (!element || typeof element !== \"object\") continue;\n if (element.id === id) return { element, parent: null };\n\n const children = element.children;\n if (Array.isArray(children) && children.length) {\n const found = findElementById(children, id);\n if (found) return { element: found.element, parent: element };\n }\n }\n return null;\n}\n\nfunction removeElementById(elements: BuilderElement[], id: string): boolean {\n for (let i = 0; i < elements.length; i++) {\n const el = elements[i];\n if (!el || typeof el !== \"object\") continue;\n\n if (el.id === id) {\n elements.splice(i, 1);\n return true;\n }\n\n if (Array.isArray(el.children) && el.children.length) {\n const removed = removeElementById(el.children, id);\n if (removed) return true;\n }\n }\n\n return false;\n}\n\nfunction normalizeOps(value: unknown): ProjectOp[] {\n if (!value) return [];\n if (Array.isArray(value)) return value as ProjectOp[];\n\n if (typeof value === \"string\") {\n try {\n const parsed = JSON.parse(value) as unknown;\n return Array.isArray(parsed) ? (parsed as ProjectOp[]) : [];\n } catch {\n return [];\n }\n }\n\n return [];\n}\n\nfunction normalizeRoute(value: unknown): string {\n if (typeof value !== \"string\") return \"\";\n const trimmed = value.trim();\n if (!trimmed) return \"\";\n return trimmed.startsWith(\"/\") ? trimmed : `/${trimmed}`;\n}\n\nexport const applyOperations = async (\n ops: any,\n workspace: string,\n): Promise<string[]> => {\n const appRoot = path.join(workspace, \"app\");\n if (!(await pathExists(appRoot))) return [];\n\n const rows: ProjectOperationRow[] = Array.isArray(ops) ? ops : [];\n if (rows.length === 0) return [];\n\n // Map route -> pageConfig.json path\n const routeToConfigPath = new Map<string, string>();\n const allDirs = await walkDirs(appRoot);\n for (const dirAbs of allDirs) {\n const pageTsx = path.join(dirAbs, \"page.tsx\");\n const pageConfigJson = path.join(dirAbs, \"pageConfig.json\");\n const hasPage = await pathExists(pageTsx);\n const hasConfig = await pathExists(pageConfigJson);\n if (!hasPage || !hasConfig) continue;\n\n const routeKey = routeFromAppDir(appRoot, dirAbs);\n routeToConfigPath.set(routeKey, pageConfigJson);\n }\n\n // Group ops per route so we only read/write each config once.\n const opsByRoute = new Map<string, { rowId: string; ops: ProjectOp[] }[]>();\n for (const row of rows) {\n if (!row || typeof row !== \"object\") continue;\n const rowId = typeof row.id === \"string\" ? row.id : \"\";\n if (!rowId) continue;\n const route = normalizeRoute((row as ProjectOperationRow).route);\n if (!route) continue;\n\n const list = normalizeOps((row as ProjectOperationRow).operation);\n if (list.length === 0) continue;\n\n const existing = opsByRoute.get(route) ?? [];\n existing.push({ rowId, ops: list });\n opsByRoute.set(route, existing);\n }\n\n const appliedIds = new Set<string>();\n\n for (const [route, entries] of opsByRoute) {\n const configPath = routeToConfigPath.get(route);\n if (!configPath) continue;\n\n let config: PageConfig;\n try {\n config = await readJsonFile<PageConfig>(configPath);\n } catch {\n continue;\n }\n\n if (!config || typeof config !== \"object\") continue;\n if (!Array.isArray(config.elements)) continue;\n\n let changed = false;\n\n for (const entry of entries) {\n let rowChanged = false;\n\n for (const op of entry.ops) {\n if (!op || typeof op !== \"object\") continue;\n const kind = (op as any).kind;\n\n if (kind === \"text\") {\n const id = (op as any).id;\n const newText = (op as any).newText;\n if (typeof id !== \"string\" || typeof newText !== \"string\") continue;\n\n const found = findElementById(config.elements, id);\n if (!found) continue;\n\n found.element.props = {\n ...(found.element.props ?? {}),\n text: newText,\n };\n changed = true;\n rowChanged = true;\n continue;\n }\n\n if (kind === \"delete\") {\n const id = (op as any).id;\n const parentId = (op as any).parentId;\n if (typeof id !== \"string\") continue;\n\n if (typeof parentId === \"string\" && parentId) {\n const parent = findElementById(config.elements, parentId)?.element;\n if (parent?.children && Array.isArray(parent.children)) {\n const before = parent.children.length;\n parent.children = parent.children.filter(\n (child) => child?.id !== id,\n );\n if (parent.children.length !== before) {\n changed = true;\n rowChanged = true;\n }\n continue;\n }\n }\n\n // Fallback: locate and remove by id anywhere in the tree (including top-level).\n if (removeElementById(config.elements, id)) {\n changed = true;\n rowChanged = true;\n }\n }\n }\n\n if (rowChanged) {\n appliedIds.add(entry.rowId);\n }\n }\n\n if (changed) {\n await writeJsonFile(configPath, config);\n }\n }\n\n return [...appliedIds];\n};\n"]}
@@ -0,0 +1,18 @@
1
+ export type ProjectOperationRow = {
2
+ id?: unknown;
3
+ route?: unknown;
4
+ operation?: unknown;
5
+ };
6
+ export type TextOp = {
7
+ kind: "text";
8
+ id: string;
9
+ newText: string;
10
+ oldText?: string;
11
+ };
12
+ export type DeleteOp = {
13
+ kind: "delete";
14
+ id: string;
15
+ parentId?: string;
16
+ };
17
+ export type ProjectOp = TextOp | DeleteOp | Record<string, unknown>;
18
+ //# sourceMappingURL=projectOps.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectOps.types.d.ts","sourceRoot":"","sources":["../../src/types/projectOps.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=projectOps.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectOps.types.js","sourceRoot":"","sources":["../../src/types/projectOps.types.ts"],"names":[],"mappings":"","sourcesContent":["export type ProjectOperationRow = {\r\n id?: unknown;\r\n route?: unknown;\r\n operation?: unknown;\r\n};\r\n\r\nexport type TextOp = {\r\n kind: \"text\";\r\n id: string;\r\n newText: string;\r\n oldText?: string;\r\n};\r\n\r\nexport type DeleteOp = {\r\n kind: \"delete\";\r\n id: string;\r\n parentId?: string;\r\n};\r\n\r\nexport type ProjectOp = TextOp | DeleteOp | Record<string, unknown>;\r\n"]}
@@ -0,0 +1,8 @@
1
+ import { BuilderElement } from "./elements.js";
2
+ export type PageConfig = {
3
+ elements: BuilderElement[];
4
+ };
5
+ export type Snapshot = {
6
+ routes: Record<string, PageConfig>;
7
+ };
8
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/types/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/types/snapshot.ts"],"names":[],"mappings":"","sourcesContent":["import { BuilderElement } from \"./elements.js\";\r\n\r\nexport type PageConfig = {\r\n elements: BuilderElement[];\r\n};\r\n\r\nexport type Snapshot = {\r\n routes: Record<string, PageConfig>;\r\n};\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedangiitb/qwintly-core",
3
- "version": "1.3.12",
3
+ "version": "1.3.14",
4
4
  "description": "Qwintly Core",
5
5
  "homepage": "https://github.com/vedangiitb/qwintly-core#readme",
6
6
  "bugs": {