@stratasync/core 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.
- package/README.md +83 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/model/base-model.d.ts +82 -0
- package/dist/model/base-model.d.ts.map +1 -0
- package/dist/model/base-model.js +219 -0
- package/dist/model/base-model.js.map +1 -0
- package/dist/model/cached-promise.d.ts +15 -0
- package/dist/model/cached-promise.d.ts.map +1 -0
- package/dist/model/cached-promise.js +50 -0
- package/dist/model/cached-promise.js.map +1 -0
- package/dist/model/collection.d.ts +33 -0
- package/dist/model/collection.d.ts.map +1 -0
- package/dist/model/collection.js +181 -0
- package/dist/model/collection.js.map +1 -0
- package/dist/model/hydration.d.ts +13 -0
- package/dist/model/hydration.d.ts.map +1 -0
- package/dist/model/hydration.js +2 -0
- package/dist/model/hydration.js.map +1 -0
- package/dist/model/observability.d.ts +23 -0
- package/dist/model/observability.d.ts.map +1 -0
- package/dist/model/observability.js +162 -0
- package/dist/model/observability.js.map +1 -0
- package/dist/reactivity/adapter.d.ts +145 -0
- package/dist/reactivity/adapter.d.ts.map +1 -0
- package/dist/reactivity/adapter.js +95 -0
- package/dist/reactivity/adapter.js.map +1 -0
- package/dist/schema/decorators.d.ts +8 -0
- package/dist/schema/decorators.d.ts.map +1 -0
- package/dist/schema/decorators.js +117 -0
- package/dist/schema/decorators.js.map +1 -0
- package/dist/schema/hash.d.ts +6 -0
- package/dist/schema/hash.d.ts.map +1 -0
- package/dist/schema/hash.js +76 -0
- package/dist/schema/hash.js.map +1 -0
- package/dist/schema/normalize.d.ts +5 -0
- package/dist/schema/normalize.d.ts.map +1 -0
- package/dist/schema/normalize.js +194 -0
- package/dist/schema/normalize.js.map +1 -0
- package/dist/schema/registry.d.ts +147 -0
- package/dist/schema/registry.d.ts.map +1 -0
- package/dist/schema/registry.js +304 -0
- package/dist/schema/registry.js.map +1 -0
- package/dist/schema/types.d.ts +215 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/store/types.d.ts +14 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +2 -0
- package/dist/store/types.js.map +1 -0
- package/dist/sync/delta-applier.d.ts +52 -0
- package/dist/sync/delta-applier.d.ts.map +1 -0
- package/dist/sync/delta-applier.js +110 -0
- package/dist/sync/delta-applier.js.map +1 -0
- package/dist/sync/rebase.d.ts +57 -0
- package/dist/sync/rebase.d.ts.map +1 -0
- package/dist/sync/rebase.js +155 -0
- package/dist/sync/rebase.js.map +1 -0
- package/dist/sync/sync-id.d.ts +17 -0
- package/dist/sync/sync-id.d.ts.map +1 -0
- package/dist/sync/sync-id.js +26 -0
- package/dist/sync/sync-id.js.map +1 -0
- package/dist/sync/types.d.ts +152 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +2 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/transaction/archive.d.ts +16 -0
- package/dist/transaction/archive.d.ts.map +1 -0
- package/dist/transaction/archive.js +23 -0
- package/dist/transaction/archive.js.map +1 -0
- package/dist/transaction/create.d.ts +31 -0
- package/dist/transaction/create.d.ts.map +1 -0
- package/dist/transaction/create.js +121 -0
- package/dist/transaction/create.js.map +1 -0
- package/dist/transaction/types.d.ts +86 -0
- package/dist/transaction/types.d.ts.map +1 -0
- package/dist/transaction/types.js +2 -0
- package/dist/transaction/types.js.map +1 -0
- package/dist/utils/assign.d.ts +9 -0
- package/dist/utils/assign.d.ts.map +1 -0
- package/dist/utils/assign.js +20 -0
- package/dist/utils/assign.js.map +1 -0
- package/dist/utils/idempotency.d.ts +16 -0
- package/dist/utils/idempotency.d.ts.map +1 -0
- package/dist/utils/idempotency.js +39 -0
- package/dist/utils/idempotency.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { generateClientTxId } from "../utils/idempotency.js";
|
|
2
|
+
import { captureArchiveState, createArchivePayload, createUnarchivePatch, createUnarchivePayload, readArchivedAt, } from "./archive.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new transaction with a unique client transaction ID
|
|
5
|
+
*/
|
|
6
|
+
const createTransaction = (options) => {
|
|
7
|
+
const tx = {
|
|
8
|
+
action: options.action,
|
|
9
|
+
clientId: options.clientId,
|
|
10
|
+
clientTxId: generateClientTxId(),
|
|
11
|
+
createdAt: Date.now(),
|
|
12
|
+
modelId: options.modelId,
|
|
13
|
+
modelName: options.modelName,
|
|
14
|
+
payload: options.payload,
|
|
15
|
+
retryCount: 0,
|
|
16
|
+
state: "queued",
|
|
17
|
+
};
|
|
18
|
+
if (options.original !== undefined) {
|
|
19
|
+
tx.original = options.original;
|
|
20
|
+
}
|
|
21
|
+
return tx;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Creates a transaction batch from an array of transactions
|
|
25
|
+
*/
|
|
26
|
+
export const createTransactionBatch = (transactions) => ({
|
|
27
|
+
batchId: generateClientTxId(),
|
|
28
|
+
createdAt: Date.now(),
|
|
29
|
+
transactions,
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Creates an INSERT transaction for a new model instance
|
|
33
|
+
*/
|
|
34
|
+
export const createInsertTransaction = (clientId, modelName, modelId, data) => createTransaction({
|
|
35
|
+
action: "I",
|
|
36
|
+
clientId,
|
|
37
|
+
modelId,
|
|
38
|
+
modelName,
|
|
39
|
+
payload: data,
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Creates an UPDATE transaction for an existing model instance
|
|
43
|
+
*/
|
|
44
|
+
export const createUpdateTransaction = (clientId, modelName, modelId, changes, original) => createTransaction({
|
|
45
|
+
action: "U",
|
|
46
|
+
clientId,
|
|
47
|
+
modelId,
|
|
48
|
+
modelName,
|
|
49
|
+
original,
|
|
50
|
+
payload: changes,
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* Creates a DELETE transaction for removing a model instance
|
|
54
|
+
*/
|
|
55
|
+
export const createDeleteTransaction = (clientId, modelName, modelId, original) => createTransaction({
|
|
56
|
+
action: "D",
|
|
57
|
+
clientId,
|
|
58
|
+
modelId,
|
|
59
|
+
modelName,
|
|
60
|
+
original,
|
|
61
|
+
payload: { ...original },
|
|
62
|
+
});
|
|
63
|
+
/**
|
|
64
|
+
* Creates an ARCHIVE transaction for soft-deleting a model instance
|
|
65
|
+
*/
|
|
66
|
+
export const createArchiveTransaction = (clientId, modelName, modelId, options = {}) => createTransaction({
|
|
67
|
+
action: "A",
|
|
68
|
+
clientId,
|
|
69
|
+
modelId,
|
|
70
|
+
modelName,
|
|
71
|
+
original: options.original,
|
|
72
|
+
payload: createArchivePayload(options.archivedAt),
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Creates an UNARCHIVE transaction for restoring a soft-deleted model instance
|
|
76
|
+
*/
|
|
77
|
+
export const createUnarchiveTransaction = (clientId, modelName, modelId, options = {}) => createTransaction({
|
|
78
|
+
action: "V",
|
|
79
|
+
clientId,
|
|
80
|
+
modelId,
|
|
81
|
+
modelName,
|
|
82
|
+
original: options.original,
|
|
83
|
+
payload: createUnarchivePayload(),
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* Creates an undo transaction for a given transaction.
|
|
87
|
+
*/
|
|
88
|
+
export const createUndoTransaction = (tx, clientId = tx.clientId) => {
|
|
89
|
+
switch (tx.action) {
|
|
90
|
+
case "I": {
|
|
91
|
+
return createDeleteTransaction(clientId, tx.modelName, tx.modelId, tx.payload);
|
|
92
|
+
}
|
|
93
|
+
case "D": {
|
|
94
|
+
if (!tx.original) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return createInsertTransaction(clientId, tx.modelName, tx.modelId, tx.original);
|
|
98
|
+
}
|
|
99
|
+
case "U": {
|
|
100
|
+
if (!tx.original) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
return createUpdateTransaction(clientId, tx.modelName, tx.modelId, tx.original, tx.payload);
|
|
104
|
+
}
|
|
105
|
+
case "A": {
|
|
106
|
+
return createUnarchiveTransaction(clientId, tx.modelName, tx.modelId, {
|
|
107
|
+
original: captureArchiveState(tx.payload),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
case "V": {
|
|
111
|
+
return createArchiveTransaction(clientId, tx.modelName, tx.modelId, {
|
|
112
|
+
archivedAt: readArchivedAt(tx.original),
|
|
113
|
+
original: createUnarchivePatch(),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
default: {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/transaction/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { TransactionAction } from "../schema/types.js";
|
|
2
|
+
import type { SyncId } from "../sync/sync-id.js";
|
|
3
|
+
/**
|
|
4
|
+
* State of a transaction in the sync pipeline
|
|
5
|
+
*/
|
|
6
|
+
export type TransactionState = "queued" | "sent" | "awaitingSync" | "completed" | "failed";
|
|
7
|
+
/**
|
|
8
|
+
* A single transaction representing a local mutation
|
|
9
|
+
*/
|
|
10
|
+
export interface Transaction {
|
|
11
|
+
/** Unique ID generated by the client for idempotency */
|
|
12
|
+
clientTxId: string;
|
|
13
|
+
/** Client instance identifier */
|
|
14
|
+
clientId: string;
|
|
15
|
+
/** Name of the model being mutated */
|
|
16
|
+
modelName: string;
|
|
17
|
+
/** ID of the model instance */
|
|
18
|
+
modelId: string;
|
|
19
|
+
/** Type of mutation */
|
|
20
|
+
action: TransactionAction;
|
|
21
|
+
/** New/changed data for the mutation */
|
|
22
|
+
payload: Record<string, unknown>;
|
|
23
|
+
/** Original data before mutation (for rollback) */
|
|
24
|
+
original?: Record<string, unknown>;
|
|
25
|
+
/** Current state in the sync pipeline */
|
|
26
|
+
state: TransactionState;
|
|
27
|
+
/** Timestamp when transaction was created */
|
|
28
|
+
createdAt: number;
|
|
29
|
+
/** Number of retry attempts */
|
|
30
|
+
retryCount: number;
|
|
31
|
+
/** Last error message if failed */
|
|
32
|
+
lastError?: string;
|
|
33
|
+
/** Sync ID required before the transaction is considered complete */
|
|
34
|
+
syncIdNeededForCompletion?: SyncId;
|
|
35
|
+
/** Batch index used for grouping transactions */
|
|
36
|
+
batchIndex?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A batch of transactions to send to the server
|
|
40
|
+
*/
|
|
41
|
+
export interface TransactionBatch {
|
|
42
|
+
/** Unique ID for the batch */
|
|
43
|
+
batchId: string;
|
|
44
|
+
/** Transactions in the batch */
|
|
45
|
+
transactions: Transaction[];
|
|
46
|
+
/** Timestamp when batch was created */
|
|
47
|
+
createdAt: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Result of a single transaction from the server
|
|
51
|
+
*/
|
|
52
|
+
export interface TransactionResult {
|
|
53
|
+
/** Client transaction ID */
|
|
54
|
+
clientTxId: string;
|
|
55
|
+
/** Whether the transaction succeeded */
|
|
56
|
+
success: boolean;
|
|
57
|
+
/** Assigned sync ID if successful */
|
|
58
|
+
syncId?: SyncId;
|
|
59
|
+
/** Error message if failed */
|
|
60
|
+
error?: string;
|
|
61
|
+
/** Error code if failed */
|
|
62
|
+
errorCode?: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Result of a batch mutation from the server
|
|
66
|
+
*/
|
|
67
|
+
export interface MutateResult {
|
|
68
|
+
/** Whether the overall batch succeeded */
|
|
69
|
+
success: boolean;
|
|
70
|
+
/** Highest sync ID after mutations */
|
|
71
|
+
lastSyncId: SyncId;
|
|
72
|
+
/** Results for each transaction */
|
|
73
|
+
results: TransactionResult[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Options for creating a transaction
|
|
77
|
+
*/
|
|
78
|
+
export interface CreateTransactionOptions {
|
|
79
|
+
clientId: string;
|
|
80
|
+
modelName: string;
|
|
81
|
+
modelId: string;
|
|
82
|
+
action: TransactionAction;
|
|
83
|
+
payload: Record<string, unknown>;
|
|
84
|
+
original?: Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transaction/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAExB,QAAQ,GAER,MAAM,GAEN,cAAc,GAEd,WAAW,GAEX,QAAQ,CAAC;AAEb;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,yCAAyC;IACzC,KAAK,EAAE,gBAAgB,CAAC;IACxB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transaction/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assigns a value to a target property only if the value is not undefined.
|
|
3
|
+
*/
|
|
4
|
+
export declare const assignIfDefined: <T, K extends keyof T>(target: T, key: K, value: T[K] | undefined) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Copies multiple optional fields from source to target, skipping undefined values.
|
|
7
|
+
*/
|
|
8
|
+
export declare const assignOptionalFields: <T, S>(target: T, source: S, keys: (keyof T & keyof S)[]) => void;
|
|
9
|
+
//# sourceMappingURL=assign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign.d.ts","sourceRoot":"","sources":["../../src/utils/assign.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAClD,QAAQ,CAAC,EACT,KAAK,CAAC,EACN,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,KACtB,IAIF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,CAAC,EAAE,CAAC,EACvC,QAAQ,CAAC,EACT,QAAQ,CAAC,EACT,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,KAC1B,IAOF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assigns a value to a target property only if the value is not undefined.
|
|
3
|
+
*/
|
|
4
|
+
export const assignIfDefined = (target, key, value) => {
|
|
5
|
+
if (value !== undefined) {
|
|
6
|
+
target[key] = value;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Copies multiple optional fields from source to target, skipping undefined values.
|
|
11
|
+
*/
|
|
12
|
+
export const assignOptionalFields = (target, source, keys) => {
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
const value = source[key];
|
|
15
|
+
if (value !== undefined) {
|
|
16
|
+
target[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=assign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign.js","sourceRoot":"","sources":["../../src/utils/assign.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,MAAS,EACT,GAAM,EACN,KAAuB,EACjB,EAAE;IACR,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACtB,CAAC;AACH,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAAS,EACT,MAAS,EACT,IAA2B,EACrB,EAAE;IACR,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACvB,MAAkC,CAAC,GAAa,CAAC,GAAG,KAAK,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a UUID v4
|
|
3
|
+
* Uses crypto.randomUUID when available, falls back to manual generation
|
|
4
|
+
*/
|
|
5
|
+
export declare const generateUUID: () => string;
|
|
6
|
+
/**
|
|
7
|
+
* Generates a unique client ID for this browser/device instance
|
|
8
|
+
* Persisted in localStorage to maintain consistency across sessions
|
|
9
|
+
*/
|
|
10
|
+
export declare const getOrCreateClientId: (storageKey?: string) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Generates a unique transaction ID
|
|
13
|
+
* Uses UUID v4 format for guaranteed uniqueness
|
|
14
|
+
*/
|
|
15
|
+
export declare const generateClientTxId: () => string;
|
|
16
|
+
//# sourceMappingURL=idempotency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/utils/idempotency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,MAa/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,mBAA6B,KAAG,MAmBnE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAAwB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a UUID v4
|
|
3
|
+
* Uses crypto.randomUUID when available, falls back to manual generation
|
|
4
|
+
*/
|
|
5
|
+
export const generateUUID = () => {
|
|
6
|
+
const cryptoRef = globalThis
|
|
7
|
+
.crypto;
|
|
8
|
+
if (cryptoRef?.randomUUID) {
|
|
9
|
+
return cryptoRef.randomUUID();
|
|
10
|
+
}
|
|
11
|
+
// Fallback implementation
|
|
12
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replaceAll(/[xy]/g, (c) => {
|
|
13
|
+
const r = Math.floor(Math.random() * 16);
|
|
14
|
+
const v = c === "x" ? r : (r % 4) + 8;
|
|
15
|
+
return v.toString(16);
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Generates a unique client ID for this browser/device instance
|
|
20
|
+
* Persisted in localStorage to maintain consistency across sessions
|
|
21
|
+
*/
|
|
22
|
+
export const getOrCreateClientId = (storageKey = "sync_client_id") => {
|
|
23
|
+
const storage = globalThis.localStorage;
|
|
24
|
+
if (!storage) {
|
|
25
|
+
return generateUUID();
|
|
26
|
+
}
|
|
27
|
+
let clientId = storage.getItem(storageKey);
|
|
28
|
+
if (!clientId) {
|
|
29
|
+
clientId = generateUUID();
|
|
30
|
+
storage.setItem(storageKey, clientId);
|
|
31
|
+
}
|
|
32
|
+
return clientId;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Generates a unique transaction ID
|
|
36
|
+
* Uses UUID v4 format for guaranteed uniqueness
|
|
37
|
+
*/
|
|
38
|
+
export const generateClientTxId = () => generateUUID();
|
|
39
|
+
//# sourceMappingURL=idempotency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/utils/idempotency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,MAAM,SAAS,GAAI,UAAyD;SACzE,MAAM,CAAC;IACV,IAAI,SAAS,EAAE,UAAU,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC;IAED,0BAA0B;IAC1B,OAAO,sCAAsC,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;QACtE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACtC,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,UAAU,GAAG,gBAAgB,EAAU,EAAE;IAM3E,MAAM,OAAO,GAAI,UAA6C,CAAC,YAAY,CAAC;IAC5E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,YAAY,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,YAAY,EAAE,CAAC;QAC1B,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAAC,YAAY,EAAE,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stratasync/core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"files": [
|
|
5
|
+
"dist"
|
|
6
|
+
],
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"lint": "oxlint .",
|
|
23
|
+
"lint:fix": "oxlint --fix .",
|
|
24
|
+
"format": "oxfmt --write .",
|
|
25
|
+
"format:check": "oxfmt --check .",
|
|
26
|
+
"check-types": "tsc --noEmit",
|
|
27
|
+
"test": "node --test --import tsx \"tests/**/*.test.ts\""
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"lefthook": "^2.1.4",
|
|
31
|
+
"oxfmt": "^0.41.0",
|
|
32
|
+
"oxlint": "^1.56.0",
|
|
33
|
+
"tsx": "^4.21.0",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"ultracite": "^7.3.2"
|
|
36
|
+
}
|
|
37
|
+
}
|