@proofkit/fmodata 0.1.0-alpha.19 → 0.1.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +198 -0
- package/dist/esm/client/builders/default-select.d.ts +4 -1
- package/dist/esm/client/builders/default-select.js +3 -2
- package/dist/esm/client/builders/default-select.js.map +1 -1
- package/dist/esm/client/builders/expand-builder.js.map +1 -1
- package/dist/esm/client/builders/query-string-builder.d.ts +1 -0
- package/dist/esm/client/builders/query-string-builder.js.map +1 -1
- package/dist/esm/client/builders/response-processor.d.ts +2 -0
- package/dist/esm/client/builders/response-processor.js +8 -3
- package/dist/esm/client/builders/response-processor.js.map +1 -1
- package/dist/esm/client/database.d.ts +27 -4
- package/dist/esm/client/database.js +17 -4
- package/dist/esm/client/database.js.map +1 -1
- package/dist/esm/client/delete-builder.d.ts +2 -0
- package/dist/esm/client/delete-builder.js +2 -0
- package/dist/esm/client/delete-builder.js.map +1 -1
- package/dist/esm/client/entity-set.d.ts +8 -7
- package/dist/esm/client/entity-set.js +21 -26
- package/dist/esm/client/entity-set.js.map +1 -1
- package/dist/esm/client/error-parser.js.map +1 -1
- package/dist/esm/client/filemaker-odata.d.ts +15 -2
- package/dist/esm/client/filemaker-odata.js +25 -2
- package/dist/esm/client/filemaker-odata.js.map +1 -1
- package/dist/esm/client/insert-builder.d.ts +2 -0
- package/dist/esm/client/insert-builder.js +2 -0
- package/dist/esm/client/insert-builder.js.map +1 -1
- package/dist/esm/client/query/query-builder.d.ts +26 -15
- package/dist/esm/client/query/query-builder.js +43 -9
- package/dist/esm/client/query/query-builder.js.map +1 -1
- package/dist/esm/client/query/response-processor.d.ts +1 -0
- package/dist/esm/client/query/types.d.ts +24 -3
- package/dist/esm/client/record-builder.d.ts +24 -13
- package/dist/esm/client/record-builder.js +50 -17
- package/dist/esm/client/record-builder.js.map +1 -1
- package/dist/esm/client/update-builder.d.ts +2 -0
- package/dist/esm/client/update-builder.js +2 -0
- package/dist/esm/client/update-builder.js.map +1 -1
- package/dist/esm/client/webhook-builder.d.ts +126 -0
- package/dist/esm/client/webhook-builder.js +197 -0
- package/dist/esm/client/webhook-builder.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/orm/field-builders.d.ts +12 -2
- package/dist/esm/orm/field-builders.js +18 -2
- package/dist/esm/orm/field-builders.js.map +1 -1
- package/dist/esm/orm/table.d.ts +23 -10
- package/dist/esm/orm/table.js +17 -30
- package/dist/esm/orm/table.js.map +1 -1
- package/dist/esm/types.d.ts +32 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/validation.d.ts +5 -5
- package/dist/esm/validation.js +44 -13
- package/dist/esm/validation.js.map +1 -1
- package/package.json +2 -2
- package/src/client/builders/default-select.ts +12 -1
- package/src/client/builders/expand-builder.ts +1 -1
- package/src/client/builders/query-string-builder.ts +6 -0
- package/src/client/builders/response-processor.ts +10 -0
- package/src/client/database.ts +54 -12
- package/src/client/delete-builder.ts +5 -1
- package/src/client/entity-set.ts +72 -44
- package/src/client/error-parser.ts +3 -0
- package/src/client/filemaker-odata.ts +39 -6
- package/src/client/insert-builder.ts +4 -0
- package/src/client/query/query-builder.ts +198 -35
- package/src/client/query/response-processor.ts +15 -25
- package/src/client/query/types.ts +35 -6
- package/src/client/record-builder.ts +159 -32
- package/src/client/update-builder.ts +4 -1
- package/src/client/webhook-builder.ts +285 -0
- package/src/index.ts +6 -0
- package/src/orm/field-builders.ts +24 -2
- package/src/orm/table.ts +40 -48
- package/src/types.ts +62 -6
- package/src/validation.ts +58 -13
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { FMTable } from '../orm.js';
|
|
2
|
+
import { ExecutionContext, ExecuteMethodOptions } from '../types.js';
|
|
3
|
+
import { FilterExpression } from '../orm/operators.js';
|
|
4
|
+
import { Column } from '../orm/column.js';
|
|
5
|
+
export type Webhook<TableName = string> = {
|
|
6
|
+
webhook: string;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
tableName: TableName;
|
|
9
|
+
notifySchemaChanges?: boolean;
|
|
10
|
+
select?: string | Column<any, any, any>[];
|
|
11
|
+
filter?: string | FilterExpression;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Webhook information returned by the API
|
|
15
|
+
*/
|
|
16
|
+
export type WebhookInfo = {
|
|
17
|
+
webHookID: number;
|
|
18
|
+
tableName: string;
|
|
19
|
+
url: string;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
notifySchemaChanges: boolean;
|
|
22
|
+
select: string;
|
|
23
|
+
filter: string;
|
|
24
|
+
pendingOperations: unknown[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Response from listing all webhooks
|
|
28
|
+
*/
|
|
29
|
+
export type WebhookListResponse = {
|
|
30
|
+
Status: string;
|
|
31
|
+
WebHook: WebhookInfo[];
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Response from adding a webhook
|
|
35
|
+
*/
|
|
36
|
+
export type WebhookAddResponse = {
|
|
37
|
+
webHookResult: {
|
|
38
|
+
webHookID: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export declare class WebhookManager {
|
|
42
|
+
private readonly databaseName;
|
|
43
|
+
private readonly context;
|
|
44
|
+
constructor(databaseName: string, context: ExecutionContext);
|
|
45
|
+
/**
|
|
46
|
+
* Adds a new webhook to the database.
|
|
47
|
+
* @param webhook - The webhook configuration object
|
|
48
|
+
* @param webhook.webhook - The webhook URL to call
|
|
49
|
+
* @param webhook.tableName - The FMTable instance for the table to monitor
|
|
50
|
+
* @param webhook.headers - Optional custom headers to include in webhook requests
|
|
51
|
+
* @param webhook.notifySchemaChanges - Whether to notify on schema changes
|
|
52
|
+
* @param webhook.select - Optional field selection (string or array of Column references)
|
|
53
|
+
* @param webhook.filter - Optional filter (string or FilterExpression)
|
|
54
|
+
* @returns Promise resolving to the created webhook data with ID
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* const result = await db.webhook.add({
|
|
58
|
+
* webhook: "https://example.com/webhook",
|
|
59
|
+
* tableName: contactsTable,
|
|
60
|
+
* headers: { "X-Custom-Header": "value" },
|
|
61
|
+
* });
|
|
62
|
+
* // result.webHookResult.webHookID contains the new webhook ID
|
|
63
|
+
* ```
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* // Using filter expressions and column arrays (same DX as query builder)
|
|
67
|
+
* const result = await db.webhook.add({
|
|
68
|
+
* webhook: "https://example.com/webhook",
|
|
69
|
+
* tableName: contacts,
|
|
70
|
+
* filter: eq(contacts.name, "John"),
|
|
71
|
+
* select: [contacts.name, contacts.PrimaryKey],
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
add(webhook: Webhook<FMTable>, options?: ExecuteMethodOptions): Promise<WebhookAddResponse>;
|
|
76
|
+
/**
|
|
77
|
+
* Deletes a webhook by ID.
|
|
78
|
+
* @param webhookId - The ID of the webhook to delete
|
|
79
|
+
* @returns Promise that resolves when the webhook is deleted
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* await db.webhook.remove(1);
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
remove(webhookId: string | number, options?: ExecuteMethodOptions): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Gets a webhook by ID.
|
|
88
|
+
* @param webhookId - The ID of the webhook to retrieve
|
|
89
|
+
* @returns Promise resolving to the webhook data
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const webhook = await db.webhook.get(1);
|
|
93
|
+
* // webhook.webHookID, webhook.tableName, webhook.url, etc.
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
get(webhookId: string | number, options?: ExecuteMethodOptions): Promise<WebhookInfo>;
|
|
97
|
+
/**
|
|
98
|
+
* Lists all webhooks.
|
|
99
|
+
* @returns Promise resolving to webhook list response with status and webhooks array
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const result = await db.webhook.list();
|
|
103
|
+
* // result.Status contains the status
|
|
104
|
+
* // result.WebHook contains the array of webhooks
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
list(options?: ExecuteMethodOptions): Promise<WebhookListResponse>;
|
|
108
|
+
/**
|
|
109
|
+
* Invokes a webhook by ID, optionally for specific row IDs.
|
|
110
|
+
* @param webhookId - The ID of the webhook to invoke
|
|
111
|
+
* @param options - Optional configuration
|
|
112
|
+
* @param options.rowIDs - Array of row IDs to trigger the webhook for
|
|
113
|
+
* @returns Promise resolving to the invocation result (type unknown until API behavior is confirmed)
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* // Invoke for all rows
|
|
117
|
+
* await db.webhook.invoke(1);
|
|
118
|
+
*
|
|
119
|
+
* // Invoke for specific rows
|
|
120
|
+
* await db.webhook.invoke(1, { rowIDs: [63, 61] });
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
invoke(webhookId: string | number, options?: {
|
|
124
|
+
rowIDs?: number[];
|
|
125
|
+
}, executeOptions?: ExecuteMethodOptions): Promise<unknown>;
|
|
126
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { isColumn } from "../orm/column.js";
|
|
2
|
+
import { FilterExpression } from "../orm/operators.js";
|
|
3
|
+
import { getTableName } from "../orm/table.js";
|
|
4
|
+
import { formatSelectFields } from "./builders/select-utils.js";
|
|
5
|
+
class WebhookManager {
|
|
6
|
+
constructor(databaseName, context) {
|
|
7
|
+
this.databaseName = databaseName;
|
|
8
|
+
this.context = context;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adds a new webhook to the database.
|
|
12
|
+
* @param webhook - The webhook configuration object
|
|
13
|
+
* @param webhook.webhook - The webhook URL to call
|
|
14
|
+
* @param webhook.tableName - The FMTable instance for the table to monitor
|
|
15
|
+
* @param webhook.headers - Optional custom headers to include in webhook requests
|
|
16
|
+
* @param webhook.notifySchemaChanges - Whether to notify on schema changes
|
|
17
|
+
* @param webhook.select - Optional field selection (string or array of Column references)
|
|
18
|
+
* @param webhook.filter - Optional filter (string or FilterExpression)
|
|
19
|
+
* @returns Promise resolving to the created webhook data with ID
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const result = await db.webhook.add({
|
|
23
|
+
* webhook: "https://example.com/webhook",
|
|
24
|
+
* tableName: contactsTable,
|
|
25
|
+
* headers: { "X-Custom-Header": "value" },
|
|
26
|
+
* });
|
|
27
|
+
* // result.webHookResult.webHookID contains the new webhook ID
|
|
28
|
+
* ```
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* // Using filter expressions and column arrays (same DX as query builder)
|
|
32
|
+
* const result = await db.webhook.add({
|
|
33
|
+
* webhook: "https://example.com/webhook",
|
|
34
|
+
* tableName: contacts,
|
|
35
|
+
* filter: eq(contacts.name, "John"),
|
|
36
|
+
* select: [contacts.name, contacts.PrimaryKey],
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
async add(webhook, options) {
|
|
41
|
+
var _a, _b;
|
|
42
|
+
const tableName = getTableName(webhook.tableName);
|
|
43
|
+
const useEntityIds = (options == null ? void 0 : options.useEntityIds) ?? ((_b = (_a = this.context)._getUseEntityIds) == null ? void 0 : _b.call(_a)) ?? false;
|
|
44
|
+
let filter;
|
|
45
|
+
if (webhook.filter !== void 0) {
|
|
46
|
+
if (webhook.filter instanceof FilterExpression) {
|
|
47
|
+
filter = webhook.filter.toODataFilter(useEntityIds);
|
|
48
|
+
} else {
|
|
49
|
+
filter = webhook.filter;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let select;
|
|
53
|
+
if (webhook.select !== void 0) {
|
|
54
|
+
if (Array.isArray(webhook.select)) {
|
|
55
|
+
const fieldNames = webhook.select.map((item) => {
|
|
56
|
+
if (isColumn(item)) {
|
|
57
|
+
return item.getFieldIdentifier(useEntityIds);
|
|
58
|
+
}
|
|
59
|
+
return String(item);
|
|
60
|
+
});
|
|
61
|
+
select = formatSelectFields(
|
|
62
|
+
fieldNames,
|
|
63
|
+
webhook.tableName,
|
|
64
|
+
useEntityIds
|
|
65
|
+
);
|
|
66
|
+
} else {
|
|
67
|
+
select = webhook.select;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const requestBody = {
|
|
71
|
+
webhook: webhook.webhook,
|
|
72
|
+
tableName
|
|
73
|
+
};
|
|
74
|
+
if (webhook.headers !== void 0) {
|
|
75
|
+
requestBody.headers = webhook.headers;
|
|
76
|
+
}
|
|
77
|
+
if (webhook.notifySchemaChanges !== void 0) {
|
|
78
|
+
requestBody.notifySchemaChanges = webhook.notifySchemaChanges;
|
|
79
|
+
}
|
|
80
|
+
if (select !== void 0) {
|
|
81
|
+
requestBody.select = select;
|
|
82
|
+
}
|
|
83
|
+
if (filter !== void 0) {
|
|
84
|
+
requestBody.filter = filter;
|
|
85
|
+
}
|
|
86
|
+
const result = await this.context._makeRequest(
|
|
87
|
+
`/${this.databaseName}/Webhook.Add`,
|
|
88
|
+
{
|
|
89
|
+
method: "POST",
|
|
90
|
+
body: JSON.stringify(requestBody),
|
|
91
|
+
...options
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
if (result.error) {
|
|
95
|
+
throw result.error;
|
|
96
|
+
}
|
|
97
|
+
return result.data;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Deletes a webhook by ID.
|
|
101
|
+
* @param webhookId - The ID of the webhook to delete
|
|
102
|
+
* @returns Promise that resolves when the webhook is deleted
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* await db.webhook.remove(1);
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
async remove(webhookId, options) {
|
|
109
|
+
const result = await this.context._makeRequest(
|
|
110
|
+
`/${this.databaseName}/Webhook.Delete(${webhookId})`,
|
|
111
|
+
{
|
|
112
|
+
method: "POST",
|
|
113
|
+
...options
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
if (result.error) {
|
|
117
|
+
throw result.error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Gets a webhook by ID.
|
|
122
|
+
* @param webhookId - The ID of the webhook to retrieve
|
|
123
|
+
* @returns Promise resolving to the webhook data
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const webhook = await db.webhook.get(1);
|
|
127
|
+
* // webhook.webHookID, webhook.tableName, webhook.url, etc.
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
async get(webhookId, options) {
|
|
131
|
+
const result = await this.context._makeRequest(
|
|
132
|
+
`/${this.databaseName}/Webhook.Get(${webhookId})`,
|
|
133
|
+
options
|
|
134
|
+
);
|
|
135
|
+
if (result.error) {
|
|
136
|
+
throw result.error;
|
|
137
|
+
}
|
|
138
|
+
return result.data;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Lists all webhooks.
|
|
142
|
+
* @returns Promise resolving to webhook list response with status and webhooks array
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* const result = await db.webhook.list();
|
|
146
|
+
* // result.Status contains the status
|
|
147
|
+
* // result.WebHook contains the array of webhooks
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
async list(options) {
|
|
151
|
+
const result = await this.context._makeRequest(
|
|
152
|
+
`/${this.databaseName}/Webhook.GetAll`,
|
|
153
|
+
options
|
|
154
|
+
);
|
|
155
|
+
if (result.error) {
|
|
156
|
+
throw result.error;
|
|
157
|
+
}
|
|
158
|
+
return result.data;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Invokes a webhook by ID, optionally for specific row IDs.
|
|
162
|
+
* @param webhookId - The ID of the webhook to invoke
|
|
163
|
+
* @param options - Optional configuration
|
|
164
|
+
* @param options.rowIDs - Array of row IDs to trigger the webhook for
|
|
165
|
+
* @returns Promise resolving to the invocation result (type unknown until API behavior is confirmed)
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* // Invoke for all rows
|
|
169
|
+
* await db.webhook.invoke(1);
|
|
170
|
+
*
|
|
171
|
+
* // Invoke for specific rows
|
|
172
|
+
* await db.webhook.invoke(1, { rowIDs: [63, 61] });
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
async invoke(webhookId, options, executeOptions) {
|
|
176
|
+
const body = {};
|
|
177
|
+
if ((options == null ? void 0 : options.rowIDs) !== void 0) {
|
|
178
|
+
body.rowIDs = options.rowIDs;
|
|
179
|
+
}
|
|
180
|
+
const result = await this.context._makeRequest(
|
|
181
|
+
`/${this.databaseName}/Webhook.Invoke(${webhookId})`,
|
|
182
|
+
{
|
|
183
|
+
method: "POST",
|
|
184
|
+
body: Object.keys(body).length > 0 ? JSON.stringify(body) : void 0,
|
|
185
|
+
...executeOptions
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
if (result.error) {
|
|
189
|
+
throw result.error;
|
|
190
|
+
}
|
|
191
|
+
return result.data;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
export {
|
|
195
|
+
WebhookManager
|
|
196
|
+
};
|
|
197
|
+
//# sourceMappingURL=webhook-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-builder.js","sources":["../../../src/client/webhook-builder.ts"],"sourcesContent":["import { FMTable, getTableName } from \"../orm\";\nimport type { ExecutionContext, ExecuteMethodOptions } from \"../types\";\nimport type { FFetchOptions } from \"@fetchkit/ffetch\";\nimport { FilterExpression } from \"../orm/operators\";\nimport { isColumn, type Column } from \"../orm/column\";\nimport { formatSelectFields } from \"./builders/select-utils\";\n\nexport type Webhook<TableName = string> = {\n webhook: string;\n headers?: Record<string, string>;\n tableName: TableName;\n notifySchemaChanges?: boolean;\n select?: string | Column<any, any, any>[];\n filter?: string | FilterExpression;\n};\n\n/**\n * Webhook information returned by the API\n */\nexport type WebhookInfo = {\n webHookID: number;\n tableName: string;\n url: string;\n headers?: Record<string, string>;\n notifySchemaChanges: boolean;\n select: string;\n filter: string;\n pendingOperations: unknown[];\n};\n\n/**\n * Response from listing all webhooks\n */\nexport type WebhookListResponse = {\n Status: string;\n WebHook: WebhookInfo[];\n};\n\n/**\n * Response from adding a webhook\n */\nexport type WebhookAddResponse = {\n webHookResult: {\n webHookID: number;\n };\n};\n\nexport class WebhookManager {\n constructor(\n private readonly databaseName: string,\n private readonly context: ExecutionContext,\n ) {}\n\n /**\n * Adds a new webhook to the database.\n * @param webhook - The webhook configuration object\n * @param webhook.webhook - The webhook URL to call\n * @param webhook.tableName - The FMTable instance for the table to monitor\n * @param webhook.headers - Optional custom headers to include in webhook requests\n * @param webhook.notifySchemaChanges - Whether to notify on schema changes\n * @param webhook.select - Optional field selection (string or array of Column references)\n * @param webhook.filter - Optional filter (string or FilterExpression)\n * @returns Promise resolving to the created webhook data with ID\n * @example\n * ```ts\n * const result = await db.webhook.add({\n * webhook: \"https://example.com/webhook\",\n * tableName: contactsTable,\n * headers: { \"X-Custom-Header\": \"value\" },\n * });\n * // result.webHookResult.webHookID contains the new webhook ID\n * ```\n * @example\n * ```ts\n * // Using filter expressions and column arrays (same DX as query builder)\n * const result = await db.webhook.add({\n * webhook: \"https://example.com/webhook\",\n * tableName: contacts,\n * filter: eq(contacts.name, \"John\"),\n * select: [contacts.name, contacts.PrimaryKey],\n * });\n * ```\n */\n async add(\n webhook: Webhook<FMTable>,\n options?: ExecuteMethodOptions,\n ): Promise<WebhookAddResponse> {\n // Extract the string table name from the FMTable instance\n const tableName = getTableName(webhook.tableName);\n\n // Get useEntityIds setting (check options first, then context, default to false)\n const useEntityIds =\n options?.useEntityIds ?? this.context._getUseEntityIds?.() ?? false;\n\n // Transform filter if it's a FilterExpression\n let filter: string | undefined;\n if (webhook.filter !== undefined) {\n if (webhook.filter instanceof FilterExpression) {\n filter = webhook.filter.toODataFilter(useEntityIds);\n } else {\n filter = webhook.filter;\n }\n }\n\n // Transform select if it's an array of Columns\n let select: string | undefined;\n if (webhook.select !== undefined) {\n if (Array.isArray(webhook.select)) {\n // Extract field identifiers from columns or use strings as-is\n const fieldNames = webhook.select.map((item) => {\n if (isColumn(item)) {\n return item.getFieldIdentifier(useEntityIds);\n }\n return String(item);\n });\n // Use formatSelectFields to properly format the select string\n select = formatSelectFields(\n fieldNames,\n webhook.tableName,\n useEntityIds,\n );\n } else {\n // Already a string, use as-is\n select = webhook.select;\n }\n }\n\n // Create request body with string table name and transformed filter/select\n const requestBody: {\n webhook: string;\n headers?: Record<string, string>;\n tableName: string;\n notifySchemaChanges?: boolean;\n select?: string;\n filter?: string;\n } = {\n webhook: webhook.webhook,\n tableName,\n };\n\n if (webhook.headers !== undefined) {\n requestBody.headers = webhook.headers;\n }\n if (webhook.notifySchemaChanges !== undefined) {\n requestBody.notifySchemaChanges = webhook.notifySchemaChanges;\n }\n if (select !== undefined) {\n requestBody.select = select;\n }\n if (filter !== undefined) {\n requestBody.filter = filter;\n }\n\n const result = await this.context._makeRequest<WebhookAddResponse>(\n `/${this.databaseName}/Webhook.Add`,\n {\n method: \"POST\",\n body: JSON.stringify(requestBody),\n ...options,\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n\n return result.data;\n }\n\n /**\n * Deletes a webhook by ID.\n * @param webhookId - The ID of the webhook to delete\n * @returns Promise that resolves when the webhook is deleted\n * @example\n * ```ts\n * await db.webhook.remove(1);\n * ```\n */\n async remove(\n webhookId: string | number,\n options?: ExecuteMethodOptions,\n ): Promise<void> {\n const result = await this.context._makeRequest(\n `/${this.databaseName}/Webhook.Delete(${webhookId})`,\n {\n method: \"POST\",\n ...options,\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n }\n\n /**\n * Gets a webhook by ID.\n * @param webhookId - The ID of the webhook to retrieve\n * @returns Promise resolving to the webhook data\n * @example\n * ```ts\n * const webhook = await db.webhook.get(1);\n * // webhook.webHookID, webhook.tableName, webhook.url, etc.\n * ```\n */\n async get(\n webhookId: string | number,\n options?: ExecuteMethodOptions,\n ): Promise<WebhookInfo> {\n const result = await this.context._makeRequest<WebhookInfo>(\n `/${this.databaseName}/Webhook.Get(${webhookId})`,\n options,\n );\n\n if (result.error) {\n throw result.error;\n }\n\n return result.data;\n }\n\n /**\n * Lists all webhooks.\n * @returns Promise resolving to webhook list response with status and webhooks array\n * @example\n * ```ts\n * const result = await db.webhook.list();\n * // result.Status contains the status\n * // result.WebHook contains the array of webhooks\n * ```\n */\n async list(options?: ExecuteMethodOptions): Promise<WebhookListResponse> {\n const result = await this.context._makeRequest<WebhookListResponse>(\n `/${this.databaseName}/Webhook.GetAll`,\n options,\n );\n\n if (result.error) {\n throw result.error;\n }\n\n return result.data;\n }\n\n /**\n * Invokes a webhook by ID, optionally for specific row IDs.\n * @param webhookId - The ID of the webhook to invoke\n * @param options - Optional configuration\n * @param options.rowIDs - Array of row IDs to trigger the webhook for\n * @returns Promise resolving to the invocation result (type unknown until API behavior is confirmed)\n * @example\n * ```ts\n * // Invoke for all rows\n * await db.webhook.invoke(1);\n *\n * // Invoke for specific rows\n * await db.webhook.invoke(1, { rowIDs: [63, 61] });\n * ```\n */\n async invoke(\n webhookId: string | number,\n options?: { rowIDs?: number[] },\n executeOptions?: ExecuteMethodOptions,\n ): Promise<unknown> {\n const body: { rowIDs?: number[] } = {};\n if (options?.rowIDs !== undefined) {\n body.rowIDs = options.rowIDs;\n }\n\n const result = await this.context._makeRequest<unknown>(\n `/${this.databaseName}/Webhook.Invoke(${webhookId})`,\n {\n method: \"POST\",\n body: Object.keys(body).length > 0 ? JSON.stringify(body) : undefined,\n ...executeOptions,\n },\n );\n\n if (result.error) {\n throw result.error;\n }\n\n return result.data;\n }\n}\n"],"names":[],"mappings":";;;;AA+CO,MAAM,eAAe;AAAA,EAC1B,YACmB,cACA,SACjB;AAFiB,SAAA,eAAA;AACA,SAAA,UAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCnB,MAAM,IACJ,SACA,SAC6B;;AAEvB,UAAA,YAAY,aAAa,QAAQ,SAAS;AAGhD,UAAM,gBACJ,mCAAS,mBAAgB,gBAAK,SAAQ,qBAAb,gCAAqC;AAG5D,QAAA;AACA,QAAA,QAAQ,WAAW,QAAW;AAC5B,UAAA,QAAQ,kBAAkB,kBAAkB;AACrC,iBAAA,QAAQ,OAAO,cAAc,YAAY;AAAA,MAAA,OAC7C;AACL,iBAAS,QAAQ;AAAA,MAAA;AAAA,IACnB;AAIE,QAAA;AACA,QAAA,QAAQ,WAAW,QAAW;AAChC,UAAI,MAAM,QAAQ,QAAQ,MAAM,GAAG;AAEjC,cAAM,aAAa,QAAQ,OAAO,IAAI,CAAC,SAAS;AAC1C,cAAA,SAAS,IAAI,GAAG;AACX,mBAAA,KAAK,mBAAmB,YAAY;AAAA,UAAA;AAE7C,iBAAO,OAAO,IAAI;AAAA,QAAA,CACnB;AAEQ,iBAAA;AAAA,UACP;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,QACF;AAAA,MAAA,OACK;AAEL,iBAAS,QAAQ;AAAA,MAAA;AAAA,IACnB;AAIF,UAAM,cAOF;AAAA,MACF,SAAS,QAAQ;AAAA,MACjB;AAAA,IACF;AAEI,QAAA,QAAQ,YAAY,QAAW;AACjC,kBAAY,UAAU,QAAQ;AAAA,IAAA;AAE5B,QAAA,QAAQ,wBAAwB,QAAW;AAC7C,kBAAY,sBAAsB,QAAQ;AAAA,IAAA;AAE5C,QAAI,WAAW,QAAW;AACxB,kBAAY,SAAS;AAAA,IAAA;AAEvB,QAAI,WAAW,QAAW;AACxB,kBAAY,SAAS;AAAA,IAAA;AAGjB,UAAA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC,IAAI,KAAK,YAAY;AAAA,MACrB;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,WAAW;AAAA,QAChC,GAAG;AAAA,MAAA;AAAA,IAEP;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,OAAO;AAAA,IAAA;AAGf,WAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYhB,MAAM,OACJ,WACA,SACe;AACT,UAAA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC,IAAI,KAAK,YAAY,mBAAmB,SAAS;AAAA,MACjD;AAAA,QACE,QAAQ;AAAA,QACR,GAAG;AAAA,MAAA;AAAA,IAEP;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,OAAO;AAAA,IAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaF,MAAM,IACJ,WACA,SACsB;AAChB,UAAA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC,IAAI,KAAK,YAAY,gBAAgB,SAAS;AAAA,MAC9C;AAAA,IACF;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,OAAO;AAAA,IAAA;AAGf,WAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAahB,MAAM,KAAK,SAA8D;AACjE,UAAA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC,IAAI,KAAK,YAAY;AAAA,MACrB;AAAA,IACF;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,OAAO;AAAA,IAAA;AAGf,WAAO,OAAO;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBhB,MAAM,OACJ,WACA,SACA,gBACkB;AAClB,UAAM,OAA8B,CAAC;AACjC,SAAA,mCAAS,YAAW,QAAW;AACjC,WAAK,SAAS,QAAQ;AAAA,IAAA;AAGlB,UAAA,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC,IAAI,KAAK,YAAY,mBAAmB,SAAS;AAAA,MACjD;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,KAAK,UAAU,IAAI,IAAI;AAAA,QAC5D,GAAG;AAAA,MAAA;AAAA,IAEP;AAEA,QAAI,OAAO,OAAO;AAChB,YAAM,OAAO;AAAA,IAAA;AAGf,WAAO,OAAO;AAAA,EAAA;AAElB;"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { textField, numberField, dateField, timeField, timestampField, container
|
|
|
3
3
|
export type { Database } from './client/database.js';
|
|
4
4
|
export type { EntitySet } from './client/entity-set.js';
|
|
5
5
|
export type { SchemaManager, Field, StringField, NumericField, DateField, TimeField, TimestampField, ContainerField, } from './client/schema-manager.js';
|
|
6
|
+
export type { Webhook, WebhookInfo, WebhookListResponse, WebhookAddResponse, } from './client/webhook-builder.js';
|
|
6
7
|
export type { Result, BatchResult, BatchItemResult, InferSchemaType, ODataRecordMetadata, Metadata, FetchHandler, ExecuteMethodOptions, ExecuteOptions, } from './types.js';
|
|
7
8
|
export { TimeoutError, AbortError, NetworkError, RetryLimitError, CircuitOpenError, } from '@fetchkit/ffetch';
|
|
8
9
|
export type { FFetchOptions } from '@fetchkit/ffetch';
|
|
@@ -24,12 +24,13 @@ export declare class FieldBuilder<TOutput = any, TInput = TOutput, TDbType = TOu
|
|
|
24
24
|
private _outputValidator?;
|
|
25
25
|
private _inputValidator?;
|
|
26
26
|
private _fieldType;
|
|
27
|
+
private _comment?;
|
|
27
28
|
constructor(fieldType: string);
|
|
28
29
|
/**
|
|
29
30
|
* Mark this field as the primary key for the table.
|
|
30
|
-
* Primary keys are automatically read-only.
|
|
31
|
+
* Primary keys are automatically read-only and non-nullable.
|
|
31
32
|
*/
|
|
32
|
-
primaryKey(): FieldBuilder<TOutput
|
|
33
|
+
primaryKey(): FieldBuilder<NonNullable<TOutput>, NonNullable<TInput>, NonNullable<TDbType>, true>;
|
|
33
34
|
/**
|
|
34
35
|
* Mark this field as non-nullable.
|
|
35
36
|
* Updates the type to exclude null/undefined.
|
|
@@ -63,6 +64,14 @@ export declare class FieldBuilder<TOutput = any, TInput = TOutput, TDbType = TOu
|
|
|
63
64
|
* // You pass true/false, FileMaker gets 1/0
|
|
64
65
|
*/
|
|
65
66
|
writeValidator<I>(validator: StandardSchemaV1<I, TDbType>): FieldBuilder<TOutput, I, TDbType, TReadOnly>;
|
|
67
|
+
/**
|
|
68
|
+
* Add a comment to this field for metadata purposes.
|
|
69
|
+
* This helps future developers understand the purpose of the field.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* textField().comment("Account name of the user who last modified each record")
|
|
73
|
+
*/
|
|
74
|
+
comment(comment: string): FieldBuilder<TOutput, TInput, TDbType, TReadOnly>;
|
|
66
75
|
/**
|
|
67
76
|
* Get the metadata configuration for this field.
|
|
68
77
|
* @internal Used by fmTableOccurrence to extract field configuration
|
|
@@ -75,6 +84,7 @@ export declare class FieldBuilder<TOutput = any, TInput = TOutput, TDbType = TOu
|
|
|
75
84
|
entityId: `FMFID:${string}` | undefined;
|
|
76
85
|
outputValidator: StandardSchemaV1<any, TOutput> | undefined;
|
|
77
86
|
inputValidator: StandardSchemaV1<TInput, any> | undefined;
|
|
87
|
+
comment: string | undefined;
|
|
78
88
|
};
|
|
79
89
|
/**
|
|
80
90
|
* Clone this builder to allow immutable chaining.
|
|
@@ -10,15 +10,17 @@ class FieldBuilder {
|
|
|
10
10
|
__publicField(this, "_outputValidator");
|
|
11
11
|
__publicField(this, "_inputValidator");
|
|
12
12
|
__publicField(this, "_fieldType");
|
|
13
|
+
__publicField(this, "_comment");
|
|
13
14
|
this._fieldType = fieldType;
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* Mark this field as the primary key for the table.
|
|
17
|
-
* Primary keys are automatically read-only.
|
|
18
|
+
* Primary keys are automatically read-only and non-nullable.
|
|
18
19
|
*/
|
|
19
20
|
primaryKey() {
|
|
20
21
|
const builder = this._clone();
|
|
21
22
|
builder._primaryKey = true;
|
|
23
|
+
builder._notNull = true;
|
|
22
24
|
builder._readOnly = true;
|
|
23
25
|
return builder;
|
|
24
26
|
}
|
|
@@ -75,6 +77,18 @@ class FieldBuilder {
|
|
|
75
77
|
builder._inputValidator = validator;
|
|
76
78
|
return builder;
|
|
77
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Add a comment to this field for metadata purposes.
|
|
82
|
+
* This helps future developers understand the purpose of the field.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* textField().comment("Account name of the user who last modified each record")
|
|
86
|
+
*/
|
|
87
|
+
comment(comment) {
|
|
88
|
+
const builder = this._clone();
|
|
89
|
+
builder._comment = comment;
|
|
90
|
+
return builder;
|
|
91
|
+
}
|
|
78
92
|
/**
|
|
79
93
|
* Get the metadata configuration for this field.
|
|
80
94
|
* @internal Used by fmTableOccurrence to extract field configuration
|
|
@@ -87,7 +101,8 @@ class FieldBuilder {
|
|
|
87
101
|
readOnly: this._readOnly,
|
|
88
102
|
entityId: this._entityId,
|
|
89
103
|
outputValidator: this._outputValidator,
|
|
90
|
-
inputValidator: this._inputValidator
|
|
104
|
+
inputValidator: this._inputValidator,
|
|
105
|
+
comment: this._comment
|
|
91
106
|
};
|
|
92
107
|
}
|
|
93
108
|
/**
|
|
@@ -104,6 +119,7 @@ class FieldBuilder {
|
|
|
104
119
|
builder._entityId = this._entityId;
|
|
105
120
|
builder._outputValidator = this._outputValidator;
|
|
106
121
|
builder._inputValidator = this._inputValidator;
|
|
122
|
+
builder._comment = this._comment;
|
|
107
123
|
return builder;
|
|
108
124
|
}
|
|
109
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-builders.js","sources":["../../../src/orm/field-builders.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Branded type for container field's database type.\n * This allows TypeScript to distinguish container fields from regular string fields\n * at the type level, enabling compile-time exclusion from select operations.\n */\nexport type ContainerDbType = string & { readonly __container: true };\n\n/**\n * FieldBuilder provides a fluent API for defining table fields with type-safe metadata.\n * Supports chaining methods to configure primary keys, nullability, read-only status, entity IDs, and validators.\n *\n * @template TOutput - The output type after applying outputValidator (what you get when reading)\n * @template TInput - The input type after applying inputValidator (what you pass when writing)\n * @template TDbType - The database type (what FileMaker stores/expects)\n * @template TReadOnly - Whether this field is read-only (for type-level exclusion from insert/update)\n */\nexport class FieldBuilder<\n TOutput = any,\n TInput = TOutput,\n TDbType = TOutput,\n TReadOnly extends boolean = false,\n> {\n private _primaryKey = false;\n private _notNull = false;\n private _readOnly = false;\n private _entityId?: `FMFID:${string}`;\n private _outputValidator?: StandardSchemaV1<any, TOutput>;\n private _inputValidator?: StandardSchemaV1<TInput, any>;\n private _fieldType: string;\n\n constructor(fieldType: string) {\n this._fieldType = fieldType;\n }\n\n /**\n * Mark this field as the primary key for the table.\n * Primary keys are automatically read-only.\n */\n primaryKey(): FieldBuilder<TOutput, TInput, TDbType, true> {\n const builder = this._clone() as any;\n builder._primaryKey = true;\n builder._readOnly = true; // Primary keys are automatically read-only\n return builder;\n }\n\n /**\n * Mark this field as non-nullable.\n * Updates the type to exclude null/undefined.\n */\n notNull(): FieldBuilder<\n NonNullable<TOutput>,\n NonNullable<TInput>,\n NonNullable<TDbType>,\n TReadOnly\n > {\n const builder = this._clone() as any;\n builder._notNull = true;\n return builder;\n }\n\n /**\n * Mark this field as read-only.\n * Read-only fields are excluded from insert and update operations.\n */\n readOnly(): FieldBuilder<TOutput, TInput, TDbType, true> {\n const builder = this._clone() as any;\n builder._readOnly = true;\n return builder;\n }\n\n /**\n * Assign a FileMaker field ID (FMFID) to this field.\n * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.\n */\n entityId(\n id: `FMFID:${string}`,\n ): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = this._clone();\n builder._entityId = id;\n return builder;\n }\n\n /**\n * Set a validator for the output (reading from database).\n * The output validator transforms/validates data coming FROM the database in list or get operations.\n *\n * @example\n * numberField().readValidator(z.coerce.boolean())\n * // FileMaker returns 0/1, you get true/false\n */\n readValidator<O, VInput = TDbType>(\n validator: StandardSchemaV1<VInput, O>,\n ): FieldBuilder<O, TInput, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._outputValidator = validator;\n return builder;\n }\n\n /**\n * Set a validator for the input (writing to database).\n * The input validator transforms/validates data going TO the database in insert, update, and filter operations.\n *\n * @example\n * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))\n * // You pass true/false, FileMaker gets 1/0\n */\n writeValidator<I>(\n validator: StandardSchemaV1<I, TDbType>,\n ): FieldBuilder<TOutput, I, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._inputValidator = validator;\n return builder;\n }\n\n /**\n * Get the metadata configuration for this field.\n * @internal Used by fmTableOccurrence to extract field configuration\n */\n _getConfig() {\n return {\n fieldType: this._fieldType,\n primaryKey: this._primaryKey,\n notNull: this._notNull,\n readOnly: this._readOnly,\n entityId: this._entityId,\n outputValidator: this._outputValidator,\n inputValidator: this._inputValidator,\n };\n }\n\n /**\n * Clone this builder to allow immutable chaining.\n * @private\n */\n private _clone(): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = new FieldBuilder<TOutput, TInput, TDbType, TReadOnly>(\n this._fieldType,\n );\n builder._primaryKey = this._primaryKey;\n builder._notNull = this._notNull;\n builder._readOnly = this._readOnly;\n builder._entityId = this._entityId;\n builder._outputValidator = this._outputValidator;\n builder._inputValidator = this._inputValidator;\n return builder;\n }\n}\n\n/**\n * Create a text field (Edm.String in FileMaker OData).\n * By default, text fields are nullable.\n *\n * @example\n * textField() // string | null\n * textField().notNull() // string\n * textField().entityId(\"FMFID:1\") // with entity ID\n */\nexport function textField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"text\",\n );\n}\n\n/**\n * Create a number field (Edm.Decimal in FileMaker OData).\n * By default, number fields are nullable.\n *\n * @example\n * numberField() // number | null\n * numberField().notNull() // number\n * numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read\n */\nexport function numberField(): FieldBuilder<\n number | null,\n number | null,\n number | null,\n false\n> {\n return new FieldBuilder<number | null, number | null, number | null, false>(\n \"number\",\n );\n}\n\n/**\n * Create a date field (Edm.Date in FileMaker OData).\n * By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD).\n *\n * @example\n * dateField() // string | null (ISO date format)\n * dateField().notNull() // string\n */\nexport function dateField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"date\",\n );\n}\n\n/**\n * Create a time field (Edm.TimeOfDay in FileMaker OData).\n * By default, time fields are nullable and represented as ISO time strings (HH:mm:ss).\n *\n * @example\n * timeField() // string | null (ISO time format)\n * timeField().notNull() // string\n */\nexport function timeField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"time\",\n );\n}\n\n/**\n * Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).\n * By default, timestamp fields are nullable and represented as ISO 8601 strings.\n *\n * @example\n * timestampField() // string | null (ISO 8601 format)\n * timestampField().notNull() // string\n * timestampField().readOnly() // typical for CreationTimestamp\n */\nexport function timestampField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"timestamp\",\n );\n}\n\n/**\n * Create a container field (Edm.Stream in FileMaker OData).\n * Container fields store binary data and are represented as base64 strings in the API.\n * By default, container fields are nullable.\n *\n * Note: Container fields cannot be selected via .select() - they can only be accessed\n * via .getSingleField() due to FileMaker OData API limitations.\n *\n * @example\n * containerField() // string | null (base64 encoded)\n * containerField().notNull() // string\n */\nexport function containerField(): FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n> {\n return new FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n >(\"container\");\n}\n\n/**\n * Create a calculated field (read-only field computed by FileMaker).\n * Calculated fields are automatically marked as read-only.\n *\n * @example\n * calcField() // string | null\n * calcField().notNull() // string\n */\nexport function calcField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n true\n> {\n const builder = new FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n >(\"calculated\");\n return builder.readOnly();\n}\n"],"names":[],"mappings":";;;AAkBO,MAAM,aAKX;AAAA,EASA,YAAY,WAAmB;AARvB,uCAAc;AACd,oCAAW;AACX,qCAAY;AACZ;AACA;AACA;AACA;AAGN,SAAK,aAAa;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpB,aAA2D;AACnD,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,cAAc;AACtB,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,UAKE;AACM,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,WAAW;AACZ,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,WAAyD;AACjD,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,SACE,IACmD;AAC7C,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,cACE,WAC6C;AACvC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,mBAAmB;AACpB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,eACE,WAC8C;AACxC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,kBAAkB;AACnB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,aAAa;AACJ,WAAA;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,iBAAiB,KAAK;AAAA,MACtB,gBAAgB,KAAK;AAAA,IACvB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOM,SAA4D;AAClE,UAAM,UAAU,IAAI;AAAA,MAClB,KAAK;AAAA,IACP;AACA,YAAQ,cAAc,KAAK;AAC3B,YAAQ,WAAW,KAAK;AACxB,YAAQ,YAAY,KAAK;AACzB,YAAQ,YAAY,KAAK;AACzB,YAAQ,mBAAmB,KAAK;AAChC,YAAQ,kBAAkB,KAAK;AACxB,WAAA;AAAA,EAAA;AAEX;AAWO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,cAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,iBAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAcO,SAAS,iBAKd;AACO,SAAA,IAAI,aAKT,WAAW;AACf;AAUO,SAAS,YAKd;AACM,QAAA,UAAU,IAAI,aAKlB,YAAY;AACd,SAAO,QAAQ,SAAS;AAC1B;"}
|
|
1
|
+
{"version":3,"file":"field-builders.js","sources":["../../../src/orm/field-builders.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * Branded type for container field's database type.\n * This allows TypeScript to distinguish container fields from regular string fields\n * at the type level, enabling compile-time exclusion from select operations.\n */\nexport type ContainerDbType = string & { readonly __container: true };\n\n/**\n * FieldBuilder provides a fluent API for defining table fields with type-safe metadata.\n * Supports chaining methods to configure primary keys, nullability, read-only status, entity IDs, and validators.\n *\n * @template TOutput - The output type after applying outputValidator (what you get when reading)\n * @template TInput - The input type after applying inputValidator (what you pass when writing)\n * @template TDbType - The database type (what FileMaker stores/expects)\n * @template TReadOnly - Whether this field is read-only (for type-level exclusion from insert/update)\n */\nexport class FieldBuilder<\n TOutput = any,\n TInput = TOutput,\n TDbType = TOutput,\n TReadOnly extends boolean = false,\n> {\n private _primaryKey = false;\n private _notNull = false;\n private _readOnly = false;\n private _entityId?: `FMFID:${string}`;\n private _outputValidator?: StandardSchemaV1<any, TOutput>;\n private _inputValidator?: StandardSchemaV1<TInput, any>;\n private _fieldType: string;\n private _comment?: string;\n\n constructor(fieldType: string) {\n this._fieldType = fieldType;\n }\n\n /**\n * Mark this field as the primary key for the table.\n * Primary keys are automatically read-only and non-nullable.\n */\n primaryKey(): FieldBuilder<\n NonNullable<TOutput>,\n NonNullable<TInput>,\n NonNullable<TDbType>,\n true\n > {\n const builder = this._clone() as any;\n builder._primaryKey = true;\n builder._notNull = true; // Primary keys are automatically non-nullable\n builder._readOnly = true; // Primary keys are automatically read-only\n return builder;\n }\n\n /**\n * Mark this field as non-nullable.\n * Updates the type to exclude null/undefined.\n */\n notNull(): FieldBuilder<\n NonNullable<TOutput>,\n NonNullable<TInput>,\n NonNullable<TDbType>,\n TReadOnly\n > {\n const builder = this._clone() as any;\n builder._notNull = true;\n return builder;\n }\n\n /**\n * Mark this field as read-only.\n * Read-only fields are excluded from insert and update operations.\n */\n readOnly(): FieldBuilder<TOutput, TInput, TDbType, true> {\n const builder = this._clone() as any;\n builder._readOnly = true;\n return builder;\n }\n\n /**\n * Assign a FileMaker field ID (FMFID) to this field.\n * When useEntityIds is enabled, this ID will be used in API requests instead of the field name.\n */\n entityId(\n id: `FMFID:${string}`,\n ): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = this._clone();\n builder._entityId = id;\n return builder;\n }\n\n /**\n * Set a validator for the output (reading from database).\n * The output validator transforms/validates data coming FROM the database in list or get operations.\n *\n * @example\n * numberField().readValidator(z.coerce.boolean())\n * // FileMaker returns 0/1, you get true/false\n */\n readValidator<O, VInput = TDbType>(\n validator: StandardSchemaV1<VInput, O>,\n ): FieldBuilder<O, TInput, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._outputValidator = validator;\n return builder;\n }\n\n /**\n * Set a validator for the input (writing to database).\n * The input validator transforms/validates data going TO the database in insert, update, and filter operations.\n *\n * @example\n * numberField().writeValidator(z.boolean().transform(v => v ? 1 : 0))\n * // You pass true/false, FileMaker gets 1/0\n */\n writeValidator<I>(\n validator: StandardSchemaV1<I, TDbType>,\n ): FieldBuilder<TOutput, I, TDbType, TReadOnly> {\n const builder = this._clone() as any;\n builder._inputValidator = validator;\n return builder;\n }\n\n /**\n * Add a comment to this field for metadata purposes.\n * This helps future developers understand the purpose of the field.\n *\n * @example\n * textField().comment(\"Account name of the user who last modified each record\")\n */\n comment(comment: string): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = this._clone();\n builder._comment = comment;\n return builder;\n }\n\n /**\n * Get the metadata configuration for this field.\n * @internal Used by fmTableOccurrence to extract field configuration\n */\n _getConfig() {\n return {\n fieldType: this._fieldType,\n primaryKey: this._primaryKey,\n notNull: this._notNull,\n readOnly: this._readOnly,\n entityId: this._entityId,\n outputValidator: this._outputValidator,\n inputValidator: this._inputValidator,\n comment: this._comment,\n };\n }\n\n /**\n * Clone this builder to allow immutable chaining.\n * @private\n */\n private _clone(): FieldBuilder<TOutput, TInput, TDbType, TReadOnly> {\n const builder = new FieldBuilder<TOutput, TInput, TDbType, TReadOnly>(\n this._fieldType,\n );\n builder._primaryKey = this._primaryKey;\n builder._notNull = this._notNull;\n builder._readOnly = this._readOnly;\n builder._entityId = this._entityId;\n builder._outputValidator = this._outputValidator;\n builder._inputValidator = this._inputValidator;\n builder._comment = this._comment;\n return builder;\n }\n}\n\n/**\n * Create a text field (Edm.String in FileMaker OData).\n * By default, text fields are nullable.\n *\n * @example\n * textField() // string | null\n * textField().notNull() // string\n * textField().entityId(\"FMFID:1\") // with entity ID\n */\nexport function textField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"text\",\n );\n}\n\n/**\n * Create a number field (Edm.Decimal in FileMaker OData).\n * By default, number fields are nullable.\n *\n * @example\n * numberField() // number | null\n * numberField().notNull() // number\n * numberField().outputValidator(z.coerce.boolean()) // transform to boolean on read\n */\nexport function numberField(): FieldBuilder<\n number | null,\n number | null,\n number | null,\n false\n> {\n return new FieldBuilder<number | null, number | null, number | null, false>(\n \"number\",\n );\n}\n\n/**\n * Create a date field (Edm.Date in FileMaker OData).\n * By default, date fields are nullable and represented as ISO date strings (YYYY-MM-DD).\n *\n * @example\n * dateField() // string | null (ISO date format)\n * dateField().notNull() // string\n */\nexport function dateField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"date\",\n );\n}\n\n/**\n * Create a time field (Edm.TimeOfDay in FileMaker OData).\n * By default, time fields are nullable and represented as ISO time strings (HH:mm:ss).\n *\n * @example\n * timeField() // string | null (ISO time format)\n * timeField().notNull() // string\n */\nexport function timeField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"time\",\n );\n}\n\n/**\n * Create a timestamp field (Edm.DateTimeOffset in FileMaker OData).\n * By default, timestamp fields are nullable and represented as ISO 8601 strings.\n *\n * @example\n * timestampField() // string | null (ISO 8601 format)\n * timestampField().notNull() // string\n * timestampField().readOnly() // typical for CreationTimestamp\n */\nexport function timestampField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n> {\n return new FieldBuilder<string | null, string | null, string | null, false>(\n \"timestamp\",\n );\n}\n\n/**\n * Create a container field (Edm.Stream in FileMaker OData).\n * Container fields store binary data and are represented as base64 strings in the API.\n * By default, container fields are nullable.\n *\n * Note: Container fields cannot be selected via .select() - they can only be accessed\n * via .getSingleField() due to FileMaker OData API limitations.\n *\n * @example\n * containerField() // string | null (base64 encoded)\n * containerField().notNull() // string\n */\nexport function containerField(): FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n> {\n return new FieldBuilder<\n string | null,\n string | null,\n ContainerDbType | null,\n false\n >(\"container\");\n}\n\n/**\n * Create a calculated field (read-only field computed by FileMaker).\n * Calculated fields are automatically marked as read-only.\n *\n * @example\n * calcField() // string | null\n * calcField().notNull() // string\n */\nexport function calcField(): FieldBuilder<\n string | null,\n string | null,\n string | null,\n true\n> {\n const builder = new FieldBuilder<\n string | null,\n string | null,\n string | null,\n false\n >(\"calculated\");\n return builder.readOnly();\n}\n"],"names":[],"mappings":";;;AAkBO,MAAM,aAKX;AAAA,EAUA,YAAY,WAAmB;AATvB,uCAAc;AACd,oCAAW;AACX,qCAAY;AACZ;AACA;AACA;AACA;AACA;AAGN,SAAK,aAAa;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpB,aAKE;AACM,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,cAAc;AACtB,YAAQ,WAAW;AACnB,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,UAKE;AACM,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,WAAW;AACZ,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,WAAyD;AACjD,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,SACE,IACmD;AAC7C,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,YAAY;AACb,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,cACE,WAC6C;AACvC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,mBAAmB;AACpB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,eACE,WAC8C;AACxC,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,kBAAkB;AACnB,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUT,QAAQ,SAAoE;AACpE,UAAA,UAAU,KAAK,OAAO;AAC5B,YAAQ,WAAW;AACZ,WAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,aAAa;AACJ,WAAA;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,iBAAiB,KAAK;AAAA,MACtB,gBAAgB,KAAK;AAAA,MACrB,SAAS,KAAK;AAAA,IAChB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOM,SAA4D;AAClE,UAAM,UAAU,IAAI;AAAA,MAClB,KAAK;AAAA,IACP;AACA,YAAQ,cAAc,KAAK;AAC3B,YAAQ,WAAW,KAAK;AACxB,YAAQ,YAAY,KAAK;AACzB,YAAQ,YAAY,KAAK;AACzB,YAAQ,mBAAmB,KAAK;AAChC,YAAQ,kBAAkB,KAAK;AAC/B,YAAQ,WAAW,KAAK;AACjB,WAAA;AAAA,EAAA;AAEX;AAWO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,cAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAUO,SAAS,YAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAWO,SAAS,iBAKd;AACA,SAAO,IAAI;AAAA,IACT;AAAA,EACF;AACF;AAcO,SAAS,iBAKd;AACO,SAAA,IAAI,aAKT,WAAW;AACf;AAUO,SAAS,YAKd;AACM,QAAA,UAAU,IAAI,aAKlB,YAAY;AACd,SAAO,QAAQ,SAAS;AAC1B;"}
|
package/dist/esm/orm/table.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ declare const FMTableNavigationPaths: unique symbol;
|
|
|
56
56
|
declare const FMTableDefaultSelect: unique symbol;
|
|
57
57
|
declare const FMTableBaseTableConfig: unique symbol;
|
|
58
58
|
declare const FMTableUseEntityIds: unique symbol;
|
|
59
|
+
declare const FMTableComment: unique symbol;
|
|
59
60
|
/**
|
|
60
61
|
* Base table class with Symbol-based internal properties.
|
|
61
62
|
* This follows the Drizzle ORM pattern where internal configuration
|
|
@@ -75,6 +76,7 @@ export declare class FMTable<TFields extends Record<string, FieldBuilder<any, an
|
|
|
75
76
|
NavigationPaths: symbol;
|
|
76
77
|
DefaultSelect: symbol;
|
|
77
78
|
BaseTableConfig: symbol;
|
|
79
|
+
Comment: symbol;
|
|
78
80
|
};
|
|
79
81
|
/** @internal */
|
|
80
82
|
[FMTableName]: TName;
|
|
@@ -83,7 +85,9 @@ export declare class FMTable<TFields extends Record<string, FieldBuilder<any, an
|
|
|
83
85
|
/** @internal */
|
|
84
86
|
[FMTableUseEntityIds]?: boolean;
|
|
85
87
|
/** @internal */
|
|
86
|
-
[
|
|
88
|
+
[FMTableComment]?: string;
|
|
89
|
+
/** @internal */
|
|
90
|
+
[FMTableSchema]: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
87
91
|
/** @internal */
|
|
88
92
|
[FMTableFields]: TFields;
|
|
89
93
|
/** @internal */
|
|
@@ -92,8 +96,8 @@ export declare class FMTable<TFields extends Record<string, FieldBuilder<any, an
|
|
|
92
96
|
[FMTableDefaultSelect]: "all" | "schema" | Record<string, Column<any, any, TName>>;
|
|
93
97
|
/** @internal */
|
|
94
98
|
[FMTableBaseTableConfig]: {
|
|
95
|
-
schema: Record<keyof TFields, StandardSchemaV1
|
|
96
|
-
inputSchema?: Record<keyof TFields, StandardSchemaV1
|
|
99
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
100
|
+
inputSchema?: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
97
101
|
idField?: keyof TFields;
|
|
98
102
|
required: readonly (keyof TFields)[];
|
|
99
103
|
readOnly: readonly (keyof TFields)[];
|
|
@@ -104,13 +108,14 @@ export declare class FMTable<TFields extends Record<string, FieldBuilder<any, an
|
|
|
104
108
|
name: TName;
|
|
105
109
|
entityId?: `FMTID:${string}`;
|
|
106
110
|
useEntityIds?: boolean;
|
|
107
|
-
|
|
111
|
+
comment?: string;
|
|
112
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
108
113
|
fields: TFields;
|
|
109
114
|
navigationPaths: TNavigationPaths;
|
|
110
115
|
defaultSelect: "all" | "schema" | Record<string, Column<any, any, TName>>;
|
|
111
116
|
baseTableConfig: {
|
|
112
|
-
schema: Record<keyof TFields, StandardSchemaV1
|
|
113
|
-
inputSchema?: Record<keyof TFields, StandardSchemaV1
|
|
117
|
+
schema: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
118
|
+
inputSchema?: Partial<Record<keyof TFields, StandardSchemaV1>>;
|
|
114
119
|
idField?: keyof TFields;
|
|
115
120
|
required: readonly (keyof TFields)[];
|
|
116
121
|
readOnly: readonly (keyof TFields)[];
|
|
@@ -157,6 +162,8 @@ export type FMTableWithColumns<TFields extends Record<string, FieldBuilder<any,
|
|
|
157
162
|
export interface FMTableOccurrenceOptions<TFields extends Record<string, FieldBuilder<any, any, any, any>>, TName extends string> {
|
|
158
163
|
/** The entity ID (FMTID) for this table occurrence */
|
|
159
164
|
entityId?: `FMTID:${string}`;
|
|
165
|
+
/** The comment for this table */
|
|
166
|
+
comment?: string;
|
|
160
167
|
/**
|
|
161
168
|
* Default select behavior:
|
|
162
169
|
* - "all": Select all fields (including related tables)
|
|
@@ -264,9 +271,9 @@ export declare function getTableEntityId<T extends FMTable<any, any>>(table: T):
|
|
|
264
271
|
/**
|
|
265
272
|
* Get the schema validator from an FMTable instance.
|
|
266
273
|
* @param table - FMTable instance
|
|
267
|
-
* @returns The StandardSchemaV1 validator
|
|
274
|
+
* @returns The StandardSchemaV1 validator record (partial - only fields with validators)
|
|
268
275
|
*/
|
|
269
|
-
export declare function getTableSchema<T extends FMTable<any, any>>(table: T): StandardSchemaV1
|
|
276
|
+
export declare function getTableSchema<T extends FMTable<any, any>>(table: T): Partial<Record<keyof T[typeof FMTableFields], StandardSchemaV1>>;
|
|
270
277
|
/**
|
|
271
278
|
* Get the fields from an FMTable instance.
|
|
272
279
|
* @param table - FMTable instance
|
|
@@ -292,8 +299,8 @@ export declare function getDefaultSelect<T extends FMTable<any, any>>(table: T):
|
|
|
292
299
|
* @returns Base table configuration object
|
|
293
300
|
*/
|
|
294
301
|
export declare function getBaseTableConfig<T extends FMTable<any, any>>(table: T): {
|
|
295
|
-
schema: Record<string | number | symbol, StandardSchemaV1<unknown, unknown
|
|
296
|
-
inputSchema?: Record<string | number | symbol, StandardSchemaV1<unknown, unknown
|
|
302
|
+
schema: Partial<Record<string | number | symbol, StandardSchemaV1<unknown, unknown>>>;
|
|
303
|
+
inputSchema?: Partial<Record<string | number | symbol, StandardSchemaV1<unknown, unknown>>> | undefined;
|
|
297
304
|
idField?: string | number | symbol | undefined;
|
|
298
305
|
required: readonly (string | number | symbol)[];
|
|
299
306
|
readOnly: readonly (string | number | symbol)[];
|
|
@@ -327,6 +334,12 @@ export declare function getFieldName<T extends FMTable<any, any>>(table: T, fiel
|
|
|
327
334
|
* @returns The FMTID string or the table name
|
|
328
335
|
*/
|
|
329
336
|
export declare function getTableId<T extends FMTable<any, any>>(table: T): string;
|
|
337
|
+
/**
|
|
338
|
+
* Get the comment from an FMTable instance.
|
|
339
|
+
* @param table - FMTable instance
|
|
340
|
+
* @returns The comment string or undefined if not set
|
|
341
|
+
*/
|
|
342
|
+
export declare function getTableComment<T extends FMTable<any, any>>(table: T): string | undefined;
|
|
330
343
|
/**
|
|
331
344
|
* Get all columns from a table as an object.
|
|
332
345
|
* Useful for selecting all fields except some using destructuring.
|