renusify 3.1.0 → 3.1.3

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.
@@ -1,4 +1,4 @@
1
- import 'renusify/directive/animate/style.scss'
1
+ import './style.scss'
2
2
 
3
3
  /**
4
4
  * @example // v-animate usage
package/index.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ // Auto-generated Vue component type declarations
2
+ // Do not edit manually - run `npm run build` to update
3
+ declare module 'vue' {
4
+ export interface GlobalComponents {
5
+ rApp: typeof import('./components/app/index.js')['rApp']
6
+ rAvatar: typeof import('./components/avatar/index.js')['rAvatar']
7
+ rBtn: typeof import('./components/button/index.js')['rBtn']
8
+ rBtnConfirm: typeof import('./components/button/buttonConfirm.js')['rBtnConfirm']
9
+ rBtnGroup: typeof import('./components/button/buttonGroup.js')['rBtnGroup']
10
+ rCalendar: typeof import('./components/calendar/index.js')['rCalendar']
11
+ rCard: typeof import('./components/card/index.js')['rCard']
12
+ rCodeEditor: typeof import('./components/codeEditor/index.js')['rCodeEditor']
13
+ rConfirm: typeof import('./components/confirm/index.js')['rConfirm']
14
+ rContainer: typeof import('./components/container/index.js')['rContainer']
15
+ rRow: typeof import('./components/container/row.js')['rRow']
16
+ rCol: typeof import('./components/container/col.js')['rCol']
17
+ rSpacer: typeof import('./components/container/spacer.js')['rSpacer']
18
+ rDivider: typeof import('./components/container/divider.js')['rDivider']
19
+ rContent: typeof import('./components/content/index.js')['rContent']
20
+ rCropper: typeof import('./components/cropper/index.js')['rCropper']
21
+ rFloat: typeof import('./components/float/index.js')['rFloat']
22
+ rForm: typeof import('./components/form/index.js')['rForm']
23
+ rInput: typeof import('./components/form/input/index.js')['rInput']
24
+ rColorInput: typeof import('./components/form/colorInput/index.js')['rColorInput']
25
+ rDateInput: typeof import('./components/form/dateInput/index.js')['rDateInput']
26
+ rFileInput: typeof import('./components/form/fileInput/index.js')['rFileInput']
27
+ rTelInput: typeof import('./components/form/telInput/index.js')['rTelInput']
28
+ rJsonInput: typeof import('./components/form/jsonInput/index.js')['rJsonInput']
29
+ rTextEditor: typeof import('./components/form/textEditor/index.js')['rTextEditor']
30
+ rTextEditorPreview: typeof import('./components/form/textEditor/preview.js')['rTextEditorPreview']
31
+ rTimeInput: typeof import('./components/form/timeInput/index.js')['rTimeInput']
32
+ rTimeRangeInput: typeof import('./components/form/timeInput/range.js')['rTimeRangeInput']
33
+ rUniqueInput: typeof import('./components/form/uniqueInput/index.js')['rUniqueInput']
34
+ rAddressInput: typeof import('./components/form/addressInput/index.js')['rAddressInput']
35
+ rCamInput: typeof import('./components/form/camInput/index.js')['rCamInput']
36
+ rCheckInput: typeof import('./components/form/checkInput/index.js')['rCheckInput']
37
+ rCheckboxInput: typeof import('./components/form/checkboxInput/index.js')['rCheckboxInput']
38
+ rGroupInput: typeof import('./components/form/groupInput/index.js')['rGroupInput']
39
+ rMaskInput: typeof import('./components/form/maskInput/index.js')['rMaskInput']
40
+ rNumberInput: typeof import('./components/form/numberInput/index.js')['rNumberInput']
41
+ rPasswordInput: typeof import('./components/form/passwordInput/index.js')['rPasswordInput']
42
+ rRadioInput: typeof import('./components/form/radioInput/index.js')['rRadioInput']
43
+ rRangeInput: typeof import('./components/form/rangeInput/index.js')['rRangeInput']
44
+ rRatingInput: typeof import('./components/form/ratingInput/index.js')['rRatingInput']
45
+ rSelectInput: typeof import('./components/form/selectInput/index.js')['rSelectInput']
46
+ rSwitchInput: typeof import('./components/form/switchInput/index.js')['rSwitchInput']
47
+ rTextArea: typeof import('./components/form/textArea/index.js')['rTextArea']
48
+ rTextInput: typeof import('./components/form/textInput/index.js')['rTextInput']
49
+ rUnitInput: typeof import('./components/form/unitInput/index.js')['rUnitInput']
50
+ rFormCreator: typeof import('./components/formCreator/index.js')['rFormCreator']
51
+ rIcon: typeof import('./components/icon/index.js')['rIcon']
52
+ rImg: typeof import('./components/img/index.js')['rImg']
53
+ rInfinite: typeof import('./components/infinite/index.js')['rInfinite']
54
+ rMap: typeof import('./components/map/index.js')['rMap']
55
+ rMapSelect: typeof import('./components/map/select.js')['rMapSelect']
56
+ rMapRoute: typeof import('./components/map/route.js')['rMapRoute']
57
+ rMenu: typeof import('./components/menu/index.js')['rMenu']
58
+ rMeta: typeof import('./components/meta/index.js')['rMeta']
59
+ rModal: typeof import('./components/modal/index.js')['rModal']
60
+ rNotify: typeof import('./components/notify/index.js')['rNotify']
61
+ rProgressCircle: typeof import('./components/progress/circle.js')['rProgressCircle']
62
+ rProgressLine: typeof import('./components/progress/line.js')['rProgressLine']
63
+ rSearchBox: typeof import('./components/searchBox/index.js')['rSearchBox']
64
+ rSlider: typeof import('./components/slider/index.js')['rSlider']
65
+ rSwiper: typeof import('./components/swiper/index.js')['rSwiper']
66
+ rTable: typeof import('./components/table/index.js')['rTable']
67
+ rTableCrud: typeof import('./components/table/crud/index.js')['rTableCrud']
68
+ rTimeAgo: typeof import('./components/timeAgo/index.js')['rTimeAgo']
69
+ rTour: typeof import('./components/tour/index.js')['rTour']
70
+ rTree: typeof import('./components/tree/index.js')['rTree']
71
+ rHighlight: typeof import('./components/highlight/index.js')['rHighlight']
72
+ }
73
+ }
package/package.json CHANGED
@@ -1,30 +1,38 @@
1
- {
2
- "name": "renusify",
3
- "version": "3.1.0",
4
- "description": "Vue3 Framework",
5
- "keywords": [
6
- "vuejs",
7
- "vue framework",
8
- "ui framework",
9
- "component framework",
10
- "ui library",
11
- "component library",
12
- "material components",
13
- "renusify"
14
- ],
15
- "homepage": "https://github.com/smkoBa/renusify",
16
- "main": "index.js",
17
- "repository": {
18
- "type": "git",
19
- "url": "https://github.com/smkoBa/renusify.git"
20
- },
21
- "author": {
22
- "name": "Smko Bayazidi",
23
- "email": "ba.smko@gmail.com"
24
- },
25
- "license": "BSD",
26
- "private": false,
27
- "scripts": {
28
- "docs:generate": "node scripts/generate-docs.mjs"
29
- }
30
- }
1
+ {
2
+ "name": "renusify",
3
+ "version": "3.1.3",
4
+ "description": "Vue3 Framework",
5
+ "keywords": [
6
+ "vuejs",
7
+ "vue framework",
8
+ "ui framework",
9
+ "component framework",
10
+ "ui library",
11
+ "component library",
12
+ "material components",
13
+ "renusify"
14
+ ],
15
+ "homepage": "https://github.com/smkoBa/renusify",
16
+ "main": "index.js",
17
+ "types": "index.d.ts",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/smkoBa/renusify.git"
21
+ },
22
+ "author": {
23
+ "name": "Smko Bayazidi",
24
+ "email": "ba.smko@gmail.com"
25
+ },
26
+ "license": "BSD",
27
+ "private": false,
28
+ "scripts": {
29
+ "docs:generate": "node scripts/generate-docs.mjs",
30
+ "build:types": "node scripts/generate-types.mjs",
31
+ "build": "npm run docs:generate && npm run build:types"
32
+ },
33
+ "peerDependencies": {
34
+ "sass": "^1.69.0",
35
+ "vue": "^3.3.0",
36
+ "vue-router": "^4.5.0"
37
+ }
38
+ }
@@ -0,0 +1,314 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+
4
+ export default function renusifyAutoPlugin(options = {}) {
5
+ const { prefix = 'r', debug = false } = options
6
+
7
+ const state = {
8
+ usedComponents: new Set(),
9
+ usedDirectives: new Set(),
10
+ componentsMap: new Map(),
11
+ directivesMap: new Map(),
12
+ rootDir: '',
13
+ }
14
+
15
+
16
+ function parseExports(filePath, exclude = []) {
17
+ try {
18
+ const content = fs.readFileSync(filePath, 'utf-8')
19
+ const clean = content
20
+ .replace(/\/\*[\s\S]*?\*\//g, '')
21
+ .replace(/\/\/.*$/gm, '')
22
+
23
+ const regex = /export\s+\*\s+as\s+([a-zA-Z_]\w*)\s+from\s+['"]([^'"]+)['"]/g
24
+ const map = new Map()
25
+ let m
26
+ while ((m = regex.exec(clean)) !== null) {
27
+ const [, name, relPath] = m
28
+ if (exclude.includes(name)) continue
29
+ let p = relPath.replace(/^\.\//, '')
30
+ if (!p.match(/\.(js|vue|ts|mjs)$/)) p = `${p}/index.js`
31
+ map.set(name, p)
32
+ }
33
+ return map
34
+ } catch (err) {
35
+ console.warn(`[renusify-auto] Could not parse ${filePath}:`, err.message)
36
+ return new Map()
37
+ }
38
+ }
39
+
40
+
41
+ function kebab2camel(s) {
42
+ return s.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())
43
+ }
44
+
45
+
46
+ function scanFile(filePath) {
47
+ try {
48
+ const content = fs.readFileSync(filePath, 'utf-8')
49
+ const tmplMatch = content.match(/<template(?:\s[^>]*)?>([\s\S]*?)<\/template>/)
50
+ if (!tmplMatch) return
51
+
52
+ const tmpl = tmplMatch[1]
53
+
54
+ const tagRe = /<\s*\/?([a-zA-Z][a-zA-Z0-9-]*)/g
55
+ let m
56
+ while ((m = tagRe.exec(tmpl)) !== null) {
57
+ const tag = m[1]
58
+ if (!tag.startsWith(prefix)) continue
59
+ const camel = kebab2camel(tag)
60
+ if (state.componentsMap.has(camel)) state.usedComponents.add(camel)
61
+ else if (state.componentsMap.has(tag)) state.usedComponents.add(tag)
62
+ }
63
+
64
+ const dirRe = /\bv-([a-zA-Z][a-zA-Z0-9-]*)/g
65
+ const builtins = new Set([
66
+ 'model', 'if', 'else', 'else-if', 'for', 'show', 'bind', 'on',
67
+ 'slot', 'text', 'html', 'cloak', 'once', 'memo', 'pre'
68
+ ])
69
+
70
+ while ((m = dirRe.exec(tmpl)) !== null) {
71
+ const d = m[1]
72
+ if (builtins.has(d)) continue
73
+ const camel = kebab2camel(d)
74
+ const candidates = [d, camel, `v${camel.charAt(0).toUpperCase()}${camel.slice(1)}`]
75
+ for (const c of candidates) {
76
+ if (state.directivesMap.has(c)) {
77
+ state.usedDirectives.add(c)
78
+ break
79
+ }
80
+ }
81
+ }
82
+ } catch {
83
+ // ignore
84
+ }
85
+ }
86
+
87
+
88
+ function scanDirSync(dir) {
89
+ let entries
90
+ try {
91
+ entries = fs.readdirSync(dir, { withFileTypes: true })
92
+ } catch {
93
+ return
94
+ }
95
+ for (const entry of entries) {
96
+ const full = path.join(dir, entry.name)
97
+ if (entry.isDirectory()) {
98
+ if (['node_modules', 'dist', '.git', '.nuxt', '.output'].includes(entry.name)) continue
99
+ scanDirSync(full)
100
+ } else if (entry.name.endsWith('.vue')) {
101
+ scanFile(full)
102
+ }
103
+ }
104
+ }
105
+
106
+
107
+ function generateImportStatements() {
108
+ const comps = [...state.usedComponents].sort()
109
+ const dirs = [...state.usedDirectives].sort()
110
+
111
+ if (comps.length === 0 && dirs.length === 0) return ''
112
+
113
+ let code = '\n'
114
+ if (comps.length > 0) {
115
+ code += `import {\n ${comps.join(',\n ')}\n} from 'renusify/components/index.js'\n`
116
+ }
117
+ if (dirs.length > 0) {
118
+ const dirNames = dirs.map(name => {
119
+ if (name.startsWith('v') || name.startsWith('V')) {
120
+ return name.charAt(1).toLowerCase() + name.slice(2)
121
+ }
122
+ return name
123
+ })
124
+ code += `import { ${dirNames.join(', ')} } from 'renusify/directive/index.js'\n`
125
+ }
126
+
127
+ return code
128
+ }
129
+
130
+
131
+ function generateComponentsObject() {
132
+ const comps = [...state.usedComponents].sort()
133
+ if (comps.length === 0) return null
134
+ return `components: {\n ${comps.join(',\n ')}\n }`
135
+ }
136
+
137
+
138
+ function generateDirectivesObject() {
139
+ const dirs = [...state.usedDirectives].sort()
140
+ if (dirs.length === 0) return null
141
+ const dirNames = dirs.map(name => {
142
+ if (name.startsWith('v') || name.startsWith('V')) {
143
+ return name.charAt(1).toLowerCase() + name.slice(2)
144
+ }
145
+ return name
146
+ })
147
+ return `directives: { ${dirNames.join(', ')} }`
148
+ }
149
+
150
+ return {
151
+ name: 'vite-plugin-renusify-auto',
152
+ enforce: 'pre',
153
+
154
+ configResolved(config) {
155
+ state.rootDir = config.root
156
+ const renusifyPath = path.join(config.root, 'node_modules/renusify')
157
+
158
+ state.componentsMap = parseExports(
159
+ path.join(renusifyPath, 'components/index.js'),
160
+ ['_register']
161
+ )
162
+ state.directivesMap = parseExports(
163
+ path.join(renusifyPath, 'directive/index.js'),
164
+ ['_registers']
165
+ )
166
+
167
+ if (config.command === 'serve') {
168
+ state.usedComponents = new Set(state.componentsMap.keys())
169
+ state.usedDirectives = new Set(state.directivesMap.keys())
170
+ if (debug) {
171
+ console.log(`[renusify-auto] Dev mode: ALL ${state.componentsMap.size} components, ${state.directivesMap.size} directives`)
172
+ }
173
+ } else {
174
+ scanDirSync(path.join(config.root, 'src'))
175
+ if (debug) {
176
+ console.log(`[renusify-auto] Build mode: ${state.usedComponents.size} components, ${state.usedDirectives.size} directives`)
177
+ console.log(' Components:', [...state.usedComponents].join(', '))
178
+ console.log(' Directives:', [...state.usedDirectives].join(', '))
179
+ }
180
+ }
181
+ },
182
+
183
+ transform(code, id) {
184
+ if (!/main\.(js|ts)$/.test(id)) return null
185
+ if (id.includes('node_modules')) return null
186
+
187
+ let newCode = code
188
+ let modified = false
189
+
190
+ const importStmts = generateImportStatements()
191
+ if (importStmts) {
192
+ const importRegex = /^import\s+[^;]+;?\s*$/gm
193
+ const allImports = code.match(importRegex)
194
+
195
+ if (allImports && allImports.length > 0) {
196
+ const lastImport = allImports[allImports.length - 1]
197
+ const lastImportIndex = code.lastIndexOf(lastImport)
198
+ const insertPos = lastImportIndex + lastImport.length
199
+ newCode = newCode.slice(0, insertPos) + importStmts + newCode.slice(insertPos)
200
+ } else {
201
+ newCode = importStmts + '\n' + newCode
202
+ }
203
+ modified = true
204
+ }
205
+
206
+ const renusifyRegex = /\.use\s*\(\s*renusify\s*,\s*\{/
207
+ const useMatch = newCode.match(renusifyRegex)
208
+
209
+ if (useMatch) {
210
+ const matchIndex = useMatch.index
211
+ const startOfOptions = matchIndex + useMatch[0].length
212
+
213
+ let braceCount = 1
214
+ let i = startOfOptions
215
+ while (i < newCode.length && braceCount > 0) {
216
+ if (newCode[i] === '{') braceCount++
217
+ else if (newCode[i] === '}') braceCount--
218
+ if (braceCount > 0) i++
219
+ }
220
+
221
+ if (braceCount === 0) {
222
+ const endOfOptions = i
223
+ const optionsContent = newCode.slice(startOfOptions, endOfOptions)
224
+ let cleanedOptions = optionsContent
225
+
226
+ cleanedOptions = removeProperty(cleanedOptions, 'components')
227
+ cleanedOptions = removeProperty(cleanedOptions, 'directives')
228
+
229
+ cleanedOptions = cleanedOptions.replace(/,(\s*)}/g, '$1}')
230
+ cleanedOptions = cleanedOptions.trim()
231
+
232
+ const componentsObj = generateComponentsObject()
233
+ const directivesObj = generateDirectivesObject()
234
+
235
+ let newOptionsContent = cleanedOptions
236
+
237
+ if (componentsObj || directivesObj) {
238
+ const needsComma = newOptionsContent.trim().length > 0 && !newOptionsContent.trim().endsWith(',')
239
+ const comma = needsComma ? ',' : ''
240
+
241
+ let additions = ''
242
+ if (componentsObj) additions += '\n ' + componentsObj
243
+ if (directivesObj) additions += (additions ? ',' : '') + '\n ' + directivesObj
244
+
245
+ if (newOptionsContent.trim().length === 0) {
246
+ newOptionsContent = additions + '\n '
247
+ } else {
248
+ newOptionsContent = newOptionsContent + comma + additions + '\n '
249
+ }
250
+ }
251
+
252
+ newCode = newCode.slice(0, startOfOptions) + newOptionsContent + newCode.slice(endOfOptions)
253
+ modified = true
254
+ }
255
+ }
256
+
257
+ if (modified) {
258
+ if (debug) {
259
+ console.log(`[renusify-auto] Transformed ${path.basename(id)}`)
260
+ }
261
+ return { code: newCode, map: null }
262
+ }
263
+
264
+ return null
265
+ },
266
+ }
267
+ }
268
+
269
+ function removeProperty(optionsStr, propName) {
270
+ const propRegex = new RegExp(`,?\\s*${propName}\\s*:\\s*`)
271
+ const match = propRegex.exec(optionsStr)
272
+
273
+ if (!match) return optionsStr
274
+
275
+ const startIndex = match.index
276
+ const valueStart = startIndex + match[0].length
277
+
278
+
279
+ let endIndex = valueStart
280
+ const firstChar = optionsStr[valueStart]
281
+
282
+ if (firstChar === '{') {
283
+
284
+ let braceCount = 1
285
+ let i = valueStart + 1
286
+ while (i < optionsStr.length && braceCount > 0) {
287
+ if (optionsStr[i] === '{') braceCount++
288
+ else if (optionsStr[i] === '}') braceCount--
289
+ i++
290
+ }
291
+ endIndex = i
292
+ } else if (firstChar === '[') {
293
+ let bracketCount = 1
294
+ let i = valueStart + 1
295
+ while (i < optionsStr.length && bracketCount > 0) {
296
+ if (optionsStr[i] === '[') bracketCount++
297
+ else if (optionsStr[i] === ']') bracketCount--
298
+ i++
299
+ }
300
+ endIndex = i
301
+ } else {
302
+ let i = valueStart
303
+ while (i < optionsStr.length && optionsStr[i] !== ',' && optionsStr[i] !== '}') {
304
+ i++
305
+ }
306
+ endIndex = i
307
+ }
308
+
309
+ if (endIndex < optionsStr.length && optionsStr[endIndex] === ',') {
310
+ endIndex++
311
+ }
312
+
313
+ return optionsStr.slice(0, startIndex) + optionsStr.slice(endIndex)
314
+ }
@@ -1,35 +1,164 @@
1
1
  class Storage {
2
- stringfy(value){
3
- return JSON.stringify(value)
2
+ constructor(encryptionKey) {
3
+ this._key = encryptionKey || this._loadKeyFromEnv();
4
+ this._available = this._checkAvailability();
5
+ if (!this._key) {
6
+ console.warn('[Storage] ⚠️ No encryption key provided. Safe methods will throw.');
4
7
  }
5
- parse(value){
6
- return JSON.parse(value)
7
- }
8
- set(key, value) {
9
- localStorage.setItem(key,this.stringfy(value))
8
+ }
9
+
10
+ _loadKeyFromEnv() {
11
+ if (typeof import.meta !== 'undefined' && import.meta.env?.VITE_STORAGE_KEY)
12
+ return import.meta.env.VITE_STORAGE_KEY;
13
+ if (typeof process !== 'undefined' && process.env?.STORAGE_KEY)
14
+ return process.env.STORAGE_KEY;
15
+ return null;
16
+ }
17
+
18
+ _checkAvailability() {
19
+ try {
20
+ const test = '__storage_test__';
21
+ localStorage.setItem(test, '1');
22
+ localStorage.removeItem(test);
23
+ return true;
24
+ } catch {
25
+ return false;
10
26
  }
27
+ }
28
+
29
+ _arrayBufferToBase64(buffer) {
30
+ const bytes = new Uint8Array(buffer);
31
+ let binary = '';
32
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
33
+ return btoa(binary);
34
+ }
35
+
36
+ _base64ToArrayBuffer(base64) {
37
+ const binary = atob(base64);
38
+ const bytes = new Uint8Array(binary.length);
39
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
40
+ return bytes.buffer;
41
+ }
42
+
43
+ async _deriveKey(password, salt) {
44
+ const enc = new TextEncoder();
45
+ const keyMaterial = await crypto.subtle.importKey(
46
+ 'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']
47
+ );
48
+ return crypto.subtle.deriveKey(
49
+ {name: 'PBKDF2', salt, iterations: 100000, hash: 'SHA-256'},
50
+ keyMaterial,
51
+ {name: 'AES-GCM', length: 256},
52
+ false,
53
+ ['encrypt', 'decrypt']
54
+ );
55
+ }
56
+
57
+ async _encrypt(plaintext) {
58
+ const salt = crypto.getRandomValues(new Uint8Array(16));
59
+ const iv = crypto.getRandomValues(new Uint8Array(12));
60
+ const key = await this._deriveKey(this._key, salt);
61
+ const cipher = await crypto.subtle.encrypt(
62
+ {name: 'AES-GCM', iv}, key, new TextEncoder().encode(plaintext)
63
+ );
64
+ return JSON.stringify({
65
+ salt: this._arrayBufferToBase64(salt),
66
+ iv: this._arrayBufferToBase64(iv),
67
+ data: this._arrayBufferToBase64(cipher)
68
+ });
69
+ }
11
70
 
12
- has(key) {
13
- return this.get(key)!==null
71
+ async _decrypt(payloadString) {
72
+ const {salt, iv, data} = JSON.parse(payloadString);
73
+ const key = await this._deriveKey(this._key, this._base64ToArrayBuffer(salt));
74
+ const decrypted = await crypto.subtle.decrypt(
75
+ {name: 'AES-GCM', iv: this._base64ToArrayBuffer(iv)},
76
+ key,
77
+ this._base64ToArrayBuffer(data)
78
+ );
79
+ return new TextDecoder().decode(decrypted);
80
+ }
81
+
82
+ stringify(value) {
83
+ return JSON.stringify(value);
84
+ }
85
+
86
+ parse(value) {
87
+ return JSON.parse(value);
88
+ }
89
+
90
+ set(key, value) {
91
+ if (!this._available) return false;
92
+ try {
93
+ localStorage.setItem(String(key), this.stringify(value));
94
+ return true;
95
+ } catch (err) {
96
+ console.error(`[Storage] set failed:`, err);
97
+ return false;
14
98
  }
99
+ }
100
+
101
+ has(key) {
102
+ if (!this._available) return false;
103
+ return localStorage.getItem(String(key)) !== null;
104
+ }
15
105
 
16
- get(key,def=null) {
17
- let i=localStorage.getItem(key)
18
- if(i===null){
19
- return def
20
- }
21
- return this.parse(i)
106
+ get(key, def = null) {
107
+ if (!this._available) return def;
108
+ const raw = localStorage.getItem(String(key));
109
+ if (raw === null) return def;
110
+ try {
111
+ return this.parse(raw);
112
+ } catch {
113
+ return def;
22
114
  }
115
+ }
23
116
 
24
- remove(key) {
25
- return localStorage.removeItem(key)
117
+ remove(key) {
118
+ if (!this._available) return false;
119
+ localStorage.removeItem(String(key));
120
+ return true;
121
+ }
122
+
123
+ pull(key, def = null) {
124
+ const data = this.get(key, def);
125
+ this.remove(key);
126
+ return data;
127
+ }
128
+
129
+ async setSafe(key, value) {
130
+ if (!this._key) throw new Error('[Storage] Encryption key not configured.');
131
+ if (!this._available) return false;
132
+ try {
133
+ const plaintext = this.stringify(value);
134
+ const encrypted = await this._encrypt(plaintext);
135
+ localStorage.setItem(String(key), encrypted);
136
+ return true;
137
+ } catch (err) {
138
+ console.error(`[Storage] setSafe failed:`, err);
139
+ return false;
26
140
  }
141
+ }
27
142
 
28
- pull(key){
29
- const d=this.get(key)
30
- this.remove(key)
31
- return d
143
+ async getSafe(key, def = null) {
144
+ if (!this._key) throw new Error('[Storage] Encryption key not configured.');
145
+ if (!this._available) return def;
146
+ const raw = localStorage.getItem(String(key));
147
+ if (raw === null) return def;
148
+ try {
149
+ const decrypted = await this._decrypt(raw);
150
+ return this.parse(decrypted);
151
+ } catch (err) {
152
+ console.warn(`[Storage] getSafe failed (tampered/invalid):`, err);
153
+ return def;
32
154
  }
155
+ }
156
+
157
+ async pullSafe(key, def = null) {
158
+ const data = await this.getSafe(key, def);
159
+ this.remove(key);
160
+ return data;
161
+ }
33
162
  }
34
163
 
35
- export default new Storage();
164
+ export default new Storage();
@@ -0,0 +1,83 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+
8
+ const CONFIG = {
9
+ inputFile: path.resolve(__dirname, '../components/index.js'),
10
+ outputFile: path.resolve(__dirname, '../index.d.ts'),
11
+ importPathPrefix: './components',
12
+ };
13
+
14
+
15
+ function parseExports(content) {
16
+ return content
17
+ .split('\n')
18
+ .map(line => line.trim())
19
+ .filter(line => line && !line.startsWith('//'))
20
+ .map(line => {
21
+ const match = line.match(/^export\s+\*\s+as\s+(\w+)\s+from\s+['"](.+)['"]\s*;?$/);
22
+ return match ? { componentName: match[1], relativePath: match[2] } : null;
23
+ })
24
+ .filter(item => item !== null);
25
+ }
26
+
27
+
28
+ function transformImportPath(relativePath, prefix) {
29
+ if (relativePath.startsWith('./')) {
30
+ return `${prefix}${relativePath.slice(1)}`;
31
+ }
32
+ return relativePath;
33
+ }
34
+
35
+
36
+ function generateDeclaration(components, prefix) {
37
+ const lines = [
38
+ '// Auto-generated Vue component type declarations',
39
+ '// Do not edit manually - run `npm run build` to update',
40
+ `declare module 'vue' {`,
41
+ ` export interface GlobalComponents {`,
42
+ ];
43
+
44
+ for (const { componentName, relativePath } of components) {
45
+ const importPath = transformImportPath(relativePath, prefix);
46
+ lines.push(` ${componentName}: typeof import('${importPath}')['${componentName}']`);
47
+ }
48
+
49
+ lines.push(` }`, `}`, '');
50
+ return lines.join('\n');
51
+ }
52
+
53
+
54
+ function main() {
55
+ try {
56
+ console.log(`Reading exports from: ${CONFIG.inputFile}`);
57
+
58
+ if (!fs.existsSync(CONFIG.inputFile)) {
59
+ throw new Error(`Input file not found: ${CONFIG.inputFile}`);
60
+ }
61
+
62
+ const content = fs.readFileSync(CONFIG.inputFile, 'utf-8');
63
+ const components = parseExports(content);
64
+
65
+ if (components.length === 0) {
66
+ console.warn('No component exports found. Check your input file format.');
67
+ } else {
68
+ console.log(`Found ${components.length} component exports`);
69
+ }
70
+
71
+ const declaration = generateDeclaration(components, CONFIG.importPathPrefix);
72
+
73
+ fs.writeFileSync(CONFIG.outputFile, declaration, 'utf-8');
74
+ console.log(`Generated: ${CONFIG.outputFile}`);
75
+ console.log(`Total components: ${components.length}`);
76
+
77
+ } catch (error) {
78
+ console.error('Error:', error.message);
79
+ process.exit(1);
80
+ }
81
+ }
82
+
83
+ main();
@@ -1,281 +0,0 @@
1
- import SimpleRng from "./random";
2
-
3
- export default class Cryptor {
4
- constructor() {
5
- this.matrix = 32;
6
- }
7
-
8
- packUint32BE(value) {
9
- const bytes = new Uint8Array(4);
10
- bytes[0] = (value >> 24) & 0xFF;
11
- bytes[1] = (value >> 16) & 0xFF;
12
- bytes[2] = (value >> 8) & 0xFF;
13
- bytes[3] = value & 0xFF;
14
- return bytes;
15
- }
16
-
17
- unpackUint32BE(bytes, offset = 0) {
18
- return ((bytes[offset] << 24) |
19
- (bytes[offset + 1] << 16) |
20
- (bytes[offset + 2] << 8) |
21
- bytes[offset + 3]) >>> 0;
22
- }
23
-
24
- encrypt(data, key) {
25
- const matrixSize = this.matrix;
26
- const pad = (matrixSize - ((10 + data.length) % matrixSize)) % matrixSize;
27
- const keyBytes = this.generatePassword(matrixSize, this.stringToBytes(key));
28
-
29
- const dataSize = this.packUint32BE(data.length);
30
-
31
- const randomPrefix = this.getRandomBytes(6);
32
- const seedRandom = randomPrefix.reduce((sum, b) => sum + b, 0);
33
-
34
- const paddedText = new Uint8Array(10 + data.length + pad);
35
- paddedText.set(dataSize, 0);
36
- paddedText.set(randomPrefix, 4);
37
- paddedText.set(data, 10);
38
-
39
- if (pad > 0) {
40
- paddedText.fill(1, 10 + data.length, 10 + data.length + pad);
41
- }
42
-
43
- const seedSum = keyBytes.reduce((sum, b) => sum + b, 0);
44
- this.shuffle(paddedText, seedSum + seedRandom, 5);
45
-
46
- for (let i = 0; i < paddedText.length; i += matrixSize) {
47
- const end = Math.min(i + matrixSize, paddedText.length);
48
- const seed = (i + matrixSize < paddedText.length) ? paddedText[i + matrixSize] : keyBytes[0];
49
- const chunkCopy = new Uint8Array(paddedText.slice(i, end));
50
- this.shuffle(chunkCopy, seed + seedRandom, 2);
51
- paddedText.set(chunkCopy, i);
52
- }
53
-
54
- this.mix(matrixSize, paddedText, keyBytes);
55
-
56
- const result = new Uint8Array(paddedText.length + 2);
57
- result.set(paddedText, 0);
58
- result[paddedText.length] = (seedRandom >> 8) & 0xFF;
59
- result[paddedText.length + 1] = seedRandom & 0xFF;
60
-
61
- return result;
62
- }
63
-
64
- encryptText(text, key) {
65
- const data = this.stringToBytes(text);
66
- const encrypted = this.encrypt(data, key);
67
- return this.base64UrlEncode(encrypted);
68
- }
69
-
70
- decrypt(encoded, key) {
71
- if (encoded.length < 8) {
72
- throw new Error('Invalid Token Matrix Length.');
73
- }
74
-
75
- const seedRandom = (encoded[encoded.length - 2] << 8) | encoded[encoded.length - 1];
76
- const decoded = new Uint8Array(encoded.slice(0, -2));
77
- const matrixSize = this.matrix;
78
-
79
- const keyBytes = this.generatePassword(matrixSize, this.stringToBytes(key));
80
- this.unmix(matrixSize, decoded, keyBytes);
81
-
82
- for (let i = Math.floor(decoded.length / matrixSize) * matrixSize; i >= 0; i -= matrixSize) {
83
- const end = Math.min(i + matrixSize, decoded.length);
84
- const seed = (i + matrixSize < decoded.length) ? decoded[i + matrixSize] : keyBytes[0];
85
- const chunkCopy = new Uint8Array(decoded.slice(i, end));
86
- this.unshuffle(chunkCopy, seed + seedRandom, 2);
87
- decoded.set(chunkCopy, i);
88
- }
89
-
90
- const seedSum = keyBytes.reduce((sum, b) => sum + b, 0);
91
- this.unshuffle(decoded, seedSum + seedRandom, 5);
92
-
93
- const dataSize = this.unpackUint32BE(decoded, 0);
94
-
95
- if (decoded.length < dataSize + 10) {
96
- throw new Error('Invalid Token Matrix Length');
97
- }
98
-
99
- return decoded.slice(10, 10 + dataSize);
100
- }
101
-
102
- decryptText(encoded, key) {
103
- const padding = encoded.length % 4;
104
- const paddedInput = padding === 0 ? encoded : encoded + '='.repeat(4 - padding);
105
-
106
- const data = this.base64UrlDecode(paddedInput);
107
- const decrypted = this.decrypt(data, key);
108
- return this.bytesToString(decrypted);
109
- }
110
-
111
- setMatrix(size) {
112
- if (size > 0) {
113
- this.matrix = size;
114
- }
115
- }
116
-
117
- generatePassword(matrix, password) {
118
- const result = new Uint8Array(matrix);
119
- const passwordLen = password.length;
120
-
121
- if (passwordLen === 0) {
122
- return result;
123
- }
124
-
125
- const repeats = Math.floor(matrix / passwordLen);
126
- const remainder = matrix % passwordLen;
127
-
128
- for (let i = 0; i < repeats; i++) {
129
- const start = i * passwordLen;
130
- result.set(password, start);
131
- }
132
-
133
- if (remainder > 0) {
134
- const start = repeats * passwordLen;
135
- result.set(password.slice(0, remainder), start);
136
- }
137
-
138
- return result;
139
- }
140
-
141
- shuffle(data, seed, step) {
142
- const rng = new SimpleRng(seed);
143
- const length = data.length;
144
-
145
- for (let i = length - 1; i > 0; i -= step) {
146
- const j = Math.floor(rng.genRange(0, i));
147
- [data[i], data[j]] = [data[j], data[i]];
148
- }
149
- }
150
-
151
- unshuffle(data, seed, step) {
152
- const rng = new SimpleRng(seed);
153
- const length = data.length;
154
- const swaps = [];
155
-
156
- for (let i = length - 1; i > 0; i -= step) {
157
- const j = Math.floor(rng.genRange(0, i));
158
- swaps.push([i, j]);
159
- }
160
-
161
- for (let k = swaps.length - 1; k >= 0; k--) {
162
- const [i, j] = swaps[k];
163
- [data[i], data[j]] = [data[j], data[i]];
164
- }
165
- }
166
-
167
- mix(blockSize, buf, key) {
168
- let prevBlock = new Uint8Array(key);
169
-
170
- for (let i = 0; i < buf.length; i += blockSize) {
171
- const blockEnd = Math.min(i + blockSize, buf.length);
172
- for (let j = 0; j < blockEnd - i && j < prevBlock.length; j++) {
173
- buf[i + j] ^= prevBlock[j];
174
- }
175
- prevBlock = new Uint8Array(buf.slice(i, blockEnd));
176
- }
177
- }
178
-
179
- unmix(blockSize, buf, key) {
180
- const blocks = [];
181
- for (let i = 0; i < buf.length; i += blockSize) {
182
- const end = Math.min(i + blockSize, buf.length);
183
- blocks.push(new Uint8Array(buf.slice(i, end)));
184
- }
185
-
186
- for (let i = blocks.length - 1; i >= 0; i--) {
187
- if (i === 0) {
188
- for (let j = 0; j < blocks[i].length && j < key.length; j++) {
189
- blocks[i][j] ^= key[j];
190
- }
191
- } else {
192
- for (let j = 0; j < blocks[i].length && j < blocks[i - 1].length; j++) {
193
- blocks[i][j] ^= blocks[i - 1][j];
194
- }
195
- }
196
- }
197
-
198
- let offset = 0;
199
- for (const block of blocks) {
200
- buf.set(block, offset);
201
- offset += block.length;
202
- }
203
- }
204
-
205
- getRandomBytes(length) {
206
- const rng = new SimpleRng(Date.now());
207
- return rng.getRandomBytes(length);
208
- }
209
-
210
- base64UrlEncode(data) {
211
- if (typeof Buffer !== 'undefined') {
212
- // Node.js
213
- return Buffer.from(data)
214
- .toString('base64')
215
- .replace(/\+/g, '-')
216
- .replace(/\//g, '_')
217
- .replace(/=+$/, '');
218
- } else {
219
- // Browser
220
- let binary = '';
221
- for (let i = 0; i < data.length; i++) {
222
- binary += String.fromCharCode(data[i]);
223
- }
224
- return btoa(binary)
225
- .replace(/\+/g, '-')
226
- .replace(/\//g, '_')
227
- .replace(/=+$/, '');
228
- }
229
- }
230
-
231
- base64UrlDecode(encoded) {
232
- let padded = encoded;
233
- const padding = encoded.length % 4;
234
- if (padding !== 0) {
235
- padded += '='.repeat(4 - padding);
236
- }
237
- const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
238
-
239
- if (typeof Buffer !== 'undefined') {
240
- // Node.js
241
- return new Uint8Array(Buffer.from(base64, 'base64'));
242
- } else {
243
- // Browser
244
- const binary = atob(base64);
245
- const bytes = new Uint8Array(binary.length);
246
- for (let i = 0; i < binary.length; i++) {
247
- bytes[i] = binary.charCodeAt(i);
248
- }
249
- return bytes;
250
- }
251
- }
252
-
253
- stringToBytes(str) {
254
- if (typeof TextEncoder !== 'undefined') {
255
- return new TextEncoder().encode(str);
256
- }
257
- if (typeof Buffer !== 'undefined') {
258
- return new Uint8Array(Buffer.from(str, 'utf-8'));
259
- }
260
- const bytes = new Uint8Array(str.length);
261
- for (let i = 0; i < str.length; i++) {
262
- bytes[i] = str.charCodeAt(i) & 0xFF;
263
- }
264
- return bytes;
265
- }
266
-
267
- bytesToString(bytes) {
268
- if (typeof TextDecoder !== 'undefined') {
269
- return new TextDecoder('utf-8').decode(bytes);
270
- }
271
- if (typeof Buffer !== 'undefined') {
272
- return Buffer.from(bytes).toString('utf-8');
273
- }
274
-
275
- let str = '';
276
- for (let i = 0; i < bytes.length; i++) {
277
- str += String.fromCharCode(bytes[i]);
278
- }
279
- return str;
280
- }
281
- }
@@ -1,52 +0,0 @@
1
- export default class SimpleRng {
2
- constructor(seed) {
3
- this.state = BigInt(seed) & 0xFFFFFFFFFFFFFFFFn;
4
- }
5
-
6
- static newWithTimeSeed() {
7
- return new SimpleRng(Date.now());
8
- }
9
-
10
- nextU32() {
11
- this.state = (this.state * 6364136223846793005n + 1442695040888963407n) & 0xFFFFFFFFFFFFFFFFn;
12
- return Number((this.state >> 32n) & 0xFFFFFFFFn);
13
- }
14
-
15
- nextU64() {
16
- const high = this.nextU32();
17
- const low = this.nextU32();
18
- return (high << 32) | low;
19
- }
20
-
21
- nextF64() {
22
- const val = this.nextU32();
23
- return val / 4294967295.0;
24
- }
25
-
26
- genRange(low, high) {
27
- return low + (high - low) * this.nextF64();
28
- }
29
-
30
- getRandomBytes(length) {
31
- const byteArray = new Uint8Array(length);
32
- const chunks = Math.floor(length / 4);
33
- const remainder = length % 4;
34
-
35
- for (let i = 0; i < chunks; i++) {
36
- const random = this.nextU32();
37
- byteArray[i * 4] = random & 0xFF;
38
- byteArray[i * 4 + 1] = (random >> 8) & 0xFF;
39
- byteArray[i * 4 + 2] = (random >> 16) & 0xFF;
40
- byteArray[i * 4 + 3] = (random >> 24) & 0xFF;
41
- }
42
-
43
- if (remainder > 0) {
44
- const random = this.nextU32();
45
- for (let i = 0; i < remainder; i++) {
46
- byteArray[chunks * 4 + i] = (random >> (i * 8)) & 0xFF;
47
- }
48
- }
49
-
50
- return byteArray;
51
- }
52
- }