UNPKG

@proofkit/fmodata

Version:
194 lines (193 loc) 7.26 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); import { EntitySet } from "./entity-set.js"; import { BatchBuilder } from "./batch-builder.js"; import { SchemaManager } from "./schema-manager.js"; class Database { constructor(databaseName, context, config) { __publicField(this, "occurrenceMap"); __publicField(this, "_useEntityIds", false); __publicField(this, "schema"); this.databaseName = databaseName; this.context = context; this.occurrenceMap = /* @__PURE__ */ new Map(); if (config == null ? void 0 : config.occurrences) { const occurrencesWithIds = []; const occurrencesWithoutIds = []; for (const occ of config.occurrences) { this.occurrenceMap.set(occ.name, occ); const hasTableId = occ.isUsingTableId(); const hasFieldIds = occ.baseTable.isUsingFieldIds(); if (hasTableId && hasFieldIds) { occurrencesWithIds.push(occ.name); } else if (!hasTableId && !hasFieldIds) { occurrencesWithoutIds.push(occ.name); } else { throw new Error( `TableOccurrence "${occ.name}" has inconsistent entity ID configuration. Both fmtId (${hasTableId ? "present" : "missing"}) and fmfIds (${hasFieldIds ? "present" : "missing"}) must be defined together.` ); } } const allOccurrencesUseEntityIds = occurrencesWithIds.length > 0 && occurrencesWithoutIds.length === 0; const hasMixedUsage = occurrencesWithIds.length > 0 && occurrencesWithoutIds.length > 0; if (config.useEntityIds !== void 0) { if (config.useEntityIds === false) { this._useEntityIds = false; } else if (config.useEntityIds === true) { if (hasMixedUsage || occurrencesWithoutIds.length > 0) { throw new Error( `useEntityIds is set to true but some occurrences do not use entity IDs. Occurrences without entity IDs: [${occurrencesWithoutIds.join(", ")}]. Either set useEntityIds to false or configure all occurrences with entity IDs.` ); } this._useEntityIds = true; } } else { if (hasMixedUsage) { throw new Error( `Cannot mix TableOccurrence instances with and without entity IDs in the same database. Occurrences with entity IDs: [${occurrencesWithIds.join(", ")}]. Occurrences without entity IDs: [${occurrencesWithoutIds.join(", ")}]. Either all table occurrences must use entity IDs (fmtId + fmfIds), none should, or explicitly set useEntityIds to false.` ); } this._useEntityIds = allOccurrencesUseEntityIds; } } else { this._useEntityIds = (config == null ? void 0 : config.useEntityIds) ?? false; } if (this.context._setUseEntityIds) { this.context._setUseEntityIds(this._useEntityIds); } this.schema = new SchemaManager(this.databaseName, this.context); } /** * Returns true if any table occurrence in this database is using entity IDs. */ isUsingEntityIds() { return this._useEntityIds; } /** * Gets a table occurrence by name. * @internal */ getOccurrence(name) { return this.occurrenceMap.get(name); } from(name) { const occurrence = this.occurrenceMap.get(name); if (occurrence) { return EntitySet.create({ occurrence, tableName: name, databaseName: this.databaseName, context: this.context, database: this }); } else { return new EntitySet({ tableName: name, databaseName: this.databaseName, context: this.context, database: this }); } } async getMetadata(args) { const result = await this.context._makeRequest(`/${this.databaseName}/$metadata`, { headers: { Accept: (args == null ? void 0 : args.format) === "xml" ? "application/xml" : "application/json" } }); if (result.error) { throw result.error; } if ((args == null ? void 0 : args.format) === "json") { const data = result.data; const metadata = data[this.databaseName]; if (!metadata) { throw new Error( `Metadata for database "${this.databaseName}" not found in response` ); } return metadata; } return result.data; } /** * Lists all available tables (entity sets) in this database. * @returns Promise resolving to an array of table names */ async listTableNames() { const result = await this.context._makeRequest(`/${this.databaseName}`); if (result.error) { throw result.error; } if (result.data.value && Array.isArray(result.data.value)) { return result.data.value.map((item) => item.name); } return []; } /** * Executes a FileMaker script. * @param scriptName - The name of the script to execute (must be valid according to OData rules) * @param options - Optional script parameter and result schema * @returns Promise resolving to script execution result */ async runScript(scriptName, options) { const body = {}; if ((options == null ? void 0 : options.scriptParam) !== void 0) { body.scriptParameterValue = options.scriptParam; } const result = await this.context._makeRequest(`/${this.databaseName}/Script.${scriptName}`, { method: "POST", body: Object.keys(body).length > 0 ? JSON.stringify(body) : void 0 }); if (result.error) { throw result.error; } const response = result.data; if ((options == null ? void 0 : options.resultSchema) && response.scriptResult !== void 0) { const validationResult = options.resultSchema["~standard"].validate( response.scriptResult.resultParameter ); const result2 = validationResult instanceof Promise ? await validationResult : validationResult; if (result2.issues) { throw new Error( `Script result validation failed: ${JSON.stringify(result2.issues)}` ); } return { resultCode: response.scriptResult.code, result: result2.value }; } return { resultCode: response.scriptResult.code, result: response.scriptResult.resultParameter }; } /** * Create a batch operation builder that allows multiple queries to be executed together * in a single atomic request. All operations succeed or fail together (transactional). * * @param builders - Array of executable query builders to batch * @returns A BatchBuilder that can be executed * @example * ```ts * const result = await db.batch([ * db.from('contacts').list().top(5), * db.from('users').list().top(5), * db.from('contacts').insert({ name: 'John' }) * ]).execute(); * * if (result.data) { * const [contacts, users, insertResult] = result.data; * } * ``` */ batch(builders) { return new BatchBuilder(builders, this.databaseName, this.context); } } export { Database }; //# sourceMappingURL=database.js.map