@olenbetong/appframe-cli 4.4.10 → 4.5.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/CHANGELOG.md +20 -0
- package/README.md +3 -0
- package/cli/af-bundle-upload.js +15 -7
- package/cli/af-resources-generate.js +50 -292
- package/package.json +6 -3
- package/src/af-bundle-upload.ts +16 -7
- package/src/af-resources-generate.ts +55 -382
- package/src/editor/TransactionsEditor.tsx +1 -2
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,348 +1,27 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { Client } from "@olenbetong/appframe-data";
|
|
3
|
+
import {
|
|
4
|
+
buildYamlConfig,
|
|
5
|
+
type CLIOptions,
|
|
6
|
+
fetchAndGenerate,
|
|
7
|
+
formatWithBiome,
|
|
8
|
+
} from "@olenbetong/appframe-vite/resources";
|
|
9
|
+
import { config } from "dotenv";
|
|
2
10
|
import inquirer from "inquirer";
|
|
3
|
-
|
|
4
11
|
import { Command } from "./lib/Command.js";
|
|
5
12
|
import { importJson } from "./lib/importJson.js";
|
|
6
13
|
import { Server } from "./lib/Server.js";
|
|
7
14
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Convert Appframe (SQL) data types to typescript/field definition types
|
|
12
|
-
* @param {string} type
|
|
13
|
-
* @param {"ts" | "ts-proc" | "field"} dateStyle
|
|
14
|
-
* @returns
|
|
15
|
-
*/
|
|
16
|
-
function afTypeToTsType(type: string | undefined, dateStyle: "ts" | "ts-proc" | "field" | boolean = false) {
|
|
17
|
-
switch (type) {
|
|
18
|
-
case "bigint":
|
|
19
|
-
return "bigint";
|
|
20
|
-
case "int":
|
|
21
|
-
case "decimal":
|
|
22
|
-
case "smallint":
|
|
23
|
-
case "tinyint":
|
|
24
|
-
case "float":
|
|
25
|
-
case "numeric":
|
|
26
|
-
return "number";
|
|
27
|
-
case "bit":
|
|
28
|
-
return "boolean";
|
|
29
|
-
case "datetime2":
|
|
30
|
-
case "datetime":
|
|
31
|
-
case "smalldatetime":
|
|
32
|
-
case "date":
|
|
33
|
-
if (dateStyle === "ts") {
|
|
34
|
-
return "Date";
|
|
35
|
-
} else if (dateStyle === "ts-proc") {
|
|
36
|
-
return "string | Date";
|
|
37
|
-
} else {
|
|
38
|
-
return type === "date" ? "date" : "datetime";
|
|
39
|
-
}
|
|
40
|
-
default:
|
|
41
|
-
return "string";
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
interface ProcedureParameter {
|
|
46
|
-
name: string;
|
|
47
|
-
type: string;
|
|
48
|
-
hasDefault: boolean;
|
|
49
|
-
required: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function getProcedureDefinition(name: string, procDefinition: any, options: CLIOptions) {
|
|
53
|
-
let parameters: ProcedureParameter[] = [];
|
|
54
|
-
let typeOverrides: Record<string, string> = {};
|
|
55
|
-
|
|
56
|
-
if (options.overrides) {
|
|
57
|
-
let overrides = options.overrides.split(",");
|
|
58
|
-
for (let override of overrides) {
|
|
59
|
-
let [param, type] = override.split(":");
|
|
60
|
-
typeOverrides[param] = type;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (let parameter of procDefinition.Parameters) {
|
|
65
|
-
parameters.push({
|
|
66
|
-
name: parameter.ParamName,
|
|
67
|
-
type: afTypeToTsType(parameter.TypeName, "field"),
|
|
68
|
-
hasDefault: parameter.has_default_value,
|
|
69
|
-
required: !parameter.has_default_value && !parameter.is_nullable,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
let output: string[] = [];
|
|
74
|
-
if (!options.global) {
|
|
75
|
-
output.push(`import { ProcedureAPI } from "@olenbetong/appframe-data";`);
|
|
76
|
-
|
|
77
|
-
if (options.expose) {
|
|
78
|
-
output.push(`import { expose } from "@olenbetong/appframe-core";`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
output.push("");
|
|
82
|
-
}
|
|
83
|
-
let paramTypeName = "ProcParams";
|
|
84
|
-
let procName = "proc";
|
|
85
|
-
if (options.id) {
|
|
86
|
-
procName = options.id;
|
|
87
|
-
paramTypeName = `${options.id}Params`;
|
|
88
|
-
if (paramTypeName.startsWith("proc")) {
|
|
89
|
-
paramTypeName = paramTypeName.substring(4);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (options.types) {
|
|
94
|
-
if (procDefinition.Parameters.length > 0) {
|
|
95
|
-
let typeOutput = [`export type ${paramTypeName} = {`];
|
|
96
|
-
for (let parameter of procDefinition.Parameters) {
|
|
97
|
-
let type = typeOverrides[parameter.ParamName];
|
|
98
|
-
let name = parameter.ParamName;
|
|
99
|
-
|
|
100
|
-
if (!type) {
|
|
101
|
-
type = afTypeToTsType(parameter.TypeName, "ts-proc");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (parameter.has_default_value || parameter.is_nullable) {
|
|
105
|
-
type += " | null";
|
|
106
|
-
name += "?";
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
typeOutput.push(`\t${name}: ${type}`);
|
|
110
|
-
}
|
|
111
|
-
typeOutput.push("};");
|
|
112
|
-
output.push(typeOutput.join("\n"));
|
|
113
|
-
output.push("");
|
|
114
|
-
} else {
|
|
115
|
-
output.push(`export type ${paramTypeName} = null | undefined | Record<string, unknown>;\n`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
output.push(`export const ${procName} = new ${
|
|
120
|
-
options.global ? "af." : ""
|
|
121
|
-
}ProcedureAPI${options.types ? `<${paramTypeName}, unknown>` : ""}({
|
|
122
|
-
procedureId: "${name}",
|
|
123
|
-
parameters: ${JSON.stringify(parameters, null, 2)},
|
|
124
|
-
timeout: 30000
|
|
125
|
-
});`);
|
|
126
|
-
|
|
127
|
-
if (options.expose) {
|
|
128
|
-
output.push("");
|
|
129
|
-
output.push(
|
|
130
|
-
`${
|
|
131
|
-
options.global ? "af.common." : ""
|
|
132
|
-
}expose("af.article.procedures.${procName}", ${procName}, { overwrite: true });`,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return output.join("\n");
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function getDataObjectDefinition(name: string, viewDefinition: any, options: CLIOptions) {
|
|
140
|
-
let fields: FieldDefinition[] = [];
|
|
141
|
-
let includeFields = typeof options.fields === "string" ? (options.fields?.split(",").filter((f) => !!f) ?? []) : [];
|
|
142
|
-
|
|
143
|
-
let aggregates: Record<string, string> = {};
|
|
144
|
-
if (options.aggregates) {
|
|
145
|
-
for (let aggregateDef of options.aggregates.split(",")) {
|
|
146
|
-
let [field, aggregate] = aggregateDef.split(":");
|
|
147
|
-
aggregates[field] = aggregate;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
for (let field of viewDefinition.Parameters) {
|
|
152
|
-
if (includeFields.length > 0 && !includeFields.includes(field.Name)) {
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let fieldDefinition: FieldDefinition = {
|
|
157
|
-
name: field.Name,
|
|
158
|
-
type: field.DataType,
|
|
159
|
-
nullable: field.Nullable,
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
if (field.HasDefault) {
|
|
163
|
-
fieldDefinition.hasDefault = true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (field.Computed) {
|
|
167
|
-
fieldDefinition.computed = true;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (field.Identity) {
|
|
171
|
-
fieldDefinition.identity = true;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (aggregates[field.Name]) {
|
|
175
|
-
fieldDefinition.aggregate = aggregates[field.Name];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
fields.push(fieldDefinition);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
let api = "generateApiDataObject";
|
|
182
|
-
let types = "";
|
|
183
|
-
let typeName = `${options.id}Record`;
|
|
184
|
-
let typeOverrides: Record<string, string> = {};
|
|
185
|
-
|
|
186
|
-
if (options.overrides) {
|
|
187
|
-
let overrides = options.overrides.split(",");
|
|
188
|
-
for (let override of overrides) {
|
|
189
|
-
let [param, type] = override.split(":");
|
|
190
|
-
typeOverrides[param] = type;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// By convention data object name starts with ds, but their type
|
|
195
|
-
// definitions should not.
|
|
196
|
-
if (typeName.startsWith("ds")) {
|
|
197
|
-
typeName = typeName.substring(2);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (options.types) {
|
|
201
|
-
api = `generateApiDataObject<${typeName}>`;
|
|
202
|
-
|
|
203
|
-
let fieldTypes = "";
|
|
204
|
-
for (let field of fields) {
|
|
205
|
-
let type = typeOverrides[field.name];
|
|
206
|
-
if (!type) {
|
|
207
|
-
type = afTypeToTsType(field.type, "ts");
|
|
208
|
-
if (field.nullable) {
|
|
209
|
-
type += " | null";
|
|
210
|
-
}
|
|
211
|
-
}
|
|
15
|
+
config({ path: `${process.cwd()}/.env`, quiet: true });
|
|
212
16
|
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
types = `export type ${typeName} = {
|
|
217
|
-
${fieldTypes}}`;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (options.global) {
|
|
221
|
-
api = `af.data.${api}`;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
let output = "";
|
|
225
|
-
if (!options.global) {
|
|
226
|
-
output += `import { generateApiDataObject${
|
|
227
|
-
options.sortOrder ? ", SortOrder" : ""
|
|
228
|
-
} } from "@olenbetong/appframe-data";`;
|
|
229
|
-
|
|
230
|
-
if (options.expose) {
|
|
231
|
-
output += `\nimport { expose } from "@olenbetong/appframe-core";`;
|
|
232
|
-
}
|
|
233
|
-
output += "\n\n";
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
if (options.master && options.master.indexOf(":") > 0) {
|
|
237
|
-
let [name, path] = options.master.split(":");
|
|
238
|
-
output += `import { ${name} } from "${path}";\n\n`;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
if (options.types) {
|
|
242
|
-
output += `${types}\n\n`;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let linkFields = "";
|
|
246
|
-
|
|
247
|
-
let dsOptions: string[] = [];
|
|
248
|
-
dsOptions.push(`resource: "${name}"`);
|
|
249
|
-
if (options.unique) {
|
|
250
|
-
dsOptions.push(`uniqueName: "${options.unique}"`);
|
|
251
|
-
}
|
|
252
|
-
dsOptions.push(`id: "${options.id}"`);
|
|
253
|
-
if (options.master && options.linkFields) {
|
|
254
|
-
dsOptions.push(`masterDataObject: ${options.master.split(":")[0]}`);
|
|
255
|
-
|
|
256
|
-
let fields = options.linkFields.split(",");
|
|
257
|
-
|
|
258
|
-
linkFields = `linkFields: {\n\t\t${fields
|
|
259
|
-
.map((field) => {
|
|
260
|
-
let [thisField, masterField] = field.split(":");
|
|
261
|
-
return `${thisField}: "${masterField ?? thisField}",`;
|
|
262
|
-
})
|
|
263
|
-
.join("\n\t\t")}\n\t}`;
|
|
264
|
-
|
|
265
|
-
dsOptions.push(linkFields);
|
|
266
|
-
}
|
|
267
|
-
dsOptions.push(`allowUpdate: ${options.permissions?.includes("U") ?? false}`);
|
|
268
|
-
dsOptions.push(`allowInsert: ${options.permissions?.includes("I") ?? false}`);
|
|
269
|
-
dsOptions.push(`allowDelete: ${options.permissions?.includes("D") ?? false}`);
|
|
270
|
-
dsOptions.push(`dynamicLoading: ${options.dynamic || false}`);
|
|
271
|
-
|
|
272
|
-
let fieldsOption = fields.map((field) => ({
|
|
273
|
-
...field,
|
|
274
|
-
type: afTypeToTsType(field.type, "field"),
|
|
275
|
-
}));
|
|
276
|
-
dsOptions.push(`fields: ${JSON.stringify(fieldsOption, null, 2).split("\n").join("\n\t")}`);
|
|
277
|
-
|
|
278
|
-
let parametersOption: string[] = [`maxRecords: ${options.maxRecords}`];
|
|
279
|
-
|
|
280
|
-
if (options.sortOrder) {
|
|
281
|
-
let sorts = options.sortOrder.split(",");
|
|
282
|
-
let sortPrefix = options.global ? "af.data.SortOrder." : "SortOrder.";
|
|
283
|
-
|
|
284
|
-
let sortOrder = sorts
|
|
285
|
-
.map((sort) => {
|
|
286
|
-
let [field, order = "asc"] = sort.split(":");
|
|
287
|
-
switch (order.toLocaleLowerCase()) {
|
|
288
|
-
case "asc":
|
|
289
|
-
order = "Asc";
|
|
290
|
-
break;
|
|
291
|
-
case "desc":
|
|
292
|
-
order = "Desc";
|
|
293
|
-
break;
|
|
294
|
-
case "ascnullslast":
|
|
295
|
-
order = "AscNullsLast";
|
|
296
|
-
break;
|
|
297
|
-
case "descnullsfirst":
|
|
298
|
-
order = "DescNullsFirst";
|
|
299
|
-
break;
|
|
300
|
-
}
|
|
301
|
-
return `{ ${field}: ${sortPrefix}${order} }`;
|
|
302
|
-
})
|
|
303
|
-
.join(", ");
|
|
304
|
-
|
|
305
|
-
parametersOption.push(`sortOrder: [${sortOrder}]`);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
if (options.groupBy) {
|
|
309
|
-
parametersOption.push(`groupBy: ${JSON.stringify(options.groupBy.split(","))}`);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
if (options.where) {
|
|
313
|
-
parametersOption.push(`whereClause: "${options.where}"`);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (options.distinct) {
|
|
317
|
-
parametersOption.push(`distinctRows: true`);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
dsOptions.push(`parameters: {\n\t\t${parametersOption.join(",\n\t\t")}\n\t}`);
|
|
321
|
-
|
|
322
|
-
output += `export const ${options.id} = ${api}({
|
|
323
|
-
${dsOptions.join(",\n\t")}
|
|
324
|
-
});
|
|
325
|
-
`;
|
|
326
|
-
|
|
327
|
-
if (options.expose) {
|
|
328
|
-
let id = typeof options.expose === "string" ? options.expose : options.id;
|
|
329
|
-
if (options.global) {
|
|
330
|
-
output += `\naf.common.expose("af.article.dataObjects.${id}", ${options.id}, { overwrite: true });`;
|
|
331
|
-
} else {
|
|
332
|
-
output += `\nexpose("af.article.dataObjects.${id}", ${options.id}, { overwrite: true });`;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return output;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
async function getResourceDefinition(resourceName: string, options: CLIOptions) {
|
|
340
|
-
let server = new Server("dev.obet.no");
|
|
341
|
-
let resource = await server.getResourceArgument(resourceName);
|
|
342
|
-
let definition = await server.getResourceDefinition(resource);
|
|
343
|
-
definition.Parameters = definition.Parameters.filter((p: any) => !["CUT", "CDL"].includes(p.Name));
|
|
17
|
+
const appPkg = await importJson("../package.json");
|
|
344
18
|
|
|
19
|
+
async function getResourceDefinition(resourceName: string, options: CLIOptions & { server: string }) {
|
|
345
20
|
if (options.fields === true) {
|
|
21
|
+
// Need to fetch the resource to show the interactive field picker
|
|
22
|
+
let server = new Server(options.server);
|
|
23
|
+
let resource = await server.getResourceArgument(resourceName);
|
|
24
|
+
let definition = await server.getResourceDefinition(resource);
|
|
346
25
|
let response = await inquirer.prompt([
|
|
347
26
|
{
|
|
348
27
|
type: "checkbox",
|
|
@@ -356,54 +35,44 @@ async function getResourceDefinition(resourceName: string, options: CLIOptions)
|
|
|
356
35
|
options.fields = response.fields.join(",");
|
|
357
36
|
}
|
|
358
37
|
|
|
359
|
-
let
|
|
360
|
-
|
|
361
|
-
if (options.unique) command.push(`--unique ${options.unique}`);
|
|
362
|
-
if (options.global) command.push("--global");
|
|
363
|
-
if (options.types) command.push("--types");
|
|
364
|
-
if (options.maxRecords && definition.ObjectType !== "P") command.push(`--max-records ${options.maxRecords}`);
|
|
365
|
-
if (options.sortOrder) command.push(`--sort-order ${options.sortOrder}`);
|
|
366
|
-
if (options.permissions) command.push(`--permissions ${options.permissions}`);
|
|
367
|
-
if (options.master) command.push(`--master ${options.master}`);
|
|
368
|
-
if (options.linkFields) command.push(`--link-fields ${options.linkFields}`);
|
|
369
|
-
if (options.expose) command.push(`--expose${typeof options.expose === "string" ? ` ${options.expose}` : ""}`);
|
|
370
|
-
if (options.dynamic) command.push(`--dynamic`);
|
|
371
|
-
if (options.overrides) command.push(`--overrides "${options.overrides}"`);
|
|
372
|
-
if (options.distinct) command.push("--distinct");
|
|
373
|
-
if (options.aggregates) command.push(`--aggregates ${options.aggregates}`);
|
|
374
|
-
if (options.groupBy) command.push(`--group-by ${options.groupBy}`);
|
|
375
|
-
if (options.where) command.push(`--where "${options.where}"`);
|
|
376
|
-
if (options.fields) command.push(`--fields ${options.fields}`);
|
|
38
|
+
let server = new Server(options.server);
|
|
39
|
+
let resource = await server.getResourceArgument(resourceName);
|
|
377
40
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
41
|
+
let { APPFRAME_LOGIN: username = "", APPFRAME_PWD: password = "" } = process.env;
|
|
42
|
+
let client = new Client(options.server);
|
|
43
|
+
await client.login(username, password);
|
|
44
|
+
|
|
45
|
+
let content = await fetchAndGenerate(resource, options, client);
|
|
46
|
+
|
|
47
|
+
if (options.output) {
|
|
48
|
+
let header = buildYamlConfig(resource, options);
|
|
49
|
+
await writeFile(options.output, `${header}\n${content}`, "utf-8");
|
|
50
|
+
await formatWithBiome(options.output);
|
|
51
|
+
console.log(`Written to ${options.output}`);
|
|
52
|
+
} else {
|
|
53
|
+
let command: string[] = [`af resources generate ${resource}`];
|
|
54
|
+
if (options.id) command.push(`--id ${options.id}`);
|
|
55
|
+
if (options.unique) command.push(`--unique ${options.unique}`);
|
|
56
|
+
if (options.global) command.push("--global");
|
|
57
|
+
if (options.types) command.push("--types");
|
|
58
|
+
if (options.maxRecords) command.push(`--max-records ${options.maxRecords}`);
|
|
59
|
+
if (options.sortOrder) command.push(`--sort-order ${options.sortOrder}`);
|
|
60
|
+
if (options.permissions) command.push(`--permissions ${options.permissions}`);
|
|
61
|
+
if (options.master) command.push(`--master ${options.master}`);
|
|
62
|
+
if (options.linkFields) command.push(`--link-fields ${options.linkFields}`);
|
|
63
|
+
if (options.expose) command.push(`--expose${typeof options.expose === "string" ? ` ${options.expose}` : ""}`);
|
|
64
|
+
if (options.dynamic) command.push("--dynamic");
|
|
65
|
+
if (options.overrides) command.push(`--overrides "${options.overrides}"`);
|
|
66
|
+
if (options.distinct) command.push("--distinct");
|
|
67
|
+
if (options.aggregates) command.push(`--aggregates ${options.aggregates}`);
|
|
68
|
+
if (options.groupBy) command.push(`--group-by ${options.groupBy}`);
|
|
69
|
+
if (options.where) command.push(`--where "${options.where}"`);
|
|
70
|
+
if (options.fields) command.push(`--fields ${options.fields}`);
|
|
71
|
+
console.log(`/*\nauto-generated by CLI:\n${command.join(" \\\n ")}\n*/`);
|
|
72
|
+
console.log(content);
|
|
73
|
+
}
|
|
384
74
|
}
|
|
385
75
|
|
|
386
|
-
type CLIOptions = {
|
|
387
|
-
server: string;
|
|
388
|
-
types?: boolean;
|
|
389
|
-
global: boolean;
|
|
390
|
-
id: string;
|
|
391
|
-
fields: string | boolean;
|
|
392
|
-
permissions?: string;
|
|
393
|
-
maxRecords?: string;
|
|
394
|
-
sortOrder?: string;
|
|
395
|
-
master?: string;
|
|
396
|
-
linkFields?: string;
|
|
397
|
-
expose?: string | boolean;
|
|
398
|
-
dynamic: boolean;
|
|
399
|
-
unique?: string;
|
|
400
|
-
overrides?: string;
|
|
401
|
-
distinct?: boolean;
|
|
402
|
-
aggregates?: string;
|
|
403
|
-
groupBy?: string;
|
|
404
|
-
where?: string;
|
|
405
|
-
};
|
|
406
|
-
|
|
407
76
|
const program = new Command();
|
|
408
77
|
program
|
|
409
78
|
.version(appPkg.version)
|
|
@@ -443,5 +112,9 @@ program
|
|
|
443
112
|
)
|
|
444
113
|
.option("--distinct", "Data object should fetch distinct data")
|
|
445
114
|
.option("--where <whereClause>", "Initial where clause to set on the data object")
|
|
115
|
+
.option(
|
|
116
|
+
"-O, --output <path>",
|
|
117
|
+
"Write output to this file instead of stdout; also sets the correct relative import path for custom.d.ts",
|
|
118
|
+
)
|
|
446
119
|
.action(getResourceDefinition);
|
|
447
120
|
await program.parseAsync(process.argv);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { TransactionFilter } from "@olenbetong/appframe-updater";
|
|
1
2
|
import { Box, Text, useApp } from "ink";
|
|
2
3
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
-
|
|
4
4
|
import type { Server } from "../lib/Server.js";
|
|
5
5
|
import { TransactionsPreviewDialog } from "./TransactionsPreviewDialog.js";
|
|
6
6
|
import { createStatusLine } from "./tableFormatting.js";
|
|
@@ -12,7 +12,6 @@ import { useTransactionsSelection } from "./useTransactionsSelection.js";
|
|
|
12
12
|
import { useTransactionsTableLayout } from "./useTransactionsTableLayout.js";
|
|
13
13
|
import { CURSOR_PREFIX_WIDTH, HEADER_PREFIX, useVirtualScrolling } from "./useVirtualScrolling.js";
|
|
14
14
|
import { withFullScreen } from "./withFullScreen.js";
|
|
15
|
-
import type { TransactionFilter } from "@olenbetong/appframe-updater";
|
|
16
15
|
|
|
17
16
|
const HEADER_LINES = 2;
|
|
18
17
|
const BASE_FOOTER_LINES = 1;
|