@getaster/data 0.0.0-stage → 0.1.0-preview.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.
Files changed (84) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +10 -0
  3. package/README.md +6 -2
  4. package/dist/authentication.d.ts +42 -0
  5. package/dist/authentication.js +121 -0
  6. package/dist/changes/changeset.d.ts +47 -0
  7. package/dist/changes/changeset.js +75 -0
  8. package/dist/collection/aggregate.d.ts +22 -0
  9. package/dist/collection/aggregate.js +94 -0
  10. package/dist/collection/collection.d.ts +96 -0
  11. package/dist/collection/collection.js +588 -0
  12. package/dist/collection/grouping.d.ts +75 -0
  13. package/dist/collection/grouping.js +190 -0
  14. package/dist/collection/groups.d.ts +31 -0
  15. package/dist/collection/groups.js +117 -0
  16. package/dist/collection/summary.d.ts +17 -0
  17. package/dist/collection/summary.js +103 -0
  18. package/dist/composition/activity.d.ts +36 -0
  19. package/dist/composition/activity.js +60 -0
  20. package/dist/composition/command.d.ts +22 -0
  21. package/dist/composition/command.js +57 -0
  22. package/dist/composition/lifetime.d.ts +11 -0
  23. package/dist/composition/lifetime.js +33 -0
  24. package/dist/composition/sessions.d.ts +64 -0
  25. package/dist/composition/sessions.js +209 -0
  26. package/dist/context.d.ts +76 -0
  27. package/dist/context.js +211 -0
  28. package/dist/criteria/ast.d.ts +79 -0
  29. package/dist/criteria/ast.js +1 -0
  30. package/dist/criteria/compile.d.ts +37 -0
  31. package/dist/criteria/compile.js +233 -0
  32. package/dist/criteria/evaluate.d.ts +20 -0
  33. package/dist/criteria/evaluate.js +171 -0
  34. package/dist/criteria/filter-draft.d.ts +79 -0
  35. package/dist/criteria/filter-draft.js +320 -0
  36. package/dist/criteria/relative.d.ts +13 -0
  37. package/dist/criteria/relative.js +82 -0
  38. package/dist/criteria/values.d.ts +20 -0
  39. package/dist/criteria/values.js +283 -0
  40. package/dist/edit/edit-model.d.ts +152 -0
  41. package/dist/edit/edit-model.js +620 -0
  42. package/dist/edit/list-edit.d.ts +116 -0
  43. package/dist/edit/list-edit.js +332 -0
  44. package/dist/edit/record-edit.d.ts +93 -0
  45. package/dist/edit/record-edit.js +317 -0
  46. package/dist/export/csv.d.ts +25 -0
  47. package/dist/export/csv.js +75 -0
  48. package/dist/index.d.ts +38 -0
  49. package/dist/index.js +35 -0
  50. package/dist/odata/errors.d.ts +25 -0
  51. package/dist/odata/errors.js +56 -0
  52. package/dist/odata/source.d.ts +65 -0
  53. package/dist/odata/source.js +193 -0
  54. package/dist/progress/status.d.ts +29 -0
  55. package/dist/progress/status.js +105 -0
  56. package/dist/schema/csdl.d.ts +13 -0
  57. package/dist/schema/csdl.js +531 -0
  58. package/dist/schema/model.d.ts +132 -0
  59. package/dist/schema/model.js +1 -0
  60. package/dist/scope/filters.d.ts +130 -0
  61. package/dist/scope/filters.js +349 -0
  62. package/dist/scope/publications.d.ts +27 -0
  63. package/dist/scope/publications.js +74 -0
  64. package/dist/scope/related-aggregate.d.ts +9 -0
  65. package/dist/scope/related-aggregate.js +67 -0
  66. package/dist/scope/scope.d.ts +181 -0
  67. package/dist/scope/scope.js +574 -0
  68. package/dist/selection/selection.d.ts +56 -0
  69. package/dist/selection/selection.js +137 -0
  70. package/dist/store/keys.d.ts +10 -0
  71. package/dist/store/keys.js +21 -0
  72. package/dist/store/store.d.ts +72 -0
  73. package/dist/store/store.js +143 -0
  74. package/dist/template/template.d.ts +19 -0
  75. package/dist/template/template.js +186 -0
  76. package/dist/transport.d.ts +28 -0
  77. package/dist/transport.js +20 -0
  78. package/dist/tree/tree.d.ts +117 -0
  79. package/dist/tree/tree.js +435 -0
  80. package/dist/validate/criteria-rule.d.ts +28 -0
  81. package/dist/validate/criteria-rule.js +22 -0
  82. package/dist/validate/validate.d.ts +13 -0
  83. package/dist/validate/validate.js +123 -0
  84. package/package.json +32 -4
