@ciwergrp/nuxid 1.6.5 → 1.7.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/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ciwergrp/nuxid",
3
3
  "configKey": "nuxid",
4
- "version": "1.6.5",
4
+ "version": "1.7.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -2,6 +2,45 @@ import { reactive, ref, toRaw } from "vue";
2
2
  function normalizeStringWhitespace(value) {
3
3
  return value.trim().replace(/\s{2,}/g, " ");
4
4
  }
5
+ function isPlainObject(value) {
6
+ return value !== null && Object.prototype.toString.call(value) === "[object Object]";
7
+ }
8
+ function flattenErrorPaths(value, currentPath = "", target = {}) {
9
+ if (Array.isArray(value)) {
10
+ const hasObjectItems = value.some((item) => item !== null && typeof item === "object");
11
+ if (!hasObjectItems) {
12
+ if (currentPath) {
13
+ target[currentPath] = value;
14
+ }
15
+ return target;
16
+ }
17
+ value.forEach((item, index) => {
18
+ const nextPath = currentPath ? `${currentPath}.${index}` : `${index}`;
19
+ flattenErrorPaths(item, nextPath, target);
20
+ });
21
+ return target;
22
+ }
23
+ if (isPlainObject(value)) {
24
+ Object.keys(value).forEach((key) => {
25
+ const nextPath = currentPath ? `${currentPath}.${key}` : key;
26
+ flattenErrorPaths(value[key], nextPath, target);
27
+ });
28
+ return target;
29
+ }
30
+ if (currentPath) {
31
+ target[currentPath] = value;
32
+ }
33
+ return target;
34
+ }
35
+ function withDotPathErrors(errors) {
36
+ if (!isPlainObject(errors) && !Array.isArray(errors)) {
37
+ return errors;
38
+ }
39
+ return {
40
+ ...errors,
41
+ ...flattenErrorPaths(errors)
42
+ };
43
+ }
5
44
  function normalizeValue(value) {
6
45
  if (typeof value === "string") {
7
46
  return normalizeStringWhitespace(value);
@@ -121,11 +160,11 @@ export default function useHttp(initialData, formOptions) {
121
160
  if (context.response._data && typeof context.response._data === "object") {
122
161
  const responseData = context.response._data;
123
162
  if (responseData.errors) {
124
- form.errors = responseData.errors;
163
+ form.errors = withDotPathErrors(responseData.errors);
125
164
  } else if (responseData.message || responseData.error) {
126
- form.errors = responseData;
165
+ form.errors = withDotPathErrors(responseData);
127
166
  } else {
128
- form.errors = responseData;
167
+ form.errors = withDotPathErrors(responseData);
129
168
  }
130
169
  } else {
131
170
  form.errors = {};
@@ -1,5 +1,5 @@
1
1
  import type { FormRules } from 'element-plus';
2
- export type ValidationRule = 'required' | 'string' | 'nullable' | 'email' | 'accepted' | `accepted_if:${string}` | 'boolean' | 'filled' | 'present' | `required_if:${string}` | `required_unless:${string}` | `required_with:${string}` | `required_with_all:${string}` | `required_without:${string}` | `required_without_all:${string}` | 'prohibited' | `prohibited_if:${string}` | `prohibited_unless:${string}` | `prohibits:${string}` | `min:${number}` | `max:${number}` | `between:${number},${number}` | `size:${number}` | `same:${string}` | 'alpha' | 'alpha_num' | 'alpha_dash' | 'alphanumeric_space' | 'alpha_space' | 'numeric' | 'integer' | 'confirmed' | `digits:${number}` | `digits_between:${number},${number}` | 'bail' | `different:${string}` | `gt:${string}` | `gte:${string}` | `lt:${string}` | `lte:${string}` | `starts_with:${string}` | `ends_with:${string}` | `regex:${string}` | `date_format:${string}` | 'date' | `before:${string}` | `after:${string}` | `before_or_equal:${string}` | `after_or_equal:${string}` | 'array' | 'distinct' | `in_array:${string}` | `required_array_keys:${string}` | 'list' | 'url' | 'ip' | 'hex_color' | `in:${string}` | `multiple_of:${number}` | `decimal:${number}` | `decimal:${number},${number}` | 'lowercase' | 'uppercase' | 'uuid' | 'ulid' | `timezone:${string}` | 'timezone';
2
+ export type ValidationRule = 'required' | 'time' | 'string' | 'nullable' | 'email' | 'accepted' | `accepted_if:${string}` | 'boolean' | 'filled' | 'present' | `required_if:${string}` | `required_unless:${string}` | `required_with:${string}` | `required_with_all:${string}` | `required_without:${string}` | `required_without_all:${string}` | 'prohibited' | `prohibited_if:${string}` | `prohibited_unless:${string}` | `prohibits:${string}` | `min:${number}` | `max:${number}` | `between:${number},${number}` | `size:${number}` | `same:${string}` | 'alpha' | 'alpha_num' | 'alpha_dash' | 'alphanumeric_space' | 'alpha_space' | 'numeric' | 'integer' | 'confirmed' | `digits:${number}` | `digits_between:${number},${number}` | 'bail' | `different:${string}` | `gt:${string}` | `gte:${string}` | `lt:${string}` | `lte:${string}` | `starts_with:${string}` | `ends_with:${string}` | `regex:${string}` | `date_format:${string}` | 'date' | `before:${string}` | `after:${string}` | `before_or_equal:${string}` | `after_or_equal:${string}` | 'array' | 'distinct' | `in_array:${string}` | `required_array_keys:${string}` | 'list' | 'url' | 'ip' | 'hex_color' | `in:${string}` | `multiple_of:${number}` | `decimal:${number}` | `decimal:${number},${number}` | 'lowercase' | 'uppercase' | 'uuid' | 'ulid' | `timezone:${string}` | 'timezone';
3
3
  export interface ValidationOptions {
4
4
  messages?: Record<string, string>;
5
5
  attributes?: Record<string, string>;
@@ -84,6 +84,55 @@ const isAcceptedValue = (value) => {
84
84
  const isBooleanValue = (value) => {
85
85
  return value === true || value === false || value === 0 || value === 1 || value === "0" || value === "1";
86
86
  };
87
+ const parseTimeToMinutes = (value) => {
88
+ if (typeof value !== "string") {
89
+ return null;
90
+ }
91
+ const match = value.match(/^([01]\d|2[0-3]):([0-5]\d)$/);
92
+ if (!match) {
93
+ return null;
94
+ }
95
+ const hours = Number(match[1]);
96
+ const minutes = Number(match[2]);
97
+ return hours * 60 + minutes;
98
+ };
99
+ const parseDateToTimestamp = (value) => {
100
+ if (typeof value !== "string") {
101
+ return null;
102
+ }
103
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
104
+ return null;
105
+ }
106
+ const date = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
107
+ if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== value) {
108
+ return null;
109
+ }
110
+ return date.getTime();
111
+ };
112
+ const compareFieldValues = (left, right, compare) => {
113
+ const leftTime = parseTimeToMinutes(left);
114
+ const rightTime = parseTimeToMinutes(right);
115
+ if (leftTime !== null || rightTime !== null) {
116
+ if (leftTime === null || rightTime === null) {
117
+ return false;
118
+ }
119
+ return compare(leftTime, rightTime);
120
+ }
121
+ const leftDate = parseDateToTimestamp(left);
122
+ const rightDate = parseDateToTimestamp(right);
123
+ if (leftDate !== null || rightDate !== null) {
124
+ if (leftDate === null || rightDate === null) {
125
+ return false;
126
+ }
127
+ return compare(leftDate, rightDate);
128
+ }
129
+ const leftNumber = Number(left);
130
+ const rightNumber = Number(right);
131
+ if (Number.isNaN(leftNumber) || Number.isNaN(rightNumber)) {
132
+ return false;
133
+ }
134
+ return compare(leftNumber, rightNumber);
135
+ };
87
136
  const createDateFormatValidator = (format, message) => {
88
137
  const tokenMap = {
89
138
  Y: "\\d{4}",
@@ -119,6 +168,17 @@ const createDateFormatValidator = (format, message) => {
119
168
  callback();
120
169
  };
121
170
  };
171
+ const createTimeValidator = (message) => {
172
+ return (_rule, value, callback) => {
173
+ if (isEmptyValue(value)) {
174
+ return callback();
175
+ }
176
+ if (parseTimeToMinutes(value) === null) {
177
+ return callback(new Error(message));
178
+ }
179
+ callback();
180
+ };
181
+ };
122
182
  const createPatternValidator = (pattern, message) => {
123
183
  return (_rule, value, callback) => {
124
184
  if (value && !pattern.test(value)) {
@@ -148,7 +208,7 @@ const createIntegerValidator = (message) => {
148
208
  };
149
209
  const createComparisonValidator = (otherField, formState, message, compare) => {
150
210
  return (_rule, value, callback) => {
151
- const otherValue = formState[otherField];
211
+ const otherValue = getNestedValue(formState, otherField);
152
212
  if (value && otherValue && !compare(value, otherValue)) {
153
213
  callback(new Error(message));
154
214
  } else {
@@ -599,6 +659,12 @@ export const createValidationRules = (definitions, formState, options = {}) => {
599
659
  trigger: pickTrigger(fieldName, "blur")
600
660
  });
601
661
  break;
662
+ case "time":
663
+ fieldRules.push({
664
+ validator: createTimeValidator(getMessage(fieldName, "time", `${attributeName} must be a valid time in HH:mm format`)),
665
+ trigger: pickTrigger(fieldName, "blur")
666
+ });
667
+ break;
602
668
  case "nullable":
603
669
  break;
604
670
  case "email":
@@ -1144,7 +1210,7 @@ export const createValidationRules = (definitions, formState, options = {}) => {
1144
1210
  }
1145
1211
  const gtOtherAttr = attributes[firstParam] || firstParam;
1146
1212
  fieldRules.push({
1147
- validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "gt", `${attributeName} must be greater than ${gtOtherAttr}`), (a, b) => Number(a) > Number(b)),
1213
+ validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "gt", `${attributeName} must be greater than ${gtOtherAttr}`), (a, b) => compareFieldValues(a, b, (x, y) => x > y)),
1148
1214
  trigger: pickTrigger(fieldName, "blur")
1149
1215
  });
1150
1216
  break;
@@ -1155,7 +1221,7 @@ export const createValidationRules = (definitions, formState, options = {}) => {
1155
1221
  }
1156
1222
  const gteOtherAttr = attributes[firstParam] || firstParam;
1157
1223
  fieldRules.push({
1158
- validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "gte", `${attributeName} must be greater than or equal to ${gteOtherAttr}`), (a, b) => Number(a) >= Number(b)),
1224
+ validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "gte", `${attributeName} must be greater than or equal to ${gteOtherAttr}`), (a, b) => compareFieldValues(a, b, (x, y) => x >= y)),
1159
1225
  trigger: "blur"
1160
1226
  });
1161
1227
  break;
@@ -1166,7 +1232,7 @@ export const createValidationRules = (definitions, formState, options = {}) => {
1166
1232
  }
1167
1233
  const ltOtherAttr = attributes[firstParam] || firstParam;
1168
1234
  fieldRules.push({
1169
- validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "lt", `${attributeName} must be less than ${ltOtherAttr}`), (a, b) => Number(a) < Number(b)),
1235
+ validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "lt", `${attributeName} must be less than ${ltOtherAttr}`), (a, b) => compareFieldValues(a, b, (x, y) => x < y)),
1170
1236
  trigger: "blur"
