@greypan/js-kit 1.1.1 → 1.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.
Files changed (50) hide show
  1. package/dist/fetch/index.d.ts +1 -0
  2. package/dist/timer/debounce.js +1 -1
  3. package/dist/url/index.js +1 -2
  4. package/dist/url/index.js.map +1 -1
  5. package/package.json +6 -4
  6. package/.turbo/turbo-build.log +0 -38
  7. package/.turbo/turbo-test.log +0 -30
  8. package/CHANGELOG.md +0 -13
  9. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/funnel.js +0 -40
  10. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/funnel.js.map +0 -1
  11. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/isNullish.js +0 -8
  12. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/isNullish.js.map +0 -1
  13. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/lazyDataLastImpl--3B10z3s.js +0 -12
  14. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/lazyDataLastImpl--3B10z3s.js.map +0 -1
  15. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/omitBy.js +0 -14
  16. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/omitBy.js.map +0 -1
  17. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/purry.js +0 -12
  18. package/dist/node_modules/.pnpm/remeda@2.39.0/node_modules/remeda/dist/purry.js.map +0 -1
  19. package/src/fetch/__tests__/compose.spec.ts +0 -105
  20. package/src/fetch/compose.ts +0 -23
  21. package/src/index.ts +0 -7
  22. package/src/number/__tests__/number.spec.ts +0 -50
  23. package/src/number/index.ts +0 -22
  24. package/src/paradigm/__tests__/go.spec.ts +0 -63
  25. package/src/paradigm/__tests__/rust.spec.ts +0 -68
  26. package/src/paradigm/go.ts +0 -38
  27. package/src/paradigm/index.ts +0 -2
  28. package/src/paradigm/rust.ts +0 -50
  29. package/src/plugin/__tests__/batch-emitter.spec.ts +0 -48
  30. package/src/plugin/__tests__/core.spec.ts +0 -110
  31. package/src/plugin/__tests__/event-emiiter.spec.ts +0 -41
  32. package/src/plugin/batching-emitter.ts +0 -61
  33. package/src/plugin/core.ts +0 -37
  34. package/src/plugin/event-emitter.ts +0 -24
  35. package/src/plugin/index.ts +0 -2
  36. package/src/random/__tests__/random.spec.ts +0 -77
  37. package/src/random/index.ts +0 -37
  38. package/src/timer/__tests__/controllable-interval.spec.ts +0 -51
  39. package/src/timer/controllable-interval.ts +0 -86
  40. package/src/timer/debounce.ts +0 -92
  41. package/src/timer/index.ts +0 -2
  42. package/src/url/README.md +0 -0
  43. package/src/url/__tests__/url.spec.ts +0 -152
  44. package/src/url/index.ts +0 -44
  45. package/src/utility-types/index.ts +0 -19
  46. package/tsconfig.app.json +0 -11
  47. package/tsconfig.json +0 -8
  48. package/tsconfig.node.json +0 -18
  49. package/tsconfig.vitest.json +0 -10
  50. package/vite.config.ts +0 -32