@@ -0,0 +1,123 @@
1
+ import { compareValues } from "../criteria/evaluate.js";
2
+ const INTEGER = new Set(["Edm.Byte", "Edm.SByte", "Edm.Int16", "Edm.Int32"]);
3
+ /** Groups: integer digits, fraction digits, exponent. */
4
+ const EXACT = /^-?(\d+)(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
5
+ /**
6
+ * Client-side validation from metadata, with the same rules the server
7
+ * applies. Messages use the field's title and say how to fix the value;
8
+ * `AsterData.RequiredMessage` and `AsterData.ErrorMessage` override them.
9
+ */
10
+ export function validateField(field, value) {
11
+ const title = field.title ?? field.name;
12
+ const custom = field.annotations["AsterData.ErrorMessage"];
13
+ const fail = (message) => [typeof custom === "string" ? custom : message];
14
+ if (value === undefined || value === null) {
15
+ if (field.nullable || field.computed)
16
+ return [];
17
+ const required = field.annotations["AsterData.RequiredMessage"];
18
+ return [typeof required === "string" ? required : `${title} is required.`];
19
+ }
20
+ const typeError = checkType(field, value);
21
+ if (typeError)
22
+ return fail(`${title} ${typeError}`);
23
+ if (typeof value === "string") {
24
+ const length = [...value].length;
25
+ if (field.maxLength !== undefined && length > field.maxLength) {
26
+ return fail(`${title} can be at most ${field.maxLength} characters; this is ${length}.`);
27
+ }
28
+ if (field.minLength !== undefined && length < field.minLength) {
29
+ return fail(field.minLength === 1
30
+ ? `${title} can't be blank.`
31
+ : `${title} needs at least ${field.minLength} characters; this is ${length}.`);
32
+ }
33
+ if (field.pattern !== undefined && !new RegExp(field.pattern, "u").test(value)) {
34
+ return fail(`“${value}” isn't a valid ${title.toLowerCase()}.`);
35
+ }
36
+ }
37
+ if (field.minimum !== undefined) {
38
+ const c = compareValues(value, field.minimum, field);
39
+ if (c < 0 || (c === 0 && field.exclusiveMinimum)) {
40
+ return fail(`${title} must be ${field.exclusiveMinimum ? "more than" : "at least"} ${field.minimum}.`);
41
+ }
42
+ }
43
+ if (field.maximum !== undefined) {
44
+ const c = compareValues(value, field.maximum, field);
45
+ if (c > 0 || (c === 0 && field.exclusiveMaximum)) {
46
+ return fail(`${title} must be ${field.exclusiveMaximum ? "less than" : "at most"} ${field.maximum}.`);
47
+ }
48
+ }
49
+ if (field.allowedValues && !field.allowedValues.some((a) => sameValue(a.value, value, field))) {
50
+ const labels = field.allowedValues.map((a) => a.label ?? String(a.value)).join(", ");
51
+ return fail(`${title} must be one of: ${labels}.`);
52
+ }
53
+ return [];
54
+ }
55
+ /** Equal by the field's type, so Decimal `"1.0"` matches `"1"`. */
56
+ function sameValue(a, b, field) {
57
+ try {
58
+ return compareValues(a, b, field) === 0;
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ }
64
+ /**
65
+ * Errors by field. On update only the fields present in `values` are
66
+ * checked, and an immutable field among them is an error.
67
+ */
68
+ export function validateEntity(type, values, mode) {
69
+ const out = {};
70
+ for (const field of type.fields) {
71
+ if (field.computed)
72
+ continue;
73
+ if (mode === "update" && !(field.name in values))
74
+ continue;
75
+ if (mode === "update" && field.immutable) {
76
+ out[field.name] = [`${field.title ?? field.name} can't be changed once it's set.`];
77
+ continue;
78
+ }
79
+ const errors = validateField(field, values[field.name]);
80
+ if (errors.length)
81
+ out[field.name] = errors;
82
+ }
83
+ return out;
84
+ }
85
+ function checkType(field, value) {
86
+ switch (field.type) {
87
+ case "Edm.Boolean":
88
+ return typeof value === "boolean" ? undefined : "must be yes or no.";
89
+ case "Edm.Single":
90
+ case "Edm.Double":
91
+ return typeof value === "number" && Number.isFinite(value) ? undefined : "must be a number.";
92
+ case "Edm.Int64":
93
+ case "Edm.Decimal": {
94
+ const text = typeof value === "number" ? String(value) : value;
95
+ const m = typeof text === "string" ? EXACT.exec(text) : null;
96
+ if (!m)
97
+ return "must be a number.";
98
+ if (field.type === "Edm.Int64" && (m[2] !== undefined || m[3] !== undefined))
99
+ return "must be a whole number.";
100
+ if (field.type === "Edm.Decimal" && field.scale !== undefined) {
101
+ const decimals = (m[2] ?? "").length - Number(m[3] ?? 0);
102
+ if (decimals > field.scale)
103
+ return `can have at most ${field.scale} decimal places.`;
104
+ }
105
+ return undefined;
106
+ }
107
+ case "Edm.Date":
108
+ return typeof value === "string" && isDate(value) ? undefined : "must be a date, like 7 Oct 2026.";
109
+ default:
110
+ if (INTEGER.has(field.type)) {
111
+ return typeof value === "number" && Number.isInteger(value) ? undefined : "must be a whole number.";
112
+ }
113
+ return typeof value === "string" ? undefined : "has the wrong kind of value.";
114
+ }
115
+ }
116
+ /** A real calendar date as `YYYY-MM-DD`. */
117
+ function isDate(text) {
118
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
119
+ if (!m)
120
+ return false;
121
+ const d = new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3])));
122
+ return d.getUTCFullYear() === Number(m[1]) && d.getUTCMonth() === Number(m[2]) - 1 && d.getUTCDate() === Number(m[3]);
123
+ }
package/package.json CHANGED
@@ -1,6 +1,34 @@
1
1
  {
2
2
  "name": "@getaster/data",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-preview.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js",
9
+ "default": "./dist/index.js"
10
+ }
11
+ },
12
+ "dependencies": {
13
+ "@preact/signals-core": "1.14.4"
14
+ },
15
+ "license": "Apache-2.0",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/GetAster/aster-ui.git",
19
+ "directory": "packages/data"
20
+ },
21
+ "types": "./dist/index.d.ts",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "LICENSE",
28
+ "NOTICE",
29
+ "README.md"
30
+ ],
31
+ "engines": {
32
+ "node": ">=22"
33
+ }
34
+ }