@fctc/interface-logic 4.2.6 → 4.2.8

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/dist/provider.js CHANGED
@@ -106,7 +106,8 @@ var initialState2 = {
106
106
  allowed_company_ids: [],
107
107
  lang: "vi_VN",
108
108
  tz: "Asia/Saigon"
109
- }
109
+ },
110
+ isLocalMode: false
110
111
  };
111
112
  var envSlice = (0, import_toolkit2.createSlice)({
112
113
  name: "env",
@@ -2315,9 +2316,9 @@ function applyBinaryOp(ast, context) {
2315
2316
  var DICT = {
2316
2317
  get(...args) {
2317
2318
  const { key, defValue } = parseArgs(args, ["key", "defValue"]);
2318
- const self = this;
2319
- if (key in self) {
2320
- return self[key];
2319
+ const self2 = this;
2320
+ if (key in self2) {
2321
+ return self2[key];
2321
2322
  } else if (defValue !== void 0) {
2322
2323
  return defValue;
2323
2324
  }
@@ -5926,7 +5927,221 @@ var handleClosingSessionService = (env) => {
5926
5927
 
5927
5928
  // src/services/pos-service/load-data-pos-session.ts
5928
5929
  var import_react33 = require("react");
5930
+
5931
+ // src/services/filesystem-service/file-service.ts
5932
+ var import_filesystem = require("@capacitor/filesystem");
5933
+ var fileService = {
5934
+ async read(path) {
5935
+ try {
5936
+ const res = await import_filesystem.Filesystem.readFile({
5937
+ path,
5938
+ directory: import_filesystem.Directory.Data,
5939
+ encoding: import_filesystem.Encoding.UTF8
5940
+ });
5941
+ if (typeof res.data === "string") return res.data;
5942
+ if (res.data instanceof Blob) return await res.data.text();
5943
+ return null;
5944
+ } catch {
5945
+ return null;
5946
+ }
5947
+ },
5948
+ async write(path, data) {
5949
+ await import_filesystem.Filesystem.writeFile({
5950
+ path,
5951
+ data,
5952
+ directory: import_filesystem.Directory.Data,
5953
+ encoding: import_filesystem.Encoding.UTF8,
5954
+ recursive: true
5955
+ });
5956
+ },
5957
+ async writeAtomic(path, data) {
5958
+ const tempPath = path + ".tmp";
5959
+ await import_filesystem.Filesystem.writeFile({
5960
+ path: tempPath,
5961
+ data,
5962
+ directory: import_filesystem.Directory.Data,
5963
+ encoding: import_filesystem.Encoding.UTF8,
5964
+ recursive: true
5965
+ });
5966
+ try {
5967
+ await import_filesystem.Filesystem.deleteFile({
5968
+ path,
5969
+ directory: import_filesystem.Directory.Data
5970
+ });
5971
+ } catch {
5972
+ }
5973
+ await import_filesystem.Filesystem.rename({
5974
+ from: tempPath,
5975
+ to: path,
5976
+ directory: import_filesystem.Directory.Data
5977
+ });
5978
+ },
5979
+ async delete(path) {
5980
+ try {
5981
+ await import_filesystem.Filesystem.deleteFile({
5982
+ path,
5983
+ directory: import_filesystem.Directory.Data
5984
+ });
5985
+ } catch {
5986
+ }
5987
+ },
5988
+ async exists(path) {
5989
+ try {
5990
+ await import_filesystem.Filesystem.stat({
5991
+ path,
5992
+ directory: import_filesystem.Directory.Data
5993
+ });
5994
+ return true;
5995
+ } catch {
5996
+ return false;
5997
+ }
5998
+ },
5999
+ async mkdir(path) {
6000
+ try {
6001
+ await import_filesystem.Filesystem.mkdir({
6002
+ path,
6003
+ directory: import_filesystem.Directory.Data,
6004
+ recursive: true
6005
+ });
6006
+ } catch (e) {
6007
+ if (!String(e?.message).includes("Exists")) {
6008
+ throw e;
6009
+ }
6010
+ }
6011
+ },
6012
+ async list(path) {
6013
+ return import_filesystem.Filesystem.readdir({
6014
+ path,
6015
+ directory: import_filesystem.Directory.Data
6016
+ });
6017
+ },
6018
+ async getUri(path) {
6019
+ return import_filesystem.Filesystem.getUri({
6020
+ path,
6021
+ directory: import_filesystem.Directory.Data
6022
+ });
6023
+ }
6024
+ };
6025
+
6026
+ // src/services/filesystem-service/json-worker.ts
6027
+ var import_meta = {};
6028
+ self.addEventListener("message", async (ev) => {
6029
+ const { id, cmd, payload } = ev.data;
6030
+ try {
6031
+ if (cmd === "parse") {
6032
+ const parsed = JSON.parse(payload);
6033
+ self.postMessage({ id, ok: true, result: parsed });
6034
+ } else if (cmd === "stringify") {
6035
+ const str = JSON.stringify(payload);
6036
+ self.postMessage({ id, ok: true, result: str });
6037
+ }
6038
+ } catch (err) {
6039
+ self.postMessage({ id, ok: false, error: err?.message || String(err) });
6040
+ }
6041
+ });
6042
+ function spawnParseWorker(raw) {
6043
+ return new Promise((resolve, reject) => {
6044
+ const worker = new Worker(new URL("./json-worker.ts", import_meta.url), {
6045
+ type: "module"
6046
+ });
6047
+ const id = Math.random().toString(36).slice(2);
6048
+ worker.onmessage = (ev) => {
6049
+ const { ok, result, error } = ev.data;
6050
+ if (ok) {
6051
+ resolve(result);
6052
+ } else {
6053
+ reject(new Error(error));
6054
+ }
6055
+ worker.terminate();
6056
+ };
6057
+ worker.postMessage({ id, cmd: "parse", payload: raw });
6058
+ });
6059
+ }
6060
+ function spawnStringifyWorker(obj) {
6061
+ return new Promise((resolve, reject) => {
6062
+ const worker = new Worker(new URL("./json-worker.ts", import_meta.url), {
6063
+ type: "module"
6064
+ });
6065
+ worker.onmessage = (ev) => {
6066
+ const { ok, result, error } = ev.data;
6067
+ if (ok) resolve(result);
6068
+ else reject(new Error(error));
6069
+ worker.terminate();
6070
+ };
6071
+ worker.postMessage({ cmd: "stringify", payload: obj });
6072
+ });
6073
+ }
6074
+
6075
+ // src/services/filesystem-service/memory-cache.ts
6076
+ var MemoryCache = class {
6077
+ map = /* @__PURE__ */ new Map();
6078
+ get(k) {
6079
+ const e = this.map.get(k);
6080
+ if (!e) return null;
6081
+ if (e.ttl && Date.now() - e.t > e.ttl) {
6082
+ this.map.delete(k);
6083
+ return null;
6084
+ }
6085
+ return e.value;
6086
+ }
6087
+ set(k, v, ttl = 5 * 60 * 1e3) {
6088
+ this.map.set(k, { value: v, t: Date.now(), ttl });
6089
+ }
6090
+ del(k) {
6091
+ this.map.delete(k);
6092
+ }
6093
+ clear() {
6094
+ this.map.clear();
6095
+ }
6096
+ };
6097
+ var memoryCache = new MemoryCache();
6098
+
6099
+ // src/services/filesystem-service/model-loader.ts
6100
+ var MODELS_DIR = "pos/models";
6101
+ var MODELS_META_DIR = "pos/models_meta";
6102
+ async function loadData(includeMeta = true) {
6103
+ const listResult = await fileService.list(MODELS_DIR);
6104
+ if (!listResult || !Array.isArray(listResult.files)) {
6105
+ return {};
6106
+ }
6107
+ const result = {};
6108
+ for (const file of listResult.files) {
6109
+ if (file.type !== "file") continue;
6110
+ if (!file.name.endsWith(".json")) continue;
6111
+ const fileName = file.name;
6112
+ const modelName = fileName.replace(/\.json$/, "");
6113
+ const dataPath = `${MODELS_DIR}/${fileName}`;
6114
+ const metaPath = `${MODELS_META_DIR}/${encodeURIComponent(
6115
+ modelName
6116
+ )}.meta.json`;
6117
+ const rawData = await fileService.read(dataPath);
6118
+ if (!rawData) continue;
6119
+ const parsedData = await spawnParseWorker(rawData);
6120
+ const data = Array.isArray(parsedData) ? parsedData : [];
6121
+ if (!includeMeta) {
6122
+ result[modelName] = { data };
6123
+ continue;
6124
+ }
6125
+ const rawMeta = await fileService.read(metaPath);
6126
+ let fields = [];
6127
+ let relations = {};
6128
+ if (rawMeta) {
6129
+ const parsedMeta = await spawnParseWorker(rawMeta);
6130
+ fields = parsedMeta?.fields ?? [];
6131
+ relations = parsedMeta?.relations ?? {};
6132
+ }
6133
+ result[modelName] = {
6134
+ data,
6135
+ fields,
6136
+ relations
6137
+ };
6138
+ }
6139
+ return result;
6140
+ }
6141
+
6142
+ // src/services/pos-service/load-data-pos-session.ts
5929
6143
  var loadDataPosSessionService = (env) => {
6144
+ const isLocalMode = env?.isLocalMode;
5930
6145
  const loadDataPosSession = (0, import_react33.useCallback)(
5931
6146
  ({
5932
6147
  model,
@@ -5937,6 +6152,9 @@ var loadDataPosSessionService = (env) => {
5937
6152
  modelsToLoad = [],
5938
6153
  searchParams
5939
6154
  }) => {
6155
+ if (isLocalMode) {
6156
+ return loadData();
6157
+ }
5940
6158
  const jsonData = {
5941
6159
  model,
5942
6160
  method: "load_data" /* LOAD_DATA */,
@@ -5963,7 +6181,7 @@ var loadDataPosSessionService = (env) => {
5963
6181
  service
5964
6182
  );
5965
6183
  },
5966
- [env]
6184
+ [env, isLocalMode]
5967
6185
  );
5968
6186
  return {
5969
6187
  loadDataPosSession
@@ -6296,6 +6514,145 @@ var usePosService = () => {
6296
6514
  return service;
6297
6515
  };
6298
6516
 
6517
+ // src/services/filesystem-service/manifest.ts
6518
+ var MANIFEST_PATH = "pos/manifest.json";
6519
+ var MANIFEST_BAK_PATH = "pos/manifest.bak.json";
6520
+ async function writeManifest(manifest) {
6521
+ const oldRaw = await fileService.read(MANIFEST_PATH);
6522
+ if (oldRaw !== null) {
6523
+ await fileService.writeAtomic(MANIFEST_BAK_PATH, oldRaw);
6524
+ }
6525
+ await fileService.writeAtomic(MANIFEST_PATH, JSON.stringify(manifest));
6526
+ try {
6527
+ await fileService.delete(MANIFEST_BAK_PATH);
6528
+ } catch {
6529
+ }
6530
+ }
6531
+
6532
+ // src/services/filesystem-service/import-snapshot.ts
6533
+ var DATA_DIR = "pos";
6534
+ var MODELS_DIR2 = `${DATA_DIR}/models`;
6535
+ var MODELS_META_DIR2 = `${DATA_DIR}/models_meta`;
6536
+ var importSnapshot = async ({ data, onProgress }) => {
6537
+ onProgress?.(1, "Parsing snapshot");
6538
+ const parsed = await spawnParseWorker(data);
6539
+ const modelNames = Object.keys(parsed);
6540
+ const total = modelNames.length;
6541
+ const manifest = { version: (/* @__PURE__ */ new Date()).toISOString(), models: {} };
6542
+ const TMP_PREFIX = `pos/data/tmp_import_${Date.now()}`;
6543
+ await fileService.writeAtomic(`${TMP_PREFIX}/.marker`, "1");
6544
+ let i = 0;
6545
+ for (const model of modelNames) {
6546
+ i++;
6547
+ onProgress?.(
6548
+ Math.round(i / total * 100),
6549
+ `Processing ${model} (${i}/${total})`
6550
+ );
6551
+ const block = parsed[model];
6552
+ const dataPart = block?.data ?? block ?? [];
6553
+ const fields = block?.fields ?? [];
6554
+ const relations = block?.relations ?? {};
6555
+ const serialized = await spawnStringifyWorker(dataPart);
6556
+ const tmpModelPath = `${TMP_PREFIX}/${encodeURIComponent(model)}.json`;
6557
+ await fileService.writeAtomic(tmpModelPath, serialized);
6558
+ const meta = {
6559
+ fields,
6560
+ relations,
6561
+ count: Array.isArray(dataPart) ? dataPart.length : 0,
6562
+ writtenAt: (/* @__PURE__ */ new Date()).toISOString()
6563
+ };
6564
+ const tmpMetaPath = `${TMP_PREFIX}/${encodeURIComponent(model)}.meta.json`;
6565
+ await fileService.writeAtomic(tmpMetaPath, JSON.stringify(meta));
6566
+ manifest.models[model] = {
6567
+ file: `${MODELS_DIR2}/${encodeURIComponent(model)}.json`,
6568
+ metaFile: `${MODELS_META_DIR2}/${encodeURIComponent(model)}.meta.json`,
6569
+ count: meta.count,
6570
+ updatedAt: meta.writtenAt
6571
+ };
6572
+ }
6573
+ onProgress?.(95, "Committing import (moving files)");
6574
+ for (const model of modelNames) {
6575
+ const tmpModelPath = `${TMP_PREFIX}/${encodeURIComponent(model)}.json`;
6576
+ const finalModelPath = `${MODELS_DIR2}/${encodeURIComponent(model)}.json`;
6577
+ const tmpMetaPath = `${TMP_PREFIX}/${encodeURIComponent(model)}.meta.json`;
6578
+ const finalMetaPath = `${MODELS_META_DIR2}/${encodeURIComponent(
6579
+ model
6580
+ )}.meta.json`;
6581
+ const tmpRaw = await fileService.read(tmpModelPath);
6582
+ if (tmpRaw !== null) await fileService.writeAtomic(finalModelPath, tmpRaw);
6583
+ const tmpMetaRaw = await fileService.read(tmpMetaPath);
6584
+ if (tmpMetaRaw !== null)
6585
+ await fileService.writeAtomic(finalMetaPath, tmpMetaRaw);
6586
+ onProgress?.(
6587
+ 95 + Math.round(
6588
+ (Object.keys(manifest.models).indexOf(model) + 1) / modelNames.length * 5
6589
+ ),
6590
+ `Committed ${model}`
6591
+ );
6592
+ }
6593
+ await writeManifest(manifest);
6594
+ try {
6595
+ for (const model of modelNames) {
6596
+ await fileService.delete(
6597
+ `${TMP_PREFIX}/${encodeURIComponent(model)}.json`
6598
+ );
6599
+ await fileService.delete(
6600
+ `${TMP_PREFIX}/${encodeURIComponent(model)}.meta.json`
6601
+ );
6602
+ }
6603
+ await fileService.delete(`${TMP_PREFIX}/.marker`);
6604
+ } catch (e) {
6605
+ console.log("Failed to cleanup tmp import files:", e);
6606
+ }
6607
+ onProgress?.(100, "Import complete");
6608
+ return manifest;
6609
+ };
6610
+ var import_snapshot_default = importSnapshot;
6611
+
6612
+ // src/services/filesystem-service/init-snapshot.ts
6613
+ var isSnapshotReady = async () => {
6614
+ try {
6615
+ const raw = await fileService.read("pos/manifest.json");
6616
+ if (!raw) return false;
6617
+ const manifest = JSON.parse(raw);
6618
+ if (!manifest.models || typeof manifest.models !== "object") {
6619
+ return false;
6620
+ }
6621
+ const modelEntries = Object.values(manifest.models);
6622
+ if (modelEntries.length === 0) return false;
6623
+ const firstModel = modelEntries[0];
6624
+ if (!firstModel.file) return false;
6625
+ const modelExists = await fileService.exists(firstModel.file);
6626
+ return modelExists;
6627
+ } catch {
6628
+ return false;
6629
+ }
6630
+ };
6631
+ async function initSnapshot(onProgress) {
6632
+ const ready = await isSnapshotReady();
6633
+ if (ready) {
6634
+ console.log("skip initialization.");
6635
+ return;
6636
+ }
6637
+ console.log("initializing from data.json...");
6638
+ const jsonData = await fetch("/data.json").then((r) => r.text());
6639
+ if (!jsonData) {
6640
+ console.error("cannot load data.json");
6641
+ return;
6642
+ }
6643
+ await import_snapshot_default({
6644
+ data: jsonData,
6645
+ onProgress
6646
+ });
6647
+ }
6648
+
6649
+ // src/services/filesystem-service/index.ts
6650
+ var useFileSystemService = () => {
6651
+ return {
6652
+ initSnapshot
6653
+ };
6654
+ };
6655
+
6299
6656
  // src/provider/version-gate-provider.tsx
6300
6657
  var import_jsx_runtime4 = require("react/jsx-runtime");
6301
6658
  var VersionGate = ({ children }) => {
@@ -6683,7 +7040,8 @@ var initialEnvState = {
6683
7040
  lang: "vi_VN",
6684
7041
  tz: "Asia/Saigon"
6685
7042
  },
6686
- excludeLanguages: []
7043
+ excludeLanguages: [],
7044
+ isLocalMode: false
6687
7045
  };
6688
7046
  var EnvContext = (0, import_react43.createContext)(null);
6689
7047
  function EnvProvider({
@@ -8766,6 +9124,16 @@ var useUpdateOrderStatus = () => {
8766
9124
  };
8767
9125
  var use_update_order_status_default = useUpdateOrderStatus;
8768
9126
 
9127
+ // src/hooks/pos/use-init-snapshot.ts
9128
+ var import_react_query113 = require("@tanstack/react-query");
9129
+ var useInitSnapshot = () => {
9130
+ const fileSystem = useFileSystemService();
9131
+ return (0, import_react_query113.useMutation)({
9132
+ mutationFn: fileSystem.initSnapshot
9133
+ });
9134
+ };
9135
+ var use_init_snapshot_default = useInitSnapshot;
9136
+
8769
9137
  // src/provider/service-provider.tsx
8770
9138
  var import_jsx_runtime6 = require("react/jsx-runtime");
8771
9139
  var ServiceContext = (0, import_react45.createContext)(null);
@@ -8884,7 +9252,8 @@ var ServiceProvider = ({
8884
9252
  useGetCity: use_get_city_default,
8885
9253
  useGetWard: use_get_ward_default,
8886
9254
  useGetCountry: use_get_country_default,
8887
- useGetPartnerTitle: use_get_partner_title_default
9255
+ useGetPartnerTitle: use_get_partner_title_default,
9256
+ useInitSnapshot: use_init_snapshot_default
8888
9257
  };
8889
9258
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ServiceContext.Provider, { value: services, children });
8890
9259
  };