Skip to content

Commit

Permalink
Added ving/utils/indentify.mjs to help identify various data structur…
Browse files Browse the repository at this point in the history
…es in a more consistent way.

* Refactored entire code base to use ving/utils/indentify.mjs.
  • Loading branch information
rizen committed Apr 24, 2024
1 parent f59f14e commit f3997c6
Show file tree
Hide file tree
Showing 20 changed files with 382 additions and 101 deletions.
18 changes: 9 additions & 9 deletions components/FormInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
<FormLabel :label="label" :id="computedId" />
<div class="p-inputgroup flex-1">
<span v-if="prepend" class="p-inputgroup-addon"> {{ prepend }} </span>
<InputNumber v-if="type == 'number' && (_.isNumber(val) || _.isNull(val) || _.isUndefined(val))"
<InputNumber v-if="type == 'number' && (isNumber(val) || isNull(val) || isUndefined(val))"
v-model="val" showButtons :placeholder="placeholder" :name="name" :id="computedId"
:autocomplete="autocomplete" :required="required" :inputClass="fieldClass" :step="step"
:incrementButtonClass="append ? 'border-noround' : ''"
:decrementButtonClass="append ? 'border-noround' : ''" />
<Password v-else-if="type == 'password' && (_.isString(val) || _.isNull(val) || _.isUndefined(val))"
<Password v-else-if="type == 'password' && (isString(val) || isNull(val) || isUndefined(val))"
v-model="val" toggleMask :placeholder="placeholder" :name="name" :id="computedId" :feedback="false"
:autocomplete="autocomplete" :required="required" :inputClass="fieldClass" class="w-full" />
<Textarea v-else-if="type == 'textarea' && (_.isString(val) || _.isNull(val) || _.isUndefined(val))"
<Textarea v-else-if="type == 'textarea' && (isString(val) || isNull(val) || isUndefined(val))"
v-model="val" :placeholder="placeholder" :name="name" :id="computedId" :autocomplete="autocomplete"
:class="fieldClass + ' border-round'" :required="required" autoResize />
<MarkdownInput v-else-if="type == 'markdown' && (_.isString(val) || _.isNull(val) || _.isUndefined(val))"
<MarkdownInput v-else-if="type == 'markdown' && (isString(val) || isNull(val) || isUndefined(val))"
v-model="val" :placeholder="placeholder" :id="computedId" @change="emit('change')"
/>
<SelectInput v-else-if="type == 'select'"
Expand All @@ -23,7 +23,7 @@
<template v-for="(_, name) in $slots" v-slot:[name]="slotData"><slot :name="name" v-bind="slotData" /></template>
</SelectInput>
<InputText
v-else-if="['text', 'email'].includes(type) && (_.isString(val) || _.isNull(val) || _.isUndefined(val))"
v-else-if="['text', 'email'].includes(type) && (isString(val) || isNull(val) || isUndefined(val))"
v-model="val" :placeholder="placeholder" :name="name" :id="computedId" :autocomplete="autocomplete"
:class="fieldClass" :required="required" />
<Message v-else severity="error" :closable="false">
Expand All @@ -36,7 +36,7 @@
</template>

