@arcote.tech/arc-adapter-db-sqlite 0.4.9 → 0.5.1

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.
Files changed (2) hide show
  1. package/dist/index.js +451 -1
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/bun-sqlite.ts
2
2
  import { Database } from "bun:sqlite";
3
3
 
4
- // ../../../../node_modules/mutative/dist/mutative.esm.mjs
4
+ // ../../../../node_modules/.bun/mutative@1.3.0/node_modules/mutative/dist/mutative.esm.mjs
5
5
  var Operation = {
6
6
  Remove: "remove",
7
7
  Replace: "replace",
@@ -2829,6 +2829,147 @@ class ArcEvent extends ArcContextElement {
2829
2829
  return ArcEvent.sharedDatabaseStoreSchema();
2830
2830
  }
2831
2831
  }
2832
+ function buildElementContext(queryElements, mutationElements, adapters) {
2833
+ const queryMap = new Map;
2834
+ const mutateMap = new Map;
2835
+ const queryProps = {};
2836
+ for (const element of queryElements) {
2837
+ if (element.queryContext) {
2838
+ const ctx = element.queryContext(adapters);
2839
+ queryProps[element.name] = ctx;
2840
+ queryMap.set(element, ctx);
2841
+ }
2842
+ }
2843
+ const mutateProps = {};
2844
+ for (const element of mutationElements) {
2845
+ if (element.mutateContext) {
2846
+ const ctx = element.mutateContext(adapters);
2847
+ mutateProps[element.name] = ctx;
2848
+ mutateMap.set(element, ctx);
2849
+ }
2850
+ }
2851
+ const queryFn = (element) => {
2852
+ const cached = queryMap.get(element);
2853
+ if (cached)
2854
+ return cached;
2855
+ if (element.queryContext) {
2856
+ const ctx = element.queryContext(adapters);
2857
+ queryMap.set(element, ctx);
2858
+ return ctx;
2859
+ }
2860
+ throw new Error(`Element "${element.name}" has no queryContext`);
2861
+ };
2862
+ Object.assign(queryFn, queryProps);
2863
+ const mutateFn = (element) => {
2864
+ const cached = mutateMap.get(element);
2865
+ if (cached)
2866
+ return cached;
2867
+ if (element.mutateContext) {
2868
+ const ctx = element.mutateContext(adapters);
2869
+ mutateMap.set(element, ctx);
2870
+ return ctx;
2871
+ }
2872
+ throw new Error(`Element "${element.name}" has no mutateContext`);
2873
+ };
2874
+ Object.assign(mutateFn, mutateProps);
2875
+ return {
2876
+ query: queryFn,
2877
+ mutate: mutateFn
2878
+ };
2879
+ }
2880
+
2881
+ class ArcFunction {
2882
+ data;
2883
+ constructor(data) {
2884
+ this.data = data;
2885
+ }
2886
+ withParams(schema) {
2887
+ return new ArcFunction({
2888
+ ...this.data,
2889
+ params: schema instanceof ArcObject ? schema : new ArcObject(schema)
2890
+ });
2891
+ }
2892
+ withResult(schema) {
2893
+ return new ArcFunction({
2894
+ ...this.data,
2895
+ result: schema instanceof ArcObject ? schema : new ArcObject(schema)
2896
+ });
2897
+ }
2898
+ query(elements) {
2899
+ return new ArcFunction({
2900
+ ...this.data,
2901
+ queryElements: elements
2902
+ });
2903
+ }
2904
+ mutate(elements) {
2905
+ return new ArcFunction({
2906
+ ...this.data,
2907
+ mutationElements: elements
2908
+ });
2909
+ }
2910
+ protectedBy(token, check) {
2911
+ const existingProtections = this.data.protections || [];
2912
+ return new ArcFunction({
2913
+ ...this.data,
2914
+ protections: [...existingProtections, { token, check }]
2915
+ });
2916
+ }
2917
+ description(desc) {
2918
+ return new ArcFunction({
2919
+ ...this.data,
2920
+ description: desc
2921
+ });
2922
+ }
2923
+ handle(handler) {
2924
+ return new ArcFunction({
2925
+ ...this.data,
2926
+ handler
2927
+ });
2928
+ }
2929
+ get isPublic() {
2930
+ return !this.hasProtections;
2931
+ }
2932
+ get hasProtections() {
2933
+ return (this.data.protections?.length ?? 0) > 0;
2934
+ }
2935
+ get protections() {
2936
+ return this.data.protections || [];
2937
+ }
2938
+ get handler() {
2939
+ return this.data.handler;
2940
+ }
2941
+ get params() {
2942
+ return this.data.params;
2943
+ }
2944
+ get result() {
2945
+ return this.data.result;
2946
+ }
2947
+ async verifyProtections(tokens) {
2948
+ if (!this.data.protections || this.data.protections.length === 0) {
2949
+ return true;
2950
+ }
2951
+ for (const protection of this.data.protections) {
2952
+ const tokenInstance = tokens.find((t) => t.getTokenDefinition() === protection.token);
2953
+ if (!tokenInstance) {
2954
+ return false;
2955
+ }
2956
+ const result = await protection.check(tokenInstance);
2957
+ if (result === false) {
2958
+ return false;
2959
+ }
2960
+ }
2961
+ return true;
2962
+ }
2963
+ buildContext(adapters) {
2964
+ return buildElementContext(this.data.queryElements || [], this.data.mutationElements || [], adapters);
2965
+ }
2966
+ toJsonSchema() {
2967
+ return {
2968
+ params: this.data.params?.toJsonSchema?.() ?? null,
2969
+ result: this.data.result?.toJsonSchema?.() ?? null
2970
+ };
2971
+ }
2972
+ }
2832
2973
  class AggregateBase {
2833
2974
  value;
2834
2975
  _id;
@@ -2866,6 +3007,315 @@ class AggregateBase {
2866
3007
  return result;
2867
3008
  }
2868
3009
  }
