trilium-api 1.0.1 → 1.0.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.
@@ -1,9 +1,11 @@
1
+ import { Client } from 'openapi-fetch';
2
+
1
3
  /**
2
4
  * This file was auto-generated by openapi-typescript.
3
5
  * Do not make direct changes to the file.
4
6
  */
5
7
 
6
- export interface paths {
8
+ interface paths {
7
9
  "/create-note": {
8
10
  parameters: {
9
11
  query?: never;
@@ -450,8 +452,7 @@ export interface paths {
450
452
  trace?: never;
451
453
  };
452
454
  }
453
- export type webhooks = Record<string, never>;
454
- export interface components {
455
+ interface components {
455
456
  schemas: {
456
457
  CreateNoteDef: {
457
458
  /** @description Note ID of the parent note in the tree */
@@ -644,8 +645,7 @@ export interface components {
644
645
  headers: never;
645
646
  pathItems: never;
646
647
  }
647
- export type $defs = Record<string, never>;
648
- export interface operations {
648
+ interface operations {
649
649
  createNote: {
650
650
  parameters: {
651
651
  query?: never;
@@ -1756,3 +1756,470 @@ export interface operations {
1756
1756
  };
1757
1757
  };
1758
1758
  }
1759
+
1760
+ /**
1761
+ * Trilium Note Mapper and Search Query Builder
1762
+ *
1763
+ * Provides utilities for mapping Trilium notes to strongly-typed objects
1764
+ * and building type-safe search queries.
1765
+ */
1766
+
1767
+ /**
1768
+ * Comparison operators for search conditions
1769
+ */
1770
+ type ComparisonOperator = '=' | '!=' | '<' | '<=' | '>' | '>=' | '*=' | '=*' | '*=*';
1771
+ /**
1772
+ * A value with an optional comparison operator
1773
+ */
1774
+ interface ConditionValue<T = string | number | boolean> {
1775
+ value: T;
1776
+ operator?: ComparisonOperator;
1777
+ }
1778
+ /**
1779
+ * Simple value or condition with operator
1780
+ */
1781
+ type SearchValue = string | number | boolean | ConditionValue;
1782
+ /**
1783
+ * Base search conditions for labels, relations, and note properties.
1784
+ * Use template literal keys for labels (#) and relations (~).
1785
+ * Regular string keys are treated as note properties.
1786
+ */
1787
+ type TriliumSearchConditions = {
1788
+ /** Labels: use #labelName as key */
1789
+ [key: `#${string}`]: SearchValue | undefined;
1790
+ } & {
1791
+ /** Relations: use ~relationName as key */
1792
+ [key: `~${string}`]: SearchValue | undefined;
1793
+ } & {
1794
+ /** Note properties: use note.property as key or just property name */
1795
+ [key: string]: SearchValue | undefined;
1796
+ };
1797
+ /**
1798
+ * Logical operators for combining search conditions
1799
+ */
1800
+ interface TriliumSearchLogical {
1801
+ /** Combine multiple conditions with AND */
1802
+ AND?: TriliumSearchHelpers[];
1803
+ /** Combine multiple conditions with OR */
1804
+ OR?: TriliumSearchHelpers[];
1805
+ /** Negate a condition */
1806
+ NOT?: TriliumSearchHelpers;
1807
+ }
1808
+ /**
1809
+ * Complete search helpers combining conditions and logical operators.
1810
+ * Can contain field conditions AND/OR logical operators.
1811
+ */
1812
+ type TriliumSearchHelpers = TriliumSearchLogical | (TriliumSearchConditions & Partial<TriliumSearchLogical>);
1813
+ /**
1814
+ * Builds a Trilium search query string from a structured helper object
1815
+ *
1816
+ * @param helpers - The search conditions and logical operators
1817
+ * @returns A properly formatted Trilium search query string
1818
+ *
1819
+ * @example
1820
+ * // Simple label search
1821
+ * buildSearchQuery({ '#blog': true })
1822
+ * // => '#blog'
1823
+ *
1824
+ * @example
1825
+ * // Label with value
1826
+ * buildSearchQuery({ '#status': 'published' })
1827
+ * // => "#status = 'published'"
1828
+ *
1829
+ * @example
1830
+ * // Complex AND/OR conditions
1831
+ * buildSearchQuery({
1832
+ * AND: [
1833
+ * { '#blog': true },
1834
+ * { OR: [
1835
+ * { '#status': 'published' },
1836
+ * { '#status': 'featured' }
1837
+ * ]}
1838
+ * ]
1839
+ * })
1840
+ * // => "#blog AND (#status = 'published' OR #status = 'featured')"
1841
+ *
1842
+ * @example
1843
+ * // Note properties with operators
1844
+ * buildSearchQuery({
1845
+ * 'note.type': 'text',
1846
+ * '#wordCount': { value: 1000, operator: '>=' }
1847
+ * })
1848
+ * // => "note.type = 'text' AND #wordCount >= 1000"
1849
+ */
1850
+ declare function buildSearchQuery(helpers: TriliumSearchHelpers): string;
1851
+ /**
1852
+ * Computed function that calculates a value from the partially mapped object
1853
+ * @template T - The target object type
1854
+ * @template K - The specific key in the target type
1855
+ */
1856
+ type ComputedFunction<T, K extends keyof T> = (partial: Partial<T>, note: TriliumNote) => T[K] | undefined;
1857
+ /**
1858
+ * Field mapping configuration for a single property
1859
+ * Can be a simple string path, a detailed configuration object, or a computed value
1860
+ *
1861
+ * @template T - The target object type
1862
+ * @template K - The specific key in the target type
1863
+ *
1864
+ * @example
1865
+ * // Shorthand string path
1866
+ * title: 'note.title'
1867
+ *
1868
+ * @example
1869
+ * // Full configuration
1870
+ * tags: {
1871
+ * from: '#tags',
1872
+ * transform: transforms.commaSeparated,
1873
+ * default: [],
1874
+ * required: false
1875
+ * }
1876
+ *
1877
+ * @example
1878
+ * // Computed value
1879
+ * readTimeMinutes: {
1880
+ * computed: (partial) => Math.ceil((partial.wordCount || 0) / 200)
1881
+ * }
1882
+ */
1883
+ type FieldMapping<T, K extends keyof T = keyof T> = string | {
1884
+ /** Source path (string) or extractor function */
1885
+ from: string | ((note: TriliumNote) => unknown);
1886
+ /** Optional transform function to convert the raw value - accepts any input type */
1887
+ transform?: (value: any, note: TriliumNote) => T[K] | undefined;
1888
+ /** Default value if extraction returns undefined */
1889
+ default?: T[K];
1890
+ /** Whether this field is required (throws if missing) */
1891
+ required?: boolean;
1892
+ } | {
1893
+ /** Computed function that calculates value from other mapped fields */
1894
+ computed: ComputedFunction<T, K>;
1895
+ /** Default value if computed returns undefined */
1896
+ default?: T[K];
1897
+ };
1898
+ /**
1899
+ * Complete mapping configuration for a type
1900
+ * Maps each property key to its field mapping configuration
1901
+ *
1902
+ * @template T - The target object type to map to
1903
+ */
1904
+ type MappingConfig<T> = {
1905
+ [K in keyof T]?: FieldMapping<T, K>;
1906
+ };
1907
+ /**
1908
+ * Maps Trilium notes to strongly-typed objects using declarative field mappings
1909
+ *
1910
+ * Supports:
1911
+ * - Direct property paths (note.title, note.noteId)
1912
+ * - Label attributes (#labelName)
1913
+ * - Relation attributes (~relationName)
1914
+ * - Custom extractor functions
1915
+ * - Transform functions
1916
+ * - Computed values from other fields
1917
+ * - Default values
1918
+ * - Required field validation
1919
+ *
1920
+ * @template T - The target type to map notes to
1921
+ *
1922
+ * @example
1923
+ * const mapper = new TriliumMapper<BlogPost>({
1924
+ * title: 'note.title',
1925
+ * slug: { from: '#slug', required: true },
1926
+ * wordCount: { from: '#wordCount', transform: transforms.number, default: 0 },
1927
+ * readTimeMinutes: {
1928
+ * computed: (partial) => Math.ceil((partial.wordCount || 0) / 200)
1929
+ * }
1930
+ * });
1931
+ *
1932
+ * const posts = mapper.map(notes);
1933
+ */
1934
+ declare class TriliumMapper<T> {
1935
+ /** The mapping configuration for this mapper */
1936
+ readonly config: MappingConfig<T>;
1937
+ /**
1938
+ * Creates a new TriliumMapper instance
1939
+ * @param config - The mapping configuration defining how to map note fields to the target type
1940
+ */
1941
+ constructor(config: MappingConfig<T>);
1942
+ /**
1943
+ * Merges multiple mapping configurations into a single configuration
1944
+ * Later configs override earlier ones for the same keys
1945
+ * Supports merging configs from base types into derived types
1946
+ *
1947
+ * @template T - The target type for the merged configuration
1948
+ * @param configs - One or more mapping configurations to merge
1949
+ * @returns A new merged mapping configuration
1950
+ *
1951
+ * @example
1952
+ * const merged = TriliumMapper.merge<BlogPost>(
1953
+ * StandardNoteMapping,
1954
+ * BlogSpecificMapping,
1955
+ * OverrideMapping
1956
+ * );
1957
+ */
1958
+ static merge<T>(...configs: (Partial<MappingConfig<T>> | MappingConfig<unknown>)[]): MappingConfig<T>;
1959
+ /**
1960
+ * Maps a single note to the target type
1961
+ * @param note - The Trilium note to map
1962
+ * @returns The mapped object of type T
1963
+ */
1964
+ map(note: TriliumNote): T;
1965
+ /**
1966
+ * Maps an array of notes to the target type
1967
+ * @param notes - The Trilium notes to map
1968
+ * @returns An array of mapped objects of type T
1969
+ */
1970
+ map(notes: TriliumNote[]): T[];
1971
+ /**
1972
+ * Maps a single note to the target type using the configured field mappings
1973
+ * Processes in two passes: first regular fields, then computed fields
1974
+ * @param note - The Trilium note to map
1975
+ * @returns The mapped object
1976
+ * @throws Error if a required field is missing
1977
+ * @private
1978
+ */
1979
+ private mapSingle;
1980
+ /**
1981
+ * Extracts a value from a note using a string path
1982
+ *
1983
+ * Supports:
1984
+ * - Label attributes: #labelName
1985
+ * - Relation attributes: ~relationName
1986
+ * - Note properties: note.property.path
1987
+ *
1988
+ * @param note - The Trilium note to extract from
1989
+ * @param path - The path string indicating where to extract the value
1990
+ * @returns The extracted value or undefined if not found
1991
+ * @private
1992
+ *
1993
+ * @example
1994
+ * extractValue(note, 'note.title') // => note.title
1995
+ * extractValue(note, '#slug') // => label attribute 'slug'
1996
+ * extractValue(note, '~template') // => relation attribute 'template'
1997
+ */
1998
+ private extractValue;
1999
+ }
2000
+ /**
2001
+ * Common transform functions for use with TriliumMapper
2002
+ */
2003
+ declare const transforms: {
2004
+ /** Convert to number */
2005
+ number: (value: unknown) => number | undefined;
2006
+ /** Convert to boolean */
2007
+ boolean: (value: unknown) => boolean | undefined;
2008
+ /** Split comma-separated string into array */
2009
+ commaSeparated: (value: unknown) => string[] | undefined;
2010
+ /** Parse JSON string */
2011
+ json: <T>(value: unknown) => T | undefined;
2012
+ /** Parse date string */
2013
+ date: (value: unknown) => Date | undefined;
2014
+ /** Trim whitespace from string */
2015
+ trim: (value: unknown) => string | undefined;
2016
+ };
2017
+ /**
2018
+ * Standard note fields that all mapped types must include.
2019
+ * Extend this interface when creating your own mapped types.
2020
+ *
2021
+ * @example
2022
+ * ```ts
2023
+ * interface BlogPost extends StandardNote {
2024
+ * slug: string;
2025
+ * published: boolean;
2026
+ * }
2027
+ * ```
2028
+ */
2029
+ interface StandardNote {
2030
+ /** The unique note ID */
2031
+ id: string;
2032
+ /** The note title */
2033
+ title: string;
2034
+ /** UTC date when the note was created */
2035
+ dateCreatedUtc: Date;
2036
+ /** UTC date when the note was last modified */
2037
+ dateLastModifiedUtc: Date;
2038
+ }
2039
+ /**
2040
+ * Standard mapping configuration for StandardNote fields.
2041
+ * Use with TriliumMapper.merge() to create mappings for types extending StandardNote.
2042
+ *
2043
+ * @example
2044
+ * ```ts
2045
+ * interface BlogPost extends StandardNote {
2046
+ * slug: string;
2047
+ * published: boolean;
2048
+ * }
2049
+ *
2050
+ * const blogMapping = TriliumMapper.merge<BlogPost>(
2051
+ * StandardNoteMapping,
2052
+ * {
2053
+ * slug: '#slug',
2054
+ * published: { from: '#published', transform: transforms.boolean, default: false },
2055
+ * }
2056
+ * );
2057
+ * ```
2058
+ */
2059
+ declare const StandardNoteMapping: MappingConfig<StandardNote>;
2060
+ /**
2061
+ * Helper type for defining custom field mappings.
2062
+ * Use this when defining mappings for types that extend StandardNote.
2063
+ * It automatically excludes StandardNote fields since they're auto-merged.
2064
+ *
2065
+ * @template T - Your custom type that extends StandardNote
2066
+ *
2067
+ * @example
2068
+ * ```ts
2069
+ * interface BlogPost extends StandardNote {
2070
+ * slug: string;
2071
+ * published: boolean;
2072
+ * }
2073
+ *
2074
+ * // Clean type - no need for verbose Omit<>
2075
+ * const blogMapping: CustomMapping<BlogPost> = {
2076
+ * slug: '#slug',
2077
+ * published: { from: '#published', transform: transforms.boolean, default: false },
2078
+ * };
2079
+ *
2080
+ * const { data } = await client.searchAndMap<BlogPost>({
2081
+ * query: '#blog',
2082
+ * mapping: blogMapping,
2083
+ * });
2084
+ * ```
2085
+ */
2086
+ type CustomMapping<T extends StandardNote> = MappingConfig<Omit<T, keyof StandardNote>>;
2087
+
2088
+ /**
2089
+ * Trilium API Client using openapi-fetch
2090
+ *
2091
+ * This provides a type-safe client for the Trilium ETAPI.
2092
+ * Types are auto-generated from the OpenAPI specification.
2093
+ */
2094
+
2095
+ type TriliumNote = components['schemas']['Note'];
2096
+ type TriliumBranch = components['schemas']['Branch'];
2097
+ type TriliumAttribute = components['schemas']['Attribute'];
2098
+ type TriliumAttachment = components['schemas']['Attachment'];
2099
+ type TriliumAppInfo = components['schemas']['AppInfo'];
2100
+
2101
+ interface TriliumClientConfig {
2102
+ baseUrl: string;
2103
+ apiKey: string;
2104
+ }
2105
+ interface SearchAndMapOptions<T extends StandardNote> {
2106
+ /** Search query - either a string or structured search helpers */
2107
+ query: string | TriliumSearchHelpers;
2108
+ /**
2109
+ * Mapping configuration for your custom fields only.
2110
+ * StandardNoteMapping (id, title, dates) is automatically merged.
2111
+ */
2112
+ mapping: CustomMapping<T>;
2113
+ /** Optional: limit number of results */
2114
+ limit?: number;
2115
+ /** Optional: order by field (e.g., 'dateModified', 'title') */
2116
+ orderBy?: string;
2117
+ /** Optional: order direction */
2118
+ orderDirection?: 'asc' | 'desc';
2119
+ /** Optional: fast search mode (less accurate but faster) */
2120
+ fastSearch?: boolean;
2121
+ }
2122
+ /** Details about a note that failed to map */
2123
+ interface MappingFailure {
2124
+ /** The note ID that failed to map */
2125
+ noteId: string;
2126
+ /** The note title for easier identification */
2127
+ noteTitle: string;
2128
+ /** The error message explaining why mapping failed */
2129
+ reason: string;
2130
+ /** The original note object */
2131
+ note: TriliumNote;
2132
+ }
2133
+ interface SearchAndMapResult<T extends StandardNote> {
2134
+ /** Mapped results as typed objects */
2135
+ data: T[];
2136
+ /** Notes that failed to map (e.g., missing required fields) */
2137
+ failures: MappingFailure[];
2138
+ }
2139
+ /** Extended Trilium client with search and map helper */
2140
+ interface TriliumClient extends Client<paths> {
2141
+ /**
2142
+ * Search notes and automatically map results to typed objects.
2143
+ * Type T must extend StandardNote to ensure consistent base fields.
2144
+ * StandardNoteMapping is automatically included - just define your custom fields!
2145
+ * Throws on API/network errors.
2146
+ *
2147
+ * @see {@link https://triliumnext.github.io/Docs/Wiki/search.html} for Trilium search syntax
2148
+ *
2149
+ * @example
2150
+ * ```ts
2151
+ * interface BlogPost extends StandardNote {
2152
+ * slug: string;
2153
+ * published: boolean;
2154
+ * }
2155
+ *
2156
+ * // Just define your custom fields - StandardNoteMapping is auto-merged!
2157
+ * const { data: posts, failures } = await client.searchAndMap<BlogPost>({
2158
+ * query: { '#blog': true, '#published': true },
2159
+ * mapping: {
2160
+ * slug: '#slug',
2161
+ * published: { from: '#published', transform: transforms.boolean, default: false },
2162
+ * },
2163
+ * limit: 10,
2164
+ * orderBy: 'dateModified',
2165
+ * orderDirection: 'desc',
2166
+ * });
2167
+ *
2168
+ * // Each post has id, title, dateCreatedUtc, dateLastModifiedUtc + your custom fields
2169
+ * posts.forEach(post => {
2170
+ * console.log(`${post.title} (${post.slug}) - ${post.id}`);
2171
+ * });
2172
+ *
2173
+ * if (failures.length > 0) {
2174
+ * console.warn(`${failures.length} notes failed to map`);
2175
+ * }
2176
+ * ```
2177
+ */
2178
+ searchAndMap<T extends StandardNote>(options: SearchAndMapOptions<T>): Promise<SearchAndMapResult<T>>;
2179
+ }
2180
+ /**
2181
+ * Create a type-safe Trilium API client
2182
+ *
2183
+ * @example
2184
+ * ```ts
2185
+ * const client = createTriliumClient({
2186
+ * baseUrl: 'http://localhost:8080',
2187
+ * apiKey: 'your-etapi-token'
2188
+ * });
2189
+ *
2190
+ * // Get app info
2191
+ * const { data, error } = await client.GET('/app-info');
2192
+ *
2193
+ * // Get a note by ID
2194
+ * const { data: note } = await client.GET('/notes/{noteId}', {
2195
+ * params: { path: { noteId: 'root' } }
2196
+ * });
2197
+ *
2198
+ * // Create a note
2199
+ * const { data: newNote } = await client.POST('/notes', {
2200
+ * body: {
2201
+ * parentNoteId: 'root',
2202
+ * title: 'My Note',
2203
+ * type: 'text',
2204
+ * content: '<p>Hello World</p>'
2205
+ * }
2206
+ * });
2207
+ *
2208
+ * // Search notes
2209
+ * const { data: searchResults } = await client.GET('/notes', {
2210
+ * params: { query: { search: '#blog' } }
2211
+ * });
2212
+ *
2213
+ * // Search and map to typed objects
2214
+ * const { data: posts } = await client.searchAndMap<BlogPost>({
2215
+ * query: { '#blog': true },
2216
+ * mapping: {
2217
+ * title: 'note.title',
2218
+ * slug: '#slug',
2219
+ * },
2220
+ * });
2221
+ * ```
2222
+ */
2223
+ declare function createTriliumClient(config: TriliumClientConfig): TriliumClient;
2224
+
2225
+ export { type CustomMapping, type MappingConfig, type MappingFailure, type StandardNote, StandardNoteMapping, type TriliumAppInfo, type TriliumAttachment, type TriliumAttribute, type TriliumBranch, type TriliumClientConfig, TriliumMapper, type TriliumNote, type TriliumSearchHelpers, buildSearchQuery, type components, createTriliumClient as createClient, createTriliumClient, type operations, type paths, transforms };