@camstack/system 1.2.117 → 1.2.118
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/addon-utils.d.ts +1 -1
- package/dist/addon-utils.js +1 -1
- package/dist/addon-utils.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.d.ts +24 -2
- package/dist/builtins/local-network/local-network.addon.js +63 -17
- package/dist/builtins/local-network/local-network.addon.mjs +62 -18
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-DMEGlqg6.js → dist-C2_1HCpW.js} +133 -15
- package/dist/{dist-D4Vmj8iw.mjs → dist-DCTpBXm4.mjs} +133 -15
- package/dist/download/model-downloader.d.ts +18 -1
- package/dist/{file-data-plane-CuE_hBli.mjs → file-data-plane-BhKdxJgf.mjs} +49 -13
- package/dist/{file-data-plane-DUHPHa-Y.js → file-data-plane-DO8KbxCe.js} +49 -13
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{retired-settings-keys--aM_vGF9.mjs → retired-settings-keys-Czd76yLZ.mjs} +1 -1
- package/dist/{retired-settings-keys-DET4YkAU.js → retired-settings-keys-DHRXLMPn.js} +1 -1
- package/package.json +1 -1
|
@@ -50,21 +50,56 @@ function buildHeaders(url) {
|
|
|
50
50
|
if (hfToken && url.includes("huggingface.co")) headers["Authorization"] = `Bearer ${hfToken}`;
|
|
51
51
|
return headers;
|
|
52
52
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
var DEFAULT_MAX_REDIRECTS = 5;
|
|
54
|
+
function normalizeDownloadOptions(third) {
|
|
55
|
+
if (typeof third === "function") return { onProgress: third };
|
|
56
|
+
return third ?? {};
|
|
57
|
+
}
|
|
58
|
+
function isRedirectStatus(status) {
|
|
59
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
60
|
+
}
|
|
61
|
+
function resolveRedirectUrl(current, location) {
|
|
62
|
+
return new URL(location, current);
|
|
63
|
+
}
|
|
64
|
+
async function downloadFile(url, destPath, onProgressOrOptions) {
|
|
60
65
|
if (fs.existsSync(destPath)) return destPath;
|
|
66
|
+
const opts = normalizeDownloadOptions(onProgressOrOptions);
|
|
67
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
68
|
+
const maxRedirects = opts.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
61
69
|
fs.mkdirSync(path$1.dirname(destPath), { recursive: true });
|
|
62
70
|
const tmpPath = destPath + ".downloading";
|
|
63
71
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
let current = url;
|
|
73
|
+
const seen = /* @__PURE__ */ new Set();
|
|
74
|
+
let response;
|
|
75
|
+
const manual = opts.redirectPolicy !== void 0;
|
|
76
|
+
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
77
|
+
const parsed = new URL(current);
|
|
78
|
+
if (opts.redirectPolicy) opts.redirectPolicy(parsed, hop);
|
|
79
|
+
if (seen.has(parsed.href)) throw new Error(`Redirect loop detected at ${parsed.href}`);
|
|
80
|
+
seen.add(parsed.href);
|
|
81
|
+
const controller = opts.timeoutMs !== void 0 ? new AbortController() : void 0;
|
|
82
|
+
const timer = controller && opts.timeoutMs !== void 0 ? setTimeout(() => controller.abort(), opts.timeoutMs) : void 0;
|
|
83
|
+
try {
|
|
84
|
+
response = await fetchImpl(current, {
|
|
85
|
+
redirect: manual ? "manual" : "follow",
|
|
86
|
+
headers: buildHeaders(current),
|
|
87
|
+
...controller ? { signal: controller.signal } : {}
|
|
88
|
+
});
|
|
89
|
+
} finally {
|
|
90
|
+
if (timer) clearTimeout(timer);
|
|
91
|
+
}
|
|
92
|
+
if (manual && isRedirectStatus(response.status)) {
|
|
93
|
+
const location = response.headers.get("location");
|
|
94
|
+
if (!location) throw new Error(`Redirect ${response.status} missing Location header`);
|
|
95
|
+
if (hop >= maxRedirects) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
96
|
+
current = resolveRedirectUrl(current, location).href;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (!response) throw new Error(`No response downloading ${url}`);
|
|
102
|
+
if (manual && isRedirectStatus(response.status)) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
68
103
|
if (!response.ok) throw new Error(`HTTP ${response.status} downloading ${url}`);
|
|
69
104
|
if (!response.body) throw new Error(`No response body from ${url}`);
|
|
70
105
|
const total = parseInt(response.headers.get("content-length") ?? "0", 10);
|
|
@@ -75,9 +110,10 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
75
110
|
for (;;) {
|
|
76
111
|
const { done, value } = await reader.read();
|
|
77
112
|
if (done || !value) break;
|
|
78
|
-
fileStream.write(value);
|
|
79
113
|
downloaded += value.length;
|
|
80
|
-
|
|
114
|
+
if (opts.maxBytes !== void 0 && downloaded > opts.maxBytes) throw new Error(`Downloaded ${downloaded} bytes exceeds the ${opts.maxBytes}-byte limit`);
|
|
115
|
+
fileStream.write(value);
|
|
116
|
+
opts.onProgress?.(downloaded, total);
|
|
81
117
|
}
|
|
82
118
|
} finally {
|
|
83
119
|
fileStream.end();
|
|
@@ -51,21 +51,56 @@ function buildHeaders(url) {
|
|
|
51
51
|
if (hfToken && url.includes("huggingface.co")) headers["Authorization"] = `Bearer ${hfToken}`;
|
|
52
52
|
return headers;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
var DEFAULT_MAX_REDIRECTS = 5;
|
|
55
|
+
function normalizeDownloadOptions(third) {
|
|
56
|
+
if (typeof third === "function") return { onProgress: third };
|
|
57
|
+
return third ?? {};
|
|
58
|
+
}
|
|
59
|
+
function isRedirectStatus(status) {
|
|
60
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
61
|
+
}
|
|
62
|
+
function resolveRedirectUrl(current, location) {
|
|
63
|
+
return new URL(location, current);
|
|
64
|
+
}
|
|
65
|
+
async function downloadFile(url, destPath, onProgressOrOptions) {
|
|
61
66
|
if (node_fs.existsSync(destPath)) return destPath;
|
|
67
|
+
const opts = normalizeDownloadOptions(onProgressOrOptions);
|
|
68
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
69
|
+
const maxRedirects = opts.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
62
70
|
node_fs.mkdirSync(node_path.dirname(destPath), { recursive: true });
|
|
63
71
|
const tmpPath = destPath + ".downloading";
|
|
64
72
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
let current = url;
|
|
74
|
+
const seen = /* @__PURE__ */ new Set();
|
|
75
|
+
let response;
|
|
76
|
+
const manual = opts.redirectPolicy !== void 0;
|
|
77
|
+
for (let hop = 0; hop <= maxRedirects; hop++) {
|
|
78
|
+
const parsed = new URL(current);
|
|
79
|
+
if (opts.redirectPolicy) opts.redirectPolicy(parsed, hop);
|
|
80
|
+
if (seen.has(parsed.href)) throw new Error(`Redirect loop detected at ${parsed.href}`);
|
|
81
|
+
seen.add(parsed.href);
|
|
82
|
+
const controller = opts.timeoutMs !== void 0 ? new AbortController() : void 0;
|
|
83
|
+
const timer = controller && opts.timeoutMs !== void 0 ? setTimeout(() => controller.abort(), opts.timeoutMs) : void 0;
|
|
84
|
+
try {
|
|
85
|
+
response = await fetchImpl(current, {
|
|
86
|
+
redirect: manual ? "manual" : "follow",
|
|
87
|
+
headers: buildHeaders(current),
|
|
88
|
+
...controller ? { signal: controller.signal } : {}
|
|
89
|
+
});
|
|
90
|
+
} finally {
|
|
91
|
+
if (timer) clearTimeout(timer);
|
|
92
|
+
}
|
|
93
|
+
if (manual && isRedirectStatus(response.status)) {
|
|
94
|
+
const location = response.headers.get("location");
|
|
95
|
+
if (!location) throw new Error(`Redirect ${response.status} missing Location header`);
|
|
96
|
+
if (hop >= maxRedirects) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
97
|
+
current = resolveRedirectUrl(current, location).href;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
if (!response) throw new Error(`No response downloading ${url}`);
|
|
103
|
+
if (manual && isRedirectStatus(response.status)) throw new Error(`Too many redirects (max ${maxRedirects}) downloading ${url}`);
|
|
69
104
|
if (!response.ok) throw new Error(`HTTP ${response.status} downloading ${url}`);
|
|
70
105
|
if (!response.body) throw new Error(`No response body from ${url}`);
|
|
71
106
|
const total = parseInt(response.headers.get("content-length") ?? "0", 10);
|
|
@@ -76,9 +111,10 @@ async function downloadFile(url, destPath, onProgress) {
|
|
|
76
111
|
for (;;) {
|
|
77
112
|
const { done, value } = await reader.read();
|
|
78
113
|
if (done || !value) break;
|
|
79
|
-
fileStream.write(value);
|
|
80
114
|
downloaded += value.length;
|
|
81
|
-
|
|
115
|
+
if (opts.maxBytes !== void 0 && downloaded > opts.maxBytes) throw new Error(`Downloaded ${downloaded} bytes exceeds the ${opts.maxBytes}-byte limit`);
|
|
116
|
+
fileStream.write(value);
|
|
117
|
+
opts.onProgress?.(downloaded, total);
|
|
82
118
|
}
|
|
83
119
|
} finally {
|
|
84
120
|
fileStream.end();
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-C2_1HCpW.js");
|
|
4
4
|
const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
|
|
5
5
|
require("./builtins/alerts/index.js");
|
|
6
6
|
const require_formatter = require("./formatter-DqAKDlvN.js");
|
|
@@ -24,7 +24,7 @@ require("./builtins/storage-orchestrator/index.js");
|
|
|
24
24
|
const require_builtins_system_config_system_config_addon = require("./builtins/system-config/system-config.addon.js");
|
|
25
25
|
require("./builtins/system-config/index.js");
|
|
26
26
|
const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
|
|
27
|
-
const require_file_data_plane = require("./file-data-plane-
|
|
27
|
+
const require_file_data_plane = require("./file-data-plane-DO8KbxCe.js");
|
|
28
28
|
const require_manifest_python_deps = require("./manifest-python-deps-CwBbX4Ut.js");
|
|
29
29
|
const require_resource_monitor = require("./resource-monitor-CdnzxBLP.js");
|
|
30
30
|
const require_lan_http_bind = require("./lan-http-bind-DmgpFP6_.js");
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { At as asNumber, B as extractNestedAddonId, Bt as parseJsonUnknown$1, Dt as ReadinessTimeoutError, Et as ReadinessRegistry, Ft as expandCapMethods, Gt as EventCategory$1, H as isArrayOutputSchema, Ht as resolveCapMount, J as lifecycleJobSchema, K as isVoidInput, Mt as createEvent, Nt as emitDownForOwnedCaps, Q as looseSchema, St as DEVICE_STATUS_METHOD, U as isCollectionArrayMethod, Ut as scopeKey, Vt as readinessKey, W as isObjectInput, Z as logLevelAtMost, bt as DATAPLANE_SECRET_HEADER$1, d as METHOD_ACCESS_MAP, f as RUNTIME_DEFAULTS, it as procedureAuthKey, jt as asString$1, kt as asJsonObject$1, ot as scopesAllowAddon, q as kebabToCamel, st as scopesAllowDeviceCap, t as ALL_CAPABILITY_DEFINITIONS, tt as objectInputDeclaresAddonId, vt as errMsg$1, xt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, y as addonSettingsCapability, zt as parseJsonObject } from "./dist-
|
|
2
|
+
import { At as asNumber, B as extractNestedAddonId, Bt as parseJsonUnknown$1, Dt as ReadinessTimeoutError, Et as ReadinessRegistry, Ft as expandCapMethods, Gt as EventCategory$1, H as isArrayOutputSchema, Ht as resolveCapMount, J as lifecycleJobSchema, K as isVoidInput, Mt as createEvent, Nt as emitDownForOwnedCaps, Q as looseSchema, St as DEVICE_STATUS_METHOD, U as isCollectionArrayMethod, Ut as scopeKey, Vt as readinessKey, W as isObjectInput, Z as logLevelAtMost, bt as DATAPLANE_SECRET_HEADER$1, d as METHOD_ACCESS_MAP, f as RUNTIME_DEFAULTS, it as procedureAuthKey, jt as asString$1, kt as asJsonObject$1, ot as scopesAllowAddon, q as kebabToCamel, st as scopesAllowDeviceCap, t as ALL_CAPABILITY_DEFINITIONS, tt as objectInputDeclaresAddonId, vt as errMsg$1, xt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, y as addonSettingsCapability, zt as parseJsonObject } from "./dist-DCTpBXm4.mjs";
|
|
3
3
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
4
4
|
import "./builtins/alerts/index.mjs";
|
|
5
5
|
import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
|
|
@@ -23,7 +23,7 @@ import "./builtins/storage-orchestrator/index.mjs";
|
|
|
23
23
|
import { SystemConfigAddon } from "./builtins/system-config/system-config.addon.mjs";
|
|
24
24
|
import "./builtins/system-config/index.mjs";
|
|
25
25
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
26
|
-
import { a as parseTokenizedUrl, c as collectModelFiles, d as downloadModel, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, o as resolveFilePath, p as fetchJson, r as createAuthenticatedFileServer, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-
|
|
26
|
+
import { a as parseTokenizedUrl, c as collectModelFiles, d as downloadModel, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, o as resolveFilePath, p as fetchJson, r as createAuthenticatedFileServer, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-BhKdxJgf.mjs";
|
|
27
27
|
import { $ as buildNativeCapProxy, A as createHubCapForwardService, At as buildHeapSample, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as runNpm, D as localProviderLink, Dt as HEAP_WATCH_INTERVAL_MS, E as ipcParentLink, Et as HEAP_RECLAIM_TRIGGER_MB, F as createUdsLogger, Ft as strandedMb, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, Mt as shouldReclaim, N as createUdsEventBus, Nt as startHeapWatch, O as HUB_CAP_FWD_ACTION, Ot as HEAP_WATCH_WARN_RATIO, P as udsChildLogToWorkerEntry, Pt as startRunnerHeapWatch, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as resolveNpmInvocation, T as ipcChildLink, Tt as HEAP_RECLAIM_MIN_INTERVAL_MS, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, jt as createV8Reclaimer, k as HUB_CAP_FWD_SERVICE, kt as RUNNER_HEAP_WATCH_INTERVAL_MS, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveAddonClass, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-SGdbr9D5.mjs";
|
|
28
28
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BWmQ5i-o.mjs";
|
|
29
29
|
import { C as evaluateExistingCert, S as SERVER_AUTH_OID, _ as CA_COMMON_NAME, a as closeLanHttp, b as LEAF_RENEWAL_WINDOW_DAYS, c as readExtraSans, d as writeExtraSans, f as writeTlsMode, g as reissueTlsLeaf, h as loadTlsCert, i as bindPendingLanHttp, l as readTlsAccessStatus, m as ensureTlsCert, n as allFamiliesListenHost, o as readLanHttpState, p as validateUploadedTls, r as applyLanHttp, s as registerLanHttpHandler, t as DEFAULT_LAN_HTTP_PORT, u as readTlsMode, v as collectCertIdentity, x as MAX_LEAF_VALIDITY_DAYS, y as CA_VALIDITY_DAYS } from "./lan-http-bind-jKrj6OjQ.mjs";
|