@leexi/shared 0.1.1 → 0.2.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.
@@ -0,0 +1,43 @@
1
+ import tailwind from 'eslint-plugin-tailwindcss';
2
+ import vue from 'eslint-plugin-vue';
3
+ import base from './base.js';
4
+ export default [
5
+ ...base,
6
+ ...tailwind.configs['flat/recommended'],
7
+ ...vue.configs['flat/recommended'],
8
+ {
9
+ files: ['**/*.vue'],
10
+ rules: {
11
+ '@stylistic/js/indent': 'off',
12
+ '@stylistic/js/object-curly-spacing': 'off',
13
+ 'tailwindcss/no-custom-classname': 'error',
14
+ 'vue/attributes-order': ['error', {
15
+ alphabetical: true,
16
+ }],
17
+ 'vue/component-name-in-template-casing': ['error', 'PascalCase', {
18
+ registeredComponentsOnly: false,
19
+ }],
20
+ 'vue/first-attribute-linebreak': ['error', {
21
+ singleline: 'beside',
22
+ }],
23
+ 'vue/multi-word-component-names': 'off',
24
+ 'vue/no-bare-strings-in-template': ['error', {
25
+ allowlist: ['Leexi'],
26
+ }],
27
+ 'vue/object-curly-spacing': ['error', 'always'],
28
+ 'vue/prefer-template': 'error',
29
+ 'vue/script-indent': ['error', 2, {
30
+ baseIndent: 1,
31
+ switchCase: 1,
32
+ }],
33
+ 'vue/template-curly-spacing': ['error', 'never'],
34
+ },
35
+ },
36
+ {
37
+ ignores: [
38
+ '.nuxt/',
39
+ '.output/',
40
+ 'dist/',
41
+ ],
42
+ },
43
+ ];
@@ -0,0 +1,8 @@
1
+ declare const _default: import("@nuxt/schema").NuxtModule<{
2
+ composables: boolean;
3
+ utils: boolean;
4
+ }, {
5
+ composables: boolean;
6
+ utils: boolean;
7
+ }, false>;
8
+ export default _default;
package/dist/module.js ADDED
@@ -0,0 +1,36 @@
1
+ import { readdirSync, statSync } from 'fs';
2
+ import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit';
3
+ export default defineNuxtModule({
4
+ defaults: {
5
+ composables: true,
6
+ utils: true,
7
+ },
8
+ meta: {
9
+ configKey: 'leexi',
10
+ name: '@leexi/shared',
11
+ },
12
+ setup: options => {
13
+ const resolver = createResolver(import.meta.url);
14
+ const addImportsDir = (dir) => {
15
+ const files = readdirSync(dir);
16
+ files.forEach(file => {
17
+ if (/index/.test(file) || /\.d\.ts/.test(file)) {
18
+ return;
19
+ }
20
+ const path = resolver.resolve(`${dir}/${file}`);
21
+ const stat = statSync(path);
22
+ if (stat.isDirectory()) {
23
+ return addImportsDir(path);
24
+ }
25
+ const [name] = file.split('.');
26
+ addImports({ as: name, from: path, name });
27
+ });
28
+ };
29
+ if (options.composables) {
30
+ addImportsDir(resolver.resolve('./composables'));
31
+ }
32
+ if (options.utils) {
33
+ addImportsDir(resolver.resolve('./utils'));
34
+ }
35
+ },
36
+ });
@@ -0,0 +1 @@
1
+ export * from './objects/index.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Deeply duplicates an object.
3
+ *
4
+ * @param object - an object
5
+ * @returns a duplicate of the same object
6
+ *
7
+ * @example
8
+ * const object = [{ foo: 'bar' }]
9
+ * const dup = deepDup(object) // => `[{ foo: 'bar' }]`
10
+ * object === dup // => `false`
11
+ */
12
+ export declare const deepDup: <T extends object>(object: T) => T;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Deeply duplicates an object.
3
+ *
4
+ * @param object - an object
5
+ * @returns a duplicate of the same object
6
+ *
7
+ * @example
8
+ * const object = [{ foo: 'bar' }]
9
+ * const dup = deepDup(object) // => `[{ foo: 'bar' }]`
10
+ * object === dup // => `false`
11
+ */
12
+ export const deepDup = (object) => {
13
+ if (!object || typeof object !== 'object') {
14
+ return object;
15
+ }
16
+ const duplicate = (value) => value && typeof value === 'object' ? deepDup(value) : value;
17
+ if (Array.isArray(object)) {
18
+ return object.map(duplicate);
19
+ }
20
+ if (object instanceof Set) {
21
+ return new Set([...object].map(duplicate));
22
+ }
23
+ if (Object.getPrototypeOf(object) === Object.prototype) {
24
+ const dup = Object.entries(object).map(([key, value]) => [key, duplicate(value)]);
25
+ return Object.fromEntries(dup);
26
+ }
27
+ return object;
28
+ };
@@ -0,0 +1,2 @@
1
+ export { deepDup } from './deepDup.js';
2
+ export { isSame } from './isSame.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Compares whether two objects are identical.
3
+ *
4
+ * @param a - an object
5
+ * @param b - another object
6
+ * @returns whether these objects are identical
7
+ *
8
+ * @example
9
+ * isSame([{ foo: 'bar' }], [{ foo: 'bar' }]) // => `true`
10
+ * isSame([{ foo: 'bar' }], [{ bar: 'foo' }]) // => `false`
11
+ */
12
+ export declare const isSame: (a: object, b: object) => boolean;
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Compares whether two objects are identical.
3
3
  *
