@dinoxx/dinox-cli 1.1.1 → 2.1.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 +44 -3
- package/dist/cli.js +4 -0
- package/dist/commands/auth/index.js +1 -2
- package/dist/commands/boxes/index.js +37 -13
- package/dist/commands/boxes/operations.d.ts +3 -3
- package/dist/commands/boxes/operations.js +51 -28
- package/dist/commands/info/index.js +30 -5
- package/dist/commands/meta/repo.js +2 -1
- package/dist/commands/notes/actions.js +20 -37
- package/dist/commands/notes/bulk.d.ts +2 -2
- package/dist/commands/notes/bulk.js +3 -18
- package/dist/commands/notes/contentPatch.d.ts +5 -1
- package/dist/commands/notes/contentPatch.js +12 -1
- package/dist/commands/notes/contentPatchCommand.d.ts +3 -0
- package/dist/commands/notes/contentPatchCommand.js +29 -8
- package/dist/commands/notes/descriptors.js +19 -16
- package/dist/commands/notes/export.js +3 -0
- package/dist/commands/notes/repo/read.d.ts +8 -0
- package/dist/commands/notes/repo/read.js +321 -0
- package/dist/commands/notes/repo/resolve.d.ts +8 -0
- package/dist/commands/notes/repo/resolve.js +187 -0
- package/dist/commands/notes/repo/search.d.ts +42 -0
- package/dist/commands/notes/repo/search.js +513 -0
- package/dist/commands/notes/repo/shared.d.ts +190 -0
- package/dist/commands/notes/repo/shared.js +102 -0
- package/dist/commands/notes/repo/write.d.ts +24 -0
- package/dist/commands/notes/repo/write.js +251 -0
- package/dist/commands/notes/repo.d.ts +7 -177
- package/dist/commands/notes/repo.js +7 -1310
- package/dist/commands/notes/searchOutput.d.ts +2 -1
- package/dist/commands/notes/searchOutput.js +2 -1
- package/dist/commands/notes/searchSql.js +9 -3
- package/dist/commands/prompt/index.d.ts +1 -0
- package/dist/commands/prompt/index.js +26 -11
- package/dist/commands/savedViews/index.d.ts +7 -0
- package/dist/commands/savedViews/index.js +458 -0
- package/dist/commands/savedViews/model.d.ts +87 -0
- package/dist/commands/savedViews/model.js +306 -0
- package/dist/commands/savedViews/repo.d.ts +123 -0
- package/dist/commands/savedViews/repo.js +512 -0
- package/dist/commands/savedViews/semantics.d.ts +46 -0
- package/dist/commands/savedViews/semantics.js +738 -0
- package/dist/commands/schema/commandMetadata.js +4 -4
- package/dist/commands/schema/index.d.ts +1 -0
- package/dist/commands/schema/index.js +23 -2
- package/dist/commands/schema/renderSkills.d.ts +6 -0
- package/dist/commands/schema/renderSkills.js +109 -11
- package/dist/commands/schema/spec.js +4 -0
- package/dist/commands/skills/index.d.ts +80 -0
- package/dist/commands/skills/index.js +572 -0
- package/dist/commands/storage/index.js +2 -2
- package/dist/commands/storage/repo/configs.d.ts +30 -0
- package/dist/commands/storage/repo/configs.js +259 -0
- package/dist/commands/storage/repo/operations.d.ts +25 -0
- package/dist/commands/storage/repo/operations.js +337 -0
- package/dist/commands/storage/repo/remote.d.ts +32 -0
- package/dist/commands/storage/repo/remote.js +132 -0
- package/dist/commands/storage/repo/resources.d.ts +12 -0
- package/dist/commands/storage/repo/resources.js +134 -0
- package/dist/commands/storage/repo/shared.d.ts +181 -0
- package/dist/commands/storage/repo/shared.js +36 -0
- package/dist/commands/storage/repo/targets.d.ts +12 -0
- package/dist/commands/storage/repo/targets.js +178 -0
- package/dist/commands/storage/repo.d.ts +3 -166
- package/dist/commands/storage/repo.js +4 -1034
- package/dist/commands/sync.js +2 -1
- package/dist/commands/tags/index.js +30 -11
- package/dist/commands/tags/operations.d.ts +3 -3
- package/dist/commands/tags/operations.js +45 -20
- package/dist/commands/templates/model.d.ts +50 -0
- package/dist/commands/templates/model.js +239 -0
- package/dist/commands/todo/index.js +3 -3
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +46 -9
- package/dist/commands/writeConfirmation.d.ts +13 -0
- package/dist/commands/writeConfirmation.js +54 -0
- package/dist/config/resolve.js +5 -10
- package/dist/config/types.d.ts +3 -6
- package/dist/constants/links.d.ts +18 -1
- package/dist/constants/links.js +26 -1
- package/dist/contract/snapshot.d.ts +30 -0
- package/dist/contract/snapshot.js +114 -0
- package/dist/daemon/client.d.ts +2 -2
- package/dist/daemon/client.js +108 -54
- package/dist/daemon/index.d.ts +5 -3
- package/dist/daemon/index.js +28 -5
- package/dist/daemon/lifecycle.d.ts +7 -2
- package/dist/daemon/lifecycle.js +53 -13
- package/dist/daemon/pid.d.ts +1 -1
- package/dist/daemon/pid.js +6 -3
- package/dist/dinox.js +9 -1
- package/dist/powersync/exclusiveRuntime.d.ts +1 -0
- package/dist/powersync/exclusiveRuntime.js +26 -8
- package/dist/powersync/runtime.d.ts +3 -2
- package/dist/powersync/runtime.js +19 -3
- package/dist/powersync/schema/content.d.ts +1 -78
- package/dist/powersync/schema/content.js +1 -78
- package/dist/powersync/schema/electronCanonical.d.ts +1561 -0
- package/dist/powersync/schema/electronCanonical.js +1154 -0
- package/dist/powersync/schema/index.d.ts +573 -129
- package/dist/powersync/schema/index.js +3 -32
- package/dist/powersync/schema/local.d.ts +1 -56
- package/dist/powersync/schema/local.js +1 -60
- package/dist/powersync/schema/note.d.ts +1 -35
- package/dist/powersync/schema/note.js +1 -35
- package/dist/powersync/schema/notesExtras.d.ts +1 -62
- package/dist/powersync/schema/notesExtras.js +1 -71
- package/dist/powersync/schema/projects.d.ts +1 -104
- package/dist/powersync/schema/projects.js +1 -104
- package/dist/powersync/schema/savedViews.d.ts +1 -0
- package/dist/powersync/schema/savedViews.js +1 -0
- package/dist/powersync/schema/storage.d.ts +1 -24
- package/dist/powersync/schema/storage.js +1 -24
- package/dist/powersync/schema/tags.d.ts +1 -37
- package/dist/powersync/schema/tags.js +1 -37
- package/dist/powersync/syncGate.d.ts +20 -2
- package/dist/powersync/uploader.d.ts +16 -2
- package/dist/powersync/uploader.js +152 -158
- package/dist/skills/check.d.ts +1 -0
- package/dist/skills/check.js +538 -70
- package/dist/skills/commandRefs.d.ts +21 -0
- package/dist/skills/commandRefs.js +132 -0
- package/dist/skills/generate.d.ts +13 -0
- package/dist/skills/generate.js +80 -0
- package/dist/skills/registry.d.ts +13 -0
- package/dist/skills/registry.js +58 -0
- package/dist/skills/retired.d.ts +60 -0
- package/dist/skills/retired.js +58 -0
- package/dist/utils/deadline.d.ts +8 -0
- package/dist/utils/deadline.js +31 -0
- package/dist/utils/dryRun.d.ts +20 -1
- package/dist/utils/dryRun.js +22 -3
- package/dist/utils/errorCodes.d.ts +311 -0
- package/dist/utils/errorCodes.js +92 -0
- package/dist/utils/errors.d.ts +15 -2
- package/dist/utils/errors.js +13 -0
- package/dist/utils/processExit.d.ts +1 -0
- package/dist/utils/processExit.js +33 -0
- package/dist/utils/updateNotice.d.ts +1 -0
- package/dist/utils/updateNotice.js +1 -1
- package/package.json +18 -8
package/dist/daemon/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { loadConfig } from '../config/store.js';
|
|
|
12
12
|
import { fingerprintDaemonRuntimeConfig, resolveConfig } from '../config/resolve.js';
|
|
13
13
|
import { hydrateResolvedAuthIdentity } from '../auth/userInfo.js';
|
|
14
14
|
import { withAsyncRelease } from '../utils/asyncRelease.js';
|
|
15
|
+
import { remainingDeadlineMs } from '../utils/deadline.js';
|
|
15
16
|
import { getPackageVersion } from '../utils/version.js';
|
|
16
17
|
const DAEMON_STOP_POLL_INTERVAL_MS = 100;
|
|
17
18
|
const DAEMON_STOP_TIMEOUT_MS = 5_000;
|
|
@@ -63,9 +64,11 @@ async function waitForDaemonExit(instanceId, timeoutMs) {
|
|
|
63
64
|
const info = await getDaemonInfo();
|
|
64
65
|
return !info || info.instanceId !== instanceId;
|
|
65
66
|
}
|
|
66
|
-
async function expectedDaemonIdentity(baseConfig) {
|
|
67
|
+
async function expectedDaemonIdentity(baseConfig, timeoutMs) {
|
|
67
68
|
const resolved = baseConfig ?? resolveConfig(await loadConfig());
|
|
68
|
-
const { config } = await hydrateResolvedAuthIdentity(resolved, {
|
|
69
|
+
const { config } = await hydrateResolvedAuthIdentity(resolved, {
|
|
70
|
+
timeoutMs: timeoutMs ?? resolved.sync.timeoutMs,
|
|
71
|
+
});
|
|
69
72
|
return {
|
|
70
73
|
version: getPackageVersion(),
|
|
71
74
|
userId: config.auth.userId ?? null,
|
|
@@ -82,9 +85,29 @@ function matchesRuntimeTokenBinding(info, version, config) {
|
|
|
82
85
|
&& (!config.auth.userId || info.userId === config.auth.userId));
|
|
83
86
|
}
|
|
84
87
|
export async function startDaemonLocked(port, detached, options = {}) {
|
|
88
|
+
const maximumTimeoutMs = options.timeoutMs === undefined
|
|
89
|
+
? undefined
|
|
90
|
+
: Math.max(0, Math.floor(options.timeoutMs));
|
|
91
|
+
const deadlineAtMs = maximumTimeoutMs === undefined
|
|
92
|
+
? undefined
|
|
93
|
+
: Date.now() + maximumTimeoutMs;
|
|
94
|
+
const remainingStartTimeoutMs = (phase) => {
|
|
95
|
+
if (deadlineAtMs === undefined || maximumTimeoutMs === undefined) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const remainingMs = remainingDeadlineMs(deadlineAtMs, maximumTimeoutMs);
|
|
99
|
+
if (remainingMs <= 0) {
|
|
100
|
+
throw new DinoxError('Failed to start daemon before the caller deadline expired.', {
|
|
101
|
+
code: 'DAEMON_START_TIMEOUT',
|
|
102
|
+
details: { phase },
|
|
103
|
+
recoverable: true,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return remainingMs;
|
|
107
|
+
};
|
|
85
108
|
const baseConfig = resolveConfig(await loadConfig());
|
|
86
109
|
const version = getPackageVersion();
|
|
87
|
-
const runningInfo = await getDaemonInfo();
|
|
110
|
+
const runningInfo = await getDaemonInfo(remainingStartTimeoutMs('initial-ping'));
|
|
88
111
|
if (runningInfo) {
|
|
89
112
|
if (matchesRuntimeTokenBinding(runningInfo, version, baseConfig)) {
|
|
90
113
|
return { running: true, port, socketPath: getDaemonSocketPath(), transport: 'socket', detached, alreadyRunning: true };
|
|
@@ -94,7 +117,7 @@ export async function startDaemonLocked(port, detached, options = {}) {
|
|
|
94
117
|
recoverable: true,
|
|
95
118
|
});
|
|
96
119
|
}
|
|
97
|
-
const expected = await expectedDaemonIdentity(baseConfig);
|
|
120
|
+
const expected = await expectedDaemonIdentity(baseConfig, remainingStartTimeoutMs('auth-hydration'));
|
|
98
121
|
if (detached) {
|
|
99
122
|
const args = ['daemon', 'start', '--port', String(port), '--no-detach'];
|
|
100
123
|
const entrypoint = process.argv[1];
|
|
@@ -107,7 +130,7 @@ export async function startDaemonLocked(port, detached, options = {}) {
|
|
|
107
130
|
env: { ...process.env, [DAEMON_CHILD_ENV]: '1' },
|
|
108
131
|
});
|
|
109
132
|
child.unref();
|
|
110
|
-
const ready = await waitForFreshDaemon(expected.version, expected.userId, expected.tokenFingerprint, expected.runtimeConfigFingerprint);
|
|
133
|
+
const ready = await waitForFreshDaemon(expected.version, expected.userId, expected.tokenFingerprint, expected.runtimeConfigFingerprint, remainingStartTimeoutMs('ready-poll'));
|
|
111
134
|
if (!ready) {
|
|
112
135
|
child.kill('SIGTERM');
|
|
113
136
|
throw new DinoxError('Failed to start daemon');
|
|
@@ -28,17 +28,22 @@ type DaemonLifecycleDependencies = {
|
|
|
28
28
|
getPackageVersion: typeof getPackageVersion;
|
|
29
29
|
printWarning: typeof printHumanReadableWarning;
|
|
30
30
|
};
|
|
31
|
-
export declare function captureDaemonSnapshot(overrides?: Partial<DaemonLifecycleDependencies
|
|
31
|
+
export declare function captureDaemonSnapshot(overrides?: Partial<DaemonLifecycleDependencies>, timeoutMs?: number): Promise<DaemonSnapshot>;
|
|
32
32
|
export declare function daemonSnapshotIsFresh(config: ResolvedDinoxConfig, snapshot: DaemonSnapshot, version?: string): boolean;
|
|
33
33
|
/** Caller must hold the daemon start lock until restore completes. */
|
|
34
34
|
export declare function suspendDaemonForExclusiveAccessLocked(config: ResolvedDinoxConfig, timeoutMs: number, options?: {
|
|
35
35
|
snapshot?: DaemonSnapshot;
|
|
36
36
|
forceStop?: boolean;
|
|
37
|
+
deadlineAtMs?: number;
|
|
37
38
|
dependencies?: Partial<DaemonLifecycleDependencies>;
|
|
38
39
|
}): Promise<SuspendedDaemon>;
|
|
39
40
|
/** Caller must hold the daemon start lock. */
|
|
40
|
-
export declare function restoreSuspendedDaemonLocked(suspended: SuspendedDaemon, overrides?: Partial<DaemonLifecycleDependencies
|
|
41
|
+
export declare function restoreSuspendedDaemonLocked(suspended: SuspendedDaemon, overrides?: Partial<DaemonLifecycleDependencies>, options?: {
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
}): Promise<boolean>;
|
|
41
44
|
export declare function withDaemonExclusiveAccess<T>(config: ResolvedDinoxConfig, timeoutMs: number, run: (control: DaemonExclusiveAccessControl) => Promise<T>, overrides?: Partial<DaemonLifecycleDependencies>, options?: {
|
|
42
45
|
deadlineAtMs?: number;
|
|
46
|
+
operationDeadlineAtMs?: number;
|
|
47
|
+
cleanupFailureMode?: 'warn' | 'throw';
|
|
43
48
|
}): Promise<T>;
|
|
44
49
|
export {};
|
package/dist/daemon/lifecycle.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { getPowerSyncDbPath } from '../config/paths.js';
|
|
3
3
|
import { fingerprintDaemonRuntimeConfig } from '../config/resolve.js';
|
|
4
|
+
import { remainingDeadlineMs, runWithinDeadline } from '../utils/deadline.js';
|
|
5
|
+
import { DinoxError } from '../utils/errors.js';
|
|
4
6
|
import { printHumanReadableWarning } from '../utils/output.js';
|
|
5
7
|
import { getPackageVersion } from '../utils/version.js';
|
|
6
8
|
import { getDaemonInfo, isDaemonFresh, shutdownDaemonForExclusiveAccess, } from './client.js';
|
|
@@ -22,6 +24,21 @@ function dependencies(overrides) {
|
|
|
22
24
|
function errorMessage(error) {
|
|
23
25
|
return error instanceof Error ? error.message : String(error);
|
|
24
26
|
}
|
|
27
|
+
function createLifecycleDeadlineError(phase, action) {
|
|
28
|
+
return new DinoxError(`Sync deadline exceeded while ${action}.`, {
|
|
29
|
+
code: 'SYNC_TIMEOUT',
|
|
30
|
+
details: { phase },
|
|
31
|
+
suggestion: 'Run `dino doctor --format json` to verify the local runtime before retrying sync.',
|
|
32
|
+
recoverable: true,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function requireRemainingDeadlineMs(deadlineAtMs, maximumTimeoutMs, phase, action) {
|
|
36
|
+
const remainingMs = remainingDeadlineMs(deadlineAtMs, maximumTimeoutMs);
|
|
37
|
+
if (deadlineAtMs !== undefined && remainingMs <= 0) {
|
|
38
|
+
throw createLifecycleDeadlineError(phase, action);
|
|
39
|
+
}
|
|
40
|
+
return Math.max(1, remainingMs);
|
|
41
|
+
}
|
|
25
42
|
function snapshotPort(snapshot) {
|
|
26
43
|
const pidFileMatches = Boolean(snapshot.info
|
|
27
44
|
&& snapshot.pidInfo
|
|
@@ -29,10 +46,10 @@ function snapshotPort(snapshot) {
|
|
|
29
46
|
&& snapshot.pidInfo.instanceId === snapshot.info.instanceId);
|
|
30
47
|
return pidFileMatches ? snapshot.pidInfo?.port ?? DEFAULT_DAEMON_PORT : DEFAULT_DAEMON_PORT;
|
|
31
48
|
}
|
|
32
|
-
export async function captureDaemonSnapshot(overrides = {}) {
|
|
49
|
+
export async function captureDaemonSnapshot(overrides = {}, timeoutMs) {
|
|
33
50
|
const deps = dependencies(overrides);
|
|
34
51
|
return {
|
|
35
|
-
info: await deps.getDaemonInfo(),
|
|
52
|
+
info: await deps.getDaemonInfo(timeoutMs),
|
|
36
53
|
pidInfo: deps.readPid(),
|
|
37
54
|
socketExists: process.platform !== 'win32' && existsSync(getDaemonSocketPath()),
|
|
38
55
|
};
|
|
@@ -44,12 +61,13 @@ export function daemonSnapshotIsFresh(config, snapshot, version = getPackageVers
|
|
|
44
61
|
/** Caller must hold the daemon start lock until restore completes. */
|
|
45
62
|
export async function suspendDaemonForExclusiveAccessLocked(config, timeoutMs, options = {}) {
|
|
46
63
|
const deps = dependencies(options.dependencies ?? {});
|
|
47
|
-
const
|
|
64
|
+
const remainingTimeoutMs = (phase, action) => requireRemainingDeadlineMs(options.deadlineAtMs, timeoutMs, phase, action);
|
|
65
|
+
const snapshot = options.snapshot ?? await captureDaemonSnapshot(deps, remainingTimeoutMs('daemon-snapshot', 'inspecting the background daemon'));
|
|
48
66
|
const wasFresh = daemonSnapshotIsFresh(config, snapshot, deps.getPackageVersion());
|
|
49
67
|
const daemonUsesTargetDatabase = !snapshot.info
|
|
50
68
|
|| getPowerSyncDbPath(snapshot.info.userId) === getPowerSyncDbPath(config.auth.userId);
|
|
51
69
|
const wasStopped = options.forceStop || daemonUsesTargetDatabase
|
|
52
|
-
? await deps.shutdownDaemon(Math.min(
|
|
70
|
+
? await deps.shutdownDaemon(Math.min(remainingTimeoutMs('daemon-shutdown', 'stopping the background daemon'), 10_000), snapshot.info?.instanceId)
|
|
53
71
|
: false;
|
|
54
72
|
return {
|
|
55
73
|
snapshot,
|
|
@@ -59,22 +77,26 @@ export async function suspendDaemonForExclusiveAccessLocked(config, timeoutMs, o
|
|
|
59
77
|
};
|
|
60
78
|
}
|
|
61
79
|
/** Caller must hold the daemon start lock. */
|
|
62
|
-
export async function restoreSuspendedDaemonLocked(suspended, overrides = {}) {
|
|
80
|
+
export async function restoreSuspendedDaemonLocked(suspended, overrides = {}, options = {}) {
|
|
63
81
|
if (!suspended.wasStopped || !suspended.wasFresh) {
|
|
64
82
|
return false;
|
|
65
83
|
}
|
|
66
84
|
const deps = dependencies(overrides);
|
|
67
|
-
await deps.startDaemonLocked(suspended.port, true, {
|
|
85
|
+
await deps.startDaemonLocked(suspended.port, true, {
|
|
86
|
+
quiet: true,
|
|
87
|
+
timeoutMs: options.timeoutMs,
|
|
88
|
+
});
|
|
68
89
|
return true;
|
|
69
90
|
}
|
|
70
91
|
export async function withDaemonExclusiveAccess(config, timeoutMs, run, overrides = {}, options = {}) {
|
|
71
92
|
const deps = dependencies(overrides);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const releaseStartLock = await deps.acquireStartLock(
|
|
93
|
+
const operationDeadlineAtMs = options.operationDeadlineAtMs ?? options.deadlineAtMs;
|
|
94
|
+
const remainingOperationTimeoutMs = (phase, action) => requireRemainingDeadlineMs(operationDeadlineAtMs, timeoutMs, phase, action);
|
|
95
|
+
const remainingCleanupTimeoutMs = () => Math.max(1, remainingDeadlineMs(options.deadlineAtMs, timeoutMs));
|
|
96
|
+
const releaseStartLock = await deps.acquireStartLock(remainingOperationTimeoutMs('daemon-lock-acquire', 'acquiring the daemon lifecycle lock'));
|
|
76
97
|
let suspended = null;
|
|
77
98
|
let restoreAllowed = true;
|
|
99
|
+
let cleanupError;
|
|
78
100
|
let outcome;
|
|
79
101
|
const control = {
|
|
80
102
|
suppressRestore() {
|
|
@@ -82,7 +104,8 @@ export async function withDaemonExclusiveAccess(config, timeoutMs, run, override
|
|
|
82
104
|
},
|
|
83
105
|
};
|
|
84
106
|
try {
|
|
85
|
-
suspended = await suspendDaemonForExclusiveAccessLocked(config,
|
|
107
|
+
suspended = await suspendDaemonForExclusiveAccessLocked(config, remainingOperationTimeoutMs('daemon-suspend', 'suspending the background daemon'), {
|
|
108
|
+
deadlineAtMs: operationDeadlineAtMs,
|
|
86
109
|
dependencies: deps,
|
|
87
110
|
});
|
|
88
111
|
try {
|
|
@@ -97,22 +120,39 @@ export async function withDaemonExclusiveAccess(config, timeoutMs, run, override
|
|
|
97
120
|
}
|
|
98
121
|
finally {
|
|
99
122
|
if (suspended && restoreAllowed) {
|
|
123
|
+
const suspendedDaemon = suspended;
|
|
100
124
|
try {
|
|
101
|
-
await restoreSuspendedDaemonLocked(
|
|
125
|
+
await runWithinDeadline(() => restoreSuspendedDaemonLocked(suspendedDaemon, deps, {
|
|
126
|
+
timeoutMs: remainingCleanupTimeoutMs(),
|
|
127
|
+
}), {
|
|
128
|
+
deadlineAtMs: options.deadlineAtMs,
|
|
129
|
+
maximumTimeoutMs: timeoutMs,
|
|
130
|
+
createTimeoutError: () => createLifecycleDeadlineError('daemon-restore', 'restoring the background daemon'),
|
|
131
|
+
});
|
|
102
132
|
}
|
|
103
133
|
catch (error) {
|
|
134
|
+
cleanupError = error;
|
|
104
135
|
deps.printWarning(`warning: failed to restore daemon after local command: ${errorMessage(error)}`);
|
|
105
136
|
}
|
|
106
137
|
}
|
|
107
138
|
try {
|
|
108
|
-
await releaseStartLock
|
|
139
|
+
await runWithinDeadline(releaseStartLock, {
|
|
140
|
+
deadlineAtMs: options.deadlineAtMs,
|
|
141
|
+
maximumTimeoutMs: timeoutMs,
|
|
142
|
+
createTimeoutError: () => createLifecycleDeadlineError('daemon-lock-release', 'releasing the daemon lifecycle lock'),
|
|
143
|
+
runWhenExpired: true,
|
|
144
|
+
});
|
|
109
145
|
}
|
|
110
146
|
catch (error) {
|
|
147
|
+
cleanupError ??= error;
|
|
111
148
|
deps.printWarning(`warning: failed to release daemon lifecycle lock: ${errorMessage(error)}`);
|
|
112
149
|
}
|
|
113
150
|
}
|
|
114
151
|
if (!outcome.ok) {
|
|
115
152
|
throw outcome.error;
|
|
116
153
|
}
|
|
154
|
+
if (cleanupError && options.cleanupFailureMode === 'throw') {
|
|
155
|
+
throw cleanupError;
|
|
156
|
+
}
|
|
117
157
|
return outcome.value;
|
|
118
158
|
}
|
package/dist/daemon/pid.d.ts
CHANGED
|
@@ -19,5 +19,5 @@ export declare function removePid(expectedInstanceId?: string, options?: {
|
|
|
19
19
|
expectedPid?: number;
|
|
20
20
|
}): boolean;
|
|
21
21
|
export declare function isProcessRunning(pid: number): boolean;
|
|
22
|
-
export declare function isLegacyDaemonProcess(pid: number, daemonUptimeMs: number): Promise<boolean>;
|
|
22
|
+
export declare function isLegacyDaemonProcess(pid: number, daemonUptimeMs: number, timeoutMs?: number): Promise<boolean>;
|
|
23
23
|
export declare function acquireDaemonStartLock(timeoutMs?: number): Promise<() => Promise<void>>;
|
package/dist/daemon/pid.js
CHANGED
|
@@ -139,10 +139,13 @@ function commandLooksLikeLegacyDaemon(command) {
|
|
|
139
139
|
return /(?:^|[\\/\s])dino(?:x)?(?:\.[cm]?[jt]s)?["']?\s+daemon\s+start(?:\s|$)/i.test(command)
|
|
140
140
|
&& /(?:^|\s)--no-detach(?:\s|$)/.test(command);
|
|
141
141
|
}
|
|
142
|
-
export async function isLegacyDaemonProcess(pid, daemonUptimeMs) {
|
|
142
|
+
export async function isLegacyDaemonProcess(pid, daemonUptimeMs, timeoutMs = 2_000) {
|
|
143
143
|
if (!Number.isInteger(pid) || pid <= 0 || !Number.isFinite(daemonUptimeMs) || daemonUptimeMs < 0) {
|
|
144
144
|
return false;
|
|
145
145
|
}
|
|
146
|
+
const commandTimeoutMs = Number.isFinite(timeoutMs)
|
|
147
|
+
? Math.max(1, Math.min(2_000, Math.floor(timeoutMs)))
|
|
148
|
+
: 2_000;
|
|
146
149
|
try {
|
|
147
150
|
if (process.platform === 'win32') {
|
|
148
151
|
const command = [
|
|
@@ -152,7 +155,7 @@ export async function isLegacyDaemonProcess(pid, daemonUptimeMs) {
|
|
|
152
155
|
' [Console]::Write($p.CommandLine);',
|
|
153
156
|
'}',
|
|
154
157
|
].join(' ');
|
|
155
|
-
const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', command], { encoding: 'utf8', timeout:
|
|
158
|
+
const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', command], { encoding: 'utf8', timeout: commandTimeoutMs, maxBuffer: 64 * 1024 });
|
|
156
159
|
const newline = stdout.indexOf('\n');
|
|
157
160
|
if (newline < 0) {
|
|
158
161
|
return false;
|
|
@@ -163,7 +166,7 @@ export async function isLegacyDaemonProcess(pid, daemonUptimeMs) {
|
|
|
163
166
|
&& Math.abs(processUptimeMs - daemonUptimeMs) <= LEGACY_DAEMON_UPTIME_TOLERANCE_MS
|
|
164
167
|
&& commandLooksLikeLegacyDaemon(stdout.slice(newline + 1).trim());
|
|
165
168
|
}
|
|
166
|
-
const { stdout } = await execFileAsync('ps', ['-ww', '-p', String(pid), '-o', 'etime=', '-o', 'command='], { encoding: 'utf8', timeout:
|
|
169
|
+
const { stdout } = await execFileAsync('ps', ['-ww', '-p', String(pid), '-o', 'etime=', '-o', 'command='], { encoding: 'utf8', timeout: commandTimeoutMs, maxBuffer: 64 * 1024 });
|
|
167
170
|
const match = stdout.trim().match(/^(\S+)\s+([\s\S]+)$/);
|
|
168
171
|
if (!match) {
|
|
169
172
|
return false;
|
package/dist/dinox.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { createCli } from './cli.js';
|
|
3
3
|
import { buildStructuredErrorPayload, isDinoxError } from './utils/errors.js';
|
|
4
4
|
import { clearRequestedStructuredOutputFormat, parseStructuredOutputFormatFromArgv, printError, printHumanReadableError, setRequestedStructuredOutputFormat, } from './utils/output.js';
|
|
5
|
+
import { exitProcessAfterFlushing } from './utils/processExit.js';
|
|
5
6
|
function normalizeArgv(argv) {
|
|
6
7
|
// pnpm/npm script forwarding can prepend a standalone "--".
|
|
7
8
|
if (argv[0] === '--') {
|
|
@@ -25,7 +26,12 @@ function isCommanderError(error) {
|
|
|
25
26
|
&& error.code.startsWith('commander.')
|
|
26
27
|
&& typeof error.exitCode === 'number';
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
+
async function exitAfterFatalCleanup(error, exitCode) {
|
|
30
|
+
if (isDinoxError(error) && error.requiresProcessExit) {
|
|
31
|
+
await exitProcessAfterFlushing(exitCode);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
main().catch(async (error) => {
|
|
29
35
|
if (isCommanderError(error)) {
|
|
30
36
|
process.exitCode = error.exitCode === 0 ? 0 : 2;
|
|
31
37
|
return;
|
|
@@ -46,6 +52,7 @@ main().catch((error) => {
|
|
|
46
52
|
setRequestedStructuredOutputFormat(format);
|
|
47
53
|
printError(payload, format);
|
|
48
54
|
clearRequestedStructuredOutputFormat();
|
|
55
|
+
await exitAfterFatalCleanup(error, exitCode);
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
51
58
|
printHumanReadableError(payload.message);
|
|
@@ -59,4 +66,5 @@ main().catch((error) => {
|
|
|
59
66
|
if (verbose && payload.stack) {
|
|
60
67
|
printHumanReadableError(payload.stack);
|
|
61
68
|
}
|
|
69
|
+
await exitAfterFatalCleanup(error, exitCode);
|
|
62
70
|
});
|
|
@@ -13,6 +13,7 @@ export declare function withExclusivePowerSync<T>(args: {
|
|
|
13
13
|
offline: boolean;
|
|
14
14
|
timeoutMs: number;
|
|
15
15
|
deadlineAtMs?: number;
|
|
16
|
+
operationDeadlineAtMs?: number;
|
|
16
17
|
waitForInitialSync?: boolean;
|
|
17
18
|
expectedTokenFingerprint?: string | null;
|
|
18
19
|
cleanupFailureMode?: 'warn' | 'throw';
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { withDaemonExclusiveAccess } from '../daemon/lifecycle.js';
|
|
2
|
+
import { runWithinDeadline, remainingDeadlineMs } from '../utils/deadline.js';
|
|
3
|
+
import { DinoxError } from '../utils/errors.js';
|
|
2
4
|
import { printHumanReadableWarning } from '../utils/output.js';
|
|
3
5
|
import { closePowerSyncAndReleaseOwner, connectPowerSync, } from './runtime.js';
|
|
4
6
|
const exclusivePowerSyncDependencies = {
|
|
@@ -10,16 +12,24 @@ const exclusivePowerSyncDependencies = {
|
|
|
10
12
|
function errorMessage(error) {
|
|
11
13
|
return error instanceof Error ? error.message : String(error);
|
|
12
14
|
}
|
|
15
|
+
function createRuntimeCleanupDeadlineError() {
|
|
16
|
+
return new DinoxError('Sync deadline exceeded while closing the local PowerSync runtime.', {
|
|
17
|
+
code: 'SYNC_TIMEOUT',
|
|
18
|
+
details: { phase: 'powersync-cleanup' },
|
|
19
|
+
suggestion: 'Run `dino doctor --format json` to verify the local runtime before retrying sync.',
|
|
20
|
+
recoverable: true,
|
|
21
|
+
requiresProcessExit: true,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
13
24
|
export async function withExclusivePowerSync(args, run, overrides = {}) {
|
|
14
25
|
const dependencies = { ...exclusivePowerSyncDependencies, ...overrides };
|
|
15
|
-
const { cleanupFailureMode, deadlineAtMs, ...connectArgs } = args;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return dependencies.withDaemonExclusiveAccess(args.config, remainingTimeoutMs(), async (daemonLifecycle) => {
|
|
26
|
+
const { cleanupFailureMode, deadlineAtMs, operationDeadlineAtMs = deadlineAtMs, ...connectArgs } = args;
|
|
27
|
+
const remainingOperationTimeoutMs = () => Math.max(1, remainingDeadlineMs(operationDeadlineAtMs, args.timeoutMs));
|
|
28
|
+
const remainingTotalTimeoutMs = () => Math.max(1, remainingDeadlineMs(deadlineAtMs, args.timeoutMs));
|
|
29
|
+
return dependencies.withDaemonExclusiveAccess(args.config, remainingTotalTimeoutMs(), async (daemonLifecycle) => {
|
|
20
30
|
const connected = await dependencies.connectPowerSync({
|
|
21
31
|
...connectArgs,
|
|
22
|
-
timeoutMs:
|
|
32
|
+
timeoutMs: remainingOperationTimeoutMs(),
|
|
23
33
|
});
|
|
24
34
|
let outcome;
|
|
25
35
|
try {
|
|
@@ -30,7 +40,11 @@ export async function withExclusivePowerSync(args, run, overrides = {}) {
|
|
|
30
40
|
}
|
|
31
41
|
let cleanupError;
|
|
32
42
|
try {
|
|
33
|
-
await dependencies.closePowerSyncAndReleaseOwner(connected.db, connected.releaseOwner)
|
|
43
|
+
await runWithinDeadline(() => dependencies.closePowerSyncAndReleaseOwner(connected.db, connected.releaseOwner), {
|
|
44
|
+
deadlineAtMs,
|
|
45
|
+
maximumTimeoutMs: args.timeoutMs,
|
|
46
|
+
createTimeoutError: createRuntimeCleanupDeadlineError,
|
|
47
|
+
});
|
|
34
48
|
}
|
|
35
49
|
catch (error) {
|
|
36
50
|
cleanupError = error;
|
|
@@ -44,5 +58,9 @@ export async function withExclusivePowerSync(args, run, overrides = {}) {
|
|
|
44
58
|
throw cleanupError;
|
|
45
59
|
}
|
|
46
60
|
return outcome.value;
|
|
47
|
-
}, {}, {
|
|
61
|
+
}, {}, {
|
|
62
|
+
deadlineAtMs,
|
|
63
|
+
operationDeadlineAtMs,
|
|
64
|
+
cleanupFailureMode,
|
|
65
|
+
});
|
|
48
66
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PowerSyncDatabase } from '@powersync/node';
|
|
2
|
-
import type { AbstractPowerSyncDatabase
|
|
2
|
+
import type { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
3
3
|
import type { ResolvedDinoxConfig } from '../config/types.js';
|
|
4
|
+
import type { SyncStatusRaw } from './syncGate.js';
|
|
4
5
|
export type ConnectResult = {
|
|
5
6
|
db: PowerSyncDatabase;
|
|
6
7
|
dbPath: string;
|
|
@@ -29,7 +30,7 @@ export declare function getStatusSnapshot(db: AbstractPowerSyncDatabase): {
|
|
|
29
30
|
message: string;
|
|
30
31
|
};
|
|
31
32
|
};
|
|
32
|
-
raw:
|
|
33
|
+
raw: SyncStatusRaw;
|
|
33
34
|
};
|
|
34
35
|
export declare function connectPowerSync(args: {
|
|
35
36
|
config: ResolvedDinoxConfig;
|
|
@@ -88,8 +88,25 @@ async function ensureDataDir() {
|
|
|
88
88
|
await fs.mkdir(dir, { recursive: true, mode: 0o700 });
|
|
89
89
|
return dir;
|
|
90
90
|
}
|
|
91
|
+
function readSyncStatus(status) {
|
|
92
|
+
if (!status)
|
|
93
|
+
return {};
|
|
94
|
+
return {
|
|
95
|
+
connected: status.connected,
|
|
96
|
+
connecting: status.connecting,
|
|
97
|
+
hasSynced: status.hasSynced,
|
|
98
|
+
lastSyncedAt: status.lastSyncedAt,
|
|
99
|
+
dataFlow: {
|
|
100
|
+
downloading: status.downloading,
|
|
101
|
+
uploading: status.uploading,
|
|
102
|
+
downloadError: status.downloadError,
|
|
103
|
+
uploadError: status.uploadError,
|
|
104
|
+
},
|
|
105
|
+
priorityStatusEntries: status.priorityStatusEntries,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
91
108
|
export function getStatusSnapshot(db) {
|
|
92
|
-
const raw = db.currentStatus
|
|
109
|
+
const raw = readSyncStatus(db.currentStatus);
|
|
93
110
|
const lastSyncedAt = raw.lastSyncedAt instanceof Date ? raw.lastSyncedAt.toISOString() : raw.lastSyncedAt ?? null;
|
|
94
111
|
const dataFlow = raw.dataFlow ?? {};
|
|
95
112
|
return {
|
|
@@ -185,8 +202,7 @@ export async function connectPowerSync(args) {
|
|
|
185
202
|
? createPowerSyncUploadHandler({
|
|
186
203
|
authorization: args.config.auth.authorization,
|
|
187
204
|
uploadBaseUrl: args.config.powersync.uploadBaseUrl,
|
|
188
|
-
|
|
189
|
-
uploadV2Path: args.config.powersync.uploadV2Path,
|
|
205
|
+
uploadPath: args.config.powersync.uploadPath,
|
|
190
206
|
timeoutMs: args.timeoutMs,
|
|
191
207
|
})
|
|
192
208
|
: undefined;
|
|
@@ -1,78 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const c_card_box: Table<{
|
|
3
|
-
id: import("@powersync/common").BaseColumnType<string | null>;
|
|
4
|
-
name: import("@powersync/common").BaseColumnType<string | null>;
|
|
5
|
-
type: import("@powersync/common").BaseColumnType<string | null>;
|
|
6
|
-
cover_url: import("@powersync/common").BaseColumnType<string | null>;
|
|
7
|
-
prompt: import("@powersync/common").BaseColumnType<string | null>;
|
|
8
|
-
headers: import("@powersync/common").BaseColumnType<string | null>;
|
|
9
|
-
priority: import("@powersync/common").BaseColumnType<number | null>;
|
|
10
|
-
created_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
11
|
-
updated_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
12
|
-
extra_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
13
|
-
user_no: import("@powersync/common").BaseColumnType<string | null>;
|
|
14
|
-
is_del: import("@powersync/common").BaseColumnType<number | null>;
|
|
15
|
-
template_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
16
|
-
}>;
|
|
17
|
-
export declare const c_card_note: Table<{
|
|
18
|
-
id: import("@powersync/common").BaseColumnType<string | null>;
|
|
19
|
-
box_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
20
|
-
content: import("@powersync/common").BaseColumnType<string | null>;
|
|
21
|
-
created_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
22
|
-
updated_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
23
|
-
extra_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
24
|
-
user_no: import("@powersync/common").BaseColumnType<string | null>;
|
|
25
|
-
is_del: import("@powersync/common").BaseColumnType<number | null>;
|
|
26
|
-
origin_note_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
27
|
-
origin_type: import("@powersync/common").BaseColumnType<string | null>;
|
|
28
|
-
output_type: import("@powersync/common").BaseColumnType<string | null>;
|
|
29
|
-
is_array: import("@powersync/common").BaseColumnType<number | null>;
|
|
30
|
-
}>;
|
|
31
|
-
export declare const c_cmd: Table<{
|
|
32
|
-
id: import("@powersync/common").BaseColumnType<string | null>;
|
|
33
|
-
zone: import("@powersync/common").BaseColumnType<string | null>;
|
|
34
|
-
type: import("@powersync/common").BaseColumnType<string | null>;
|
|
35
|
-
cmd: import("@powersync/common").BaseColumnType<string | null>;
|
|
36
|
-
name: import("@powersync/common").BaseColumnType<string | null>;
|
|
37
|
-
priority: import("@powersync/common").BaseColumnType<number | null>;
|
|
38
|
-
is_show: import("@powersync/common").BaseColumnType<number | null>;
|
|
39
|
-
description: import("@powersync/common").BaseColumnType<string | null>;
|
|
40
|
-
extra_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
41
|
-
user_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
42
|
-
insert_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
43
|
-
update_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
44
|
-
is_del: import("@powersync/common").BaseColumnType<number | null>;
|
|
45
|
-
template_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
46
|
-
meta_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
47
|
-
output: import("@powersync/common").BaseColumnType<string | null>;
|
|
48
|
-
output_param: import("@powersync/common").BaseColumnType<string | null>;
|
|
49
|
-
category: import("@powersync/common").BaseColumnType<string | null>;
|
|
50
|
-
}>;
|
|
51
|
-
export declare const c_note_template: Table<{
|
|
52
|
-
id: import("@powersync/common").BaseColumnType<string | null>;
|
|
53
|
-
content: import("@powersync/common").BaseColumnType<string | null>;
|
|
54
|
-
name: import("@powersync/common").BaseColumnType<string | null>;
|
|
55
|
-
priority: import("@powersync/common").BaseColumnType<number | null>;
|
|
56
|
-
is_show: import("@powersync/common").BaseColumnType<number | null>;
|
|
57
|
-
extra_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
58
|
-
user_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
59
|
-
insert_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
60
|
-
update_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
61
|
-
is_del: import("@powersync/common").BaseColumnType<number | null>;
|
|
62
|
-
}>;
|
|
63
|
-
export declare const c_zettel_box: Table<{
|
|
64
|
-
id: import("@powersync/common").BaseColumnType<string | null>;
|
|
65
|
-
name: import("@powersync/common").BaseColumnType<string | null>;
|
|
66
|
-
path: import("@powersync/common").BaseColumnType<string | null>;
|
|
67
|
-
parent_id: import("@powersync/common").BaseColumnType<string | null>;
|
|
68
|
-
description: import("@powersync/common").BaseColumnType<string | null>;
|
|
69
|
-
color: import("@powersync/common").BaseColumnType<string | null>;
|
|
70
|
-
priority: import("@powersync/common").BaseColumnType<number | null>;
|
|
71
|
-
is_show: import("@powersync/common").BaseColumnType<number | null>;
|
|
72
|
-
cover_url: import("@powersync/common").BaseColumnType<string | null>;
|
|
73
|
-
created_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
74
|
-
updated_at: import("@powersync/common").BaseColumnType<string | null>;
|
|
75
|
-
extra_data: import("@powersync/common").BaseColumnType<string | null>;
|
|
76
|
-
user_no: import("@powersync/common").BaseColumnType<string | null>;
|
|
77
|
-
is_del: import("@powersync/common").BaseColumnType<number | null>;
|
|
78
|
-
}>;
|
|
1
|
+
export { c_card_box, c_card_note, c_cmd, c_note_template, c_zettel_box, } from './electronCanonical.js';
|
|
@@ -1,78 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export const c_card_box = new Table({
|
|
3
|
-
id: column.text,
|
|
4
|
-
name: column.text,
|
|
5
|
-
type: column.text,
|
|
6
|
-
cover_url: column.text,
|
|
7
|
-
prompt: column.text,
|
|
8
|
-
headers: column.text,
|
|
9
|
-
priority: column.integer,
|
|
10
|
-
created_at: column.text,
|
|
11
|
-
updated_at: column.text,
|
|
12
|
-
extra_data: column.text,
|
|
13
|
-
user_no: column.text,
|
|
14
|
-
is_del: column.integer,
|
|
15
|
-
template_id: column.text,
|
|
16
|
-
});
|
|
17
|
-
export const c_card_note = new Table({
|
|
18
|
-
id: column.text,
|
|
19
|
-
box_id: column.text,
|
|
20
|
-
content: column.text,
|
|
21
|
-
created_at: column.text,
|
|
22
|
-
updated_at: column.text,
|
|
23
|
-
extra_data: column.text,
|
|
24
|
-
user_no: column.text,
|
|
25
|
-
is_del: column.integer,
|
|
26
|
-
origin_note_id: column.text,
|
|
27
|
-
origin_type: column.text,
|
|
28
|
-
output_type: column.text,
|
|
29
|
-
is_array: column.integer,
|
|
30
|
-
});
|
|
31
|
-
export const c_cmd = new Table({
|
|
32
|
-
id: column.text,
|
|
33
|
-
zone: column.text,
|
|
34
|
-
type: column.text,
|
|
35
|
-
cmd: column.text,
|
|
36
|
-
name: column.text,
|
|
37
|
-
priority: column.integer,
|
|
38
|
-
is_show: column.integer,
|
|
39
|
-
description: column.text,
|
|
40
|
-
extra_data: column.text,
|
|
41
|
-
user_id: column.text,
|
|
42
|
-
insert_at: column.text,
|
|
43
|
-
update_at: column.text,
|
|
44
|
-
is_del: column.integer,
|
|
45
|
-
template_id: column.text,
|
|
46
|
-
meta_data: column.text,
|
|
47
|
-
output: column.text,
|
|
48
|
-
output_param: column.text,
|
|
49
|
-
category: column.text,
|
|
50
|
-
});
|
|
51
|
-
export const c_note_template = new Table({
|
|
52
|
-
id: column.text,
|
|
53
|
-
content: column.text,
|
|
54
|
-
name: column.text,
|
|
55
|
-
priority: column.integer,
|
|
56
|
-
is_show: column.integer,
|
|
57
|
-
extra_data: column.text,
|
|
58
|
-
user_id: column.text,
|
|
59
|
-
insert_at: column.text,
|
|
60
|
-
update_at: column.text,
|
|
61
|
-
is_del: column.integer,
|
|
62
|
-
});
|
|
63
|
-
export const c_zettel_box = new Table({
|
|
64
|
-
id: column.text,
|
|
65
|
-
name: column.text,
|
|
66
|
-
path: column.text,
|
|
67
|
-
parent_id: column.text,
|
|
68
|
-
description: column.text,
|
|
69
|
-
color: column.text,
|
|
70
|
-
priority: column.integer,
|
|
71
|
-
is_show: column.integer,
|
|
72
|
-
cover_url: column.text,
|
|
73
|
-
created_at: column.text,
|
|
74
|
-
updated_at: column.text,
|
|
75
|
-
extra_data: column.text,
|
|
76
|
-
user_no: column.text,
|
|
77
|
-
is_del: column.integer,
|
|
78
|
-
});
|
|
1
|
+
export { c_card_box, c_card_note, c_cmd, c_note_template, c_zettel_box, } from './electronCanonical.js';
|