@ragestudio/scylla-odm 0.12.0 → 0.13.0

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/client.js CHANGED
@@ -45,11 +45,11 @@ var Client = class {
45
45
  }
46
46
  models = models.filter((schema) => schema instanceof Model);
47
47
  this.mapper = new Cassandra.mapping.Mapper(this.driver, { models: buildMapper_default(models) });
48
+ globalThis.__scylla_client = this;
48
49
  for (let model of models) {
49
50
  this.models.set(model.name, model);
50
51
  if (options?.sync === true) await model._sync();
51
52
  }
52
- globalThis.__scylla_client = this;
53
53
  console.log("Connecting to ScyllaDB");
54
54
  await this.connectWithRetry();
55
55
  console.log("ScyllaDB Connected");
package/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":["loadModels","buildMapper"],"sources":["../src/client.ts"],"sourcesContent":["import type {\n\tClient as T_CassandraClient,\n\tClientOptions as T_CassandraClientOptions,\n\tmapping as T_CassandraMapping,\n} from \"cassandra-driver\"\nimport type { ClientConfig } from \"./types\"\n\n//@ts-ignore\nimport path from \"node:path\"\n//@ts-ignore\nimport Cassandra from \"cassandra-driver\"\nimport loadModels from \"./utils/loadModels\"\nimport buildMapper from \"./utils/buildMapper\"\n\nimport { Model } from \"./model\"\nimport { InferDocument } from \"./types\"\n\nconst DEFAULT_MAX_RETRIES = 3\nconst DEFAULT_RETRY_DELAY = 1000\nconst { SCYLLA_CONTACT_POINTS, SCYLLA_LOCAL_DATA_CENTER, SCYLLA_KEYSPACE } =\n\tprocess.env\n\nexport class Client {\n\tconstructor(config: ClientConfig = {}) {\n\t\tif (globalThis.__scylla_client) {\n\t\t\tthrow new Error(\n\t\t\t\t\"An instance of Scylla Client is already initialized\",\n\t\t\t)\n\t\t}\n\n\t\tthis.config = {\n\t\t\tmodelsPath: path.resolve(process.cwd(), \"db\"),\n\t\t\tcontactPoints:\n\t\t\t\t(config.contactPoints ?? SCYLLA_CONTACT_POINTS)\n\t\t\t\t\t? SCYLLA_CONTACT_POINTS.split(\",\")\n\t\t\t\t\t: [\"127.0.0.1\"],\n\t\t\tlocalDataCenter:\n\t\t\t\tconfig.localDataCenter ??\n\t\t\t\tSCYLLA_LOCAL_DATA_CENTER ??\n\t\t\t\t\"datacenter1\",\n\t\t\tkeyspace: config.keyspace ?? SCYLLA_KEYSPACE ?? \"default\",\n\t\t\tport: 9042,\n\t\t\tmaxRetries: DEFAULT_MAX_RETRIES,\n\t\t\tretryDelay: DEFAULT_RETRY_DELAY,\n\t\t\t...config,\n\t\t}\n\n\t\tconst clientOptions: T_CassandraClientOptions = {\n\t\t\tcontactPoints: this.config.contactPoints,\n\t\t\tlocalDataCenter: this.config.localDataCenter,\n\t\t\tkeyspace: this.config.keyspace,\n\t\t\tprotocolOptions: {\n\t\t\t\tport: this.config.port,\n\t\t\t},\n\t\t}\n\n\t\tif (this.config.pooling) {\n\t\t\tclientOptions.pooling = this.config.pooling\n\t\t}\n\n\t\tthis.driver = new Cassandra.Client(clientOptions)\n\t}\n\n\tconfig: ClientConfig\n\tdriver: T_CassandraClient\n\tmapper: T_CassandraMapping.Mapper\n\tmodels: Map<string, Model<any>> = new Map()\n\n\tmodel(name: string): Model<any> | undefined {\n\t\treturn this.models.get(name)\n\t}\n\n\tasync initialize(options: { sync?: boolean } = {}) {\n\t\tlet models: Model<any>[]\n\n\t\ttry {\n\t\t\tmodels = await loadModels(this.config.modelsPath)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to load models: ${error.message}`)\n\t\t}\n\n\t\tmodels = models.filter((schema) => schema instanceof Model)\n\n\t\tthis.mapper = new Cassandra.mapping.Mapper(this.driver, {\n\t\t\tmodels: buildMapper(models),\n\t\t})\n\n\t\tfor (let model of models) {\n\t\t\tthis.models.set(\n\t\t\t\tmodel.name,\n\t\t\t\tmodel as Model<InferDocument<typeof model.schema>>,\n\t\t\t)\n\n\t\t\tif (options?.sync === true) {\n\t\t\t\tawait model._sync()\n\t\t\t}\n\t\t}\n\n\t\tglobalThis.__scylla_client = this\n\n\t\tconsole.log(\"Connecting to ScyllaDB\")\n\t\tawait this.connectWithRetry()\n\t\tconsole.log(\"ScyllaDB Connected\")\n\t}\n\n\tprivate async connectWithRetry(): Promise<void> {\n\t\tlet lastError: Error | null = null\n\n\t\tfor (let attempt = 1; attempt <= this.config.maxRetries!; attempt++) {\n\t\t\ttry {\n\t\t\t\tawait this.driver.connect()\n\t\t\t\treturn\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Connection attempt ${attempt} failed: ${error.message}`,\n\t\t\t\t)\n\n\t\t\t\tif (attempt < this.config.maxRetries!) {\n\t\t\t\t\tconsole.log(`Retrying in ${this.config.retryDelay}ms...`)\n\t\t\t\t\tawait this.delay(this.config.retryDelay!)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Failed to connect to ScyllaDB after ${this.config.maxRetries} attempts: ${lastError?.message}`,\n\t\t)\n\t}\n\n\tprivate delay(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms))\n\t}\n\n\tasync shutdown(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.driver.shutdown()\n\t\t\tconsole.log(\"ScyllaDB connection closed\")\n\n\t\t\tdelete globalThis.__scylla_client\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Error shutting down ScyllaDB connection:\", error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync executeWithRetry<T>(\n\t\toperation: () => Promise<T>,\n\t\toperationName: string = \"operation\",\n\t): Promise<T> {\n\t\tlet lastError: Error | null = null\n\n\t\tfor (let attempt = 1; attempt <= this.config.maxRetries!; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn await operation()\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\n\t\t\t\t// check if error is retryable\n\t\t\t\tif (\n\t\t\t\t\tthis.isRetryableError(error) &&\n\t\t\t\t\tattempt < this.config.maxRetries!\n\t\t\t\t) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Operation ${operationName} attempt ${attempt} failed: ${error.message}`,\n\t\t\t\t\t)\n\t\t\t\t\tconsole.log(`Retrying in ${this.config.retryDelay}ms...`)\n\n\t\t\t\t\tawait this.delay(this.config.retryDelay!)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// if not retryable or last attempt, throw\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Operation ${operationName} failed after ${this.config.maxRetries} attempts: ${lastError?.message}`,\n\t\t)\n\t}\n\n\tprivate isRetryableError(error: any): boolean {\n\t\t// retry on network errors, timeouts, and certain ScyllaDB errors\n\t\tconst retryableMessages = [\n\t\t\t\"timeout\",\n\t\t\t\"connection\",\n\t\t\t\"network\",\n\t\t\t\"unavailable\",\n\t\t\t\"overloaded\",\n\t\t\t\"no hosts available\",\n\t\t]\n\n\t\tconst errorMessage = error.message?.toLowerCase() || \"\"\n\n\t\treturn retryableMessages.some((msg) => errorMessage.includes(msg))\n\t}\n}\n\nexport default Client\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":["loadModels","buildMapper"],"sources":["../src/client.ts"],"sourcesContent":["import type {\n\tClient as T_CassandraClient,\n\tClientOptions as T_CassandraClientOptions,\n\tmapping as T_CassandraMapping,\n} from \"cassandra-driver\"\nimport type { ClientConfig } from \"./types\"\n\n//@ts-ignore\nimport path from \"node:path\"\n//@ts-ignore\nimport Cassandra from \"cassandra-driver\"\nimport loadModels from \"./utils/loadModels\"\nimport buildMapper from \"./utils/buildMapper\"\n\nimport { Model } from \"./model\"\nimport { InferDocument } from \"./types\"\n\nconst DEFAULT_MAX_RETRIES = 3\nconst DEFAULT_RETRY_DELAY = 1000\nconst { SCYLLA_CONTACT_POINTS, SCYLLA_LOCAL_DATA_CENTER, SCYLLA_KEYSPACE } =\n\tprocess.env\n\nexport class Client {\n\tconstructor(config: ClientConfig = {}) {\n\t\tif (globalThis.__scylla_client) {\n\t\t\tthrow new Error(\n\t\t\t\t\"An instance of Scylla Client is already initialized\",\n\t\t\t)\n\t\t}\n\n\t\tthis.config = {\n\t\t\tmodelsPath: path.resolve(process.cwd(), \"db\"),\n\t\t\tcontactPoints:\n\t\t\t\t(config.contactPoints ?? SCYLLA_CONTACT_POINTS)\n\t\t\t\t\t? SCYLLA_CONTACT_POINTS.split(\",\")\n\t\t\t\t\t: [\"127.0.0.1\"],\n\t\t\tlocalDataCenter:\n\t\t\t\tconfig.localDataCenter ??\n\t\t\t\tSCYLLA_LOCAL_DATA_CENTER ??\n\t\t\t\t\"datacenter1\",\n\t\t\tkeyspace: config.keyspace ?? SCYLLA_KEYSPACE ?? \"default\",\n\t\t\tport: 9042,\n\t\t\tmaxRetries: DEFAULT_MAX_RETRIES,\n\t\t\tretryDelay: DEFAULT_RETRY_DELAY,\n\t\t\t...config,\n\t\t}\n\n\t\tconst clientOptions: T_CassandraClientOptions = {\n\t\t\tcontactPoints: this.config.contactPoints,\n\t\t\tlocalDataCenter: this.config.localDataCenter,\n\t\t\tkeyspace: this.config.keyspace,\n\t\t\tprotocolOptions: {\n\t\t\t\tport: this.config.port,\n\t\t\t},\n\t\t}\n\n\t\tif (this.config.pooling) {\n\t\t\tclientOptions.pooling = this.config.pooling\n\t\t}\n\n\t\tthis.driver = new Cassandra.Client(clientOptions)\n\t}\n\n\tconfig: ClientConfig\n\tdriver: T_CassandraClient\n\tmapper: T_CassandraMapping.Mapper\n\tmodels: Map<string, Model<any>> = new Map()\n\n\tmodel(name: string): Model<any> | undefined {\n\t\treturn this.models.get(name)\n\t}\n\n\tasync initialize(options: { sync?: boolean } = {}) {\n\t\tlet models: Model<any>[]\n\n\t\ttry {\n\t\t\tmodels = await loadModels(this.config.modelsPath)\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to load models: ${error.message}`)\n\t\t}\n\n\t\tmodels = models.filter((schema) => schema instanceof Model)\n\n\t\tthis.mapper = new Cassandra.mapping.Mapper(this.driver, {\n\t\t\tmodels: buildMapper(models),\n\t\t})\n\n\t\tglobalThis.__scylla_client = this\n\n\t\tfor (let model of models) {\n\t\t\tthis.models.set(\n\t\t\t\tmodel.name,\n\t\t\t\tmodel as Model<InferDocument<typeof model.schema>>,\n\t\t\t)\n\n\t\t\tif (options?.sync === true) {\n\t\t\t\tawait model._sync()\n\t\t\t}\n\t\t}\n\n\t\tconsole.log(\"Connecting to ScyllaDB\")\n\t\tawait this.connectWithRetry()\n\t\tconsole.log(\"ScyllaDB Connected\")\n\t}\n\n\tprivate async connectWithRetry(): Promise<void> {\n\t\tlet lastError: Error | null = null\n\n\t\tfor (let attempt = 1; attempt <= this.config.maxRetries!; attempt++) {\n\t\t\ttry {\n\t\t\t\tawait this.driver.connect()\n\t\t\t\treturn\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\t\t\t\tconsole.warn(\n\t\t\t\t\t`Connection attempt ${attempt} failed: ${error.message}`,\n\t\t\t\t)\n\n\t\t\t\tif (attempt < this.config.maxRetries!) {\n\t\t\t\t\tconsole.log(`Retrying in ${this.config.retryDelay}ms...`)\n\t\t\t\t\tawait this.delay(this.config.retryDelay!)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Failed to connect to ScyllaDB after ${this.config.maxRetries} attempts: ${lastError?.message}`,\n\t\t)\n\t}\n\n\tprivate delay(ms: number): Promise<void> {\n\t\treturn new Promise((resolve) => setTimeout(resolve, ms))\n\t}\n\n\tasync shutdown(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.driver.shutdown()\n\t\t\tconsole.log(\"ScyllaDB connection closed\")\n\n\t\t\tdelete globalThis.__scylla_client\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Error shutting down ScyllaDB connection:\", error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync executeWithRetry<T>(\n\t\toperation: () => Promise<T>,\n\t\toperationName: string = \"operation\",\n\t): Promise<T> {\n\t\tlet lastError: Error | null = null\n\n\t\tfor (let attempt = 1; attempt <= this.config.maxRetries!; attempt++) {\n\t\t\ttry {\n\t\t\t\treturn await operation()\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error\n\n\t\t\t\t// check if error is retryable\n\t\t\t\tif (\n\t\t\t\t\tthis.isRetryableError(error) &&\n\t\t\t\t\tattempt < this.config.maxRetries!\n\t\t\t\t) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Operation ${operationName} attempt ${attempt} failed: ${error.message}`,\n\t\t\t\t\t)\n\t\t\t\t\tconsole.log(`Retrying in ${this.config.retryDelay}ms...`)\n\n\t\t\t\t\tawait this.delay(this.config.retryDelay!)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// if not retryable or last attempt, throw\n\t\t\t\tthrow error\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Operation ${operationName} failed after ${this.config.maxRetries} attempts: ${lastError?.message}`,\n\t\t)\n\t}\n\n\tprivate isRetryableError(error: any): boolean {\n\t\t// retry on network errors, timeouts, and certain ScyllaDB errors\n\t\tconst retryableMessages = [\n\t\t\t\"timeout\",\n\t\t\t\"connection\",\n\t\t\t\"network\",\n\t\t\t\"unavailable\",\n\t\t\t\"overloaded\",\n\t\t\t\"no hosts available\",\n\t\t]\n\n\t\tconst errorMessage = error.message?.toLowerCase() || \"\"\n\n\t\treturn retryableMessages.some((msg) => errorMessage.includes(msg))\n\t}\n}\n\nexport default Client\n"],"mappings":"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"}
@@ -1,9 +1,7 @@
1
- import typeChecker from "../utils/typeChecker.js";
2
1
  import fillDefaults from "../utils/fillDefaults.js";
