@olenbetong/appframe-vite 6.17.0 → 6.17.1
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.
|
@@ -3,7 +3,7 @@ import { authenticate } from "@olenbetong/appframe-auth";
|
|
|
3
3
|
import { Client, generateApiDataHandler } from "@olenbetong/appframe-data";
|
|
4
4
|
import { config } from "dotenv";
|
|
5
5
|
import { getAppHostname } from "./devServer.js";
|
|
6
|
-
import { fetchAndGenerate, writeGeneratedFile } from "./resourceGenerate.js";
|
|
6
|
+
import { fetchAndGenerate, getUniqueDefinitionName, writeGeneratedFile } from "./resourceGenerate.js";
|
|
7
7
|
import { entryToCLIOptions, readResourcesConfig, writeResourcesConfig, } from "./resourcesConfig.js";
|
|
8
8
|
config({ quiet: true });
|
|
9
9
|
/** Views holding the CMS article configuration. They are registered on demand. */
|
|
@@ -155,8 +155,10 @@ function dataObjectToEntry(datasource, fields, outputDir, warnings) {
|
|
|
155
155
|
entry.maxRecords = datasource.MaxRecords;
|
|
156
156
|
if (datasource.WhereClause)
|
|
157
157
|
entry.where = datasource.WhereClause;
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
// A table as the unique table means its security view: the data API saves through views.
|
|
159
|
+
let unique = datasource.UniqueTableName ? getUniqueDefinitionName(datasource.UniqueTableName) : null;
|
|
160
|
+
if (unique && unique !== datasource.ViewName) {
|
|
161
|
+
entry.unique = unique;
|
|
160
162
|
}
|
|
161
163
|
if (datasource.DynamicLoading)
|
|
162
164
|
entry.dynamic = true;
|
|
@@ -55,6 +55,11 @@ export declare function parseYamlConfig(fileContent: string): {
|
|
|
55
55
|
export declare function getCustomImportPath(outputPath: string): string;
|
|
56
56
|
export declare function getProcedureDefinition(name: string, procDefinition: any, options: CLIOptions): string;
|
|
57
57
|
export declare function getDataObjectDefinition(name: string, viewDefinition: any, options: CLIOptions): string;
|
|
58
|
+
/**
|
|
59
|
+
* The object to read a unique table's columns from. Tables are not data API resources, so a
|
|
60
|
+
* table (`atbl_`) is read through its security view (`atbv_`), which has the same columns.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getUniqueDefinitionName(unique: string): string;
|
|
58
63
|
/**
|
|
59
64
|
* Fetch the resource definition from an authenticated Appframe client.
|
|
60
65
|
*/
|
package/lib/resourceGenerate.js
CHANGED
|
@@ -373,6 +373,11 @@ export function getDataObjectDefinition(name, viewDefinition, options) {
|
|
|
373
373
|
}
|
|
374
374
|
if (aggregates[field.Name]) {
|
|
375
375
|
fieldDefinition.aggregate = aggregates[field.Name];
|
|
376
|
+
// A count is a number whatever the column it counts, and never null.
|
|
377
|
+
if (/^COUNT/i.test(aggregates[field.Name])) {
|
|
378
|
+
fieldDefinition.type = "int";
|
|
379
|
+
fieldDefinition.nullable = false;
|
|
380
|
+
}
|
|
376
381
|
}
|
|
377
382
|
fields.push(fieldDefinition);
|
|
378
383
|
}
|
|
@@ -520,6 +525,13 @@ ${fieldTypes}}`;
|
|
|
520
525
|
// ---------------------------------------------------------------------------
|
|
521
526
|
// Server interaction
|
|
522
527
|
// ---------------------------------------------------------------------------
|
|
528
|
+
/**
|
|
529
|
+
* The object to read a unique table's columns from. Tables are not data API resources, so a
|
|
530
|
+
* table (`atbl_`) is read through its security view (`atbv_`), which has the same columns.
|
|
531
|
+
*/
|
|
532
|
+
export function getUniqueDefinitionName(unique) {
|
|
533
|
+
return unique.startsWith("atbl_") ? `atbv_${unique.slice(5)}` : unique;
|
|
534
|
+
}
|
|
523
535
|
/**
|
|
524
536
|
* Fetch the resource definition from an authenticated Appframe client.
|
|
525
537
|
*/
|
|
@@ -567,11 +579,11 @@ export async function fetchAndGenerate(resourceName, options, client) {
|
|
|
567
579
|
// lacks. CMS data objects know to leave those out of a save; mark them ignored so these do too.
|
|
568
580
|
if (definition.ObjectType === "V" && options.unique) {
|
|
569
581
|
try {
|
|
570
|
-
let uniqueDefinition = await fetchResourceDefinition(client, options.unique);
|
|
582
|
+
let uniqueDefinition = await fetchResourceDefinition(client, getUniqueDefinitionName(options.unique));
|
|
571
583
|
options.uniqueFields = (uniqueDefinition.Parameters ?? []).map((p) => p.Name);
|
|
572
584
|
}
|
|
573
585
|
catch (error) {
|
|
574
|
-
console.warn(`Could not read the unique table '${options.unique}' for '${resourceName}', so no fields are marked ignored: ${error instanceof Error ? error.message.split(" — ")[0] : error}`);
|
|
586
|
+
console.warn(`Could not read the unique table '${getUniqueDefinitionName(options.unique)}' for '${resourceName}', so no fields are marked ignored: ${error instanceof Error ? error.message.split(" — ")[0] : error}`);
|
|
575
587
|
}
|
|
576
588
|
}
|
|
577
589
|
return definition.ObjectType === "V"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getDataObjectDefinition } from "./resourceGenerate.js";
|
|
2
|
+
import { getDataObjectDefinition, getUniqueDefinitionName } from "./resourceGenerate.js";
|
|
3
3
|
import { entryToCLIOptions } from "./resourcesConfig.js";
|
|
4
4
|
const definition = {
|
|
5
5
|
ObjectType: "V",
|
|
@@ -31,3 +31,28 @@ describe("fields outside the unique table", () => {
|
|
|
31
31
|
expect(generate(undefined)).not.toContain('"ignored"');
|
|
32
32
|
});
|
|
33
33
|
});
|
|
34
|
+
describe("getUniqueDefinitionName", () => {
|
|
35
|
+
it("reads a table through its security view", () => {
|
|
36
|
+
expect(getUniqueDefinitionName("atbl_Production_Plans")).toBe("atbv_Production_Plans");
|
|
37
|
+
});
|
|
38
|
+
it("keeps views as they are", () => {
|
|
39
|
+
expect(getUniqueDefinitionName("atbv_Production_Plans")).toBe("atbv_Production_Plans");
|
|
40
|
+
expect(getUniqueDefinitionName("atbx_Accounting_Projects")).toBe("atbx_Accounting_Projects");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("count aggregates", () => {
|
|
44
|
+
it("types a counted column as a number", () => {
|
|
45
|
+
let options = entryToCLIOptions({
|
|
46
|
+
id: "dsSummary",
|
|
47
|
+
resource: "aviw_Production_Plans",
|
|
48
|
+
output: "src/dsSummary.ts",
|
|
49
|
+
global: true,
|
|
50
|
+
types: true,
|
|
51
|
+
groupBy: ["ProjectID"],
|
|
52
|
+
aggregates: [{ field: "ProjectName", aggregate: "COUNT" }],
|
|
53
|
+
}, "example.com");
|
|
54
|
+
let output = getDataObjectDefinition("aviw_Production_Plans", definition, options);
|
|
55
|
+
expect(output).toContain("ProjectName: number;");
|
|
56
|
+
expect(output).toMatch(/"name": "ProjectName",\s*"type": "number"/);
|
|
57
|
+
});
|
|
58
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-vite",
|
|
3
|
-
"version": "6.17.
|
|
3
|
+
"version": "6.17.1",
|
|
4
4
|
"description": "Tools to use and deploy Vite applications to Appframe",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@olenbetong/appframe-auth": "^0.1.0",
|
|
33
33
|
"@olenbetong/appframe-data": "^1.8.4",
|
|
34
|
-
"body-parser": "^2.
|
|
34
|
+
"body-parser": "^2.4.0",
|
|
35
35
|
"chalk": "6.0.1",
|
|
36
36
|
"chokidar": "^5.0.0",
|
|
37
37
|
"commander": "15.0.0",
|
|
38
|
-
"dotenv": "^18.0.
|
|
38
|
+
"dotenv": "^18.0.9",
|
|
39
39
|
"fuzzy": "^0.1.3",
|
|
40
40
|
"inquirer": "^14.2.4",
|
|
41
41
|
"inquirer-autocomplete-standalone": "^0.8.1",
|