<script setup>
import _ from 'lodash';
import {isNumber, isString, isNull, isUndefined, isNil} from '#ving/utils/identify.mjs';
const props = defineProps({
Expand Down Expand Up @@ -87,20 +87,20 @@ let invalidReason = '';
const invalidForm = inject('invalidForm', (a) => { });
const empty = computed(() => _.isNil(props.modelValue) || props.modelValue === '');
const empty = computed(() => isNil(props.modelValue));
const invalid = computed(() => {
if (props.required && empty.value) {
invalidReason = `${displayName} is required.`;
invalidForm([props.name, true, invalidReason]);
return true;
}
else if (props.mustMatch !== undefined && props.mustMatch.value !== props.modelValue) {
else if (!isUndefined(props.mustMatch) && props.mustMatch.value !== props.modelValue) {
invalidReason = `${displayName} must match ${props.mustMatch.field}.`;
invalidForm([props.name, true, invalidReason]);
return true;
}
else if (props.type == 'email' && !_.isNil(props.modelValue) && !(props.modelValue.toString().match(/.+@.+\..+/))) {
else if (props.type == 'email' && !isNil(props.modelValue) && !(props.modelValue.toString().match(/.+@.+\..+/))) {
invalidReason = `${displayName} doesn't look like an email address.`;
invalidForm([props.name, true, invalidReason]);
return true;
Expand Down
7 changes: 4 additions & 3 deletions composables/currentUserStore.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { defineStore } from 'pinia';
import ua from 'ua-parser-js';
import { isObject, isUndefined } from '#ving/utils/identify.mjs';

const query = { includeOptions: true, includeMeta: true, includeLinks: true };

Expand All @@ -15,7 +16,7 @@ export const useCurrentUserStore = defineStore('currentUser', {
const response = await useRest(`/api/${restVersion()}/user/whoami`, {
query,
});
if (response.data && typeof response.data == 'object') {
if (isObject(response.data)) {
this.setState(response.data);
}
return response;
Expand Down Expand Up @@ -95,10 +96,10 @@ export const useCurrentUserStore = defineStore('currentUser', {
return response;
},
async isAuthenticated() {
if (this.props?.id === undefined) {
if (isUndefined(this.props?.id)) {
await this.fetch();
}
return this.props?.id !== undefined;
return !isUndefined(this.props?.id);
},
},
});
8 changes: 5 additions & 3 deletions composables/useDateTime.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { format, parseISO, parseJSON, parse, getUnixTime } from 'date-fns';
import { ouch } from '#ving/utils/ouch.mjs';
import { isArray, isString } from '#ving/utils/identify.mjs';

const dt = {

/**
Expand All @@ -11,17 +13,17 @@ const dt = {
* @returns A javascript Date object
*/
determineDate(input) {
if (Array.isArray(input) && typeof input[0] === "string") {
if (isArray(input) && isString(input[0])) {
// date + input pattern
return parse(input[0], input[1], new Date());
}
else if (input instanceof Date) {
return input;
}
else if (typeof input === 'string' && input.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/)) {
else if (isString(input) && input.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/)) {
return parseISO(input);
}
else if (typeof input === 'string' && input.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+/)) {
else if (isString(input) && input.match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+/)) {
return parseJSON(input);
}
console.error('Have no idea what type this date is: ', input);
Expand Down
7 changes: 4 additions & 3 deletions composables/useVingRecord.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineStore } from 'pinia';
import { defu } from "defu";
import { v4 } from 'uuid';
import { ouch } from '#ving/utils/ouch.mjs';
import { isObject, isUndefined } from '#ving/utils/identify.mjs';

export default (behavior) => {
const notify = useNotifyStore();
Expand Down Expand Up @@ -104,7 +105,7 @@ export default (behavior) => {
*/
async delete(options = {}) {
let message = "Are you sure?";
if (this.props && typeof this.props == 'object' && "name" in this.props) {
if (isObject(this.props) && "name" in this.props) {
message = "Are you sure you want to delete " + this.props.name + "?";
}
if (options.skipConfirm || confirm(message)) {
Expand Down Expand Up @@ -293,10 +294,10 @@ export default (behavior) => {
*/
save: function (name, value) {
const update = {};
if (this.props && value === undefined) {
if (this.props && isUndefined(value)) {
update[name] = this.props[name];
}
else if (value !== undefined) {
else if (!isUndefined(value)) {
update[name] = value;
}
return this.partialUpdate(update);
Expand Down
2 changes: 2 additions & 0 deletions docs/change-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ outline: deep
* Implemented: replace axios with ofetch for CLI and jobs #117.
* Implemented: replace lodash defaultsDeep with defu #118
* NOTE: You will have to run npm i to get new modules.
* Added ving/utils/indentify.mjs to help identify various data structures in a more consistent way.
* Refactored entire code base to use ving/utils/indentify.mjs.

## 2024-04-22
* Added MarkdownInput form control component for editing markdown text.
Expand Down
4 changes: 4 additions & 0 deletions docs/subsystems/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Provides light wrappers around the javascript `find()` function that throws an e

A bunch of wrappers around node's `fs` library to give you easy to use and terse filesystem functions for checking if a file/folder exists, or reading/writing JSON files, or sanitizing filenames, and more.

### identify

A bunch of utilites to identify whether a variable is an array, or an object or undefined, etc. You can do all this in javascript, but this ensures we do the same tests consistently through-out ving and its shorter to write too.

### miniHash

Provides a function to give something similar to an MD5 hash, or a SHA1 hash, but returns a shorter string (around 8 characters). This is very useful when you need to be able to disambiguate files or other content, but you also need the resulting string to be shorter than a normal file hash. Note that because it's shorter there is a greater chance of collision, but if you know the risks you can work around them.
Expand Down
3 changes: 2 additions & 1 deletion pages/user/login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
</template>

<script setup>
import { isString } from '#ving/utils/identify.mjs';
let login = ref('');
let password = ref('');
const config = useRuntimeConfig();
Expand All @@ -62,7 +63,7 @@ async function tryLogin() {
const response = await currentUser.login(login.value, password.value);
const query = useRoute().query;
if (!response.error)
if (query.redirectAfter && typeof query.redirectAfter == 'string')
if (isString(query.redirectAfter))
await navigateTo(query.redirectAfter)
else
await navigateTo('/');
Expand Down
3 changes: 2 additions & 1 deletion ving/config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { readJSON } from '#ving/utils/fs.mjs';
import { isUndefined } from '#ving/utils/identify.mjs';

let config = undefined;
/**
* Reads `ving.json`
* @returns An object with the contents of `ving.json`
*/
export const getConfig = async () => {
if (config !== undefined)
if (!isUndefined(config))
return config;
config = await readJSON('./ving.json');
return config;
Expand Down
3 changes: 2 additions & 1 deletion ving/generator/nuxtpages.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getContext, renderTemplate, toFile } from '@featherscloud/pinion';
import { splitByCase, upperFirst } from 'scule';
import { stringDefault, booleanDefault, numberDefault } from '#ving/schema/helpers.mjs';
import { isUndefined } from '#ving/utils/identify.mjs';

const makeWords = (value) => splitByCase(value).join(' ');
const makeLabel = (value) => upperFirst(splitByCase(value).join(' '));
Expand Down Expand Up @@ -66,7 +67,7 @@ const prop2type = (prop) => {
if (prop.type == 'int') {
return 'number';
}
if (prop.type == 'string' && (prop.length > 256 || prop.length == undefined)) {
if (prop.type == 'string' && (prop.length > 256 || isUndefined(prop.length))) {
return 'textarea';
}
else {
Expand Down
3 changes: 2 additions & 1 deletion ving/generator/vingrecord.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const describeExample = ({ bare }) => {
out.meta.bar = 'bar';
}
if (params?.include?.extra.includes('foo')) {
if (out.extra === undefined) {
if (isUndefined(out.extra)) {
out.extra = {};
}
out.extra.foo = 'foo';
Expand Down Expand Up @@ -92,6 +92,7 @@ const shortcutQueryExample = ({ bare, name }) => {
const recordTemplate = ({ name, bare, schema }) =>
`import { VingRecord, VingKind } from "#ving/record/VingRecord.mjs";
${bare ? '' : "import {eq} from '#ving/drizzle/orm.mjs';"}
${bare ? '' : "import { isUndefined } from '#ving/utils/identify.mjs';"}
/** Management of individual ${name}s.
* @class
Expand Down
Loading

0 comments on commit f3997c6

Please sign in to comment.