@@ -1,92 +0,0 @@
1
- /**
2
- * @description remeda debounce 废弃了,这是 remeda 官方提供的替代封装
3
- * @link https://github.com/remeda/remeda/blob/main/packages/remeda/src/funnel.remeda-debounce.test.ts#L10
4
- */
5
- import { funnel } from 'remeda'
6
-
7
- type StrictFunction = (...args: never) => unknown
8
- type Debouncer<F extends StrictFunction, IsNullable extends boolean = true> = {
9
- readonly call: (...args: Parameters<F>) => ReturnType<F> | (true extends IsNullable ? undefined : never)
10
- readonly cancel: () => void
11
- readonly flush: () => ReturnType<F> | undefined
12
- readonly isPending: boolean
13
- readonly cachedValue: ReturnType<F> | undefined
14
- }
15
-
16
- type DebounceOptions = {
17
- readonly waitMs?: number
18
- readonly maxWaitMs?: number
19
- }
20
-
21
- export function debounce<F extends StrictFunction>(
22
- func: F,
23
- options: DebounceOptions & { readonly timing?: 'trailing' }
24
- ): Debouncer<F>
25
- export function debounce<F extends StrictFunction>(
26
- func: F,
27
- options:
28
- | (DebounceOptions & { readonly timing: 'both' })
29
- | (Omit<DebounceOptions, 'maxWaitMs'> & { readonly timing: 'leading' })
30
- ): Debouncer<F, false /* call CAN'T return null */>
31
- export function debounce<F extends StrictFunction>(
32
- func: F,
33
- {
34
- timing,
35
- waitMs,
36
- maxWaitMs
37
- }: DebounceOptions & {
38
- readonly timing?: 'both' | 'leading' | 'trailing'
39
- }
40
- ) {
41
- if (maxWaitMs !== undefined && waitMs !== undefined && maxWaitMs < waitMs) {
42
- throw new Error(`debounce: maxWaitMs (${maxWaitMs.toString()}) cannot be less than waitMs (${waitMs.toString()})`)
43
- }
44
-
45
- let cachedValue: ReturnType<F> | undefined
46
-
47
- const debouncingFunnel = funnel(
48
- (args: Parameters<F>) => {
49
- // Every time the function is invoked the cached value is updated.
50
- // @ts-expect-error [ts2345, ts2322] -- TypeScript infers the generic sub-
51
- // types too eagerly, making itself blind to the fact that the types
52
- // match here.
53
- cachedValue = func(...args)
54
- },
55
- {
56
- // Debounce stores the latest args it was called with for the next
57
- // invocation of the callback.
58
- reducer: (_, ...args: Parameters<F>) => args,
59
- minQuietPeriodMs: waitMs ?? maxWaitMs ?? 0,
60
- ...(maxWaitMs !== undefined && { maxBurstDurationMs: maxWaitMs }),
61
- ...(timing === 'leading'
62
- ? { triggerAt: 'start' }
63
- : timing === 'both'
64
- ? { triggerAt: 'both' }
65
- : { triggerAt: 'end' })
66
- }
67
- )
68
-
69
- return {
70
- call: (...args: Parameters<F>) => {
71
- debouncingFunnel.call(...args)
72
- return cachedValue
73
- },
74
-
75
- flush: () => {
76
- debouncingFunnel.flush()
77
- return cachedValue
78
- },
79
-
80
- cancel: () => {
81
- debouncingFunnel.cancel()
82
- },
83
-
84
- get isPending() {
85
- return !debouncingFunnel.isIdle
86
- },
87
-
88
- get cachedValue() {
89
- return cachedValue
90
- }
91
- }
92
- }
@@ -1,2 +0,0 @@
1
- export * from './controllable-interval'
2
- export * from './debounce'
package/src/url/README.md DELETED
File without changes
@@ -1,152 +0,0 @@
1
- import { describe, expect, it } from 'vite-plus/test'
2
-
3
- import { urlParse, urlStringify } from '..'
4
-
5
- describe('url 单元测试', () => {
6
- describe('urlParse 测试', () => {
7
- it('应当能够解析带 Hash 的 URL', () => {
8
- expect(urlParse('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#specifications')).toEqual({
9
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL',
10
- query: {},
11
- hash: '#specifications'
12
- })
13
- expect(urlParse('https://www.deepl.com/en/translator#en/zh/placeholder')).toEqual({
14
- base: 'https://www.deepl.com/en/translator',
15
- query: {},
16
- hash: '#en/zh/placeholder'
17
- })
18
- })
19
-
20
- it('应当能够解析带 Query 参数的 URL', () => {
21
- expect(urlParse('https://segmentfault.com/search?q=xyz&w=123&e=aaa')).toEqual({
22
- base: 'https://segmentfault.com/search',
23
- query: {
24
- q: 'xyz',
25
- w: '123',
26
- e: 'aaa'
27
- },
28
- hash: ''
29
- })
30
- })
31
-
32
- it('应当能够解析仅包含路径(相对路径)的 URL', () => {
33
- expect(urlParse('/search?q=xyz&w=123&e=aaa#heading-1')).toEqual({
34
- base: '/search',
35
- query: {
36
- q: 'xyz',
37
- w: '123',
38
- e: 'aaa'
39
- },
40
- hash: '#heading-1'
41
- })
42
- })
43
-
44
- it('应当能够对 Query 参数进行自动解码 (decode)', () => {
45
- expect(
46
- urlParse('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL?%E9%94%AE1=%E5%80%BC1&%E9%94%AE2=%E5%80%BC2')
47
- ).toEqual({
48
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL',
49
- query: {
50
- 键1: '值1',
51
- 键2: '值2'
52
- },
53
- hash: ''
54
- })
55
- })
56
- })
57
-
58
- describe('urlStringify 测试', () => {
59
- it('应当能够处理可选的参数成员 (仅 base、base+query、base+hash)', () => {
60
- expect(
61
- urlStringify({
62
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL'
63
- })
64
- ).toBe('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL')
65
-
66
- expect(
67
- urlStringify({
68
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL',
69
- query: {
70
- q: 'xyz',
71
- w: '123',
72
- e: 'aaa'
73
- }
74
- })
75
- ).toBe('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL?q=xyz&w=123&e=aaa')
76
-
77
- expect(
78
- urlStringify({
79
- base: 'https://www.deepl.com/en/translator',
80
- hash: '#en/zh/placeholder'
81
- })
82
- ).toBe('https://www.deepl.com/en/translator#en/zh/placeholder')
83
- })
84
-
85
- it('应当能够完整序列化包含 base, query 和 hash 的对象', () => {
86
- expect(
87
- urlStringify({
88
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL',
89
- query: {
90
- q: 'xyz',
91
- w: '123',
92
- e: 'aaa'
93
- },
94
- hash: '#specifications'
95
- })
96
- ).toBe('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL?q=xyz&w=123&e=aaa#specifications')
97
- })
98
-
99
- it('应当能够对 Query 参数进行自动编码 (encode)', () => {
100
- expect(
101
- urlStringify({
102
- base: 'https://developer.mozilla.org/en-US/docs/Web/API/URL/URL',
103
- query: {
104
- 键1: '值1',
105
- 键2: '值2'
106
- },
107
- hash: ''
108
- })
109
- ).toBe('https://developer.mozilla.org/en-US/docs/Web/API/URL/URL?%E9%94%AE1=%E5%80%BC1&%E9%94%AE2=%E5%80%BC2')
110
- })
111
- })
112
-
113
- describe('urlParse|urlStringify 边缘情况与容错测试', () => {
114
- it('urlParse: 应当按照 URL 标准处理纯净 URL (自动补全根路径斜杠)', () => {
115
- const res = urlParse('https://google.com')
116
- expect(res.base).toBe('https://google.com/')
117
- })
118
-
119
- it('urlParse: 应当处理 Query 只有键没有值的情况', () => {
120
- const res = urlParse('https://test.com?debug&source=web')
121
- expect(res.base).toBe('https://test.com/')
122
- expect(res.query).toEqual({
123
- debug: '',
124
- source: 'web'
125
- })
126
- })
127
-
128
- it('urlParse: 重复键应当采用“覆盖”策略(保留最后一个)', () => {
129
- const url = 'https://test.com?id=1&id=2&id=3'
130
- const res = urlParse(url)
131
- expect(res.query).toEqual({ id: '3' })
132
- })
133
-
134
- it('urlStringify: 应当处理 Hash 不带 # 前缀的情况 (自动补全)', () => {
135
- expect(
136
- urlStringify({
137
- base: 'https://test.com/',
138
- hash: 'section1'
139
- })
140
- ).toBe('https://test.com/#section1')
141
- })
142
-
143
- it('urlStringify: 应当能正确处理带斜杠的标准 base', () => {
144
- expect(
145
- urlStringify({
146
- base: 'https://test.com/',
147
- query: { a: 1 }
148
- })
149
- ).toBe('https://test.com/?a=1')
150
- })
151
- })
152
- })
package/src/url/index.ts DELETED
@@ -1,44 +0,0 @@
1
- import { isNullish, omitBy } from 'remeda'
2
-
3
- type QueryValue = string | number | boolean | undefined | null
4
- interface URLObject {
5
- base: string
6
- query: Record<string, QueryValue>
7
- hash: string
8
- }
9
-
10
- export function urlParse(url = ''): URLObject {
11
- const isRelative = !/^(https?:)?\/\//.test(url)
12
-
13
- try {
14
- // 如果 url 是相对路径,就借用 http://n.n 作为 base
15
- const parsed = new URL(url, isRelative ? 'http://n.n' : undefined)
16
-
17
- return {
18
- base: isRelative ? parsed.pathname : `${parsed.origin}${parsed.pathname}`,
19
- query: Object.fromEntries(parsed.searchParams),
20
- hash: parsed.hash
21
- }
22
- } catch {
23
- throw new Error('Invalid URL.')
24
- }
25
- }
26
-
27
- export function urlStringify(opts: Partial<URLObject>, omitNil = true): string {
28
- const { base = '', query = {}, hash = '' } = opts
29
-
30
- const cleanQuery = omitNil ? omitBy(query, isNullish) : query
31
- const params = new URLSearchParams()
32
-
33
- Object.entries(cleanQuery).forEach(([key, val]) => {
34
- params.append(key, String(val))
35
- })
36
-
37
- // 修复 Hash 自动补全 # 的问题
38
- const normalizedHash = hash ? (hash.startsWith('#') ? hash : `#${hash}`) : ''
39
- const queryString = params.toString()
40
- if (!queryString) return base + normalizedHash
41
-
42
- const connector = base.includes('?') ? '&' : '?'
43
- return `${base}${connector}${queryString}${normalizedHash}`
44
- }
@@ -1,19 +0,0 @@
1
- export type ValueOf<T> = T[keyof T]
2
-
3
- export type ArrayItem<T extends unknown[]> = T extends (infer R)[] ? R : never
4
-
5
- export type ArgumentType<T> = T extends (...args: (infer R)[]) => unknown ? R : never
6
-
7
- export type DeepPartial<T> = Partial<{
8
- [K in keyof T]: DeepPartial<T[K]>
9
- }>
10
-
11
- export type DeepRequired<T> = Required<{
12
- [K in keyof T]: DeepRequired<T[K]>
13
- }>
14
-
15
- export type ClassPropertyTypes<T> = {
16
- [K in keyof T]: T[K]
17
- }
18
-
19
- export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
package/tsconfig.app.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "paths": {
4
- "@/*": ["./src/*"]
5
- },
6
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
7
- },
8
- "exclude": ["src/**/__tests__"],
9
- "extends": "@vue/tsconfig/tsconfig.dom.json",
10
- "include": ["src/**/*"]
11
- }
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.node.json" },
5
- { "path": "./tsconfig.app.json" },
6
- { "path": "./tsconfig.vitest.json" }
7
- ]
8
- }
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "module": "ESNext",
4
- "moduleResolution": "Bundler",
5
- "noEmit": true,
6
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
7
- "types": ["node"]
8
- },
9
- "extends": "@tsconfig/node24/tsconfig.json",
10
- "include": [
11
- "vite.config.*",
12
- "vitest.config.*",
13
- "cypress.config.*",
14
- "nightwatch.conf.*",
15
- "playwright.config.*",
16
- "eslint.config.*"
17
- ]
18
- }
@@ -1,10 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "lib": [],
4
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo",
5
- "types": ["node", "jsdom"]
6
- },
7
- "exclude": [],
8
- "extends": "./tsconfig.app.json",
9
- "include": ["src/**/__tests__"]
10
- }
package/vite.config.ts DELETED
@@ -1,32 +0,0 @@
1
- import { resolve } from 'node:path'
2
-
3
- import dts from 'vite-plugin-dts'
4
- import { type UserConfig } from 'vite-plus'
5
-
6
- export default {
7
- resolve: {
8
- tsconfigPaths: true
9
- },
10
- plugins: [
11
- dts({
12
- tsconfigPath: './tsconfig.app.json'
13
- })
14
- ],
15
- build: {
16
- sourcemap: true,
17
- lib: {
18
- entry: resolve(import.meta.dirname, 'src/index.ts'),
19
- formats: ['es']
20
- },
21
- rollupOptions: {
22
- external: [],
23
- output: {
24
- preserveModules: true,
25
- // 指定源码根目录,这样 dist 下就不会多出一层 'src' 目录
26
- preserveModulesRoot: 'src',
27
- dir: 'dist',
28
- entryFileNames: '[name].js'
29
- }
30
- }
31
- }
32
- } satisfies UserConfig