3
2
  //#region src/operations/update.ts
4
3
  async function update_default(query) {
5
4
  query = fillDefaults(this.schema, query);
6
- typeChecker(this, query);
7
5
  if (typeof query.__v !== "undefined") if (Number.isNaN(query.__v)) query.__v = 0;
8
6
  else query.__v = query.__v + 1;
9
7
  const operation = async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","names":[],"sources":["../../src/operations/update.ts"],"sourcesContent":["import type Model from \"../model\"\nimport fillDefaults from \"../utils/fillDefaults\"\nimport typeChecker from \"../utils/typeChecker\"\n\nexport default async function (this: Model, query: any) {\n\tquery = fillDefaults(this.schema, query)\n\n\ttypeChecker(this, query)\n\n\tif (typeof query.__v !== \"undefined\") {\n\t\tif (Number.isNaN(query.__v)) {\n\t\t\tquery.__v = 0\n\t\t} else {\n\t\t\tquery.__v = query.__v + 1\n\t\t}\n\t}\n\n\tconst operation = async () => {\n\t\tawait this.mapper.update(query)\n\t\treturn this._wrap(query)\n\t}\n\n\treturn this.client.executeWithRetry(operation, `update on ${this.name}`)\n}\n"],"mappings":";;;AAIA,eAAA,eAA4C,OAAY;AACvD,SAAQ,aAAa,KAAK,QAAQ,MAAM;AAExC,aAAY,MAAM,MAAM;AAExB,KAAI,OAAO,MAAM,QAAQ,YACxB,KAAI,OAAO,MAAM,MAAM,IAAI,CAC1B,OAAM,MAAM;KAEZ,OAAM,MAAM,MAAM,MAAM;CAI1B,MAAM,YAAY,YAAY;AAC7B,QAAM,KAAK,OAAO,OAAO,MAAM;AAC/B,SAAO,KAAK,MAAM,MAAM;;AAGzB,QAAO,KAAK,OAAO,iBAAiB,WAAW,aAAa,KAAK,OAAO"}
