@pro-acc/pos-core 0.0.1 → 0.0.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/README.md +3 -1
- package/app/repository/factory.ts +121 -35
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Pro-Acc POS/Restoran ortak Nuxt 4 katmanı. UI uygulaması ve veritabanı bu paketten bağımsızdır; tüketici kendi Prisma istemcisini, server/service sınıflarını ve API plugin'ini sağlar.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
pnpm add @pro-acc/ui@0.0.2 @pro-acc/pos-core@0.0.
|
|
6
|
+
pnpm add @pro-acc/ui@0.0.2 @pro-acc/pos-core@0.0.2
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
POS/Restoran Nuxt yapılandırması extends: ["@pro-acc/pos-core"] kullanır. Bu katman @pro-acc/ui modülünü pos:true ile kaydeder. Paylaşılan route'lar hizmetleri tüketici kökü üzerinden (~~/server/service) çağırır; uygulama override davranışı korunur.
|
|
@@ -12,4 +12,6 @@ Yalnız HTTP güvenliği ve güncelleme kontrolü isteyen uygulama extends: ["@p
|
|
|
12
12
|
|
|
13
13
|
UI bileşenleri/store'ları yalnız @pro-acc/ui paketinde tanımlıdır. Bu paket ortak sayfalar, repository modülleri ve Nitro servis/API kodunu tutar. Hesap/DB anahtarları tüketici runtimeConfig ile sağlanır.
|
|
14
14
|
|
|
15
|
+
CRUD factory 0.0.2 ile aynı Nuxt fetcher'ındaki eşzamanlı, eşit GET sorgularını birleştirir. Tamamlanan yanıtlar önbellekte tutulmaz; mutasyon eski uçuşları geçersizleştirir. Özel headers/signal/hook taşıyan istekler paylaşılmaz. Farklı fetcher/Nuxt örnekleri birbirinden izoledir. Main aynı factory'yi `@pro-acc/pos-core/app/repository/factory` export'undan kullanabilir.
|
|
16
|
+
|
|
15
17
|
[GitHub kaynakları](https://github.com/olcan123/pro-acc-packages/tree/main/packages/pos-core) · [npm](https://www.npmjs.com/package/@pro-acc/pos-core)
|
|
@@ -1,35 +1,121 @@
|
|
|
1
|
-
// factory.ts — Frontend API modülleri için generic temel CRUD sınıfı (main deseni).
|
|
2
|
-
import type { $Fetch, FetchOptions } from "ofetch";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
1
|
+
// factory.ts — Frontend API modülleri için generic temel CRUD sınıfı (main deseni).
|
|
2
|
+
import type { $Fetch, FetchOptions } from "ofetch";
|
|
3
|
+
|
|
4
|
+
const coalescers = new WeakMap<$Fetch, $Fetch>();
|
|
5
|
+
|
|
6
|
+
/** Yalnız sade JSON sorgularını kararlı anahtara çevirir; sinyal/özel başlıklar paylaşılmaz. */
|
|
7
|
+
export function readRequestKey(
|
|
8
|
+
resource: unknown,
|
|
9
|
+
options: Record<string, any> = {},
|
|
10
|
+
): string | undefined {
|
|
11
|
+
if (
|
|
12
|
+
typeof resource !== "string" ||
|
|
13
|
+
Object.keys(options).some((key) => !["method", "query", "params"].includes(key))
|
|
14
|
+
)
|
|
15
|
+
return;
|
|
16
|
+
if (String(options.method || "GET").toUpperCase() !== "GET") return;
|
|
17
|
+
const seen = new Set<object>();
|
|
18
|
+
const normalize = (value: any): any => {
|
|
19
|
+
if (value === null || ["string", "boolean", "undefined"].includes(typeof value)) return value;
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
21
|
+
if (value instanceof Date) return value.toISOString();
|
|
22
|
+
if (!value || typeof value !== "object" || seen.has(value))
|
|
23
|
+
throw new Error("Paylaşılmayan sorgu");
|
|
24
|
+
seen.add(value);
|
|
25
|
+
try {
|
|
26
|
+
if (Array.isArray(value)) return value.map(normalize);
|
|
27
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) throw new Error("Özel sorgu nesnesi");
|
|
28
|
+
return Object.fromEntries(
|
|
29
|
+
Object.keys(value)
|
|
30
|
+
.sort()
|
|
31
|
+
.map((key) => [key, normalize(value[key])]),
|
|
32
|
+
);
|
|
33
|
+
} finally {
|
|
34
|
+
seen.delete(value);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
return JSON.stringify([resource, normalize(options.query), normalize(options.params)]);
|
|
39
|
+
} catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Sadece uçuşta olan GET'leri fetcher/Nuxt örneği içinde paylaşır; tamamlanan veri saklanmaz. */
|
|
45
|
+
function coalesceReads(fetcher: $Fetch): $Fetch {
|
|
46
|
+
const existing = coalescers.get(fetcher);
|
|
47
|
+
if (existing) return existing;
|
|
48
|
+
const pending = new Map<string, Promise<any>>();
|
|
49
|
+
const wrapped = new Proxy(fetcher, {
|
|
50
|
+
apply(target, receiver, args) {
|
|
51
|
+
const [resource, options = {}] = args;
|
|
52
|
+
const method = String(options.method || "GET").toUpperCase();
|
|
53
|
+
if (!["GET", "HEAD", "OPTIONS"].includes(method)) {
|
|
54
|
+
pending.clear();
|
|
55
|
+
try {
|
|
56
|
+
return Promise.resolve(Reflect.apply(target, receiver, args)).finally(() =>
|
|
57
|
+
pending.clear(),
|
|
58
|
+
);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
pending.clear();
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const key = readRequestKey(resource, options);
|
|
65
|
+
if (key === undefined) return Reflect.apply(target, receiver, args);
|
|
66
|
+
const inFlight = pending.get(key);
|
|
67
|
+
// İki tüketicinin JSON sonucunu yerelde değiştirmesi birbirini etkilemez.
|
|
68
|
+
if (inFlight) return inFlight.then((value) => structuredClone(value));
|
|
69
|
+
const request = Promise.resolve(Reflect.apply(target, receiver, args)).finally(() => {
|
|
70
|
+
if (pending.get(key) === request) pending.delete(key);
|
|
71
|
+
});
|
|
72
|
+
pending.set(key, request);
|
|
73
|
+
return request;
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
coalescers.set(fetcher, wrapped);
|
|
77
|
+
coalescers.set(wrapped, wrapped);
|
|
78
|
+
return wrapped;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default class FetchFactory<T> {
|
|
82
|
+
private $fetch: $Fetch;
|
|
83
|
+
|
|
84
|
+
constructor(fetcher: $Fetch) {
|
|
85
|
+
this.$fetch = coalesceReads(fetcher);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Liste (GET). */
|
|
89
|
+
async getAll(resource: string, options?: FetchOptions<"json">): Promise<T[]> {
|
|
90
|
+
return this.$fetch<T[]>(resource, { method: "GET", ...options });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Tekil (GET /:id). */
|
|
94
|
+
async getById(resource: string, id: number | string, options?: FetchOptions<"json">): Promise<T> {
|
|
95
|
+
return this.$fetch<T>(`${resource}/${id}`, { method: "GET", ...options });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Oluştur (POST). */
|
|
99
|
+
async create(resource: string, data: any, options?: FetchOptions<"json">): Promise<T> {
|
|
100
|
+
return this.$fetch<T>(resource, { method: "POST", body: data, ...options });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Güncelle (PUT /:id). */
|
|
104
|
+
async update(
|
|
105
|
+
resource: string,
|
|
106
|
+
id: number | string,
|
|
107
|
+
data: any,
|
|
108
|
+
options?: FetchOptions<"json">,
|
|
109
|
+
): Promise<T> {
|
|
110
|
+
return this.$fetch<T>(`${resource}/${id}`, { method: "PUT", body: data, ...options });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Sil (DELETE /:id). */
|
|
114
|
+
async remove(
|
|
115
|
+
resource: string,
|
|
116
|
+
id: number | string,
|
|
117
|
+
options?: FetchOptions<"json">,
|
|
118
|
+
): Promise<void> {
|
|
119
|
+
return this.$fetch<void>(`${resource}/${id}`, { method: "DELETE", ...options });
|
|
120
|
+
}
|
|
121
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pro-acc/pos-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Pro-Acc POS/Restoran ortak Nuxt sayfa, API, servis ve güvenlik katmanı",
|
|
5
5
|
"homepage": "https://github.com/olcan123/pro-acc-packages/tree/main/packages/pos-core#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"registry": "https://registry.npmjs.org/"
|
|
188
188
|
},
|
|
189
189
|
"scripts": {
|
|
190
|
-
"test": "node --test tests
|
|
190
|
+
"test": "node --test tests/*.test.mjs"
|
|
191
191
|
},
|
|
192
192
|
"dependencies": {
|
|
193
193
|
"@pro-acc/ui": "0.0.2",
|