@dinoxx/dinox-cli 2.1.1 → 2.3.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/dist/cli.js +4 -0
- package/dist/commands/domain/options.d.ts +10 -0
- package/dist/commands/domain/options.js +75 -0
- package/dist/commands/domain/run.d.ts +24 -0
- package/dist/commands/domain/run.js +137 -0
- package/dist/commands/notes/actions.js +72 -20
- package/dist/commands/notes/createFromTemplate.d.ts +35 -0
- package/dist/commands/notes/createFromTemplate.js +58 -0
- package/dist/commands/notes/descriptors.js +12 -5
- package/dist/commands/notes/dryRun.d.ts +1 -0
- package/dist/commands/notes/dryRun.js +8 -2
- package/dist/commands/notes/repo/read.js +4 -23
- package/dist/commands/notes/repo/shared.d.ts +2 -0
- package/dist/commands/notes/repo/write.d.ts +3 -0
- package/dist/commands/notes/repo/write.js +16 -5
- package/dist/commands/properties/index.d.ts +16 -0
- package/dist/commands/properties/index.js +640 -0
- package/dist/commands/properties/repo.d.ts +150 -0
- package/dist/commands/properties/repo.js +272 -0
- package/dist/commands/savedViews/fields.d.ts +28 -0
- package/dist/commands/savedViews/fields.js +87 -0
- package/dist/commands/savedViews/index.js +203 -164
- package/dist/commands/savedViews/model.d.ts +27 -69
- package/dist/commands/savedViews/model.js +63 -279
- package/dist/commands/savedViews/repo.d.ts +64 -62
- package/dist/commands/savedViews/repo.js +309 -428
- package/dist/commands/schema/renderSkills.js +29 -5
- package/dist/commands/schema/spec.js +4 -0
- package/dist/commands/templates/index.d.ts +4 -0
- package/dist/commands/templates/index.js +290 -0
- package/dist/commands/templates/model.d.ts +12 -34
- package/dist/commands/templates/model.js +39 -83
- package/dist/commands/templates/repo.d.ts +53 -0
- package/dist/commands/templates/repo.js +78 -0
- package/dist/skills/registry.js +7 -0
- package/dist/utils/errorCodes.d.ts +212 -0
- package/dist/utils/errorCodes.js +53 -0
- package/dist/vendor/electron/domain/note-templates.d.ts +3 -0
- package/dist/vendor/electron/domain/note-templates.js +232 -0
- package/dist/vendor/electron/domain/properties.d.ts +10 -0
- package/dist/vendor/electron/domain/properties.js +1538 -0
- package/dist/vendor/electron/domain/saved-view-analytics.d.ts +45 -0
- package/dist/vendor/electron/domain/saved-view-analytics.js +365 -0
- package/dist/vendor/electron/domain/saved-view-relative-date.d.ts +21 -0
- package/dist/vendor/electron/domain/saved-view-relative-date.js +153 -0
- package/dist/vendor/electron/domain/saved-views.d.ts +61 -0
- package/dist/vendor/electron/domain/saved-views.js +1117 -0
- package/dist/vendor/electron/rpc.d.ts +22 -0
- package/dist/vendor/electron/rpc.js +27 -0
- package/dist/vendor/electron/shared/ai-errors.d.ts +11 -0
- package/dist/vendor/electron/shared/ai-errors.js +107 -0
- package/dist/vendor/electron/shared/external-types.d.ts +2 -0
- package/dist/vendor/electron/shared/external-types.js +1 -0
- package/dist/vendor/electron/shared/index.d.ts +9 -0
- package/dist/vendor/electron/shared/index.js +7 -0
- package/dist/vendor/electron/shared/note-properties.d.ts +312 -0
- package/dist/vendor/electron/shared/note-properties.js +982 -0
- package/dist/vendor/electron/shared/note-templates.d.ts +82 -0
- package/dist/vendor/electron/shared/note-templates.js +84 -0
- package/dist/vendor/electron/shared/powersync-read-models.d.ts +1710 -0
- package/dist/vendor/electron/shared/powersync-read-models.js +1 -0
- package/dist/vendor/electron/shared/saved-views.d.ts +394 -0
- package/dist/vendor/electron/shared/saved-views.js +981 -0
- package/dist/vendor/electron/sql-utils.d.ts +5 -0
- package/dist/vendor/electron/sql-utils.js +32 -0
- package/package.json +6 -3
- package/dist/commands/savedViews/semantics.d.ts +0 -46
- package/dist/commands/savedViews/semantics.js +0 -738
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AbstractPowerSyncDatabase } from '@powersync/common';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { PowerSyncCommandRunResponse } from './shared/index.js';
|
|
4
|
+
export type SqlExecutor = {
|
|
5
|
+
execute(sql: string, params?: unknown[]): Promise<unknown>;
|
|
6
|
+
getAll<T = unknown>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
7
|
+
getOptional<T = unknown>(sql: string, params?: unknown[]): Promise<T | null | undefined>;
|
|
8
|
+
};
|
|
9
|
+
export type ReadModelDefinition<TInput = any, TRow = unknown> = {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly inputSchema: z.ZodType<TInput>;
|
|
12
|
+
readonly fetch: (db: AbstractPowerSyncDatabase, input: TInput) => Promise<TRow[]>;
|
|
13
|
+
readonly tables: (input: TInput) => string[];
|
|
14
|
+
};
|
|
15
|
+
export type CommandDefinition<TInput = any, TResult = unknown> = {
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly inputSchema: z.ZodType<TInput>;
|
|
18
|
+
readonly run: (db: AbstractPowerSyncDatabase, input: TInput) => Promise<PowerSyncCommandRunResponse<TResult>>;
|
|
19
|
+
};
|
|
20
|
+
export declare function defineReadModel<TInput, TRow>(definition: ReadModelDefinition<TInput, TRow>): ReadModelDefinition<TInput, TRow>;
|
|
21
|
+
export declare function defineCommand<TInput, TResult>(definition: CommandDefinition<TInput, TResult>): CommandDefinition<TInput, TResult>;
|
|
22
|
+
export declare function rowsFromResult(result: unknown): Array<Record<string, unknown>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function defineReadModel(definition) {
|
|
2
|
+
return definition;
|
|
3
|
+
}
|
|
4
|
+
export function defineCommand(definition) {
|
|
5
|
+
return definition;
|
|
6
|
+
}
|
|
7
|
+
// Mirrors desktop PowerSyncTransportUtils.rowsFromResult.
|
|
8
|
+
export function rowsFromResult(result) {
|
|
9
|
+
if (!result)
|
|
10
|
+
return [];
|
|
11
|
+
if (Array.isArray(result))
|
|
12
|
+
return result;
|
|
13
|
+
const value = result;
|
|
14
|
+
if (value.rows?._array)
|
|
15
|
+
return value.rows._array;
|
|
16
|
+
const rows = value.rows;
|
|
17
|
+
if (rows && typeof rows.length === 'number' && typeof rows.item === 'function') {
|
|
18
|
+
const item = rows.item;
|
|
19
|
+
const values = [];
|
|
20
|
+
for (let index = 0; index < rows.length; index += 1)
|
|
21
|
+
values.push(item.call(rows, index));
|
|
22
|
+
return values;
|
|
23
|
+
}
|
|
24
|
+
if (value.value !== undefined)
|
|
25
|
+
return value.value;
|
|
26
|
+
return [result];
|
|
27
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const AI_ERROR_CODE_AUTH_REQUIRED = "AUTH_REQUIRED";
|
|
2
|
+
export declare const AI_ERROR_CODE_FORBIDDEN = "FORBIDDEN";
|
|
3
|
+
export declare const AI_ERROR_CODE_SESSION_CHANGED = "SESSION_CHANGED";
|
|
4
|
+
export declare const AI_ERROR_CODE_INSUFFICIENT_POINTS = "INSUFFICIENT_POINTS";
|
|
5
|
+
export declare const AI_ERROR_CODE_INVALID_STRUCTURED_OUTPUT = "INVALID_STRUCTURED_OUTPUT";
|
|
6
|
+
export type AiErrorCode = typeof AI_ERROR_CODE_AUTH_REQUIRED | typeof AI_ERROR_CODE_FORBIDDEN | typeof AI_ERROR_CODE_SESSION_CHANGED | typeof AI_ERROR_CODE_INSUFFICIENT_POINTS | typeof AI_ERROR_CODE_INVALID_STRUCTURED_OUTPUT;
|
|
7
|
+
export type AgentOperationErrorKind = 'aborted' | 'auth' | 'rate_limit' | 'context_overflow' | 'transient_transport' | 'invalid_tool_input' | 'unknown_effect' | 'provider' | 'tool' | 'internal';
|
|
8
|
+
export declare function isContextOverflowErrorMessage(message: string, options?: {
|
|
9
|
+
provider?: string | null;
|
|
10
|
+
}): boolean;
|
|
11
|
+
export declare function classifyAgentOperationError(error: unknown, fallback?: Extract<AgentOperationErrorKind, 'provider' | 'tool' | 'internal'>): AgentOperationErrorKind;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Generated by scripts/sync-electron-domain.ts from dinox-electron/packages/shared/src/ai-errors.ts. Do not edit manually.
|
|
2
|
+
export const AI_ERROR_CODE_AUTH_REQUIRED = 'AUTH_REQUIRED';
|
|
3
|
+
export const AI_ERROR_CODE_FORBIDDEN = 'FORBIDDEN';
|
|
4
|
+
export const AI_ERROR_CODE_SESSION_CHANGED = 'SESSION_CHANGED';
|
|
5
|
+
export const AI_ERROR_CODE_INSUFFICIENT_POINTS = 'INSUFFICIENT_POINTS';
|
|
6
|
+
export const AI_ERROR_CODE_INVALID_STRUCTURED_OUTPUT = 'INVALID_STRUCTURED_OUTPUT';
|
|
7
|
+
// Mirrors pi-ai 1.0 `utils/overflow.ts` OVERFLOW_PATTERNS; re-diff on pi upgrades.
|
|
8
|
+
const CONTEXT_OVERFLOW_ERROR_PATTERNS = [
|
|
9
|
+
/prompt (?:is )?too long/i,
|
|
10
|
+
/prompt exceeds max length/i,
|
|
11
|
+
/request_too_large/i,
|
|
12
|
+
/input is too long for requested model/i,
|
|
13
|
+
/exceeds the context window/i,
|
|
14
|
+
/exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
|
|
15
|
+
/input token count.*exceeds the maximum/i,
|
|
16
|
+
/maximum prompt length is \d+/i,
|
|
17
|
+
/reduce the length of the messages/i,
|
|
18
|
+
/maximum context length is \d+ tokens/i,
|
|
19
|
+
/exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,
|
|
20
|
+
/input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
|
|
21
|
+
/exceeds the limit of \d+/i,
|
|
22
|
+
/exceeds the available context size/i,
|
|
23
|
+
/greater than the context length/i,
|
|
24
|
+
/context window exceeds limit/i,
|
|
25
|
+
/exceeded model token limit/i,
|
|
26
|
+
/too large for model with \d+ maximum context length/i,
|
|
27
|
+
/model_context_window_exceeded/i,
|
|
28
|
+
/prompt too long; exceeded (?:max )?context length/i,
|
|
29
|
+
/range of input length should be/i,
|
|
30
|
+
/context[_ ]length[_ ]exceeded/i,
|
|
31
|
+
/too many tokens/i,
|
|
32
|
+
/token limit exceeded/i,
|
|
33
|
+
];
|
|
34
|
+
// Cerebras reports overflow as a bodyless 400/413. Other providers send the same
|
|
35
|
+
// shape for unrelated failures, so it only counts for Cerebras (pi-ai 0.86).
|
|
36
|
+
const CEREBRAS_BODYLESS_OVERFLOW_PATTERN = /^4(?:00|13)\s*(?:status code)?\s*\(no body\)/i;
|
|
37
|
+
const NON_CONTEXT_OVERFLOW_ERROR_PATTERNS = [
|
|
38
|
+
/^(Throttling error|Service unavailable):/i,
|
|
39
|
+
/rate limit/i,
|
|
40
|
+
/too many requests/i,
|
|
41
|
+
];
|
|
42
|
+
export function isContextOverflowErrorMessage(message, options = {}) {
|
|
43
|
+
if (!message.trim()) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (NON_CONTEXT_OVERFLOW_ERROR_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (CONTEXT_OVERFLOW_ERROR_PATTERNS.some((pattern) => pattern.test(message))) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return Boolean(options.provider?.toLowerCase().includes('cerebras'))
|
|
53
|
+
&& CEREBRAS_BODYLESS_OVERFLOW_PATTERN.test(message);
|
|
54
|
+
}
|
|
55
|
+
export function classifyAgentOperationError(error, fallback = 'internal') {
|
|
56
|
+
const record = error && typeof error === 'object' && !Array.isArray(error)
|
|
57
|
+
? error
|
|
58
|
+
: null;
|
|
59
|
+
const status = readErrorStatus(record);
|
|
60
|
+
const message = collectErrorText(error).toLowerCase();
|
|
61
|
+
if (record?.name === 'AbortError' || /\b(abort(?:ed)?|cancelled|canceled)\b|已中断/.test(message)) {
|
|
62
|
+
return 'aborted';
|
|
63
|
+
}
|
|
64
|
+
if (status === 401 || status === 403 || /\b(unauthorized|forbidden|invalid api key|authentication)\b|登录|鉴权/.test(message)) {
|
|
65
|
+
return 'auth';
|
|
66
|
+
}
|
|
67
|
+
if (status === 429 || /\b(rate.?limit|too many requests|quota exceeded)\b|限流/.test(message)) {
|
|
68
|
+
return 'rate_limit';
|
|
69
|
+
}
|
|
70
|
+
if (/context.{0,16}(length|window|limit)|maximum context|too many tokens|上下文.{0,8}(超|过长)/.test(message)) {
|
|
71
|
+
return 'context_overflow';
|
|
72
|
+
}
|
|
73
|
+
if (/invalid.{0,12}(tool|argument|input)|tool.{0,12}(schema|validation)|工具.{0,8}(参数|输入).{0,8}(无效|错误)/.test(message)) {
|
|
74
|
+
return 'invalid_tool_input';
|
|
75
|
+
}
|
|
76
|
+
if (/unknown.?effect|副作用.{0,8}(未知|不确定)/.test(message)) {
|
|
77
|
+
return 'unknown_effect';
|
|
78
|
+
}
|
|
79
|
+
if ((status != null && status >= 500)
|
|
80
|
+
|| /\b(timeout|timed out|econnreset|econnrefused|enotfound|network|socket|fetch failed|service unavailable|bad gateway)\b/.test(message)) {
|
|
81
|
+
return 'transient_transport';
|
|
82
|
+
}
|
|
83
|
+
return fallback;
|
|
84
|
+
}
|
|
85
|
+
function readErrorStatus(record) {
|
|
86
|
+
if (!record)
|
|
87
|
+
return null;
|
|
88
|
+
for (const key of ['status', 'statusCode', 'httpStatus']) {
|
|
89
|
+
const value = record[key];
|
|
90
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
function collectErrorText(error) {
|
|
96
|
+
if (error instanceof Error) {
|
|
97
|
+
return `${error.name} ${error.message} ${error.cause ? collectErrorText(error.cause) : ''}`;
|
|
98
|
+
}
|
|
99
|
+
if (typeof error === 'string')
|
|
100
|
+
return error;
|
|
101
|
+
if (!error || typeof error !== 'object')
|
|
102
|
+
return String(error ?? '');
|
|
103
|
+
const record = error;
|
|
104
|
+
return [record.name, record.message, record.code, record.error]
|
|
105
|
+
.filter((value) => typeof value === 'string')
|
|
106
|
+
.join(' ');
|
|
107
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './ai-errors.js';
|
|
2
|
+
export * from './note-properties.js';
|
|
3
|
+
export * from './saved-views.js';
|
|
4
|
+
export * from './note-templates.js';
|
|
5
|
+
export * from './powersync-read-models.js';
|
|
6
|
+
export type PowerSyncCommandRunResponse<T = unknown> = {
|
|
7
|
+
result: T;
|
|
8
|
+
affectedTables: string[];
|
|
9
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Hand-written barrel standing in for desktop's `@app/shared` package entry. Only the
|
|
2
|
+
// vendored modules are re-exported; everything else stays desktop-only.
|
|
3
|
+
export * from './ai-errors.js';
|
|
4
|
+
export * from './note-properties.js';
|
|
5
|
+
export * from './saved-views.js';
|
|
6
|
+
export * from './note-templates.js';
|
|
7
|
+
export * from './powersync-read-models.js';
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Note Properties domain types + pure helpers.
|
|
3
|
+
*
|
|
4
|
+
* Property values live on `c_note.properties` as a JSON map (key -> value), while
|
|
5
|
+
* `c_property_def` provides the account-owned semantic catalog (key/name/type/
|
|
6
|
+
* options). Unknown keys remain readable and degrade to untyped text.
|
|
7
|
+
*
|
|
8
|
+
* This module is pure (no DB, no React) so it can be shared by the main-process
|
|
9
|
+
* command handlers and the renderer UI.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Shape of the note's properties JSON: key -> raw value. Arrays are allowed
|
|
13
|
+
* (multi-value); the type semantics come from the c_property_def catalog.
|
|
14
|
+
*/
|
|
15
|
+
export interface FilePropertyRef {
|
|
16
|
+
resourceId: string;
|
|
17
|
+
path?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PlacePropertyValue {
|
|
20
|
+
lat: number;
|
|
21
|
+
lon: number;
|
|
22
|
+
name?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface UniqueIdPropertyConfig {
|
|
25
|
+
prefix: string;
|
|
26
|
+
next: number;
|
|
27
|
+
}
|
|
28
|
+
export type NotePropertyValue = string | number | boolean | string[] | FilePropertyRef[] | PlacePropertyValue;
|
|
29
|
+
export type NoteProperties = Record<string, NotePropertyValue>;
|
|
30
|
+
/**
|
|
31
|
+
* Lossless JSON-object representation used by read-modify-write paths. Unknown
|
|
32
|
+
* values are preserved so an older client cannot erase fields written by a
|
|
33
|
+
* newer client while updating an unrelated property.
|
|
34
|
+
*/
|
|
35
|
+
export type RawNoteProperties = Record<string, unknown>;
|
|
36
|
+
/**
|
|
37
|
+
* Supported current-client view of `c_note.properties`.
|
|
38
|
+
*
|
|
39
|
+
* A missing key means the property is not declared on the note, while an
|
|
40
|
+
* explicit `null` keeps a durable empty slot created manually or by a template.
|
|
41
|
+
* Raw read-modify-write paths use `RawNoteProperties` so future value shapes
|
|
42
|
+
* remain intact even when this typed view cannot render them yet.
|
|
43
|
+
*/
|
|
44
|
+
export type StoredNotePropertyValue = NotePropertyValue | null;
|
|
45
|
+
export type StoredNoteProperties = Record<string, StoredNotePropertyValue>;
|
|
46
|
+
/**
|
|
47
|
+
* Legacy value patch. Non-null values set a property; `null` removes the key.
|
|
48
|
+
* New callers use the explicit slot operation for clear/remove semantics.
|
|
49
|
+
*/
|
|
50
|
+
export type NotePropertiesPatch = Record<string, NotePropertyValue | null>;
|
|
51
|
+
export type NotePropertySlotOperation = 'declare' | 'clear' | 'remove';
|
|
52
|
+
export declare const NOTE_PROPERTY_LIMITS: {
|
|
53
|
+
readonly keyLength: 64;
|
|
54
|
+
readonly textLength: 2000;
|
|
55
|
+
readonly arrayLength: 50;
|
|
56
|
+
readonly mutationKeys: 100;
|
|
57
|
+
};
|
|
58
|
+
/** Property types with a stable value contract and public editing support. */
|
|
59
|
+
export declare const ACTIVE_PROPERTY_TYPES: readonly ["text", "number", "date", "select", "multi_select", "status", "url", "email", "phone", "checkbox", "files", "relation", "unique_id", "place"];
|
|
60
|
+
/** Types whose storage format is locked but not yet editable. None remain. */
|
|
61
|
+
export declare const RESERVED_PROPERTY_TYPES: readonly [];
|
|
62
|
+
export type ActivePropertyType = (typeof ACTIVE_PROPERTY_TYPES)[number];
|
|
63
|
+
export type PropertyType = ActivePropertyType | (typeof RESERVED_PROPERTY_TYPES)[number];
|
|
64
|
+
export type PropertyDefSource = 'manual' | 'ai';
|
|
65
|
+
export declare const PROPERTY_OPTION_COLORS: readonly ["gray", "red", "orange", "yellow", "green", "blue", "purple", "pink"];
|
|
66
|
+
export type PropertyOptionColor = (typeof PROPERTY_OPTION_COLORS)[number];
|
|
67
|
+
export declare const STATUS_PROPERTY_GROUPS: readonly ["todo", "in_progress", "complete"];
|
|
68
|
+
export type StatusPropertyGroup = (typeof STATUS_PROPERTY_GROUPS)[number];
|
|
69
|
+
export interface PropertyOption {
|
|
70
|
+
id: string;
|
|
71
|
+
label: string;
|
|
72
|
+
color: PropertyOptionColor;
|
|
73
|
+
sortRank: number;
|
|
74
|
+
archived: boolean;
|
|
75
|
+
/** Status workflow bucket. Omitted for ordinary select options. */
|
|
76
|
+
group?: StatusPropertyGroup;
|
|
77
|
+
}
|
|
78
|
+
/** Command input: existing options carry their id; main assigns ids to new items. */
|
|
79
|
+
export interface PropertyOptionInput {
|
|
80
|
+
id?: string;
|
|
81
|
+
label: string;
|
|
82
|
+
color?: PropertyOptionColor;
|
|
83
|
+
sortRank?: number;
|
|
84
|
+
archived?: boolean;
|
|
85
|
+
group?: StatusPropertyGroup;
|
|
86
|
+
}
|
|
87
|
+
export declare const DEFAULT_STATUS_OPTION_INPUTS: readonly PropertyOptionInput[];
|
|
88
|
+
export interface PropertyOptionsEnvelopeV1 {
|
|
89
|
+
version: 1;
|
|
90
|
+
items: PropertyOption[];
|
|
91
|
+
}
|
|
92
|
+
export declare const PROPERTY_OPTION_LIMITS: {
|
|
93
|
+
readonly items: 200;
|
|
94
|
+
readonly labelLength: 120;
|
|
95
|
+
};
|
|
96
|
+
export declare const PROPERTY_OPTION_LABEL_MAX_LENGTH: 120;
|
|
97
|
+
export declare const PROPERTY_NUMBER_PRECISION_MAX = 12;
|
|
98
|
+
export declare const PROPERTY_DEF_CONFIG_KEY_PREFIX = "property_def.config.v1.";
|
|
99
|
+
export type PropertyDefOptionsParseResult = {
|
|
100
|
+
status: 'empty';
|
|
101
|
+
} | {
|
|
102
|
+
status: 'valid';
|
|
103
|
+
options: PropertyOption[];
|
|
104
|
+
} | {
|
|
105
|
+
status: 'legacy';
|
|
106
|
+
labels: string[];
|
|
107
|
+
} | {
|
|
108
|
+
status: 'invalid';
|
|
109
|
+
} | {
|
|
110
|
+
status: 'unsupported';
|
|
111
|
+
version: unknown;
|
|
112
|
+
};
|
|
113
|
+
export type PropertyDefConfigParseResult = {
|
|
114
|
+
status: 'empty';
|
|
115
|
+
} | {
|
|
116
|
+
status: 'valid';
|
|
117
|
+
config: PropertyDefConfig;
|
|
118
|
+
} | {
|
|
119
|
+
status: 'invalid';
|
|
120
|
+
} | {
|
|
121
|
+
status: 'unsupported';
|
|
122
|
+
version: unknown;
|
|
123
|
+
};
|
|
124
|
+
export type PropertyDefConfigDefaults = 'legacy' | 'new';
|
|
125
|
+
export declare function buildPropertyDefConfigKey(definitionId: string): string;
|
|
126
|
+
export type DatePropertyDefConfig = {
|
|
127
|
+
version: 1;
|
|
128
|
+
type: 'date';
|
|
129
|
+
mode: 'date' | 'datetime';
|
|
130
|
+
};
|
|
131
|
+
export type NumberPropertyDefConfig = {
|
|
132
|
+
version: 1;
|
|
133
|
+
type: 'number';
|
|
134
|
+
format: 'number' | 'percent' | 'currency';
|
|
135
|
+
precision?: number;
|
|
136
|
+
currency?: string;
|
|
137
|
+
unit?: string;
|
|
138
|
+
min?: number;
|
|
139
|
+
max?: number;
|
|
140
|
+
step?: number;
|
|
141
|
+
};
|
|
142
|
+
export type SelectPropertyDefConfig = {
|
|
143
|
+
version: 1;
|
|
144
|
+
type: 'select';
|
|
145
|
+
mode: 'open' | 'closed';
|
|
146
|
+
};
|
|
147
|
+
export type MultiSelectPropertyDefConfig = {
|
|
148
|
+
version: 1;
|
|
149
|
+
type: 'multi_select';
|
|
150
|
+
mode: 'open' | 'closed';
|
|
151
|
+
maxSelections?: number;
|
|
152
|
+
};
|
|
153
|
+
export type UrlPropertyDefConfig = {
|
|
154
|
+
version: 1;
|
|
155
|
+
type: 'url';
|
|
156
|
+
schemes?: Array<'http' | 'https'>;
|
|
157
|
+
};
|
|
158
|
+
export type PropertyDefConfig = DatePropertyDefConfig | NumberPropertyDefConfig | SelectPropertyDefConfig | MultiSelectPropertyDefConfig | UrlPropertyDefConfig;
|
|
159
|
+
export declare function isPropertyDefSource(value: unknown): value is PropertyDefSource;
|
|
160
|
+
/** Domain form of a synced property-definition catalog entry (camelCase). */
|
|
161
|
+
export interface PropertyDef {
|
|
162
|
+
id: string;
|
|
163
|
+
/** Stable key written into the note properties JSON. Immutable after creation. */
|
|
164
|
+
key: string;
|
|
165
|
+
/** Display name. Renamable without migrating note data. */
|
|
166
|
+
name: string;
|
|
167
|
+
type: PropertyType;
|
|
168
|
+
/** Stable options for select / multi_select / status; note values store option ids. */
|
|
169
|
+
options?: PropertyOption[];
|
|
170
|
+
/** Counter stored in `c_property_def.options` for `unique_id` (not the select envelope). */
|
|
171
|
+
uniqueId?: UniqueIdPropertyConfig;
|
|
172
|
+
/** Effective type configuration, including legacy defaults when no companion row exists. */
|
|
173
|
+
config?: PropertyDefConfig;
|
|
174
|
+
/** Explicit companion config exists but is malformed, unsupported, or type-mismatched. */
|
|
175
|
+
configInvalid: boolean;
|
|
176
|
+
/** True until a legacy string-array definition has been migrated to stable option ids. */
|
|
177
|
+
optionsMigrationPending: boolean;
|
|
178
|
+
/** Stable option storage exists but is malformed or uses an unsupported version. */
|
|
179
|
+
optionsInvalid: boolean;
|
|
180
|
+
/** Semantic description (AI disambiguation anchor). */
|
|
181
|
+
description?: string;
|
|
182
|
+
icon?: string;
|
|
183
|
+
/** Whether compact note summaries should surface this property by default. */
|
|
184
|
+
showOnCard: boolean;
|
|
185
|
+
source: PropertyDefSource;
|
|
186
|
+
sortRank: number;
|
|
187
|
+
}
|
|
188
|
+
/** Raw catalog row shape returned by the PowerSync read model (snake_case, nullable). */
|
|
189
|
+
export interface PropertyDefRow {
|
|
190
|
+
id: string;
|
|
191
|
+
user_id: string | null;
|
|
192
|
+
key: string | null;
|
|
193
|
+
name: string | null;
|
|
194
|
+
type: string | null;
|
|
195
|
+
options: string | null;
|
|
196
|
+
/** Companion c_config_property.c_value selected by the catalog read model. */
|
|
197
|
+
config_json: string | null;
|
|
198
|
+
description: string | null;
|
|
199
|
+
icon: string | null;
|
|
200
|
+
sort_rank: number | null;
|
|
201
|
+
show_on_card: number | null;
|
|
202
|
+
source: string | null;
|
|
203
|
+
created_at: string | null;
|
|
204
|
+
updated_at: string | null;
|
|
205
|
+
is_del: number | null;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Property key validity: non-empty, <=64 chars, no newlines/tabs. A key is one
|
|
209
|
+
* flat name. Field refs keep a single `prop.` prefix and take the remainder as
|
|
210
|
+
* that name, so dots inside the name stay part of the name. `__proto__` is
|
|
211
|
+
* reserved because common object validators cannot round-trip it safely.
|
|
212
|
+
*/
|
|
213
|
+
export declare function isPropertyKeyValid(key: unknown): key is string;
|
|
214
|
+
export declare function isFilePropertyPathValid(path: unknown): path is string;
|
|
215
|
+
export declare function isFilePropertyRef(value: unknown): value is FilePropertyRef;
|
|
216
|
+
/** Reject a malformed file list instead of dropping attachments. An empty list is `[]`. */
|
|
217
|
+
export declare function normalizeFilePropertyValue(value: unknown): FilePropertyRef[] | null;
|
|
218
|
+
export declare function normalizePlacePropertyValue(value: unknown): PlacePropertyValue | null;
|
|
219
|
+
export declare function isPlacePropertyValue(value: unknown): value is PlacePropertyValue;
|
|
220
|
+
export declare function formatPlaceProperty(value: PlacePropertyValue): string;
|
|
221
|
+
export declare function normalizeUniqueIdPrefix(raw: string | null | undefined, fallbackName?: string | null): string;
|
|
222
|
+
export declare function isIssuedUniqueId(value: unknown): value is number;
|
|
223
|
+
export declare function parseUniqueIdPropertyConfig(raw: string | null | undefined): UniqueIdPropertyConfig | undefined;
|
|
224
|
+
export declare function serializeUniqueIdPropertyConfig(config: UniqueIdPropertyConfig): string;
|
|
225
|
+
export declare function formatUniqueIdProperty(value: number, config?: Pick<UniqueIdPropertyConfig, 'prefix'> | null): string;
|
|
226
|
+
/**
|
|
227
|
+
* Strictly parse the raw JSON object. `null` means the stored value is present
|
|
228
|
+
* but malformed or uses an unsupported top-level shape.
|
|
229
|
+
*/
|
|
230
|
+
export declare function tryParseRawNoteProperties(raw: string | null | undefined): RawNoteProperties | null;
|
|
231
|
+
/** Forgiving read projection used by UI/read paths; malformed storage appears empty. */
|
|
232
|
+
export declare function parseRawNoteProperties(raw: string | null | undefined): RawNoteProperties;
|
|
233
|
+
/** Parse the supported three-state view; unknown values are omitted from the UI. */
|
|
234
|
+
export declare function parseStoredNoteProperties(raw: string | null | undefined): StoredNoteProperties;
|
|
235
|
+
/** Read only committed values; declared-but-empty slots are intentionally omitted. */
|
|
236
|
+
export declare function parseNoteProperties(raw: string | null | undefined): NoteProperties;
|
|
237
|
+
/** Serialize persisted values + empty slots; an empty object normalizes to NULL. */
|
|
238
|
+
export declare function serializeStoredNoteProperties(properties: Readonly<Record<string, unknown>>): string | null;
|
|
239
|
+
/** Serialize a lossless raw property object; an empty object normalizes to NULL. */
|
|
240
|
+
export declare function serializeRawNoteProperties(properties: Readonly<RawNoteProperties>): string | null;
|
|
241
|
+
/** Serialize the non-empty value view. */
|
|
242
|
+
export declare function serializeNoteProperties(properties: NoteProperties): string | null;
|
|
243
|
+
export interface MergePropertiesResult {
|
|
244
|
+
next: RawNoteProperties;
|
|
245
|
+
changedKeys: string[];
|
|
246
|
+
}
|
|
247
|
+
export interface FillEmptyPropertiesResult extends MergePropertiesResult {
|
|
248
|
+
skippedKeys: string[];
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Legacy value merge: null removes a key, non-null values overwrite, and all
|
|
252
|
+
* unrelated JSON entries are preserved. Returns the list of changed keys.
|
|
253
|
+
*/
|
|
254
|
+
export declare function mergeNotePropertiesPatch(current: Readonly<RawNoteProperties>, patch: NotePropertiesPatch): MergePropertiesResult;
|
|
255
|
+
/**
|
|
256
|
+
* Fill only fields that are still explicitly declared as empty. Missing fields
|
|
257
|
+
* and fields with any current value are skipped, allowing AI/review flows to
|
|
258
|
+
* avoid overwriting a concurrent user edit in the same transaction.
|
|
259
|
+
*/
|
|
260
|
+
export declare function fillEmptyNoteProperties(current: Readonly<RawNoteProperties>, values: NoteProperties): FillEmptyPropertiesResult;
|
|
261
|
+
/**
|
|
262
|
+
* Apply an explicit field-slot operation: declare adds only missing slots, clear
|
|
263
|
+
* makes every target explicitly empty, and remove deletes the slot entirely.
|
|
264
|
+
*/
|
|
265
|
+
export declare function applyNotePropertySlotOperation(current: Readonly<RawNoteProperties>, operation: NotePropertySlotOperation, keys: readonly string[]): MergePropertiesResult;
|
|
266
|
+
/** Normalize accepted date input and reject ISO-like strings with impossible calendar dates. */
|
|
267
|
+
export declare function normalizeDateValueToIso(value: unknown): string | null;
|
|
268
|
+
/** Normalize a configured date value without conflating a calendar date with an instant. */
|
|
269
|
+
export declare function normalizeDatePropertyValue(value: unknown, mode: DatePropertyDefConfig['mode']): string | null;
|
|
270
|
+
/** Validate a number against its semantic constraints without rounding the stored value. */
|
|
271
|
+
export declare function normalizeNumberPropertyValue(value: unknown, config: NumberPropertyDefConfig): number | null;
|
|
272
|
+
/** Validate and canonicalize an absolute URL under the definition's allowed schemes. */
|
|
273
|
+
export declare function normalizeUrlPropertyValue(value: unknown, config?: UrlPropertyDefConfig): string | null;
|
|
274
|
+
/**
|
|
275
|
+
* Coerce a candidate value into the legal shape for a target type; returns null
|
|
276
|
+
* when it cannot be coerced. Only does shape coercion — the select-option
|
|
277
|
+
* whitelist belongs to the validation/policy layer.
|
|
278
|
+
*/
|
|
279
|
+
export declare function coercePropertyValue(type: PropertyType, value: unknown): NotePropertyValue | null;
|
|
280
|
+
/** UI display value -> chip text (arrays joined with "、"). */
|
|
281
|
+
export declare function formatPropertyValue(value: NotePropertyValue): string;
|
|
282
|
+
/** Infer a type from the value shape when the catalog is missing (orphan keys). */
|
|
283
|
+
export declare function inferPropertyTypeFromValue(value: NotePropertyValue): ActivePropertyType;
|
|
284
|
+
export declare function isPropertyType(value: unknown): value is PropertyType;
|
|
285
|
+
export declare function isPropertyOptionColor(value: unknown): value is PropertyOptionColor;
|
|
286
|
+
/** Normalize the user-visible option identity used for display and uniqueness. */
|
|
287
|
+
export declare function normalizePropertyOptionLabel(value: unknown): string | null;
|
|
288
|
+
/** Case-insensitive uniqueness key. Callers should reject an empty result. */
|
|
289
|
+
export declare function propertyOptionLabelKey(value: string): string;
|
|
290
|
+
export declare function findPropertyOptionById(options: readonly PropertyOption[], id: string): PropertyOption | undefined;
|
|
291
|
+
export declare function findPropertyOptionByLabel(options: readonly PropertyOption[], label: string): PropertyOption | undefined;
|
|
292
|
+
/** Validate, deduplicate, and put options in their canonical `(sortRank,id)` order. */
|
|
293
|
+
export declare function normalizePropertyOptions(values: readonly unknown[]): PropertyOption[] | undefined;
|
|
294
|
+
/** Parse both the stable v1 envelope and legacy label arrays without conflating them. */
|
|
295
|
+
export declare function parsePropertyDefOptionsEnvelope(raw: string | null | undefined): PropertyDefOptionsParseResult;
|
|
296
|
+
/** Read only migrated stable options. Legacy labels remain migration-only data. */
|
|
297
|
+
export declare function parsePropertyDefOptions(raw: string | null | undefined): PropertyOption[] | undefined;
|
|
298
|
+
/** Read legacy label options for the explicit migration command only. */
|
|
299
|
+
export declare function parseLegacyPropertyDefOptions(raw: string | null | undefined): string[] | undefined;
|
|
300
|
+
export declare function serializePropertyDefOptions(options: readonly PropertyOption[]): string;
|
|
301
|
+
/** Validate and canonicalize a structured property-definition config object. */
|
|
302
|
+
export declare function normalizePropertyDefConfig(value: unknown): PropertyDefConfig | undefined;
|
|
303
|
+
/** Parse a companion config without hiding malformed or future-version rows. */
|
|
304
|
+
export declare function parsePropertyDefConfigEnvelope(raw: string | null | undefined): PropertyDefConfigParseResult;
|
|
305
|
+
/** Parse only an explicit valid companion config; other states return undefined. */
|
|
306
|
+
export declare function parsePropertyDefConfig(raw: string | null | undefined): PropertyDefConfig | undefined;
|
|
307
|
+
/** Option definitions stay open so unmatched input can create options inline. */
|
|
308
|
+
export declare function getDefaultPropertyDefConfig(type: PropertyType, _defaults?: PropertyDefConfigDefaults): PropertyDefConfig | undefined;
|
|
309
|
+
export declare function resolvePropertyDefConfig(type: PropertyType, raw: string | null | undefined): PropertyDefConfig | undefined;
|
|
310
|
+
export declare function serializePropertyDefConfig(config: PropertyDefConfig): string;
|
|
311
|
+
/** Map a raw c_property_def row into the domain object (unknown type -> text). */
|
|
312
|
+
export declare function mapPropertyDef(record: PropertyDefRow): PropertyDef;
|