@coffer-org/plugin-transit 1.4.1 → 2.0.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/bus_route/index.d.ts +1 -1
- package/dist/bus_route/index.js +5 -5
- package/dist/index.js +4 -4
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +13 -12
- package/dist/runtime/sync.d.ts +1 -2
- package/dist/runtime/sync.js +6 -31
- package/dist/schema.js +132 -54
- package/package.json +4 -4
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("@coffer-org/sdk/
|
|
1
|
+
declare const _default: import("@coffer-org/sdk/shelf").ShelfDef;
|
|
2
2
|
export default _default;
|
package/dist/bus_route/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineShelf } from '@coffer-org/sdk/shelf';
|
|
2
2
|
import { field } from '@coffer-org/sdk/fields';
|
|
3
|
-
export default
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
export default defineShelf({
|
|
4
|
+
shelf: 'bus_route',
|
|
5
|
+
library: 'transit',
|
|
6
6
|
label: 'transit.bus_route.label',
|
|
7
7
|
icon: 'lucide:bus',
|
|
8
8
|
views: {
|
|
9
|
-
|
|
9
|
+
list: { fields: ['route_number', 'from', 'to'] },
|
|
10
10
|
},
|
|
11
11
|
fields: [
|
|
12
12
|
field.title({ key: 'name', label: 'core.fields.name' }),
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineLibrary } from '@coffer-org/sdk/library';
|
|
2
2
|
import { definePlugin } from '@coffer-org/sdk/plugin';
|
|
3
3
|
import { field } from '@coffer-org/sdk/fields';
|
|
4
4
|
import { defineSettings } from '@coffer-org/sdk/settings';
|
|
@@ -7,10 +7,10 @@ export default definePlugin({
|
|
|
7
7
|
id: 'transit',
|
|
8
8
|
version: '1.0.0',
|
|
9
9
|
dependsOn: [],
|
|
10
|
-
|
|
10
|
+
libraries: [
|
|
11
11
|
{
|
|
12
|
-
meta:
|
|
13
|
-
|
|
12
|
+
meta: defineLibrary({ id: 'transit', label: 'transit.library.label', icon: 'lucide:bus', agent: 'Local bus routes and their departure schedules (bus_route).' }),
|
|
13
|
+
shelves: [bus_route],
|
|
14
14
|
},
|
|
15
15
|
],
|
|
16
16
|
settings: defineSettings({
|
package/dist/runtime/index.d.ts
CHANGED
package/dist/runtime/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
export { startSync, stopSync } from "./sync.js";
|
|
1
|
+
import { runOnce } from "./sync.js";
|
|
2
|
+
export { runOnce } from "./sync.js";
|
|
3
|
+
const SYNC_INTERVAL_MS = Number(process.env['TRANSIT_SYNC_INTERVAL_MS']) || 6 * 60 * 60 * 1000;
|
|
5
4
|
export const serverHooks = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
backgroundTasks: [
|
|
6
|
+
{
|
|
7
|
+
name: 'transit-sync',
|
|
8
|
+
intervalMs: SYNC_INTERVAL_MS,
|
|
9
|
+
run: async () => {
|
|
10
|
+
await runOnce();
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
],
|
|
12
14
|
agent: {
|
|
13
|
-
instructions: '
|
|
14
|
-
'weekday_times/saturday_times/sunday_times — departure schedule.' +
|
|
15
|
+
instructions: 'bus_route: weekday_times/saturday_times/sunday_times — departure schedule.' +
|
|
15
16
|
' When the schedule changes, update *_times via update_record.',
|
|
16
17
|
},
|
|
17
18
|
};
|
package/dist/runtime/sync.d.ts
CHANGED
|
@@ -12,5 +12,4 @@ export interface BusRouteRecord {
|
|
|
12
12
|
notes: string | null;
|
|
13
13
|
}
|
|
14
14
|
export declare function buildBusEvents(records: BusRouteRecord[]): IcsFile[];
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function stopSync(): void;
|
|
15
|
+
export declare function runOnce(): Promise<void>;
|
package/dist/runtime/sync.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getEm } from '@coffer-org/server/db';
|
|
2
2
|
import { getPluginSettings } from '@coffer-org/server/plugin-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { syncIcs, buildVEvent, buildRRule } from '@coffer-org/dav';
|
|
4
4
|
import { getLogger } from '@coffer-org/sdk/logger';
|
|
5
5
|
const log = getLogger('transit');
|
|
6
6
|
const REF_DATE = { weekday: '20240101', saturday: '20240106', sunday: '20240107' };
|
|
@@ -55,7 +55,7 @@ export function buildBusEvents(records) {
|
|
|
55
55
|
}
|
|
56
56
|
return files;
|
|
57
57
|
}
|
|
58
|
-
async function runOnce() {
|
|
58
|
+
export async function runOnce() {
|
|
59
59
|
const fork = getEm().fork();
|
|
60
60
|
const rows = (await fork.find('transit__bus_route', {}));
|
|
61
61
|
const icsFiles = buildBusEvents(rows);
|
|
@@ -63,34 +63,9 @@ async function runOnce() {
|
|
|
63
63
|
const calendar = pluginSettings['caldav_calendar'];
|
|
64
64
|
if (!calendar)
|
|
65
65
|
throw new Error('[transit-sync] caldav_calendar is required but not set');
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
collectionUrl: settings.collectionUrl,
|
|
71
|
-
username: settings.principal,
|
|
72
|
-
password: settings.password,
|
|
73
|
-
});
|
|
74
|
-
const coll = new CalDavCollection(ops);
|
|
75
|
-
const result = await coll.syncEvents('bus-route-', icsFiles);
|
|
66
|
+
const result = await syncIcs(calendar, {
|
|
67
|
+
principal: pluginSettings['caldav_username'],
|
|
68
|
+
password: pluginSettings['caldav_password'],
|
|
69
|
+
}, 'bus-route-', icsFiles);
|
|
76
70
|
log.debug(`synced: ${result.written.length} written, ${result.deleted.length} deleted, ${result.failed.length} failed`);
|
|
77
71
|
}
|
|
78
|
-
const INTERVAL_MS = Number(process.env['TRANSIT_SYNC_INTERVAL_MS'] ?? 0) || 6 * 60 * 60 * 1000;
|
|
79
|
-
let timer;
|
|
80
|
-
export async function startSync() {
|
|
81
|
-
try {
|
|
82
|
-
await runOnce();
|
|
83
|
-
}
|
|
84
|
-
catch (e) {
|
|
85
|
-
log.error(`initial sync failed: ${e.message}`);
|
|
86
|
-
}
|
|
87
|
-
timer = setInterval(() => {
|
|
88
|
-
void runOnce().catch((e) => log.error(`sync error: ${e.message}`));
|
|
89
|
-
}, INTERVAL_MS);
|
|
90
|
-
}
|
|
91
|
-
export function stopSync() {
|
|
92
|
-
if (timer !== undefined) {
|
|
93
|
-
clearInterval(timer);
|
|
94
|
-
timer = undefined;
|
|
95
|
-
}
|
|
96
|
-
}
|
package/dist/schema.js
CHANGED
|
@@ -21,8 +21,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
enumerable: true
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
|
-
//#region ../sdk/src/
|
|
25
|
-
function
|
|
24
|
+
//#region ../sdk/src/library.ts
|
|
25
|
+
function defineLibrary(v) {
|
|
26
26
|
return v;
|
|
27
27
|
}
|
|
28
28
|
//#endregion
|
|
@@ -154,7 +154,10 @@ function assignProp(target, prop, value) {
|
|
|
154
154
|
}
|
|
155
155
|
function mergeDefs(...defs) {
|
|
156
156
|
const mergedDescriptors = {};
|
|
157
|
-
for (const def of defs)
|
|
157
|
+
for (const def of defs) {
|
|
158
|
+
const descriptors = Object.getOwnPropertyDescriptors(def);
|
|
159
|
+
Object.assign(mergedDescriptors, descriptors);
|
|
160
|
+
}
|
|
158
161
|
return Object.defineProperties({}, mergedDescriptors);
|
|
159
162
|
}
|
|
160
163
|
function esc(str) {
|
|
@@ -476,7 +479,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
476
479
|
}, ctx);
|
|
477
480
|
if (result instanceof Promise) throw new $ZodAsyncError();
|
|
478
481
|
if (result.issues.length) {
|
|
479
|
-
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
482
|
+
const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
480
483
|
captureStackTrace(e, _params?.callee);
|
|
481
484
|
throw e;
|
|
482
485
|
}
|
|
@@ -493,7 +496,7 @@ var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
|
493
496
|
}, ctx);
|
|
494
497
|
if (result instanceof Promise) result = await result;
|
|
495
498
|
if (result.issues.length) {
|
|
496
|
-
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
499
|
+
const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
497
500
|
captureStackTrace(e, params?.callee);
|
|
498
501
|
throw e;
|
|
499
502
|
}
|
|
@@ -1945,7 +1948,7 @@ var $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
|
|
|
1945
1948
|
inst._zod.optin = "optional";
|
|
1946
1949
|
inst._zod.optout = "optional";
|
|
1947
1950
|
defineLazy(inst._zod, "values", () => {
|
|
1948
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1951
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1949
1952
|
});
|
|
1950
1953
|
defineLazy(inst._zod, "pattern", () => {
|
|
1951
1954
|
const pattern = def.innerType._zod.pattern;
|
|
@@ -1979,7 +1982,7 @@ var $ZodNullable = /*@__PURE__*/ $constructor("$ZodNullable", (inst, def) => {
|
|
|
1979
1982
|
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)}|null)$`) : void 0;
|
|
1980
1983
|
});
|
|
1981
1984
|
defineLazy(inst._zod, "values", () => {
|
|
1982
|
-
return def.innerType._zod.values ? new Set([...def.innerType._zod.values, null]) : void 0;
|
|
1985
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, null]) : void 0;
|
|
1983
1986
|
});
|
|
1984
1987
|
inst._zod.parse = (payload, ctx) => {
|
|
1985
1988
|
if (payload.value === null) return payload;
|
|
@@ -4587,7 +4590,7 @@ function password(raw) {
|
|
|
4587
4590
|
* Internal API-token list — keyValue-shaped collection (name + write-only
|
|
4588
4591
|
* token + timestamps), custom renderer (`kind:'internalApiToken'`, own
|
|
4589
4592
|
* create/revoke UI — same trick as url()/perWeekday()). "Internal" = not a
|
|
4590
|
-
* general-purpose field type for plugin
|
|
4593
|
+
* general-purpose field type for plugin shelves, only for the core account
|
|
4591
4594
|
* settings page. `token` is `kind:'password'` so maskSecrets/preserveTree
|
|
4592
4595
|
* already mask/preserve it for free.
|
|
4593
4596
|
*/
|
|
@@ -4606,6 +4609,25 @@ function internalApiToken(o) {
|
|
|
4606
4609
|
]
|
|
4607
4610
|
});
|
|
4608
4611
|
}
|
|
4612
|
+
/**
|
|
4613
|
+
* Internal "connected apps" list — the OAuth clients (claude.ai & co) the user
|
|
4614
|
+
* has authorized for MCP access. Same "internal" caveat and custom-renderer
|
|
4615
|
+
* trick as internalApiToken(): read-only rows + a revoke action, never part of
|
|
4616
|
+
* the parent form's save.
|
|
4617
|
+
*/
|
|
4618
|
+
function internalOauthGrants(o) {
|
|
4619
|
+
return group({
|
|
4620
|
+
key: o.key,
|
|
4621
|
+
label: o.label ?? o.key,
|
|
4622
|
+
multiple: true,
|
|
4623
|
+
view: { kind: "internalOauthGrants" },
|
|
4624
|
+
fields: [
|
|
4625
|
+
string({ key: "clientName" }),
|
|
4626
|
+
string({ key: "createdAt" }),
|
|
4627
|
+
string({ key: "lastUsedAt" })
|
|
4628
|
+
]
|
|
4629
|
+
});
|
|
4630
|
+
}
|
|
4609
4631
|
var SLUG_RE = /^[a-z0-9-]+$/;
|
|
4610
4632
|
function slug(raw) {
|
|
4611
4633
|
const o = normalizeOpts(raw);
|
|
@@ -4686,7 +4708,7 @@ var TEL_RE = /^\+?[\d\s()-]{4,}$/;
|
|
|
4686
4708
|
/** Loose URL: будь-який scheme:// АБО host-з-крапкою (+опц. порт/шлях). Без пробілів. */
|
|
4687
4709
|
var LINK_RE = /^([a-z][a-z0-9+.-]*:\/\/\S+|[\w-]+(\.[\w-]+)+(:\d+)?(\/\S*)?)$/i;
|
|
4688
4710
|
/** CSS named colors (CSS Color Module L4) — для f.colorname. */
|
|
4689
|
-
var CSS_COLOR_NAMES = new Set([
|
|
4711
|
+
var CSS_COLOR_NAMES = /* @__PURE__ */ new Set([
|
|
4690
4712
|
"aliceblue",
|
|
4691
4713
|
"antiquewhite",
|
|
4692
4714
|
"aqua",
|
|
@@ -5035,7 +5057,8 @@ var presets = {
|
|
|
5035
5057
|
weight,
|
|
5036
5058
|
dimensions,
|
|
5037
5059
|
country,
|
|
5038
|
-
internalApiToken
|
|
5060
|
+
internalApiToken,
|
|
5061
|
+
internalOauthGrants
|
|
5039
5062
|
};
|
|
5040
5063
|
//#endregion
|
|
5041
5064
|
//#region ../../node_modules/iso-639-1/src/data.js
|
|
@@ -5147,7 +5170,7 @@ var require_data = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5147
5170
|
},
|
|
5148
5171
|
cs: {
|
|
5149
5172
|
name: "Czech",
|
|
5150
|
-
nativeName: "
|
|
5173
|
+
nativeName: "čeština"
|
|
5151
5174
|
},
|
|
5152
5175
|
cu: {
|
|
5153
5176
|
name: "Old Church Slavonic",
|
|
@@ -5611,7 +5634,7 @@ var require_data = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
5611
5634
|
},
|
|
5612
5635
|
sk: {
|
|
5613
5636
|
name: "Slovak",
|
|
5614
|
-
nativeName: "
|
|
5637
|
+
nativeName: "slovenčtina"
|
|
5615
5638
|
},
|
|
5616
5639
|
sl: {
|
|
5617
5640
|
name: "Slovenian",
|
|
@@ -5864,7 +5887,7 @@ function group(o) {
|
|
|
5864
5887
|
required: o.required,
|
|
5865
5888
|
unique: r.unique,
|
|
5866
5889
|
label: o.label,
|
|
5867
|
-
icon:
|
|
5890
|
+
icon: o.icon,
|
|
5868
5891
|
display: v.display ?? "wrap",
|
|
5869
5892
|
kind: v.kind,
|
|
5870
5893
|
fixed: r.fixed,
|
|
@@ -5875,11 +5898,9 @@ function group(o) {
|
|
|
5875
5898
|
function row(o) {
|
|
5876
5899
|
return group({
|
|
5877
5900
|
label: o.label,
|
|
5901
|
+
icon: o.icon,
|
|
5878
5902
|
fields: o.fields,
|
|
5879
|
-
view: {
|
|
5880
|
-
...o.view,
|
|
5881
|
-
display: "scroll"
|
|
5882
|
-
}
|
|
5903
|
+
view: { display: "scroll" }
|
|
5883
5904
|
});
|
|
5884
5905
|
}
|
|
5885
5906
|
/** Tabular collection (array of rows → <table>, aligned by columns). Sugar. */
|
|
@@ -5887,14 +5908,12 @@ function table(o) {
|
|
|
5887
5908
|
return group({
|
|
5888
5909
|
key: o.key,
|
|
5889
5910
|
label: o.label,
|
|
5911
|
+
icon: o.icon,
|
|
5890
5912
|
fields: o.fields,
|
|
5891
5913
|
multiple: true,
|
|
5892
5914
|
required: o.required,
|
|
5893
5915
|
rules: o.rules,
|
|
5894
|
-
view: {
|
|
5895
|
-
...o.view,
|
|
5896
|
-
display: "table"
|
|
5897
|
-
}
|
|
5916
|
+
view: { display: "table" }
|
|
5898
5917
|
});
|
|
5899
5918
|
}
|
|
5900
5919
|
/**
|
|
@@ -5910,11 +5929,9 @@ function sheet(o) {
|
|
|
5910
5929
|
});
|
|
5911
5930
|
return group({
|
|
5912
5931
|
label: o.label,
|
|
5932
|
+
icon: o.icon,
|
|
5913
5933
|
fields: flat,
|
|
5914
|
-
view: {
|
|
5915
|
-
...o.view,
|
|
5916
|
-
display: "sheet"
|
|
5917
|
-
}
|
|
5934
|
+
view: { display: "sheet" }
|
|
5918
5935
|
});
|
|
5919
5936
|
}
|
|
5920
5937
|
/**
|
|
@@ -5946,8 +5963,8 @@ function keyed(o) {
|
|
|
5946
5963
|
return {
|
|
5947
5964
|
...(o.container ?? group)({
|
|
5948
5965
|
label: o.label,
|
|
5949
|
-
|
|
5950
|
-
|
|
5966
|
+
icon: o.icon,
|
|
5967
|
+
fields: [o.by, ...o.fields]
|
|
5951
5968
|
}),
|
|
5952
5969
|
key: o.key,
|
|
5953
5970
|
multiple: true,
|
|
@@ -5992,6 +6009,34 @@ function wrapKey(opts, meta) {
|
|
|
5992
6009
|
noEditControl: true
|
|
5993
6010
|
}
|
|
5994
6011
|
};
|
|
6012
|
+
if (opts.emphasis) m = {
|
|
6013
|
+
...m,
|
|
6014
|
+
hints: {
|
|
6015
|
+
...m.hints,
|
|
6016
|
+
emphasis: opts.emphasis
|
|
6017
|
+
}
|
|
6018
|
+
};
|
|
6019
|
+
if (opts.noLabel) m = {
|
|
6020
|
+
...m,
|
|
6021
|
+
hints: {
|
|
6022
|
+
...m.hints,
|
|
6023
|
+
noLabel: true
|
|
6024
|
+
}
|
|
6025
|
+
};
|
|
6026
|
+
if (opts.role) m = {
|
|
6027
|
+
...m,
|
|
6028
|
+
hints: {
|
|
6029
|
+
...m.hints,
|
|
6030
|
+
role: opts.role
|
|
6031
|
+
}
|
|
6032
|
+
};
|
|
6033
|
+
if (opts.pinned) m = {
|
|
6034
|
+
...m,
|
|
6035
|
+
hints: {
|
|
6036
|
+
...m.hints,
|
|
6037
|
+
pinned: true
|
|
6038
|
+
}
|
|
6039
|
+
};
|
|
5995
6040
|
if (opts.default !== void 0) m = {
|
|
5996
6041
|
...m,
|
|
5997
6042
|
default: opts.default
|
|
@@ -6355,8 +6400,8 @@ function relation(raw) {
|
|
|
6355
6400
|
displayKey: o.displayKey ?? "name"
|
|
6356
6401
|
},
|
|
6357
6402
|
relation: {
|
|
6358
|
-
|
|
6359
|
-
|
|
6403
|
+
library: raw.options.library,
|
|
6404
|
+
shelf: raw.options.shelf
|
|
6360
6405
|
},
|
|
6361
6406
|
...multi && { json: true },
|
|
6362
6407
|
zod: optionalize(s, required)
|
|
@@ -6736,15 +6781,44 @@ function period(raw) {
|
|
|
6736
6781
|
zod: optionalize(s, required)
|
|
6737
6782
|
});
|
|
6738
6783
|
}
|
|
6784
|
+
/** Keys a file entry may carry. Everything else is rejected — see fileEntryIssue. */
|
|
6785
|
+
var FILE_KEYS = /* @__PURE__ */ new Set([
|
|
6786
|
+
"name",
|
|
6787
|
+
"mime",
|
|
6788
|
+
"size"
|
|
6789
|
+
]);
|
|
6790
|
+
/** Keys that mean "the author pasted a remote address" — the one mistake worth naming. */
|
|
6791
|
+
var FILE_URL_KEYS = [
|
|
6792
|
+
"url",
|
|
6793
|
+
"src",
|
|
6794
|
+
"href",
|
|
6795
|
+
"link"
|
|
6796
|
+
];
|
|
6797
|
+
/**
|
|
6798
|
+
* A file entry points at a file already uploaded to the server: `{ name }`, where
|
|
6799
|
+
* name is the bare filename returned by POST /api/upload. Anything else — a remote
|
|
6800
|
+
* URL, an extra key, a path — is refused here, so a record can never hold a
|
|
6801
|
+
* reference the server cannot serve. `mime`/`size` are accepted (legacy payloads
|
|
6802
|
+
* and the web uploader send them) but the server overwrites them from disk.
|
|
6803
|
+
* Returns a vmsg code, or null when the entry is well-formed.
|
|
6804
|
+
*/
|
|
6805
|
+
function fileEntryIssue(it) {
|
|
6806
|
+
if (typeof it !== "object" || it === null || Array.isArray(it)) return "file_structure";
|
|
6807
|
+
const rec = it;
|
|
6808
|
+
if (FILE_URL_KEYS.some((k) => k in rec)) return "file_remote_url";
|
|
6809
|
+
const name = rec["name"];
|
|
6810
|
+
if (typeof name !== "string" || name === "") return "file_structure";
|
|
6811
|
+
if (name.includes("://") || name.startsWith("//")) return "file_remote_url";
|
|
6812
|
+
if (/[\\/]/.test(name) || name.includes("..")) return "file_name";
|
|
6813
|
+
for (const k of Object.keys(rec)) if (!FILE_KEYS.has(k)) return "file_unknown_key";
|
|
6814
|
+
if (rec["mime"] !== void 0 && typeof rec["mime"] !== "string") return "file_structure";
|
|
6815
|
+
if (rec["size"] !== void 0 && typeof rec["size"] !== "number") return "file_structure";
|
|
6816
|
+
return null;
|
|
6817
|
+
}
|
|
6739
6818
|
function makeFile(kind, raw) {
|
|
6740
6819
|
const o = normalizeOpts(raw);
|
|
6741
6820
|
const required = o.required ?? false;
|
|
6742
6821
|
const multiple = o.multiple ?? false;
|
|
6743
|
-
const rowSchema = object({
|
|
6744
|
-
name: string$1().min(1),
|
|
6745
|
-
mime: string$1().optional(),
|
|
6746
|
-
size: number$1().optional()
|
|
6747
|
-
});
|
|
6748
6822
|
const s = unknown().superRefine((raw, ctx) => {
|
|
6749
6823
|
if (typeof raw === "string") try {
|
|
6750
6824
|
JSON.parse(raw);
|
|
@@ -6757,12 +6831,15 @@ function makeFile(kind, raw) {
|
|
|
6757
6831
|
}
|
|
6758
6832
|
const parsed = jsonValue(raw);
|
|
6759
6833
|
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
6760
|
-
for (const it of items)
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6834
|
+
for (const it of items) {
|
|
6835
|
+
const code = fileEntryIssue(it);
|
|
6836
|
+
if (code) {
|
|
6837
|
+
ctx.addIssue({
|
|
6838
|
+
code: ZodIssueCode.custom,
|
|
6839
|
+
message: vmsg(code)
|
|
6840
|
+
});
|
|
6841
|
+
return;
|
|
6842
|
+
}
|
|
6766
6843
|
}
|
|
6767
6844
|
});
|
|
6768
6845
|
return wrapKey(o, {
|
|
@@ -7681,7 +7758,7 @@ var createDefaultQueryTester = function(query, options) {
|
|
|
7681
7758
|
};
|
|
7682
7759
|
createDefaultQueryTester.createEqualsOperation;
|
|
7683
7760
|
//#endregion
|
|
7684
|
-
//#region ../sdk/src/
|
|
7761
|
+
//#region ../sdk/src/shelf.ts
|
|
7685
7762
|
/** Flat [storageKey, FieldMeta] pairs of the parent table's columns.
|
|
7686
7763
|
* layout group → flattened; embedded group → prefix `key__`; collection → skipped. */
|
|
7687
7764
|
function fieldEntries(items) {
|
|
@@ -7694,11 +7771,11 @@ function fieldEntries(items) {
|
|
|
7694
7771
|
}
|
|
7695
7772
|
return out;
|
|
7696
7773
|
}
|
|
7697
|
-
function
|
|
7774
|
+
function defineShelf(m) {
|
|
7698
7775
|
const keys = fieldEntries(m.fields).map(([k]) => k);
|
|
7699
7776
|
const dup = keys.find((k, i) => keys.indexOf(k) !== i);
|
|
7700
|
-
if (dup) throw new Error(`[
|
|
7701
|
-
if (m.standalone !== false && !m.views?.
|
|
7777
|
+
if (dup) throw new Error(`[shelf] ${m.library}/${m.shelf}: duplicate key '${dup}'`);
|
|
7778
|
+
if (m.standalone !== false && !m.views?.list?.fields?.length) console.warn(`[shelf] ${m.library}/${m.shelf}: standalone shelf without an explicit views.list`);
|
|
7702
7779
|
return m;
|
|
7703
7780
|
}
|
|
7704
7781
|
//#endregion
|
|
@@ -7709,16 +7786,16 @@ function defineModule(m) {
|
|
|
7709
7786
|
* 48 Кишинів→Чореску, 48 Чореску→Кишинів.
|
|
7710
7787
|
* Час відправлень зберігається як JSON-масиви рядків "HH:MM".
|
|
7711
7788
|
*/
|
|
7712
|
-
var bus_route_default =
|
|
7713
|
-
|
|
7714
|
-
|
|
7789
|
+
var bus_route_default = defineShelf({
|
|
7790
|
+
shelf: "bus_route",
|
|
7791
|
+
library: "transit",
|
|
7715
7792
|
label: "transit.bus_route.label",
|
|
7716
7793
|
icon: "lucide:bus",
|
|
7717
|
-
views: {
|
|
7794
|
+
views: { list: { fields: [
|
|
7718
7795
|
"route_number",
|
|
7719
7796
|
"from",
|
|
7720
7797
|
"to"
|
|
7721
|
-
] },
|
|
7798
|
+
] } },
|
|
7722
7799
|
fields: [
|
|
7723
7800
|
field.title({
|
|
7724
7801
|
key: "name",
|
|
@@ -7775,13 +7852,14 @@ var src_default = definePlugin({
|
|
|
7775
7852
|
id: "transit",
|
|
7776
7853
|
version: "1.0.0",
|
|
7777
7854
|
dependsOn: [],
|
|
7778
|
-
|
|
7779
|
-
meta:
|
|
7855
|
+
libraries: [{
|
|
7856
|
+
meta: defineLibrary({
|
|
7780
7857
|
id: "transit",
|
|
7781
|
-
label: "transit.
|
|
7782
|
-
icon: "lucide:bus"
|
|
7858
|
+
label: "transit.library.label",
|
|
7859
|
+
icon: "lucide:bus",
|
|
7860
|
+
agent: "Local bus routes and their departure schedules (bus_route)."
|
|
7783
7861
|
}),
|
|
7784
|
-
|
|
7862
|
+
shelves: [bus_route_default]
|
|
7785
7863
|
}],
|
|
7786
7864
|
settings: defineSettings({
|
|
7787
7865
|
label: "transit.settings.label",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffer-org/plugin-transit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24"
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"test": "node --import tsx/esm --test 'src/runtime/*.test.ts'"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@coffer-org/sdk": "^
|
|
29
|
-
"@coffer-org/server": "^
|
|
30
|
-
"@coffer-org/dav": "^
|
|
28
|
+
"@coffer-org/sdk": "^2.0.0",
|
|
29
|
+
"@coffer-org/server": "^2.0.1",
|
|
30
|
+
"@coffer-org/dav": "^2.0.0"
|
|
31
31
|
},
|
|
32
32
|
"coffer": {
|
|
33
33
|
"schema": "dist/schema.js"
|