4
- * @param {object} a - an object
5
- * @param {object} b - another object
6
- * @returns {boolean} whether these objects are identical
4
+ * @param a - an object
5
+ * @param b - another object
6
+ * @returns whether these objects are identical
7
7
  *
8
8
  * @example
9
9
  * isSame([{ foo: 'bar' }], [{ foo: 'bar' }]) // => `true`
package/package.json CHANGED
@@ -1,22 +1,39 @@
1
1
  {
2
2
  "name": "@leexi/shared",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.2.0",
5
5
  "scripts": {
6
+ "build": "yarn lint && yarn test --reporter default && tsc && tsc -p tsconfig.build.json",
6
7
  "lint": "eslint .",
8
+ "postinstall": "nuxt prepare",
7
9
  "test": "vitest run"
8
10
  },
9
11
  "exports": {
10
- "./composables": "./src/composables/index.js",
11
- "./eslint/base": "./src/eslint/base.js",
12
- "./eslint/vue": "./src/eslint/vue.js",
13
- "./utils": "./src/utils/index.js",
14
- ".": "./src/module.js"
12
+ "./composables": {
13
+ "import": "./dist/composables/index.js",
14
+ "types": "./dist/composables/index.d.ts"
15
+ },
16
+ "./eslint/base": {
17
+ "import": "./dist/eslint/base.js",
18
+ "types": "./dist/eslint/base.d.ts"
19
+ },
20
+ "./eslint/vue": {
21
+ "import": "./dist/eslint/vue.js",
22
+ "types": "./dist/eslint/vue.d.ts"
23
+ },
24
+ "./utils": {
25
+ "import": "./dist/utils/index.js",
26
+ "types": "./dist/utils/index.d.ts"
27
+ },
28
+ ".": {
29
+ "import": "./dist/module.js",
30
+ "types": "./dist/module.d.ts"
31
+ }
15
32
  },
16
33
  "files": [
17
- "src"
34
+ "dist"
18
35
  ],
19
- "main": "./src/module.js",
36
+ "main": "./dist/module.js",
20
37
  "dependencies": {
21
38
  "@stylistic/eslint-plugin-js": "^4.2.0",
22
39
  "@stylistic/eslint-plugin-ts": "^4.2.0",
@@ -30,6 +47,7 @@
30
47
  },
31
48
  "devDependencies": {
32
49
  "@nuxt/test-utils": "^3.17.2",
50
+ "@types/node": "^22.14.0",
33
51
  "eslint": "^9.23.0",
34
52
  "happy-dom": "^17.4.4",
35
53
  "nuxt": "^3.16.2",
@@ -1 +0,0 @@
1
- export { useLocalStorage } from './useLocalStorage.js';
@@ -1,30 +0,0 @@
1
- import { useState, watch } from '#imports';
2
-
3
- /**
4
- * Creates a reactive pointer to a specific localStorage value.
5
- * The value is stored in the localStorage as a JSON stringified data to enable parsing primitives and objects
6
- *
7
- * @template T extends unknown
8
- * @param {string} key - a key pointing to a localStorage value
9
- * @param {T} [defaultValue] - an optional default value used if the localStorage value is undefined
10
- * @returns {Ref<T>} a reactive variable pointing to that localStorage value
11
- *
12
- * @example
13
- * const fooOne = useLocalStorage('foo')
14
- * const fooTwo = useLocalStorage('foo', 'bar')
15
- * fooOne.value // => 'bar'
16
- * localStorage.foo // => '"bar"'
17
- */
18
- export const useLocalStorage = (key, defaultValue) => {
19
- const data = useState(key, () => JSON.parse(localStorage?.getItem(key) || null) || defaultValue);
20
-
21
- watch(data, () => {
22
- if (data.value) {
23
- localStorage?.setItem(key, JSON.stringify(data.value));
24
- } else {
25
- localStorage?.removeItem(key);
26
- }
27
- }, { immediate: true });
28
-
29
- return data;
30
- };
@@ -1,117 +0,0 @@
1
- import js from '@eslint/js';
2
- import stylisticJS from '@stylistic/eslint-plugin-js';
3
- import stylisticTS from '@stylistic/eslint-plugin-ts';
4
- import globals from 'globals';
5
- import tseslint from 'typescript-eslint';
6
-
7
- export default [
8
- js.configs.recommended,
9
- ...tseslint.configs.recommended,
10
-
11
- // base config
12
- {
13
- languageOptions: {
14
- globals: {
15
- ...globals.browser,
16
- ...globals.node,
17
- },
18
- parserOptions: {
19
- ecmaVersion: 'latest',
20
- sourceType: 'module',
21
- },
22
- },
23
- plugins: {
24
- '@stylistic/js': stylisticJS,
25
- },
26
- rules: {
27
- 'arrow-body-style': ['error', 'as-needed'],
28
- 'eqeqeq': ['error', 'smart'],
29
- 'no-console': 'error',
30
- 'no-unused-vars': ['error', {
31
- argsIgnorePattern: '^_',
32
- destructuredArrayIgnorePattern: '^_',
33
- ignoreRestSiblings: true,
34
- }],
35
- 'prefer-const': ['error', {
36
- destructuring: 'all',
37
- }],
38
- 'prefer-template': 'error',
39
-
40
- '@stylistic/js/array-bracket-spacing': ['error', 'never'],
41
- '@stylistic/js/comma-dangle': ['error', 'always-multiline'],
42
- '@stylistic/js/comma-spacing': 'error',
43
- '@stylistic/js/eol-last': ['error', 'always'],
44
- '@stylistic/js/indent': ['error', 2, {
45
- SwitchCase: 1,
46
- }],
47
- '@stylistic/js/key-spacing': 'error',
48
- '@stylistic/js/keyword-spacing': 'error',
49
- '@stylistic/js/no-multi-spaces': 'error',
50
- '@stylistic/js/no-multiple-empty-lines': ['error', {
51
- max: 1,
52
- }],
53
- '@stylistic/js/no-trailing-spaces': 'error',
54
- '@stylistic/js/object-curly-spacing': ['error', 'always'],
55
- '@stylistic/js/quotes': ['error', 'single'],
56
- '@stylistic/js/quote-props': ['error', 'consistent-as-needed'],
57
- '@stylistic/js/semi': ['error', 'always'],
58
- '@stylistic/js/semi-spacing': 'error',
59
- '@stylistic/js/space-before-blocks': ['error', 'always'],
60
- '@stylistic/js/space-before-function-paren': ['error', 'always'],
61
- '@stylistic/js/space-in-parens': ['error', 'never'],
62
- '@stylistic/js/space-infix-ops': 'error',
63
- '@stylistic/js/spaced-comment': 'error',
64
- '@stylistic/js/template-curly-spacing': ['error', 'never'],
65
-
66
- '@typescript-eslint/no-unused-expressions': 'off',
67
- '@typescript-eslint/no-unused-vars': ['error', {
68
- argsIgnorePattern: '^_',
69
- destructuredArrayIgnorePattern: '^_',
70
- ignoreRestSiblings: true,
71
- }],
72
- },
73
- },
74
-
75
- // typescript
76
- {
77
- files: ['**/*.ts'],
78
- plugins: {
79
- '@stylistic/ts': stylisticTS,
80
- },
81
- rules: {
82
- '@stylistic/js/comma-dangle': 'off',
83
- '@stylistic/js/comma-spacing': 'off',
84
- '@stylistic/js/indent': 'off',
85
- '@stylistic/js/key-spacing': 'off',
86
- '@stylistic/js/keyword-spacing': 'off',
87
- '@stylistic/js/object-curly-spacing': 'off',
88
- '@stylistic/js/quotes': 'off',
89
- '@stylistic/js/quote-props': 'off',
90
- '@stylistic/js/semi': 'off',
91
- '@stylistic/js/space-before-blocks': 'off',
92
- '@stylistic/js/space-before-function-paren': 'off',
93
- '@stylistic/js/space-infix-ops': 'off',
94
-
95
- '@stylistic/ts/comma-dangle': ['error', 'always-multiline'],
96
- '@stylistic/ts/comma-spacing': 'error',
97
- '@stylistic/ts/indent': ['error', 2, {
98
- SwitchCase: 1,
99
- }],
100
- '@stylistic/ts/key-spacing': 'error',
101
- '@stylistic/ts/keyword-spacing': 'error',
102
- '@stylistic/ts/object-curly-spacing': ['error', 'always'],
103
- '@stylistic/ts/quotes': ['error', 'single'],
104
- '@stylistic/ts/quote-props': ['error', 'consistent-as-needed'],
105
- '@stylistic/ts/semi': ['error', 'always'],
106
- '@stylistic/ts/space-before-blocks': ['error', 'always'],
107
- '@stylistic/ts/space-before-function-paren': ['error', 'always'],
108
- '@stylistic/ts/space-infix-ops': 'error',
109
- },
110
- },
111
-
112
- {
113
- ignores: [
114
- 'node_modules/',
115
- ],
116
- },
117
- ];
package/src/eslint/vue.js DELETED
@@ -1,49 +0,0 @@
1
-
2
- import tailwind from 'eslint-plugin-tailwindcss';
3
- import vue from 'eslint-plugin-vue';
4
- import base from './base.js';
5
-
6
- export default [
7
- ...base,
8
- ...tailwind.configs['flat/recommended'],
9
- ...vue.configs['flat/recommended'],
10
-
11
- {
12
- files: ['**/*.vue'],
13
- rules: {
14
- '@stylistic/js/indent': 'off',
15
- '@stylistic/js/object-curly-spacing': 'off',
16
-
17
- 'tailwindcss/no-custom-classname': 'error',
18
-
19
- 'vue/attributes-order': ['error', {
20
- alphabetical: true,
21
- }],
22
- 'vue/component-name-in-template-casing': ['error', 'PascalCase', {
23
- registeredComponentsOnly: false,
24
- }],
25
- 'vue/first-attribute-linebreak': ['error', {
26
- singleline: 'beside',
27
- }],
28
- 'vue/multi-word-component-names': 'off',
29
- 'vue/no-bare-strings-in-template': ['error', {
30
- allowlist: ['Leexi'],
31
- }],
32
- 'vue/object-curly-spacing': ['error', 'always'],
33
- 'vue/prefer-template': 'error',
34
- 'vue/script-indent': ['error', 2, {
35
- baseIndent: 1,
36
- switchCase: 1,
37
- }],
38
- 'vue/template-curly-spacing': ['error', 'never'],
39
- },
40
- },
41
-
42
- {
43
- ignores: [
44
- '.nuxt/',
45
- '.output/',
46
- 'dist/',
47
- ],
48
- },
49
- ];
package/src/module.js DELETED
@@ -1,33 +0,0 @@
1
- import { readdirSync, statSync } from 'fs';
2
- import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit';
3
-
4
- export default defineNuxtModule({
5
- defaults: {
6
- composables: true,
7
- utils: true,
8
- },
9
- meta: {
10
- configKey: 'leexi',
11
- name: '@leexi/shared',
12
- },
13
- setup: options => {
14
- const resolver = createResolver(import.meta.url);
15
-
16
- const addImportsDir = dir => {
17
- const files = readdirSync(dir);
18
- files.forEach(file => {
19
- if (file === 'index.js') { return; }
20
-
21
- const path = resolver.resolve(`${dir}/${file}`);
22
- const stat = statSync(path);
23
- if (stat.isDirectory()) { return addImportsDir(path); }
24
-
25
- const name = file.replace('.js', '');
26
- addImports({ as: name, from: path, name });
27
- });
28
- };
29
-
30
- if (options.composables) { addImportsDir(resolver.resolve('./composables')); }
31
- if (options.utils) { addImportsDir(resolver.resolve('./utils')); }
32
- },
33
- });
@@ -1,31 +0,0 @@
1
- /**
2
- * Deeply duplicates an object.
3
- *
4
- * @param {object} object - an object
5
- * @returns {object} a duplicate of the same object
6
- *
7
- * @example
8
- * const object = [{ foo: 'bar' }]
9
- * const dup = deepDup(object) // => `[{ foo: 'bar' }]`
10
- * object === dup // => `false`
11
- */
12
- export const deepDup = object => {
13
- if (!object || typeof object !== 'object') { return object; }
14
-
15
- const duplicate = value => typeof value === 'object' ? deepDup(value) : value;
16
-
17
- if (Array.isArray(object)) {
18
- return object.map(duplicate);
19
- }
20
-
21
- if (object instanceof Set) {
22
- return new Set([...object].map(duplicate));
23
- }
24
-
25
- if (Object.getPrototypeOf(object) === Object.prototype) {
26
- const dup = Object.entries(object).map(([key, value]) => [key, duplicate(value)]);
27
- return Object.fromEntries(dup);
28
- }
29
-
30
- return object;
31
- };
File without changes