@yhong91/vibetime 0.1.3 → 0.1.4
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/bin/vibetime.mjs +65 -23
- package/package.json +1 -1
package/bin/vibetime.mjs
CHANGED
|
@@ -1195,7 +1195,7 @@ function countTextLines(text) {
|
|
|
1195
1195
|
}
|
|
1196
1196
|
|
|
1197
1197
|
// src/lib/constants.ts
|
|
1198
|
-
var PACKAGE_VERSION = true ? "0.1.
|
|
1198
|
+
var PACKAGE_VERSION = true ? "0.1.4" : "0.1.1";
|
|
1199
1199
|
var DEFAULT_API_URL = "http://121.196.224.82:3001";
|
|
1200
1200
|
var DEFAULT_BACKFILL_BATCH_SIZE = 50;
|
|
1201
1201
|
var DEFAULT_BACKFILL_BATCH_BYTES = 800 * 1024;
|
|
@@ -8072,7 +8072,7 @@ async function deleteMachine(remote, id) {
|
|
|
8072
8072
|
}
|
|
8073
8073
|
|
|
8074
8074
|
// src/lib/types.ts
|
|
8075
|
-
var BACKFILL_STATE_SCHEMA_VERSION =
|
|
8075
|
+
var BACKFILL_STATE_SCHEMA_VERSION = 5;
|
|
8076
8076
|
|
|
8077
8077
|
// src/cli.ts
|
|
8078
8078
|
function createRegistry() {
|
|
@@ -8593,10 +8593,12 @@ async function importBackfillPlan(plan, options, ctx, registry) {
|
|
|
8593
8593
|
return 1;
|
|
8594
8594
|
}
|
|
8595
8595
|
const sourceDefs = registry.all().filter((a) => supportedSources.has(a.id) && (source === "all" || a.id === source)).map((a) => ({ id: a.id, label: a.label, paths: a.sourcePaths(home, ctx.env) }));
|
|
8596
|
+
const remote = resolveRemoteFromOptions(options, ctx);
|
|
8597
|
+
const remoteKey = backfillRemoteKey(remote?.baseUrl ?? DEFAULT_API_URL);
|
|
8596
8598
|
if (options.force) {
|
|
8597
|
-
await purgeForcedSources(sourceDefs, home, options, ctx);
|
|
8599
|
+
await purgeForcedSources(sourceDefs, home, remoteKey, options, ctx);
|
|
8598
8600
|
}
|
|
8599
|
-
const incrementalState = shouldUseIncrementalBackfill(options) ? await readBackfillIncrementalState(home, ctx) : void 0;
|
|
8601
|
+
const incrementalState = shouldUseIncrementalBackfill(options) ? await readBackfillIncrementalState(home, remoteKey, ctx) : void 0;
|
|
8600
8602
|
if (!options.json) {
|
|
8601
8603
|
write(ctx.stdout, `importRun ${plan.importRun.importRunId}
|
|
8602
8604
|
`);
|
|
@@ -8624,13 +8626,15 @@ async function importBackfillPlan(plan, options, ctx, registry) {
|
|
|
8624
8626
|
`);
|
|
8625
8627
|
}
|
|
8626
8628
|
if (counts.failed === 0 && counts.conflicts === 0 && incrementalState) {
|
|
8627
|
-
await updateBackfillIncrementalState(home, incrementalState, selectedFilesBySource);
|
|
8629
|
+
await updateBackfillIncrementalState(home, remoteKey, incrementalState, selectedFilesBySource);
|
|
8628
8630
|
}
|
|
8629
8631
|
return counts.failed > 0 || counts.conflicts > 0 && !options["skip-conflicts"] ? 1 : 0;
|
|
8630
8632
|
}
|
|
8631
|
-
async function purgeForcedSources(sourceDefs, home, options, ctx) {
|
|
8633
|
+
async function purgeForcedSources(sourceDefs, home, remoteKey, options, ctx) {
|
|
8632
8634
|
try {
|
|
8633
|
-
await
|
|
8635
|
+
const file = await readBackfillIncrementalStateFile(home);
|
|
8636
|
+
delete file.remotes[remoteKey];
|
|
8637
|
+
await writeBackfillIncrementalStateFile(home, file);
|
|
8634
8638
|
} catch (error) {
|
|
8635
8639
|
debug(ctx, `Failed to clear backfill watermark: ${error.message}
|
|
8636
8640
|
`);
|
|
@@ -8826,36 +8830,75 @@ function syncLocalTriggerStatePath(home) {
|
|
|
8826
8830
|
function syncLocalTriggerLockPath(home) {
|
|
8827
8831
|
return path18.join(home, ".vibetime", "sync-local-trigger.lock");
|
|
8828
8832
|
}
|
|
8829
|
-
|
|
8833
|
+
function backfillRemoteKey(baseUrl) {
|
|
8834
|
+
try {
|
|
8835
|
+
const url = new URL(baseUrl);
|
|
8836
|
+
return `${url.protocol}//${url.host}${url.pathname.replace(/\/+$/, "")}`;
|
|
8837
|
+
} catch {
|
|
8838
|
+
return baseUrl.replace(/\/+$/, "");
|
|
8839
|
+
}
|
|
8840
|
+
}
|
|
8841
|
+
function sanitizeBackfillSources(raw) {
|
|
8842
|
+
const sources = {};
|
|
8843
|
+
if (!isPlainObject(raw)) {
|
|
8844
|
+
return sources;
|
|
8845
|
+
}
|
|
8846
|
+
for (const source of BACKFILL_SOURCE_IDS) {
|
|
8847
|
+
const item = raw[source];
|
|
8848
|
+
if (isPlainObject(item) && typeof item.watermarkTs === "string" && !Number.isNaN(Date.parse(item.watermarkTs))) {
|
|
8849
|
+
sources[source] = { watermarkTs: item.watermarkTs };
|
|
8850
|
+
}
|
|
8851
|
+
}
|
|
8852
|
+
return sources;
|
|
8853
|
+
}
|
|
8854
|
+
async function readBackfillIncrementalStateFile(home, ctx) {
|
|
8855
|
+
const empty = { version: BACKFILL_STATE_SCHEMA_VERSION, remotes: {} };
|
|
8830
8856
|
const statePath = backfillIncrementalStatePath(home);
|
|
8831
8857
|
const state = await readJsonIfExists(statePath);
|
|
8832
8858
|
if (state === null) {
|
|
8833
|
-
return
|
|
8859
|
+
return empty;
|
|
8834
8860
|
}
|
|
8835
|
-
if (!isPlainObject(state)
|
|
8861
|
+
if (!isPlainObject(state)) {
|
|
8836
8862
|
if (ctx) {
|
|
8837
8863
|
debug(ctx, `backfill-state malformed at ${statePath}; ignoring watermarks
|
|
8838
8864
|
`);
|
|
8839
8865
|
}
|
|
8840
|
-
return
|
|
8866
|
+
return empty;
|
|
8841
8867
|
}
|
|
8842
8868
|
if (state.version !== BACKFILL_STATE_SCHEMA_VERSION) {
|
|
8843
8869
|
if (ctx) {
|
|
8844
8870
|
debug(ctx, `backfill-state version ${String(state.version)} at ${statePath} differs from current v${BACKFILL_STATE_SCHEMA_VERSION}; dropping watermarks so the next sync re-imports under the new parser
|
|
8845
8871
|
`);
|
|
8846
8872
|
}
|
|
8847
|
-
return
|
|
8873
|
+
return empty;
|
|
8848
8874
|
}
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8875
|
+
if (!isPlainObject(state.remotes)) {
|
|
8876
|
+
if (ctx) {
|
|
8877
|
+
debug(ctx, `backfill-state malformed at ${statePath}; ignoring watermarks
|
|
8878
|
+
`);
|
|
8879
|
+
}
|
|
8880
|
+
return empty;
|
|
8881
|
+
}
|
|
8882
|
+
const remotes = {};
|
|
8883
|
+
for (const [remoteKey, entry] of Object.entries(state.remotes)) {
|
|
8884
|
+
if (!isPlainObject(entry)) {
|
|
8885
|
+
continue;
|
|
8854
8886
|
}
|
|
8887
|
+
remotes[remoteKey] = { sources: sanitizeBackfillSources(entry.sources) };
|
|
8855
8888
|
}
|
|
8856
|
-
return { version: BACKFILL_STATE_SCHEMA_VERSION,
|
|
8889
|
+
return { version: BACKFILL_STATE_SCHEMA_VERSION, remotes };
|
|
8857
8890
|
}
|
|
8858
|
-
async function
|
|
8891
|
+
async function writeBackfillIncrementalStateFile(home, file) {
|
|
8892
|
+
const statePath = backfillIncrementalStatePath(home);
|
|
8893
|
+
await mkdir4(path18.dirname(statePath), { recursive: true });
|
|
8894
|
+
await writeFile3(statePath, `${JSON.stringify(file, null, 2)}
|
|
8895
|
+
`, "utf8");
|
|
8896
|
+
}
|
|
8897
|
+
async function readBackfillIncrementalState(home, remoteKey, ctx) {
|
|
8898
|
+
const file = await readBackfillIncrementalStateFile(home, ctx);
|
|
8899
|
+
return { version: BACKFILL_STATE_SCHEMA_VERSION, sources: file.remotes[remoteKey]?.sources ?? {} };
|
|
8900
|
+
}
|
|
8901
|
+
async function updateBackfillIncrementalState(home, remoteKey, state, selectedFilesBySource) {
|
|
8859
8902
|
for (const [source, files] of selectedFilesBySource.entries()) {
|
|
8860
8903
|
const latest = maxTimestamp(files.map((f) => f.modifiedAt));
|
|
8861
8904
|
if (!latest) {
|
|
@@ -8863,10 +8906,9 @@ async function updateBackfillIncrementalState(home, state, selectedFilesBySource
|
|
|
8863
8906
|
}
|
|
8864
8907
|
state.sources[source] = { watermarkTs: latest };
|
|
8865
8908
|
}
|
|
8866
|
-
const
|
|
8867
|
-
|
|
8868
|
-
await
|
|
8869
|
-
`, "utf8");
|
|
8909
|
+
const file = await readBackfillIncrementalStateFile(home);
|
|
8910
|
+
file.remotes[remoteKey] = { sources: state.sources };
|
|
8911
|
+
await writeBackfillIncrementalStateFile(home, file);
|
|
8870
8912
|
}
|
|
8871
8913
|
async function readSyncLocalTriggerState(statePath) {
|
|
8872
8914
|
let state;
|
package/package.json
CHANGED