import { LimeType } from '../limetype'; import { PrivateProps } from '../util'; import { LimeFile } from '../file/file'; /** * The value types stored in a LimeObject property. * * Lime object properties hold typed primitives defined by the limetype schema: * - `string` — `string`, `text`, `phone`, `link`, `xml`, `option`, and all * date/time types (stored as ISO strings) * - `number` — `integer`, `decimal`, `percent`, and relation ids * (`user`, `belongsto`, `hasone`) * - `boolean` — `yesno` * - `string[]` — `set` (array of option keys) * - `null` — when the property has no value * * `hasmany` / `hasandbelongstomany` relations are managed through separate * commands. Files are accessed via {@link LimeObject.getFile} and are not * represented as a property value. * * @public * @group Lime objects */ export type LimeObjectValue = string | number | boolean | null | string[]; /** * The data portion of a Lime object — its user-defined property values * keyed by property name. * * System fields (`id`, `createdtime`, `timestamp`, `descriptive`) are * managed by the platform and are not part of this shape. * * @public * @group Lime objects */ export type LimeObjectData = { [property: string]: LimeObjectValue; }; /** * The system properties managed by the platform on every Lime object. * * These are the underscore-less names used on hydrated {@link LimeObject}s * after the runtime normalizes a raw record. Raw records returned by query * repositories carry the same fields with a `_` prefix; see * {@link LimeObjectRecord}. * * @public * @group Lime objects */ export type LimeObjectSystemProperties = { /** * Unique identifier for this object. * * The ID is a positive integer that uniquely identifies this record within * its {@link LimeType}. IDs are auto-generated and immutable. * * @example Read the id of a cached object * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const limeObject = repository.getObject('company', 1234); * * if (limeObject) { * console.log(`Object ID: ${limeObject.id}`); // "Object ID: 1234" * } * ``` */ id: number; /** * ISO 8601 timestamp when this object was created. * * This is an audit field that records when the record was first created * in the system. The timestamp includes date and time with timezone. * * @example Format the creation date * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const limeObject = repository.getObject('company', 1234); * * if (limeObject) { * const created = new Date(limeObject.createdtime); * console.log(`Created on: ${created.toLocaleDateString()}`); * } * ``` */ createdtime: string; /** * ISO 8601 timestamp of the last modification to this object. * * Updated automatically whenever any property of the object changes. * * @example Show how long ago the object changed * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const limeObject = repository.getObject('company', 1234); * * if (limeObject) { * const updated = new Date(limeObject.timestamp); * const minutesAgo = (Date.now() - updated.getTime()) / 60_000; * console.log(`Last updated ${Math.floor(minutesAgo)} minutes ago`); * } * ``` */ timestamp: string; /** * Human-readable text representation of this object. * * This is the display name shown in lists, dropdowns, and references. * Calculated from labels set on the {@link LimeType}'s properties. * Can be a single field or a combination of multiple fields. * * @example Display names for two different limetypes * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * * const company = repository.getObject('company', 1234); * const person = repository.getObject('person', 5678); * * console.log(company?.descriptive); // "Acme Corporation" * console.log(person?.descriptive); // "John Doe" (firstname + lastname) * ``` */ descriptive: string; }; /** * The raw shape of a Lime object as returned by query repositories. System * fields are prefixed with `_` and the limetype is included as `_limetype`. * The runtime normalizes these into the underscore-less form before storing * in state or wrapping as a {@link LimeObject}. * * Use this when consuming raw responses (for example * {@link ObjectResponse.objects}) rather than fully wrapped objects returned * from {@link LimeObjectRepository.getObject | getObject}. * * @remarks * Unlike {@link LimeObjectData} — which describes a hydrated object's * primitive property values — raw records may carry a **nested record** * for relation properties. A `belongsto` or `hasone` property arrives as * a {@link LimeObjectRecord}. * * @public * @group Lime objects */ export type LimeObjectRecord = PrivateProps & { _limetype: string; [property: string]: LimeObjectValue | LimeObjectRecord; }; /** * Represents a business object instance in Lime CRM. * * A {@link LimeObject} is an instance of a {@link LimeType} with actual data values. * It contains the object's properties, metadata, and methods for accessing data including * related objects. Use the `getValue()` method to access properties — it supports dot * notation for navigating relations. * * Key characteristics: * - Each object has a unique numeric ID * - Contains audit timestamps (created, last updated) * - Has a descriptive text representation * - Use getValue() to access properties, with dot notation for relations * - Can have attached files * * @example Use a decorator to get the current object * ```ts * import { State } from '@stencil/core'; * import { * LimeObject, * SelectCurrentLimeObject, * } from '@limetech/lime-web-components'; * * class MyComponent { * @State() * @SelectCurrentLimeObject() * private limeObject: LimeObject; * * private logObject() { * console.log(this.limeObject.descriptive); * console.log(this.limeObject.id); * console.log(new Date(this.limeObject.createdtime).toLocaleDateString()); * console.log(this.limeObject.getValue('name')); * } * } * ``` * * @example Access properties using getValue() with dot notation * ```ts * import { State } from '@stencil/core'; * import { * LimeObject, * SelectCurrentLimeObject, * } from '@limetech/lime-web-components'; * * class MyComponent { * @State() * @SelectCurrentLimeObject() * private deal: LimeObject; * * private readDealValues() { * const dealName = this.deal.getValue('name'); * const dealValue = this.deal.getValue('value'); * * // The path must have been loaded, otherwise the result is `undefined`. * const companyName = this.deal.getValue('company.name'); * * return { dealName, dealValue, companyName }; * } * } * ``` * * @remarks * Only loaded properties are readable. Nested objects and properties are not * lazy loaded, so decide which paths to load up front. See * {@link LimeObject.getValue | getValue}. * * The system fields `id`, `createdtime`, `timestamp`, and `descriptive` come * from {@link LimeObjectSystemProperties}. Property values are typed as * {@link LimeObjectValue}. * * @public * @group Lime objects */ export interface LimeObject extends LimeObjectSystemProperties { /** * Get the value of a property using dot notation to navigate relations. * * This method provides type-safe property access with support for navigating * through related objects. Use dot notation to traverse relations, e.g., * `company.address.city` to get the city of a company's address. * * This is the recommended way to access all properties, including simple * values and relations. * * Only properties that were loaded are returned. There is no lazy loading * today, so reading a property or a relation that was not loaded returns * `undefined` instead of fetching it. Ask for the paths you need up front * through {@link LoadOptions.properties}, using dot notation for values on * related objects. * * @param name - Property name or path. Use dots to navigate relations. * @returns The property value, or `undefined` if the property was not * loaded. For relations, returns the related {@link LimeObject}. * * @example Simple property access * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const deal = repository.getObject('deal', 1234); * * const name = deal?.getValue('name'); * const status = deal?.getValue('status'); * const value = deal?.getValue('value'); * ``` * * @example Values on related objects have to be loaded first * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * * const deal = await repository.loadObject('deal', 1234, { * properties: ['name', 'company.name', 'contact.email'], * }); * * const companyName = deal?.getValue('company.name'); * const contactEmail = deal?.getValue('contact.email'); * * // Not loaded above, so this is `undefined` rather than a fetch * const contactPhone = deal?.getValue('contact.phone'); * ``` * * @see {@link LoadOptions.properties} to choose which properties are loaded */ getValue(name: string): any; /** * Get the {@link LimeType} definition for this object. * * Returns the type definition containing schema information, property * definitions, ACL rules, and other metadata about this object's type. * * @returns The {@link LimeType} definition. * * @example Read schema and permissions from the type * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const limeObject = repository.getObject('deal', 1234); * * if (limeObject) { * const limetype = limeObject.getLimetype(); * console.log(`Object type: ${limetype.name}`); * console.log(`Display name: ${limetype.localname.singular}`); * * const canEdit = limetype.acl.update; * * const nameProperty = limetype.getProperty('name'); * console.log(`Name is required: ${nameProperty.required}`); * } * ``` */ getLimetype(): LimeType; /** * Get an attached file from a file property. * * Returns the {@link LimeFile} object for file attachments. Use this to * access file metadata (name, size, MIME type) and download URLs. * * @param name - Name of the file property. * @returns The {@link LimeFile} if a file is attached, undefined otherwise. * * @example Get a file attachment * ```ts * import { PlatformServiceName } from '@limetech/lime-web-components'; * * const repository = platform.get(PlatformServiceName.LimeObjectRepository); * const limeObject = repository.getObject('deal', 1234); * * const document = limeObject?.getFile('contract_pdf'); * * if (document) { * console.log(`File: ${document.filename}`); * console.log(`Size: ${document.size} bytes`); * console.log(`Extension: ${document.extension}`); * * const downloadUrl = document.getUrl('download'); * } * ``` */ getFile(name: string): LimeFile | undefined; /** * Dynamic property access for object properties. * * Properties are accessible via bracket notation, but prefer * {@link getValue} instead for consistent and relation-aware access. */ [property: string]: any; } /** * A {@link LimeObject} carrying edits the user has not saved yet: the * persisted row overlaid with what the user has typed. * * While an object is being created there is no persisted row behind it, so * the system fields, `id` included, may all be missing. The accessors stay * required, because a provider publishing bare form values would leave every * consumer with nothing to read. * * @beta * @group Lime objects */ export type LimeObjectDraft = Partial & Pick;