namespace _zeitbild.repository.resource { /** */ type type_local_resource_event_stuff = { event : _zeitbild.type_event_object; local_resource_id : int; } /** */ var _local_resource_event_store : ( null | lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > ) = null; /** */ var _local_resource_core_store : ( null | lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > ) = null; /** */ var _caldav_resource_store : ( null | lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > ) = null; /** */ var _resource_core_store : ( null | lib_plankton.storage.type_store< _zeitbild.type_resource_id, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > ) = null; /** */ function get_local_resource_event_store( ) : lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > { if (_local_resource_event_store === null) { _local_resource_event_store = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "local_resource_events", "key_name": "id", } ); } else { // do nothing } return _local_resource_event_store; } /** */ function get_local_resource_core_store( ) : lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > { if (_local_resource_core_store === null) { _local_resource_core_store = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "local_resources", "key_name": "id", } ); } else { // do nothing } return _local_resource_core_store; } /** */ function get_caldav_resource_store( ) : lib_plankton.storage.type_store< int, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > { if (_caldav_resource_store === null) { _caldav_resource_store = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "caldav_resources", "key_name": "id", } ); } else { // do nothing } return _caldav_resource_store; } /** */ function get_resource_core_store( ) : lib_plankton.storage.type_store< _zeitbild.type_resource_id, Record, {}, lib_plankton.storage.type_sql_table_autokey_search_term, Record > { if (_resource_core_store === null) { _resource_core_store = lib_plankton.storage.sql_table_autokey_store( { "database_implementation": _zeitbild.database.get_implementation(), "table_name": "resources", "key_name": "id", } ); } else { // do nothing } return _resource_core_store; } /** */ function encode_local_resource_event( stuff : type_local_resource_event_stuff ) : Record { const encode_datetime : ((datetime : lib_plankton.pit.type_datetime) => string) = ((datetime) => { return lib_plankton.string.coin( "{{timezone_shift}}|{{date}}{{macro_time}}", { "timezone_shift": datetime.timezone_shift.toFixed(0).padStart(2, "0"), "date": lib_plankton.string.coin( "{{year}}-{{month}}-{{day}}", { "year": datetime.date.year.toFixed(0).padStart(4, "0"), "month": datetime.date.month.toFixed(0).padStart(2, "0"), "day": datetime.date.day.toFixed(0).padStart(2, "0"), } ), "macro_time": ( (datetime.time === null) ? "" : lib_plankton.string.coin( "T{{hour}}:{{minute}}:{{second}}", { "hour": datetime.time.hour.toFixed(0).padStart(2, "0"), "minute": datetime.time.minute.toFixed(0).padStart(2, "0"), "second": datetime.time.second.toFixed(0).padStart(2, "0"), } ) ), } ); }); return { "local_resource_id": stuff.local_resource_id, "name": stuff.event.name, "public": stuff.event.public, "begin": encode_datetime(stuff.event.begin), "end": ( (stuff.event.end === null) ? null : encode_datetime(stuff.event.end) ), "location": stuff.event.location, "description": stuff.event.description, } } /** */ function decode_local_resource_event( row : Record ) : type_local_resource_event_stuff { const decode_datetime : ((datetime_raw : string) => lib_plankton.pit.type_datetime) = ((datetime_raw) => { const parts : Array = datetime_raw.split("|"); const timezone_shift : int = parseInt(parts[0]); if (parts[1].length <= 10) { return { "timezone_shift": timezone_shift, "date": { "year": parseInt(parts[1].slice(0, 4)), "month": parseInt(parts[1].slice(5, 7)), "day": parseInt(parts[1].slice(8, 10)), }, "time": null }; } else { return { "timezone_shift": timezone_shift, "date": { "year": parseInt(parts[1].slice(0, 4)), "month": parseInt(parts[1].slice(5, 7)), "day": parseInt(parts[1].slice(8, 10)), }, "time": { "hour": parseInt(parts[1].slice(11, 13)), "minute": parseInt(parts[1].slice(14, 16)), "second": parseInt(parts[1].slice(17, 19)), } }; } }); return { "local_resource_id": row["local_resource_id"], "event": { "name": row["name"], "public": row["public"], "begin": decode_datetime(row["begin"]), "end": ( (row["end"] === null) ? null : decode_datetime(row["end"]) ), "location": row["location"], "description": row["description"], } }; } /** */ /* function encode_resource_core( stuff : { object : _zeitbild.type_resource_object; sub_id : int; } ) : Record { return { "kind": stuff.object.kind, "sub_id": stuff.sub_id }; } */ /** * @todo data */ /* function decode_resource_core( row : Record ) : { object : _zeitbild.type_resource_object; sub_id : int; } { return { "object": { "kind": row["kind"], "data": null, }, "sub_id": row["sub_id"], }; } */ /** */ export async function read( resource_id : _zeitbild.type_resource_id ) : Promise<_zeitbild.type_resource_object> { const dataset_core : Record = await get_resource_core_store().read(resource_id); switch (dataset_core.kind) { case "local": { const dataset_extra_local_core : Record = await get_local_resource_core_store().read(dataset_core.sub_id); const datasets_extra_local_event_ids : Array> = await get_local_resource_event_store().search( { "expression": "(local_resource_id = $local_resource_id)", "arguments": { "local_resource_id": dataset_core.sub_id, } } ); return Promise.resolve<_zeitbild.type_resource_object>( { "kind": "local", "data": { "event_ids": ( datasets_extra_local_event_ids .map((hit) => hit.preview["id"]) ) } } ); } case "caldav": { const dataset_extra_caldav : Record = await get_caldav_resource_store().read(dataset_core.sub_id); return Promise.resolve<_zeitbild.type_resource_object>( { "kind": "caldav", "data": { "url": dataset_extra_caldav["url"], "read_only": dataset_extra_caldav["read_only"], } } ); break; } default: { return Promise.reject<_zeitbild.type_resource_object>( new Error("invalid resource kind: " + dataset_core.kind) ); break; } } } /** */ export async function create( resource_object : _zeitbild.type_resource_object ) : Promise<_zeitbild.type_resource_id> { switch (resource_object.kind) { case "local": { const local_resource_id : int = await get_local_resource_core_store().create( { "_dummy": null, } ); const resource_id : _zeitbild.type_resource_id = await get_resource_core_store().create( { "kind": "local", "sub_id": local_resource_id, } ); return Promise.resolve<_zeitbild.type_resource_id>(resource_id); break; } case "caldav": { const caldav_resource_id : int = await get_caldav_resource_store().create( { "url": resource_object.data.url, "read_only": resource_object.data.read_only, } ); const resource_id : _zeitbild.type_resource_id = await get_resource_core_store().create( { "kind": "caldav", "sub_id": caldav_resource_id, } ); return Promise.resolve<_zeitbild.type_resource_id>(resource_id); break; } default: { // @ts-ignore throw (new Error("invalid resource kind: " + resource_object.kind)); break; } } } /** * @todo allow kind change? */ export async function update( resource_id : _zeitbild.type_resource_id, resource_object : _zeitbild.type_resource_object ) : Promise { const dataset_core : Record = await get_resource_core_store().read(resource_id); if (dataset_core["kind"] !== resource_object.kind) { return Promise.reject(new Error("resource kind may not be altered")); } else { switch (resource_object.kind) { case "local": { // event_id list may not be altered directly /* const current_event_id_rows : {key : int; preview : Array>;} = await get_local_resource_event_chest().search( { "expression": "(local_resource_id = $local_resource_id)", "arguments": { "local_resource_id": dataset_core["sub_id"] } } ); const contrast : { only_left : Array<{key : int; left : any;}>; both : Array<{key : int; left : any; right : any;}>; only_right : Array<{key : int; right : any;}>; } = lib_plankton.list.contrast< {key : Array; preview : Record;}, _zeitbild.type_local_resource_event_id >( event_rows, (hit => hit.key), resource_object.data.event_ids, (x => x) ); // TODO: single delete? for await (const entry of constrast.only_left) { await get_local_resource_event_store().delete( entry.key ); } /* for await (const entry of contrast.both) { await get_local_resource_event_store().update( entry.left.key, encode_local_resource_event(entry.right.object) ); } for await (const entry of contrast.only_right) { const event_id : type_local_resource_event_id = await get_local_resource_event_store().create( encode_local_resource_event(entry.right.object) ); } */ break; } case "caldav": { await get_caldav_resource_store().update( dataset_core["sub_id"], { "url": resource_object.data.url, "read_only": resource_object.data.read_only, } ); break; } default: { // @ts-ignore throw (new Error("invalid resource kind: " + resource_object.kind)); break; } } } } /** */ export async function local_resource_event_read( resource_id : _zeitbild.type_resource_id, local_resource_event_id : _zeitbild.type_local_resource_event_id ) : Promise<_zeitbild.type_event_object> { const dataset_core : Record = await get_resource_core_store().read(resource_id); if (! (dataset_core.kind === "local")) { throw (new Error("not a local resource")); } else { return ( get_local_resource_event_store().read( local_resource_event_id ) .then( (row) => Promise.resolve(decode_local_resource_event(row)) ) .then( (local_resource_event_stuff : type_local_resource_event_stuff) => Promise.resolve( local_resource_event_stuff.event ) ) ); } } /** */ export async function local_resource_event_create( resource_id : _zeitbild.type_resource_id, event_object : _zeitbild.type_event_object ) : Promise<_zeitbild.type_local_resource_event_id> { const dataset_core : Record = await get_resource_core_store().read(resource_id); if (! (dataset_core.kind === "local")) { throw (new Error("not a local resource")); } else { return get_local_resource_event_store().create( encode_local_resource_event( { "local_resource_id": dataset_core["sub_id"], "event": event_object, } ) ); } } /** */ export async function local_resource_event_update( resource_id : _zeitbild.type_resource_id, event_id : _zeitbild.type_local_resource_event_id, event_object : _zeitbild.type_event_object ) : Promise { const dataset_core : Record = await get_resource_core_store().read(resource_id); if (! (dataset_core.kind === "local")) { throw (new Error("not a local resource")); } else { return get_local_resource_event_store().update( event_id, encode_local_resource_event( { "local_resource_id": dataset_core["sub_id"], "event": event_object, } ) ); } } /** */ export async function local_resource_event_delete( resource_id : _zeitbild.type_resource_id, local_resource_event_id : _zeitbild.type_local_resource_event_id ) : Promise { const dataset_core : Record = await get_resource_core_store().read(resource_id); if (! (dataset_core.kind === "local")) { throw (new Error("not a local resource")); } else { return ( get_local_resource_event_store().delete( local_resource_event_id ) .then( () => Promise.resolve(undefined) ) ); } } }