1171
1237
  });
1172
1238
  break;
@@ -1177,7 +1243,7 @@ export const createValidationRules = (definitions, formState, options = {}) => {
1177
1243
  }
1178
1244
  const lteOtherAttr = attributes[firstParam] || firstParam;
1179
1245
  fieldRules.push({
1180
- validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "lte", `${attributeName} must be less than or equal to ${lteOtherAttr}`), (a, b) => Number(a) <= Number(b)),
1246
+ validator: createComparisonValidator(firstParam, dataToValidate, getMessage(fieldName, "lte", `${attributeName} must be less than or equal to ${lteOtherAttr}`), (a, b) => compareFieldValues(a, b, (x, y) => x <= y)),
1181
1247
  trigger: "blur"
1182
1248
  });
1183
1249
  break;
@@ -0,0 +1,52 @@
1
+ ---
2
+ title: Dependencies
3
+ ---
4
+
5
+ # Dependencies
6
+
7
+ This page documents dependencies introduced by `@ciwergrp/nuxid`.
8
+
9
+ ## Does this already exist?
10
+
11
+ Not as a dedicated page/menu.
12
+
13
+ - Existing docs under [Third-Party](/built-in-modules/) explain some integrations.
14
+ - This page is the complete dependency inventory.
15
+
16
+ ## Package Dependencies (installed with `@ciwergrp/nuxid`)
17
+
18
+ When you install `@ciwergrp/nuxid`, these direct package dependencies are installed:
19
+
20
+ - `@element-plus/nuxt`
21
+ - `@formatjs/intl`
22
+ - `@inquirer/prompts`
23
+ - `@nuxt/icon`
24
+ - `@nuxt/kit`
25
+ - `@sentry/nuxt`
26
+ - `@sindresorhus/slugify`
27
+ - `@sindresorhus/transliterate`
28
+ - `@tailwindcss/vite`
29
+ - `@vueuse/nuxt`
30
+ - `date-fns`
31
+ - `element-plus`
32
+ - `hls.js`
33
+ - `lodash-es`
34
+ - `pinia`
35
+ - `socket.io-client`
36
+ - `tailwindcss`
37
+ - `vite`
38
+
39
+ ## Nuxt Module Dependencies Added to Your App
40
+
41
+ Nuxid adds/integrates Nuxt modules as follows:
42
+
43
+ - Always declared module dependency: `@sentry/nuxt` (via `moduleDependencies`)
44
+ - Conditionally installed when enabled in `nuxid` options:
45
+ - `@nuxt/icon` (`nuxid.icon`)
46
+ - `@element-plus/nuxt` (`nuxid.elementPlus`)
47
+ - `@vueuse/nuxt` (`nuxid.vueuse`)
48
+
49
+ ## Notes
50
+
51
+ - Enabling `nuxid.pinia` integrates Pinia runtime/composables but does not call `installModule('@pinia/nuxt')`.
52
+ - Versions follow this repository's `package.json`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciwergrp/nuxid",
3
- "version": "1.6.5",
3
+ "version": "1.7.0",
4
4
  "description": "All-in-one essential modules for Nuxt",
5
5
  "repository": {
6
6
  "type": "git",