@signal24/vue-foundation 4.2.0 → 4.2.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@signal24/vue-foundation",
3
3
  "type": "module",
4
- "version": "4.2.0",
4
+ "version": "4.2.2",
5
5
  "description": "Common components, directives, and helpers for Vue 3 apps",
6
6
  "module": "./dist/vue-foundation.es.js",
7
7
  "bin": {
@@ -39,15 +39,17 @@
39
39
  "date-fns": "^2.30.0",
40
40
  "lodash": "^4.17.21",
41
41
  "type-fest": "^3.11.0",
42
+ "uuid": "^9.0.0",
42
43
  "vue": "^3.3.4"
43
44
  },
44
45
  "devDependencies": {
45
46
  "@nabla/vite-plugin-eslint": "^1.5.0",
46
- "@rushstack/eslint-patch": "^1.2.0",
47
+ "@rushstack/eslint-patch": "^1.3.0",
47
48
  "@tsconfig/node18": "^2.0.1",
48
49
  "@types/jsdom": "^21.1.1",
49
50
  "@types/lodash": "^4.14.194",
50
51
  "@types/node": "^18.15.11",
52
+ "@types/uuid": "^9.0.1",
51
53
  "@vitejs/plugin-vue": "^4.2.3",
52
54
  "@vue/eslint-config-prettier": "^7.1.0",
53
55
  "@vue/eslint-config-typescript": "^11.0.3",
@@ -58,7 +60,7 @@
58
60
  "eslint-plugin-cypress": "^2.13.3",
59
61
  "eslint-plugin-simple-import-sort": "^10.0.0",
60
62
  "eslint-plugin-unused-imports": "^2.0.0",
61
- "eslint-plugin-vue": "^9.13.0",
63
+ "eslint-plugin-vue": "^9.14.0",
62
64
  "jsdom": "^22.0.0",
63
65
  "openapi-typescript-codegen": "^0.24.0",
64
66
  "prettier": "^2.8.8",
@@ -20,8 +20,7 @@
20
20
  <script lang="ts" setup>
21
21
  import { computed } from 'vue';
22
22
 
23
- import { formatError } from '@/helpers/error';
24
-
23
+ import { formatError } from '../helpers/error';
25
24
  import Modal from './modal.vue';
26
25
 
27
26
  const props = defineProps<{
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <VfSmartSelect v-model="selectedItem" :options="options" :formatter="ezFormatter" :null-title="nullTitle" />
2
+ <VfSmartSelect v-model="selectedItem" :options="computedOpts" :formatter="ezFormatter" :null-title="nullTitle" />
3
3
  </template>
4
4
 
5
5
  <script lang="ts" setup>
@@ -18,7 +18,7 @@ const props = defineProps<{
18
18
  formatter?: (value: any) => string;
19
19
  }>();
20
20
 
21
- const options = computed(() => {
21
+ const computedOpts = computed(() => {
22
22
  return Array.isArray(props.options)
23
23
  ? props.options.map(o => ({ value: o, label: o }))
24
24
  : Object.entries(props.options).map(([value, label]) => ({
@@ -38,14 +38,14 @@ const emit = defineEmits<{
38
38
  (e: 'update:modelValue', value: string | null): void;
39
39
  }>();
40
40
 
41
- const selectedItem = ref<GenericObject | null>(options.value.find(o => o.value === props.modelValue) ?? null);
41
+ const selectedItem = ref<GenericObject | null>(computedOpts.value.find(o => o.value === props.modelValue) ?? null);
42
42
  watch(
43
43
  () => props.modelValue,
44
44
  value => {
45
- selectedItem.value = options.value.find(o => o.value === value) ?? null;
45
+ selectedItem.value = computedOpts.value.find(o => o.value === value) ?? null;
46
46
  }
47
47
  );
48
48
  watch(selectedItem, value => {
49
- emit('update:modelValue', value ? options.value.find(o => isEqual(o, value))?.value ?? null : null);
49
+ emit('update:modelValue', value ? computedOpts.value.find(o => isEqual(o, value))?.value ?? null : null);
50
50
  });
51
51
  </script>
@@ -1,7 +1,7 @@
1
1
  import { format } from 'date-fns';
2
2
  import type { DirectiveBinding, ObjectDirective } from 'vue';
3
3
 
4
- import { VfOptions } from '@/config';
4
+ import { VfOptions } from '../config';
5
5
 
6
6
  export const vDatetime: ObjectDirective<HTMLElement, string> = {
7
7
  beforeMount: applyDateTime,
@@ -1,5 +1,4 @@
1
- import { showAlert } from '@/components/alert-helpers';
2
-
1
+ import { showAlert } from '../components/alert-helpers';
3
2
  import { VfOptions } from '../config';
4
3
 
5
4
  export class UserError extends Error {
@@ -1,4 +1,4 @@
1
- import type { AnyComponentPublicInstance } from '@/components';
1
+ import type { AnyComponentPublicInstance } from '../components/modal-container';
2
2
 
3
3
  /*///////////////////////////////////////////////
4
4
  Component Overlay Masking
@@ -51,7 +51,7 @@ interface IFormMaskState {
51
51
  [FormMaskState]?: {
52
52
  disabledElements: HTMLElement[];
53
53
  waitButton: HTMLElement;
54
- buttonText: string;
54
+ buttonHtml: string;
55
55
  };
56
56
  }
57
57
  type FormMaskElement = Element & IFormMaskState;
@@ -63,7 +63,7 @@ export function maskForm(formOrCmp: Element | AnyComponentPublicInstance, button
63
63
  const buttonEl = (
64
64
  buttonSelector instanceof Element ? buttonSelector : form.querySelectorAll(buttonSelector ?? 'button:not([disabled])')[0]
65
65
  ) as HTMLElement;
66
- const originalButtonText = buttonEl.tagName === 'INPUT' ? (buttonEl as HTMLInputElement).value : buttonEl.innerText;
66
+ const originalButtonHtml = buttonEl.tagName === 'INPUT' ? (buttonEl as HTMLInputElement).value : buttonEl.innerHTML;
67
67
  buttonEl.setAttribute('disabled', 'disabled');
68
68
  buttonEl.innerText = buttonText ?? 'Please wait...';
69
69
 
@@ -74,7 +74,7 @@ export function maskForm(formOrCmp: Element | AnyComponentPublicInstance, button
74
74
  (form as FormMaskElement)[FormMaskState] = {
75
75
  disabledElements: inputs,
76
76
  waitButton: buttonEl,
77
- buttonText: originalButtonText
77
+ buttonHtml: originalButtonHtml
78
78
  };
79
79
 
80
80
  return () => unmaskForm(form);
@@ -89,7 +89,7 @@ export function unmaskForm(formOrCmp: Element | AnyComponentPublicInstance) {
89
89
  form.classList.remove('vf-masked');
90
90
 
91
91
  state.disabledElements.forEach(el => el.removeAttribute('disabled'));
92
- state.waitButton.innerText = state.buttonText;
92
+ state.waitButton.innerHTML = state.buttonHtml;
93
93
  state.waitButton.removeAttribute('disabled');
94
94
 
95
95
  delete (form as FormMaskElement)[FormMaskState];
@@ -18,17 +18,17 @@ interface IBaseHttpRequest {
18
18
  request<T>(options: IRequestOptions): ICancelablePromise<T>;
19
19
  }
20
20
 
21
- interface IApiClient {
21
+ export interface IApiClient {
22
22
  request: IBaseHttpRequest;
23
23
  }
24
24
 
25
- interface IApiError extends Error {
25
+ export interface IApiError extends Error {
26
26
  status: number;
27
27
  statusText: string;
28
28
  body: any;
29
29
  }
30
30
 
31
- declare class ICancelablePromise<T = any> {
31
+ export declare class ICancelablePromise<T = any> {
32
32
  constructor(executor: (resolve: (value: any) => void, reject: (reason: any) => void, onCancel: (cancel: () => void) => void) => void);
33
33
  then<TResult1 = any, TResult2 = never>(
34
34
  onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,
@@ -46,7 +46,7 @@ interface IWrappedApiClientOptions<P extends ICancelablePromise = ICancelablePro
46
46
  CancelablePromise: new (...arguments_: Arguments) => P;
47
47
  }
48
48
 
49
- function isApiError(err: any): err is IApiError {
49
+ export function isApiError(err: any): err is IApiError {
50
50
  return err instanceof Error && 'status' in err && 'body' in err;
51
51
  }
52
52
 
@@ -1,3 +1,5 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+
1
3
  // placing this here so we don't have to use the ESLint rule everywhere
2
4
  // eslint-disable-next-line vue/prefer-import-from-vue
3
5
  export { escapeHtml } from '@vue/shared';
@@ -25,3 +27,7 @@ export function formatUSCurrency(value: string | number) {
25
27
  .replace(/\B(?=(\d{3})+(?!\d))/g, ',')
26
28
  );
27
29
  }
30
+
31
+ export function uuid() {
32
+ return uuidv4();
33
+ }
@@ -2,14 +2,15 @@
2
2
 
3
3
  import { existsSync } from 'fs';
4
4
 
5
- import { generateOpenapiClient } from './vite-openapi-plugin.js';
5
+ import { generateOpenapiClient, loadOpenapiOverrides } from './vite-openapi-plugin.js';
6
6
 
7
7
  if (!process.argv[2]) {
8
- throw new Error('Usage: vf-generate-openapi-client <openapi-yaml-path>');
8
+ throw new Error('Usage: vf-generate-openapi-client <openapi-yaml-path> [<openapi-output-path>]');
9
9
  }
10
10
 
11
11
  if (!existsSync(process.argv[2])) {
12
12
  throw new Error(`OpenAPI YAML file not found: ${process.argv[2]}`);
13
13
  }
14
14
 
15
- await generateOpenapiClient(process.argv[2]);
15
+ loadOpenapiOverrides();
16
+ await generateOpenapiClient(process.argv[2], process.argv[3]);
@@ -4,9 +4,33 @@ import { rm } from 'node:fs/promises';
4
4
 
5
5
  import * as OpenAPI from 'openapi-typescript-codegen';
6
6
 
7
+ const DEFAULT_OUT_PATH = './src/openapi-client-generated';
8
+
7
9
  let generatedHash: string | null = null;
10
+ let overridesMap: Record<string, string> | null = null;
11
+
12
+ export function loadOpenapiOverrides() {
13
+ if (!existsSync('./openapi-specs.overrides.json')) {
14
+ return;
15
+ }
8
16
 
9
- export function openapiClientGeneratorPlugin(openapiYamlPath: string) {
17
+ try {
18
+ const overridesContent = readFileSync('./openapi-specs.overrides.json', 'utf8');
19
+ overridesMap = JSON.parse(overridesContent);
20
+ } catch (e) {
21
+ console.error('Failed to load openapi-specs.overrides.json:', e);
22
+ }
23
+ }
24
+
25
+ export function openapiClientGeneratorPlugin(
26
+ openapiYamlPath: string,
27
+ outPath: string = DEFAULT_OUT_PATH
28
+ ): {
29
+ name: string;
30
+ apply: 'serve';
31
+ buildStart(): void;
32
+ closeBundle(): void;
33
+ } {
10
34
  let generator: ReturnType<typeof getGenerator> = null;
11
35
 
12
36
  return {
@@ -14,7 +38,11 @@ export function openapiClientGeneratorPlugin(openapiYamlPath: string) {
14
38
  apply: 'serve',
15
39
 
16
40
  buildStart() {
17
- generator = getGenerator(openapiYamlPath);
41
+ // apply a slight delay so any output doesn't get pushed off screen
42
+ setTimeout(() => {
43
+ loadOpenapiOverrides();
44
+ generator = getGenerator(openapiYamlPath, outPath);
45
+ }, 250);
18
46
  },
19
47
 
20
48
  closeBundle() {
@@ -23,19 +51,21 @@ export function openapiClientGeneratorPlugin(openapiYamlPath: string) {
23
51
  };
24
52
  }
25
53
 
26
- function getGenerator(openapiYamlPath: string) {
27
- if (!existsSync(openapiYamlPath)) {
28
- console.log(`OpenAPI YAML file not found: ${openapiYamlPath}`);
54
+ function getGenerator(openapiYamlPath: string, outPath: string) {
55
+ const resolvedPath = overridesMap?.[openapiYamlPath] ?? openapiYamlPath;
56
+
57
+ if (!existsSync(resolvedPath)) {
58
+ console.log(`OpenAPI YAML file not found: ${resolvedPath}`);
29
59
  return null;
30
60
  }
31
61
 
32
- const watcher = watch(openapiYamlPath);
62
+ const watcher = watch(resolvedPath);
33
63
  watcher.on('change', () => {
34
64
  // give the writes a moment to settle
35
- setTimeout(() => generateOpenapiClient(openapiYamlPath), 100);
65
+ setTimeout(() => generateOpenapiClient(resolvedPath, outPath), 100);
36
66
  });
37
67
 
38
- generateOpenapiClient(openapiYamlPath);
68
+ generateOpenapiClient(resolvedPath, outPath);
39
69
 
40
70
  return {
41
71
  close() {
@@ -44,7 +74,7 @@ function getGenerator(openapiYamlPath: string) {
44
74
  };
45
75
  }
46
76
 
47
- export async function generateOpenapiClient(openapiYamlPath: string) {
77
+ async function generateOpenapiClientInternal(openapiYamlPath: string, outPath: string = DEFAULT_OUT_PATH) {
48
78
  const yaml = readFileSync(openapiYamlPath, 'utf8');
49
79
  const hash = createHash('sha256').update(yaml).digest('hex');
50
80
 
@@ -56,21 +86,26 @@ export async function generateOpenapiClient(openapiYamlPath: string) {
56
86
 
57
87
  try {
58
88
  try {
59
- await rm('./src/openapi-client-generated', { recursive: true });
89
+ await rm(outPath, { recursive: true });
60
90
  } catch (e) {
61
91
  // ignore
62
92
  }
63
93
 
64
94
  await OpenAPI.generate({
65
95
  input: openapiYamlPath,
66
- output: './src/openapi-client-generated',
96
+ output: outPath,
67
97
  clientName: 'ApiClient',
68
98
  useOptions: true,
69
99
  useUnionTypes: true
70
100
  });
71
101
 
72
- console.log(`[${new Date().toISOString()}] Generated client from ${openapiYamlPath} to ./src/openapi-client/`);
102
+ console.log(`[${new Date().toISOString()}] Generated client from ${openapiYamlPath} to ${outPath}/`);
73
103
  } catch (err) {
74
104
  console.error(`[${new Date().toISOString()}] Error generating client from ${openapiYamlPath}:`, err);
75
105
  }
76
106
  }
107
+
108
+ export async function generateOpenapiClient(openapiYamlPath: string, outPath: string = DEFAULT_OUT_PATH) {
109
+ const resolvedPath = overridesMap?.[openapiYamlPath] ?? openapiYamlPath;
110
+ return generateOpenapiClientInternal(resolvedPath, outPath);
111
+ }
@@ -27,7 +27,7 @@ export default defineConfig({
27
27
  output: {
28
28
  assetFileNames: assetInfo => {
29
29
  if (assetInfo.name === 'index.css') return 'vue-foundation.css';
30
- return assetInfo.name;
30
+ return assetInfo.name!;
31
31
  },
32
32
  exports: 'named',
33
33
  globals: {
File without changes