3010
+ class ArcCommand extends ArcContextElement {
3011
+ data;
3012
+ #fn;
3013
+ constructor(data, fn) {
3014
+ super(data.name);
3015
+ this.data = data;
3016
+ this.#fn = fn ?? new ArcFunction({
3017
+ params: data.params,
3018
+ result: null,
3019
+ queryElements: data.queryElements,
3020
+ mutationElements: data.mutationElements,
3021
+ protections: data.protections || [],
3022
+ handler: data.handler ?? null,
3023
+ description: data.description
3024
+ });
3025
+ }
3026
+ description(description) {
3027
+ const newFn = this.#fn.description(description);
3028
+ return new ArcCommand({ ...this.data, description }, newFn);
3029
+ }
3030
+ get isPublic() {
3031
+ return this.#fn.isPublic;
3032
+ }
3033
+ query(elements) {
3034
+ const newFn = this.#fn.query(elements);
3035
+ return new ArcCommand({ ...this.data, queryElements: elements }, newFn);
3036
+ }
3037
+ mutate(elements) {
3038
+ const newFn = this.#fn.mutate(elements);
3039
+ return new ArcCommand({ ...this.data, mutationElements: elements }, newFn);
3040
+ }
3041
+ withParams(schema) {
3042
+ const newFn = this.#fn.withParams(schema);
3043
+ return new ArcCommand({
3044
+ ...this.data,
3045
+ params: schema instanceof ArcObject ? schema : new ArcObject(schema)
3046
+ }, newFn);
3047
+ }
3048
+ withResult(...schemas) {
3049
+ return new ArcCommand({ ...this.data, results: schemas }, this.#fn);
3050
+ }
3051
+ handle(handler) {
3052
+ const newFn = new ArcFunction({
3053
+ ...this.#fn.data,
3054
+ handler
3055
+ });
3056
+ return new ArcCommand({ ...this.data, handler }, newFn);
3057
+ }
3058
+ protectBy(token, check) {
3059
+ const newFn = this.#fn.protectedBy(token, check);
3060
+ const existingProtections = this.data.protections || [];
3061
+ return new ArcCommand({
3062
+ ...this.data,
3063
+ protections: [...existingProtections, { token, check }]
3064
+ }, newFn);
3065
+ }
3066
+ get hasProtections() {
3067
+ return this.#fn.hasProtections;
3068
+ }
3069
+ get protections() {
3070
+ return this.#fn.protections;
3071
+ }
3072
+ async verifyProtections(tokens) {
3073
+ return this.#fn.verifyProtections(tokens);
3074
+ }
3075
+ async init(environment, adapters) {
3076
+ if (environment === "server" && this.data.handler && adapters.commandWire?.registerCommandHandler) {
3077
+ adapters.commandWire.registerCommandHandler(this.data.name, async (params) => {
3078
+ const executeFunc = this.mutateContext(adapters);
3079
+ return await executeFunc(params);
3080
+ });
3081
+ }
3082
+ }
3083
+ mutateContext(adapters) {
3084
+ const executeFunc = async (params) => {
3085
+ if (this.data.handler) {
3086
+ return await this.executeLocally(params, adapters);
3087
+ }
3088
+ if (!adapters.commandWire) {
3089
+ throw new Error(`Command "${this.data.name}" has no handler and no commandWire adapter available for remote execution`);
3090
+ }
3091
+ return await adapters.commandWire.executeCommand(this.data.name, params);
3092
+ };
3093
+ return Object.assign(executeFunc, { params: this.data.params });
3094
+ }
3095
+ async executeLocally(params, adapters) {
3096
+ if (!this.data.handler) {
3097
+ throw new Error(`Command "${this.data.name}" has no handler`);
3098
+ }
3099
+ const context2 = this.buildCommandContext(adapters);
3100
+ return await this.data.handler(context2, params);
3101
+ }
3102
+ buildCommandContext(adapters) {
3103
+ const context2 = this.#fn.buildContext(adapters);
3104
+ if (this.#fn.hasProtections && adapters.authAdapter) {
3105
+ const decoded = adapters.authAdapter.getDecoded();
3106
+ if (decoded) {
3107
+ context2.$auth = {
3108
+ params: decoded.params,
3109
+ tokenName: decoded.tokenName
3110
+ };
3111
+ } else {
3112
+ throw new Error(`Command "${this.data.name}" requires authentication but no valid token found`);
3113
+ }
3114
+ }
3115
+ return context2;
3116
+ }
3117
+ toJsonSchema() {
3118
+ const parametersSchema = this.data.params ? this.data.params.toJsonSchema?.() ?? {
3119
+ type: "object",
3120
+ properties: {}
3121
+ } : { type: "object", properties: {} };
3122
+ return {
3123
+ type: "function",
3124
+ name: this.data.name,
3125
+ description: this.data.description ?? undefined,
3126
+ parameters: parametersSchema,
3127
+ strict: true
3128
+ };
3129
+ }
3130
+ }
3131
+ class ArcListener extends ArcContextElement {
3132
+ data;
3133
+ #fn;
3134
+ unsubscribers = [];
3135
+ constructor(data, fn) {
3136
+ super(data.name);
3137
+ this.data = data;
3138
+ this.#fn = fn ?? new ArcFunction({
3139
+ params: null,
3140
+ result: null,
3141
+ queryElements: data.queryElements,
3142
+ mutationElements: data.mutationElements,
3143
+ protections: [],
3144
+ handler: null,
3145
+ description: data.description
3146
+ });
3147
+ }
3148
+ description(description) {
3149
+ const newFn = this.#fn.description(description);
3150
+ return new ArcListener({ ...this.data, description }, newFn);
3151
+ }
3152
+ listenTo(events) {
3153
+ return new ArcListener({ ...this.data, eventElements: events }, this.#fn);
3154
+ }
3155
+ query(elements) {
3156
+ const newFn = this.#fn.query(elements);
3157
+ return new ArcListener({ ...this.data, queryElements: elements }, newFn);
3158
+ }
3159
+ mutate(elements) {
3160
+ const newFn = this.#fn.mutate(elements);
3161
+ return new ArcListener({ ...this.data, mutationElements: elements }, newFn);
3162
+ }
3163
+ async() {
3164
+ return new ArcListener({ ...this.data, isAsync: true }, this.#fn);
3165
+ }
3166
+ handle(handler) {
3167
+ return new ArcListener({ ...this.data, handler }, this.#fn);
3168
+ }
3169
+ get eventElements() {
3170
+ return this.data.eventElements || [];
3171
+ }
3172
+ get isAsync() {
3173
+ return this.data.isAsync;
3174
+ }
3175
+ async init(environment, adapters) {
3176
+ if (environment !== "server") {
3177
+ return;
3178
+ }
3179
+ if (!this.data.handler) {
3180
+ console.warn(`Listener "${this.data.name}" has no handler`);
3181
+ return;
3182
+ }
3183
+ if (!adapters.eventPublisher) {
3184
+ console.warn(`Listener "${this.data.name}" cannot subscribe: no eventPublisher adapter`);
3185
+ return;
3186
+ }
3187
+ for (const eventElement of this.data.eventElements) {
3188
+ const unsubscribe = adapters.eventPublisher.subscribe(eventElement.name, async (event2) => {
3189
+ await this.handleEvent(event2, adapters);
3190
+ });
3191
+ this.unsubscribers.push(unsubscribe);
3192
+ }
3193
+ }
3194
+ async handleEvent(event2, adapters) {
3195
+ if (!this.data.handler)
3196
+ return;
3197
+ const context2 = this.#fn.buildContext(adapters);
3198
+ if (adapters.authAdapter) {
3199
+ const decoded = adapters.authAdapter.getDecoded();
3200
+ if (decoded) {
3201
+ context2.$auth = {
3202
+ params: decoded.params,
3203
+ tokenName: decoded.tokenName
3204
+ };
3205
+ }
3206
+ }
3207
+ if (this.data.isAsync) {
3208
+ Promise.resolve(this.data.handler(context2, event2)).catch((error) => {
3209
+ console.error(`Async listener "${this.data.name}" error:`, error);
3210
+ });
3211
+ } else {
3212
+ await this.data.handler(context2, event2);
3213
+ }
3214
+ }
3215
+ destroy() {
3216
+ for (const unsubscribe of this.unsubscribers) {
3217
+ unsubscribe();
3218
+ }
3219
+ this.unsubscribers = [];
3220
+ }
3221
+ }
3222
+ class ArcRoute extends ArcContextElement {
3223
+ data;
3224
+ #fn;
3225
+ constructor(data, fn) {
3226
+ super(data.name);
3227
+ this.data = data;
3228
+ this.#fn = fn ?? new ArcFunction({
3229
+ params: null,
3230
+ result: null,
3231
+ queryElements: data.queryElements,
3232
+ mutationElements: data.mutationElements,
3233
+ protections: data.protections || [],
3234
+ handler: null,
3235
+ description: data.description
3236
+ });
3237
+ }
3238
+ description(description) {
3239
+ const newFn = this.#fn.description(description);
3240
+ return new ArcRoute({ ...this.data, description }, newFn);
3241
+ }
3242
+ path(path) {
3243
+ return new ArcRoute({ ...this.data, path }, this.#fn);
3244
+ }
3245
+ public() {
3246
+ return new ArcRoute({ ...this.data, isPublic: true }, this.#fn);
3247
+ }
3248
+ query(elements) {
3249
+ const newFn = this.#fn.query(elements);
3250
+ return new ArcRoute({ ...this.data, queryElements: elements }, newFn);
3251
+ }
3252
+ mutate(elements) {
3253
+ const newFn = this.#fn.mutate(elements);
3254
+ return new ArcRoute({ ...this.data, mutationElements: elements }, newFn);
3255
+ }
3256
+ protectBy(token, check) {
3257
+ const newFn = this.#fn.protectedBy(token, check);
3258
+ const existingProtections = this.data.protections || [];
3259
+ return new ArcRoute({
3260
+ ...this.data,
3261
+ protections: [...existingProtections, { token, check }]
3262
+ }, newFn);
3263
+ }
3264
+ handle(handlers) {
3265
+ return new ArcRoute({ ...this.data, handlers }, this.#fn);
3266
+ }
3267
+ get routePath() {
3268
+ return this.data.path || `/${this.data.name}`;
3269
+ }
3270
+ get fullPath() {
3271
+ return `/route${this.routePath}`;
3272
+ }
3273
+ get isPublic() {
3274
+ return this.data.isPublic;
3275
+ }
3276
+ get hasProtections() {
3277
+ return this.#fn.hasProtections;
3278
+ }
3279
+ get protections() {
3280
+ return this.data.protections || [];
3281
+ }
3282
+ getHandler(method) {
3283
+ return this.data.handlers?.[method];
3284
+ }
3285
+ matchesPath(pathname) {
3286
+ const routePath = this.fullPath;
3287
+ const routeParts = routePath.split("/").filter(Boolean);
3288
+ const pathParts = pathname.split("/").filter(Boolean);
3289
+ if (routeParts.length !== pathParts.length) {
3290
+ return { matches: false, params: {} };
3291
+ }
3292
+ const params = {};
3293
+ for (let i = 0;i < routeParts.length; i++) {
3294
+ const routePart = routeParts[i];
3295
+ const pathPart = pathParts[i];
3296
+ if (routePart.startsWith(":")) {
3297
+ const paramName = routePart.slice(1);
3298
+ params[paramName] = pathPart;
3299
+ } else if (routePart !== pathPart) {
3300
+ return { matches: false, params: {} };
3301
+ }
3302
+ }
3303
+ return { matches: true, params };
3304
+ }
3305
+ async verifyProtections(tokens) {
3306
+ if (this.data.isPublic) {
3307
+ return true;
3308
+ }
3309
+ return this.#fn.verifyProtections(tokens);
3310
+ }
3311
+ buildContext(adapters, authParams) {
3312
+ const context2 = this.#fn.buildContext(adapters);
3313
+ if (authParams) {
3314
+ context2.$auth = authParams;
3315
+ }
3316
+ return context2;
3317
+ }
3318
+ }
2869
3319
  class DataStorage {
2870
3320
  async commitChanges(changes) {
2871
3321
  await Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-adapter-db-sqlite",
3
- "version": "0.4.9",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  "test": "bun test"
21
21
  },
22
22
  "peerDependencies": {
23
- "@arcote.tech/arc": "^0.4.9"
23
+ "@arcote.tech/arc": "^0.5.1"
24
24
  },
25
25
  "devDependencies": {
26
26
  "typescript": "^5.0.0"