1
+ {"version":3,"file":"update.js","names":[],"sources":["../../src/operations/update.ts"],"sourcesContent":["import type Model from \"../model\"\nimport fillDefaults from \"../utils/fillDefaults\"\n//import typeChecker from \"../utils/typeChecker\"\n\nexport default async function (this: Model, query: any) {\n\tquery = fillDefaults(this.schema, query)\n\n\t//typeChecker(this, query)\n\n\tif (typeof query.__v !== \"undefined\") {\n\t\tif (Number.isNaN(query.__v)) {\n\t\t\tquery.__v = 0\n\t\t} else {\n\t\t\tquery.__v = query.__v + 1\n\t\t}\n\t}\n\n\tconst operation = async () => {\n\t\tawait this.mapper.update(query)\n\t\treturn this._wrap(query)\n\t}\n\n\treturn this.client.executeWithRetry(operation, `update on ${this.name}`)\n}\n"],"mappings":";;AAIA,eAAA,eAA4C,OAAY;AACvD,SAAQ,aAAa,KAAK,QAAQ,MAAM;AAIxC,KAAI,OAAO,MAAM,QAAQ,YACxB,KAAI,OAAO,MAAM,MAAM,IAAI,CAC1B,OAAM,MAAM;KAEZ,OAAM,MAAM,MAAM,MAAM;CAI1B,MAAM,YAAY,YAAY;AAC7B,QAAM,KAAK,OAAO,OAAO,MAAM;AAC/B,SAAO,KAAK,MAAM,MAAM;;AAGzB,QAAO,KAAK,OAAO,iBAAiB,WAAW,aAAa,KAAK,OAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ragestudio/scylla-odm",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "An ODM for ScyllaDB",
5
5
  "license": "MIT",
6
6
  "author": "RageStudio",
package/result/index.js CHANGED
@@ -1,4 +1,3 @@
1
- import typeChecker from "../utils/typeChecker.js";
2
1
  //#region src/result/index.ts
3
2
  var Result = class {
4
3
  constructor(data, model) {
@@ -16,7 +15,6 @@ var Result = class {
16
15
  async save() {
17
16
  try {
18
17
  const data = this.toRaw();
19
- typeChecker(this._model, data);
20
18
  return await this._model.update(data);
21
19
  } catch (error) {
22
20
  throw new Error(`Failed to save result: ${error.message}`);
@@ -47,7 +45,6 @@ var Result = class {
47
45
  }
48
46
  isValid() {
49
47
  try {
50
- typeChecker(this._model, this.toRaw());
51
48
  return true;
52
49
  } catch {
53
50
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/result/index.ts"],"sourcesContent":["import type { Model } from \"../model\"\nimport typeChecker from \"../utils/typeChecker\"\n\nexport class Result<TDoc = any> {\n\tconstructor(data: TDoc, model: Model<TDoc>) {\n\t\tif (data == null) {\n\t\t\tthrow new Error(\"Cannot create Result with null or undefined data\")\n\t\t}\n\n\t\tif (typeof data !== \"object\" || Array.isArray(data)) {\n\t\t\tthrow new Error(\"Result data must be an object\")\n\t\t}\n\n\t\tObject.assign(this, data)\n\n\t\tObject.defineProperty(this, \"_model\", {\n\t\t\tvalue: model,\n\t\t\tenumerable: false,\n\t\t\twritable: false,\n\t\t\tconfigurable: false,\n\t\t})\n\t}\n\n\t_model: Model<TDoc>\n\n\tasync save() {\n\t\ttry {\n\t\t\tconst data = this.toRaw()\n\n\t\t\ttypeChecker(this._model, data)\n\n\t\t\treturn await this._model.update(data as any)\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(`Failed to save result: ${error.message}`)\n\t\t}\n\t}\n\n\tasync delete() {\n\t\ttry {\n\t\t\treturn await this._model.delete(this.toRaw() as any)\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(`Failed to delete result: ${error.message}`)\n\t\t}\n\t}\n\n\ttoRaw(): TDoc {\n\t\tconst raw: any = {}\n\n\t\tfor (const key in this) {\n\t\t\tif (key === \"_model\") continue\n\n\t\t\tif (this.propertyIsEnumerable(key)) {\n\t\t\t\tconst value = (this as any)[key]\n\n\t\t\t\ttry {\n\t\t\t\t\tJSON.stringify(value)\n\t\t\t\t\traw[key] = value\n\t\t\t\t} catch (error) {\n\t\t\t\t\traw[key] = String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn raw as TDoc\n\t}\n\n\tisValid(): boolean {\n\t\ttry {\n\t\t\ttypeChecker(this._model, this.toRaw())\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tgetChangedFields(original: Partial<TDoc>): (keyof TDoc)[] {\n\t\tconst current = this.toRaw() as Record<string, any>\n\t\tconst changed: (keyof TDoc)[] = []\n\n\t\tfor (const key in current) {\n\t\t\tif (!(key in original) || current[key] !== (original as any)[key]) {\n\t\t\t\tchanged.push(key as keyof TDoc)\n\t\t\t}\n\t\t}\n\n\t\treturn changed\n\t}\n}\n\nexport default Result\n"],"mappings":";;AAGA,IAAa,SAAb,MAAgC;CAC/B,YAAY,MAAY,OAAoB;AAC3C,MAAI,QAAQ,KACX,OAAM,IAAI,MAAM,mDAAmD;AAGpE,MAAI,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAClD,OAAM,IAAI,MAAM,gCAAgC;AAGjD,SAAO,OAAO,MAAM,KAAK;AAEzB,SAAO,eAAe,MAAM,UAAU;GACrC,OAAO;GACP,YAAY;GACZ,UAAU;GACV,cAAc;GACd,CAAC;;CAGH;CAEA,MAAM,OAAO;AACZ,MAAI;GACH,MAAM,OAAO,KAAK,OAAO;AAEzB,eAAY,KAAK,QAAQ,KAAK;AAE9B,UAAO,MAAM,KAAK,OAAO,OAAO,KAAY;WACpC,OAAY;AACpB,SAAM,IAAI,MAAM,0BAA0B,MAAM,UAAU;;;CAI5D,MAAM,SAAS;AACd,MAAI;AACH,UAAO,MAAM,KAAK,OAAO,OAAO,KAAK,OAAO,CAAQ;WAC5C,OAAY;AACpB,SAAM,IAAI,MAAM,4BAA4B,MAAM,UAAU;;;CAI9D,QAAc;EACb,MAAM,MAAW,EAAE;AAEnB,OAAK,MAAM,OAAO,MAAM;AACvB,OAAI,QAAQ,SAAU;AAEtB,OAAI,KAAK,qBAAqB,IAAI,EAAE;IACnC,MAAM,QAAS,KAAa;AAE5B,QAAI;AACH,UAAK,UAAU,MAAM;AACrB,SAAI,OAAO;aACH,OAAO;AACf,SAAI,OAAO,OAAO,MAAM;;;;AAK3B,SAAO;;CAGR,UAAmB;AAClB,MAAI;AACH,eAAY,KAAK,QAAQ,KAAK,OAAO,CAAC;AACtC,UAAO;UACA;AACP,UAAO;;;CAIT,iBAAiB,UAAyC;EACzD,MAAM,UAAU,KAAK,OAAO;EAC5B,MAAM,UAA0B,EAAE;AAElC,OAAK,MAAM,OAAO,QACjB,KAAI,EAAE,OAAO,aAAa,QAAQ,SAAU,SAAiB,KAC5D,SAAQ,KAAK,IAAkB;AAIjC,SAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/result/index.ts"],"sourcesContent":["import type { Model } from \"../model\"\n//import typeChecker from \"../utils/typeChecker\"\n\nexport class Result<TDoc = any> {\n\tconstructor(data: TDoc, model: Model<TDoc>) {\n\t\tif (data == null) {\n\t\t\tthrow new Error(\"Cannot create Result with null or undefined data\")\n\t\t}\n\n\t\tif (typeof data !== \"object\" || Array.isArray(data)) {\n\t\t\tthrow new Error(\"Result data must be an object\")\n\t\t}\n\n\t\tObject.assign(this, data)\n\n\t\tObject.defineProperty(this, \"_model\", {\n\t\t\tvalue: model,\n\t\t\tenumerable: false,\n\t\t\twritable: false,\n\t\t\tconfigurable: false,\n\t\t})\n\t}\n\n\t_model: Model<TDoc>\n\n\tasync save() {\n\t\ttry {\n\t\t\tconst data = this.toRaw()\n\n\t\t\t//typeChecker(this._model, data)\n\n\t\t\treturn await this._model.update(data as any)\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(`Failed to save result: ${error.message}`)\n\t\t}\n\t}\n\n\tasync delete() {\n\t\ttry {\n\t\t\treturn await this._model.delete(this.toRaw() as any)\n\t\t} catch (error: any) {\n\t\t\tthrow new Error(`Failed to delete result: ${error.message}`)\n\t\t}\n\t}\n\n\ttoRaw(): TDoc {\n\t\tconst raw: any = {}\n\n\t\tfor (const key in this) {\n\t\t\tif (key === \"_model\") continue\n\n\t\t\tif (this.propertyIsEnumerable(key)) {\n\t\t\t\tconst value = (this as any)[key]\n\n\t\t\t\ttry {\n\t\t\t\t\tJSON.stringify(value)\n\t\t\t\t\traw[key] = value\n\t\t\t\t} catch (error) {\n\t\t\t\t\traw[key] = String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn raw as TDoc\n\t}\n\n\tisValid(): boolean {\n\t\ttry {\n\t\t\t//typeChecker(this._model, this.toRaw())\n\t\t\treturn true\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tgetChangedFields(original: Partial<TDoc>): (keyof TDoc)[] {\n\t\tconst current = this.toRaw() as Record<string, any>\n\t\tconst changed: (keyof TDoc)[] = []\n\n\t\tfor (const key in current) {\n\t\t\tif (!(key in original) || current[key] !== (original as any)[key]) {\n\t\t\t\tchanged.push(key as keyof TDoc)\n\t\t\t}\n\t\t}\n\n\t\treturn changed\n\t}\n}\n\nexport default Result\n"],"mappings":";AAGA,IAAa,SAAb,MAAgC;CAC/B,YAAY,MAAY,OAAoB;AAC3C,MAAI,QAAQ,KACX,OAAM,IAAI,MAAM,mDAAmD;AAGpE,MAAI,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAClD,OAAM,IAAI,MAAM,gCAAgC;AAGjD,SAAO,OAAO,MAAM,KAAK;AAEzB,SAAO,eAAe,MAAM,UAAU;GACrC,OAAO;GACP,YAAY;GACZ,UAAU;GACV,cAAc;GACd,CAAC;;CAGH;CAEA,MAAM,OAAO;AACZ,MAAI;GACH,MAAM,OAAO,KAAK,OAAO;AAIzB,UAAO,MAAM,KAAK,OAAO,OAAO,KAAY;WACpC,OAAY;AACpB,SAAM,IAAI,MAAM,0BAA0B,MAAM,UAAU;;;CAI5D,MAAM,SAAS;AACd,MAAI;AACH,UAAO,MAAM,KAAK,OAAO,OAAO,KAAK,OAAO,CAAQ;WAC5C,OAAY;AACpB,SAAM,IAAI,MAAM,4BAA4B,MAAM,UAAU;;;CAI9D,QAAc;EACb,MAAM,MAAW,EAAE;AAEnB,OAAK,MAAM,OAAO,MAAM;AACvB,OAAI,QAAQ,SAAU;AAEtB,OAAI,KAAK,qBAAqB,IAAI,EAAE;IACnC,MAAM,QAAS,KAAa;AAE5B,QAAI;AACH,UAAK,UAAU,MAAM;AACrB,SAAI,OAAO;aACH,OAAO;AACf,SAAI,OAAO,OAAO,MAAM;;;;AAK3B,SAAO;;CAGR,UAAmB;AAClB,MAAI;AAEH,UAAO;UACA;AACP,UAAO;;;CAIT,iBAAiB,UAAyC;EACzD,MAAM,UAAU,KAAK,OAAO;EAC5B,MAAM,UAA0B,EAAE;AAElC,OAAK,MAAM,OAAO,QACjB,KAAI,EAAE,OAAO,aAAa,QAAQ,SAAU,SAAiB,KAC5D,SAAQ,KAAK,IAAkB;AAIjC,SAAO"}
@@ -15,13 +15,19 @@ const intTypes = new Set([
15
15
  ]);
16
16
  const floatTypes = new Set(["double", "float"]);
17
17
  const longTypes = new Set(["bigint", "counter"]);
18
+ function stripFrozen(raw) {
19
+ let t = raw;
20
+ while (t.startsWith("frozen<")) t = t.slice(7, -1);
21
+ return t;
22
+ }
18
23
  function isValidValue(value, expectedType) {
19
24
  if (value === null || value === void 0) return true;
20
- if (stringTypes.has(expectedType)) return typeof value === "string";
21
- if (intTypes.has(expectedType)) return Number.isInteger(value);
22
- if (floatTypes.has(expectedType)) return typeof value === "number";
23
- if (longTypes.has(expectedType)) return typeof value === "bigint" || typeof value === "number" || value instanceof types.Long;
24
- switch (expectedType) {
25
+ const typeName = stripFrozen(expectedType.toLowerCase().trim());
26
+ if (stringTypes.has(typeName)) return typeof value === "string";
27
+ if (intTypes.has(typeName)) return Number.isInteger(value);
28
+ if (floatTypes.has(typeName)) return typeof value === "number";
29
+ if (longTypes.has(typeName)) return typeof value === "bigint" || typeof value === "number" || value instanceof types.Long;
30
+ switch (typeName) {
25
31
  case "boolean": return typeof value === "boolean";
26
32
  case "decimal": return typeof value === "number" || typeof value === "string" || value instanceof types.BigDecimal;
27
33
  case "varint": return typeof value === "bigint" || typeof value === "number" || value instanceof types.Integer;
@@ -32,8 +38,9 @@ function isValidValue(value, expectedType) {
32
38
  case "timeuuid": return typeof value === "string" || value instanceof types.TimeUuid;
33
39
  case "blob": return Buffer.isBuffer(value) || value instanceof Uint8Array;
34
40
  }
35
- if (expectedType.startsWith("list<") || expectedType.startsWith("set<")) return Array.isArray(value) || value instanceof Set;
36
- if (expectedType.startsWith("map<")) return typeof value === "object" && !Array.isArray(value) && value !== null;
41
+ if (typeName.startsWith("list<") || typeName.startsWith("set<")) return Array.isArray(value) || value instanceof Set;
42
+ if (typeName.startsWith("map<")) return typeof value === "object" && !Array.isArray(value) && value !== null;
43
+ if (typeName.startsWith("tuple<")) return Array.isArray(value);
37
44
  return false;
38
45
  }
39
46
  function typeChecker(model, data) {
@@ -41,7 +48,9 @@ function typeChecker(model, data) {
41
48
  const fields = model.schema.fields;
42
49
  for (const [key, value] of Object.entries(data)) {
43
50
  if (!isValidFieldName(fields, key)) throw new Error(`[${model.name}] Validation error: Field '${key}' does not exist in schema`);
44
- const expectedType = (fields[key].type || "text").toLowerCase();
51
+ const fieldConfig = fields[key];
52
+ const expectedType = (fieldConfig.type || "text").toLowerCase();
53
+ if (fieldConfig.required && (value === null || value === void 0)) throw new TypeError(`[${model.name}] Validation error: Field '${key}' is required but received ${value}`);
45
54
  if (!isValidValue(value, expectedType)) {
46
55
  const receivedType = Array.isArray(value) ? "array" : typeof value;
47
56
  throw new TypeError(`[${model.name}] Validation error: Invalid type for field '${key}'. Expected[${expectedType}], but received [${receivedType}]`);
@@ -1 +1 @@
1
- {"version":3,"file":"typeChecker.js","names":["cassandra"],"sources":["../../src/utils/typeChecker.ts"],"sourcesContent":["// @ts-ignore\nimport cassandra from \"cassandra-driver\"\nconst { types } = cassandra\nimport type { Model } from \"../model\"\nimport { isValidFieldName } from \"./queryParser\"\n\nconst stringTypes = new Set([\"ascii\", \"text\", \"varchar\", \"inet\"])\nconst intTypes = new Set([\"int\", \"smallint\", \"tinyint\"])\nconst floatTypes = new Set([\"double\", \"float\"])\nconst longTypes = new Set([\"bigint\", \"counter\"])\n\nfunction isValidValue(value: any, expectedType: string): boolean {\n\tif (value === null || value === undefined) return true\n\n\tif (stringTypes.has(expectedType)) return typeof value === \"string\"\n\tif (intTypes.has(expectedType)) return Number.isInteger(value)\n\tif (floatTypes.has(expectedType)) return typeof value === \"number\"\n\tif (longTypes.has(expectedType)) {\n\t\treturn (\n\t\t\ttypeof value === \"bigint\" ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\tvalue instanceof types.Long\n\t\t)\n\t}\n\n\tswitch (expectedType) {\n\t\tcase \"boolean\":\n\t\t\treturn typeof value === \"boolean\"\n\t\tcase \"decimal\":\n\t\t\treturn (\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\ttypeof value === \"string\" ||\n\t\t\t\tvalue instanceof types.BigDecimal\n\t\t\t)\n\t\tcase \"varint\":\n\t\t\treturn (\n\t\t\t\ttypeof value === \"bigint\" ||\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\tvalue instanceof types.Integer\n\t\t\t)\n\t\tcase \"timestamp\":\n\t\t\treturn (\n\t\t\t\tvalue instanceof Date ||\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\ttypeof value === \"string\"\n\t\t\t)\n\t\tcase \"date\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.LocalDate\n\t\tcase \"time\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.LocalTime\n\t\tcase \"uuid\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.Uuid\n\t\tcase \"timeuuid\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.TimeUuid\n\t\tcase \"blob\":\n\t\t\treturn Buffer.isBuffer(value) || value instanceof Uint8Array\n\t}\n\n\tif (expectedType.startsWith(\"list<\") || expectedType.startsWith(\"set<\")) {\n\t\treturn Array.isArray(value) || value instanceof Set\n\t}\n\tif (expectedType.startsWith(\"map<\")) {\n\t\treturn (\n\t\t\ttypeof value === \"object\" && !Array.isArray(value) && value !== null\n\t\t)\n\t}\n\n\treturn false\n}\n\nexport default function typeChecker(model: Model<any>, data: any): boolean {\n\tif (!data || typeof data !== \"object\" || Array.isArray(data)) {\n\t\tthrow new TypeError(\n\t\t\t`[${model.name}] Validation error: Data payload must be an object`,\n\t\t)\n\t}\n\n\tconst fields = model.schema.fields\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (!isValidFieldName(fields, key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`[${model.name}] Validation error: Field '${key}' does not exist in schema`,\n\t\t\t)\n\t\t}\n\n\t\tconst fieldConfig = fields[key]\n\t\tconst expectedType = (fieldConfig.type || \"text\").toLowerCase()\n\n\t\tif (!isValidValue(value, expectedType)) {\n\t\t\tconst receivedType = Array.isArray(value) ? \"array\" : typeof value\n\t\t\tthrow new TypeError(\n\t\t\t\t`[${model.name}] Validation error: Invalid type for field '${key}'. ` +\n\t\t\t\t\t`Expected[${expectedType}], but received [${receivedType}]`,\n\t\t\t)\n\t\t}\n\t}\n\n\treturn true\n}\n"],"mappings":";;;AAEA,MAAM,EAAE,UAAUA;AAIlB,MAAM,cAAc,IAAI,IAAI;CAAC;CAAS;CAAQ;CAAW;CAAO,CAAC;AACjE,MAAM,WAAW,IAAI,IAAI;CAAC;CAAO;CAAY;CAAU,CAAC;AACxD,MAAM,aAAa,IAAI,IAAI,CAAC,UAAU,QAAQ,CAAC;AAC/C,MAAM,YAAY,IAAI,IAAI,CAAC,UAAU,UAAU,CAAC;AAEhD,SAAS,aAAa,OAAY,cAA+B;AAChE,KAAI,UAAU,QAAQ,UAAU,KAAA,EAAW,QAAO;AAElD,KAAI,YAAY,IAAI,aAAa,CAAE,QAAO,OAAO,UAAU;AAC3D,KAAI,SAAS,IAAI,aAAa,CAAE,QAAO,OAAO,UAAU,MAAM;AAC9D,KAAI,WAAW,IAAI,aAAa,CAAE,QAAO,OAAO,UAAU;AAC1D,KAAI,UAAU,IAAI,aAAa,CAC9B,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;AAIzB,SAAQ,cAAR;EACC,KAAK,UACJ,QAAO,OAAO,UAAU;EACzB,KAAK,UACJ,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;EAEzB,KAAK,SACJ,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;EAEzB,KAAK,YACJ,QACC,iBAAiB,QACjB,OAAO,UAAU,YACjB,OAAO,UAAU;EAEnB,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,WACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,SAAS,MAAM,IAAI,iBAAiB;;AAGpD,KAAI,aAAa,WAAW,QAAQ,IAAI,aAAa,WAAW,OAAO,CACtE,QAAO,MAAM,QAAQ,MAAM,IAAI,iBAAiB;AAEjD,KAAI,aAAa,WAAW,OAAO,CAClC,QACC,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,IAAI,UAAU;AAIlE,QAAO;;AAGR,SAAwB,YAAY,OAAmB,MAAoB;AAC1E,KAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAC3D,OAAM,IAAI,UACT,IAAI,MAAM,KAAK,oDACf;CAGF,MAAM,SAAS,MAAM,OAAO;AAE5B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;AAChD,MAAI,CAAC,iBAAiB,QAAQ,IAAI,CACjC,OAAM,IAAI,MACT,IAAI,MAAM,KAAK,6BAA6B,IAAI,4BAChD;EAIF,MAAM,gBADc,OAAO,KACO,QAAQ,QAAQ,aAAa;AAE/D,MAAI,CAAC,aAAa,OAAO,aAAa,EAAE;GACvC,MAAM,eAAe,MAAM,QAAQ,MAAM,GAAG,UAAU,OAAO;AAC7D,SAAM,IAAI,UACT,IAAI,MAAM,KAAK,8CAA8C,IAAI,cACpD,aAAa,mBAAmB,aAAa,GAC1D;;;AAIH,QAAO"}
1
+ {"version":3,"file":"typeChecker.js","names":["cassandra"],"sources":["../../src/utils/typeChecker.ts"],"sourcesContent":["// @ts-ignore\nimport cassandra from \"cassandra-driver\"\nconst { types } = cassandra\nimport type { Model } from \"../model\"\nimport { isValidFieldName } from \"./queryParser\"\n\nconst stringTypes = new Set([\"ascii\", \"text\", \"varchar\", \"inet\"])\nconst intTypes = new Set([\"int\", \"smallint\", \"tinyint\"])\nconst floatTypes = new Set([\"double\", \"float\"])\nconst longTypes = new Set([\"bigint\", \"counter\"])\n\nfunction stripFrozen(raw: string): string {\n\tlet t = raw\n\n\twhile (t.startsWith(\"frozen<\")) {\n\t\tt = t.slice(7, -1)\n\t}\n\n\treturn t\n}\n\nfunction isValidValue(value: any, expectedType: string): boolean {\n\tif (value === null || value === undefined) return true\n\n\tconst typeName = stripFrozen(expectedType.toLowerCase().trim())\n\n\tif (stringTypes.has(typeName)) return typeof value === \"string\"\n\tif (intTypes.has(typeName)) return Number.isInteger(value)\n\tif (floatTypes.has(typeName)) return typeof value === \"number\"\n\tif (longTypes.has(typeName)) {\n\t\treturn (\n\t\t\ttypeof value === \"bigint\" ||\n\t\t\ttypeof value === \"number\" ||\n\t\t\tvalue instanceof types.Long\n\t\t)\n\t}\n\n\tswitch (typeName) {\n\t\tcase \"boolean\":\n\t\t\treturn typeof value === \"boolean\"\n\t\tcase \"decimal\":\n\t\t\treturn (\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\ttypeof value === \"string\" ||\n\t\t\t\tvalue instanceof types.BigDecimal\n\t\t\t)\n\t\tcase \"varint\":\n\t\t\treturn (\n\t\t\t\ttypeof value === \"bigint\" ||\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\tvalue instanceof types.Integer\n\t\t\t)\n\t\tcase \"timestamp\":\n\t\t\treturn (\n\t\t\t\tvalue instanceof Date ||\n\t\t\t\ttypeof value === \"number\" ||\n\t\t\t\ttypeof value === \"string\"\n\t\t\t)\n\t\tcase \"date\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.LocalDate\n\t\tcase \"time\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.LocalTime\n\t\tcase \"uuid\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.Uuid\n\t\tcase \"timeuuid\":\n\t\t\treturn typeof value === \"string\" || value instanceof types.TimeUuid\n\t\tcase \"blob\":\n\t\t\treturn Buffer.isBuffer(value) || value instanceof Uint8Array\n\t}\n\n\tif (typeName.startsWith(\"list<\") || typeName.startsWith(\"set<\")) {\n\t\treturn Array.isArray(value) || value instanceof Set\n\t}\n\tif (typeName.startsWith(\"map<\")) {\n\t\treturn (\n\t\t\ttypeof value === \"object\" && !Array.isArray(value) && value !== null\n\t\t)\n\t}\n\tif (typeName.startsWith(\"tuple<\")) {\n\t\treturn Array.isArray(value)\n\t}\n\n\treturn false\n}\n\nexport default function typeChecker(model: Model<any>, data: any): boolean {\n\tif (!data || typeof data !== \"object\" || Array.isArray(data)) {\n\t\tthrow new TypeError(\n\t\t\t`[${model.name}] Validation error: Data payload must be an object`,\n\t\t)\n\t}\n\n\tconst fields = model.schema.fields\n\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (!isValidFieldName(fields, key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`[${model.name}] Validation error: Field '${key}' does not exist in schema`,\n\t\t\t)\n\t\t}\n\n\t\tconst fieldConfig = fields[key]\n\t\tconst expectedType = (fieldConfig.type || \"text\").toLowerCase()\n\n\t\tif (fieldConfig.required && (value === null || value === undefined)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`[${model.name}] Validation error: Field '${key}' is required but received ${value}`,\n\t\t\t)\n\t\t}\n\n\t\tif (!isValidValue(value, expectedType)) {\n\t\t\tconst receivedType = Array.isArray(value) ? \"array\" : typeof value\n\n\t\t\tthrow new TypeError(\n\t\t\t\t`[${model.name}] Validation error: Invalid type for field '${key}'. ` +\n\t\t\t\t\t`Expected[${expectedType}], but received [${receivedType}]`,\n\t\t\t)\n\t\t}\n\t}\n\n\treturn true\n}\n"],"mappings":";;;AAEA,MAAM,EAAE,UAAUA;AAIlB,MAAM,cAAc,IAAI,IAAI;CAAC;CAAS;CAAQ;CAAW;CAAO,CAAC;AACjE,MAAM,WAAW,IAAI,IAAI;CAAC;CAAO;CAAY;CAAU,CAAC;AACxD,MAAM,aAAa,IAAI,IAAI,CAAC,UAAU,QAAQ,CAAC;AAC/C,MAAM,YAAY,IAAI,IAAI,CAAC,UAAU,UAAU,CAAC;AAEhD,SAAS,YAAY,KAAqB;CACzC,IAAI,IAAI;AAER,QAAO,EAAE,WAAW,UAAU,CAC7B,KAAI,EAAE,MAAM,GAAG,GAAG;AAGnB,QAAO;;AAGR,SAAS,aAAa,OAAY,cAA+B;AAChE,KAAI,UAAU,QAAQ,UAAU,KAAA,EAAW,QAAO;CAElD,MAAM,WAAW,YAAY,aAAa,aAAa,CAAC,MAAM,CAAC;AAE/D,KAAI,YAAY,IAAI,SAAS,CAAE,QAAO,OAAO,UAAU;AACvD,KAAI,SAAS,IAAI,SAAS,CAAE,QAAO,OAAO,UAAU,MAAM;AAC1D,KAAI,WAAW,IAAI,SAAS,CAAE,QAAO,OAAO,UAAU;AACtD,KAAI,UAAU,IAAI,SAAS,CAC1B,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;AAIzB,SAAQ,UAAR;EACC,KAAK,UACJ,QAAO,OAAO,UAAU;EACzB,KAAK,UACJ,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;EAEzB,KAAK,SACJ,QACC,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,iBAAiB,MAAM;EAEzB,KAAK,YACJ,QACC,iBAAiB,QACjB,OAAO,UAAU,YACjB,OAAO,UAAU;EAEnB,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,WACJ,QAAO,OAAO,UAAU,YAAY,iBAAiB,MAAM;EAC5D,KAAK,OACJ,QAAO,OAAO,SAAS,MAAM,IAAI,iBAAiB;;AAGpD,KAAI,SAAS,WAAW,QAAQ,IAAI,SAAS,WAAW,OAAO,CAC9D,QAAO,MAAM,QAAQ,MAAM,IAAI,iBAAiB;AAEjD,KAAI,SAAS,WAAW,OAAO,CAC9B,QACC,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,IAAI,UAAU;AAGlE,KAAI,SAAS,WAAW,SAAS,CAChC,QAAO,MAAM,QAAQ,MAAM;AAG5B,QAAO;;AAGR,SAAwB,YAAY,OAAmB,MAAoB;AAC1E,KAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,KAAK,CAC3D,OAAM,IAAI,UACT,IAAI,MAAM,KAAK,oDACf;CAGF,MAAM,SAAS,MAAM,OAAO;AAE5B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;AAChD,MAAI,CAAC,iBAAiB,QAAQ,IAAI,CACjC,OAAM,IAAI,MACT,IAAI,MAAM,KAAK,6BAA6B,IAAI,4BAChD;EAGF,MAAM,cAAc,OAAO;EAC3B,MAAM,gBAAgB,YAAY,QAAQ,QAAQ,aAAa;AAE/D,MAAI,YAAY,aAAa,UAAU,QAAQ,UAAU,KAAA,GACxD,OAAM,IAAI,UACT,IAAI,MAAM,KAAK,6BAA6B,IAAI,6BAA6B,QAC7E;AAGF,MAAI,CAAC,aAAa,OAAO,aAAa,EAAE;GACvC,MAAM,eAAe,MAAM,QAAQ,MAAM,GAAG,UAAU,OAAO;AAE7D,SAAM,IAAI,UACT,IAAI,MAAM,KAAK,8CAA8C,IAAI,cACpD,aAAa,mBAAmB,aAAa,GAC1D;;;AAIH,QAAO"}