@hamak/ui-store 0.9.0 → 0.9.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.
@@ -1,5 +1,5 @@
1
- export type { FileSystemNode, DirectoryNode, FileNode, FileSystemNodeBase, FileSystemNodeState, FileMemoState, FileSystemState, FileContentSchema } from '@hamak/shared-utils';
2
- export { fileSystemNodeInitialState } from '@hamak/shared-utils';
1
+ export type { FileSystemNode, DirectoryNode, FileNode, FileSystemNodeBase, FileSystemNodeState, FileMemoState, FileSystemState, FileContentSchema, FileSystemNodePermissions, ResolvedFileSystemNodePermissions } from '@hamak/shared-utils';
2
+ export { fileSystemNodeInitialState, resolveNodePermissions, resolvePermissions, isWritable, isReadOnly } from '@hamak/shared-utils';
3
3
  export * from './contracts/filesystem-manager.contract.js';
4
4
  export * from './contracts/filesystem-facade.contract.js';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/fs/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAGjE,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/api/fs/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,cAAc,EACd,aAAa,EACb,QAAQ,EACR,kBAAkB,EAClB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,yBAAyB,EACzB,iCAAiC,EAClC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,EACV,UAAU,EACX,MAAM,qBAAqB,CAAC;AAG7B,cAAc,yCAAyC,CAAC;AACxD,cAAc,wCAAwC,CAAC"}
@@ -1,4 +1,4 @@
1
- export { fileSystemNodeInitialState } from '@hamak/shared-utils';
1
+ export { fileSystemNodeInitialState, resolveNodePermissions, resolvePermissions, isWritable, isReadOnly } from '@hamak/shared-utils';
2
2
  // Filesystem contracts
3
3
  export * from './contracts/filesystem-manager.contract.js';
4
4
  export * from './contracts/filesystem-facade.contract.js';
@@ -1 +1 @@
1
- {"version":3,"file":"autosave-middleware.d.ts","sourceRoot":"","sources":["../../../src/impl/autosave/autosave-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAElE,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,WAAW,CAAC;AAgFnB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,iCAAiC;IACjC,QAAQ,EAAE,yBAAyB,CAAC;IAEpC,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qCAAqC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAExC,gCAAgC;IAChC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAEvC,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAEjE,+BAA+B;IAC/B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAClF;AAcD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,UAAU,CA6RZ"}
1
+ {"version":3,"file":"autosave-middleware.d.ts","sourceRoot":"","sources":["../../../src/impl/autosave/autosave-middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAElE,OAAO,KAAK,EAAE,yBAAyB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,WAAW,CAAC;AAgFnB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,iCAAiC;IACjC,QAAQ,EAAE,yBAAyB,CAAC;IAEpC,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qCAAqC;IACrC,aAAa,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAExC,gCAAgC;IAChC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAEvC,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAEjE,+BAA+B;IAC/B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAClF;AAcD;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,UAAU,CA+RZ"}
@@ -7,6 +7,7 @@
7
7
  * 3. Delegates save operations to registered providers
8
8
  * 4. Handles retries on failure
9
9
  */
10
+ import { resolvePermissions } from '@hamak/shared-utils';
10
11
  import { AutosaveActionTypes, autosaveActions, DEFAULT_AUTOSAVE_CONFIG, } from '../../api/index.js';
11
12
  import { resolveAutosaveConfig, getNodeAtPath, pathToKey, } from './autosave-config-resolver.js';
12
13
  /**
@@ -247,7 +248,9 @@ export function createAutosaveMiddleware(config) {
247
248
  if (root) {
248
249
  // Resolve config
249
250
  const autosaveConfig = resolveAutosaveConfig(root, path, mergedDefaultConfig);
250
- if (autosaveConfig.enabled) {
251
+ // Effective enable also requires the node to be writable — a
252
+ // read-only node forces autosave off regardless of config.
253
+ if (autosaveConfig.enabled && resolvePermissions(root, path).write) {
251
254
  // Get node
252
255
  const node = getNodeAtPath(root, path);
253
256
  if (node) {
@@ -1,11 +1,12 @@
1
1
  import { FileNode, FileSystemNode, FileSystemState, FileContentSchema } from '../../../api/index.js';
2
+ import { type FileSystemNodePermissions } from '@hamak/shared-utils';
2
3
  import { StructureNodeCommand } from './structure-commands.js';
3
4
  import { DataUpdater } from '../utils/data-updater.js';
4
5
  /**
5
6
  * Base interface for filesystem commands
6
7
  */
7
8
  export interface FsCommandBase {
8
- name: 'mkdir' | 'set-file' | 'remove' | 'update-file-content' | 'set-file-content' | 'set-extension-state' | 'set-content-loading';
9
+ name: 'mkdir' | 'set-file' | 'remove' | 'update-file-content' | 'set-file-content' | 'set-extension-state' | 'set-content-loading' | 'set-permissions';
9
10
  path: string | string[];
10
11
  }
11
12
  /**
@@ -66,10 +67,18 @@ export interface SetContentLoadingCommand extends FsCommandBase {
66
67
  name: 'set-content-loading';
67
68
  loading: boolean;
68
69
  }
70
+ /**
71
+ * Set (merge) client-side permissions on a node. Typically issued by the
72
+ * provider that loaded the node, reflecting the source's real ACL.
73
+ */
74
+ export interface SetPermissionsCommand extends FsCommandBase {
75
+ name: 'set-permissions';
76
+ permissions: FileSystemNodePermissions;
77
+ }
69
78
  /**
70
79
  * Union type for all filesystem commands
71
80
  */
72
- export type FileSystemCommand = MkdirCommand | RemoveCommand | SetFileCommand | UpdateFileContentCommand | SetFileContentCommand | SetExtensionStateCommand | SetContentLoadingCommand;
81
+ export type FileSystemCommand = MkdirCommand | RemoveCommand | SetFileCommand | UpdateFileContentCommand | SetFileContentCommand | SetExtensionStateCommand | SetContentLoadingCommand | SetPermissionsCommand;
73
82
  export { pathSteps, parentPathSteps } from '@hamak/shared-utils';
74
83
  /**
75
84
  * Get filesystem node at path
@@ -89,6 +98,7 @@ export declare class FileSystemCommandHandler {
89
98
  private executeSetContentCommand;
90
99
  private executeSetExtensionState;
91
100
  private executeSetContentLoading;
101
+ private executeSetPermissions;
92
102
  protected current<T = any>(o: T): T;
93
103
  protected original<T = any>(o: T): T | undefined;
94
104
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fs-commands.d.ts","sourceRoot":"","sources":["../../../../src/impl/fs/commands/fs-commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fs-commands.d.ts","sourceRoot":"","sources":["../../../../src/impl/fs/commands/fs-commands.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { fileSystemNodeInitialState } from '../../../api/index.js';
2
- import { pathSteps } from '@hamak/shared-utils';
2
+ import { pathSteps, resolvePermissions } from '@hamak/shared-utils';
3
3
  import { DataUpdater } from '../utils/data-updater.js';
4
4
  import { produce, current, isDraft, original } from 'immer';
5
5
  import { deepEqual } from '../utils/deep-equal.js';
@@ -70,6 +70,7 @@ export class FileSystemCommandHandler {
70
70
  case 'remove': return this.executeRemove(state, command);
71
71
  case 'set-extension-state': return this.executeSetExtensionState(state, command);
72
72
  case 'set-content-loading': return this.executeSetContentLoading(state, command);
73
+ case 'set-permissions': return this.executeSetPermissions(state, command);
73
74
  }
74
75
  }
75
76
  executeMkdir(state, command) {
@@ -125,6 +126,11 @@ export class FileSystemCommandHandler {
125
126
  && !(recursive === true)) {
126
127
  return;
127
128
  }
129
+ // Permission gate: node (with inheritance) must allow removal.
130
+ if (child !== undefined && !resolvePermissions(root, steps).remove) {
131
+ console.warn(`Remove denied (read-only) at location`, path);
132
+ return;
133
+ }
128
134
  delete parentDir.children[last];
129
135
  }
130
136
  });
@@ -161,6 +167,11 @@ export class FileSystemCommandHandler {
161
167
  const fileNode = getFileSystemNode(root, path);
162
168
  if (fileNode !== undefined) {
163
169
  if (fileNode.type === 'file') {
170
+ // Permission gate: local edits require write (loads use fromRemote).
171
+ if (!resolvePermissions(root, path).write) {
172
+ console.warn(`Edit denied (read-only) at location`, path);
173
+ return;
174
+ }
164
175
  this.contentCommandHandler.execute(fileNode, contentCommand);
165
176
  this.contentMayChange(fileNode);
166
177
  }
@@ -194,6 +205,12 @@ export class FileSystemCommandHandler {
194
205
  const fileNode = getFileSystemNode(root, path);
195
206
  if (fileNode !== undefined) {
196
207
  if (fileNode.type === 'file') {
208
+ // Permission gate: a local (non-remote) set requires write.
209
+ // Remote loads (fromRemote) are always allowed.
210
+ if (!fromRemote && !resolvePermissions(root, path).write) {
211
+ console.warn(`Edit denied (read-only) at location`, path);
212
+ return;
213
+ }
197
214
  fileNode.content = content;
198
215
  if (fileNode.state === undefined) {
199
216
  fileNode.state = fileSystemNodeInitialState(true);
@@ -266,6 +283,26 @@ export class FileSystemCommandHandler {
266
283
  }
267
284
  });
268
285
  }
286
+ executeSetPermissions(state, command) {
287
+ const { path, permissions } = command;
288
+ return produce(state, draft => {
289
+ const { root } = draft;
290
+ const node = getFileSystemNode(root, path);
291
+ if (node === undefined) {
292
+ console.warn(`No node found at location`, path);
293
+ return;
294
+ }
295
+ if (node.state === undefined) {
296
+ node.state = fileSystemNodeInitialState();
297
+ }
298
+ // Merge onto any existing permissions so a provider can set fields
299
+ // incrementally (e.g. { write: false } then { reason }).
300
+ node.state.permissions = {
301
+ ...node.state.permissions,
302
+ ...permissions
303
+ };
304
+ });
305
+ }
269
306
  current(o) {
270
307
  if (o === null || o === undefined) {
271
308
  return o;
@@ -2,6 +2,7 @@ import { Action } from '@reduxjs/toolkit';
2
2
  import { FileSystemCommandHandler } from '../commands/fs-commands.js';
3
3
  import { FileSystemNode, FileSystemState, FileContentSchema, FileSystemNodeActionParams, FileSystemNodeAction, Selector } from '../../../api/index.js';
4
4
  import { StructureNodeCommand } from '../commands/structure-commands.js';
5
+ import type { FileSystemNodePermissions } from '@hamak/shared-utils';
5
6
  /**
6
7
  * Factory function to create a FileSystemAdapter
7
8
  */
@@ -36,6 +37,7 @@ export declare class FileSystemNodeActions {
36
37
  private readonly _setFileContentType;
37
38
  private readonly _setExtensionStateType;
38
39
  private readonly _setContentLoadingType;
40
+ private readonly _setPermissionsType;
39
41
  private actionTypeSet;
40
42
  constructor(sliceName: string);
41
43
  get mkdirType(): string;
@@ -45,6 +47,7 @@ export declare class FileSystemNodeActions {
45
47
  get setFileContentType(): string;
46
48
  get setExtensionStateType(): string;
47
49
  get setContentLoadingType(): string;
50
+ get setPermissionsType(): string;
48
51
  isFileSystemNodeAction(action: Action): action is FileSystemNodeAction;
49
52
  mkdir(path: string | string[], parents?: boolean, extensionStates?: Record<string, unknown>): FileSystemNodeAction;
50
53
  setFile(path: string | string[], content: any, schema: FileContentSchema, params?: FileSystemNodeActionParams): FileSystemNodeAction;
@@ -58,5 +61,11 @@ export declare class FileSystemNodeActions {
58
61
  * re-fetch is in flight. Passing `true` also clears any prior load error.
59
62
  */
60
63
  setContentLoading(path: string | string[], loading: boolean): FileSystemNodeAction;
64
+ /**
65
+ * Set (merge) client-side permissions on a node. Absent permissions mean a
66
+ * node is fully permissive; providers use this to reflect a source's ACL
67
+ * (e.g. a read-only listing: `{ write: false, reason: 'Query result' }`).
68
+ */
69
+ setPermissions(path: string | string[], permissions: FileSystemNodePermissions): FileSystemNodeAction;
61
70
  }
62
71
  //# sourceMappingURL=fs-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fs-adapter.d.ts","sourceRoot":"","sources":["../../../../src/impl/fs/core/fs-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EACL,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,cAAc,EAEd,eAAe,EACf,iBAAiB,EACjB,0BAA0B,EAC1B,oBAAoB,EACpB,QAAQ,EACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,qBAExD;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,KAAK,eAAe,CAAA;AAEjG;;GAEG;AACH,qBAAa,iBAAiB;aAKO,SAAS,EAAE,MAAM;IAJpD,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAA;IACvC,QAAQ,CAAC,cAAc,EAAE,wBAAwB,CAAA;IACjD,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAA;gBAEN,SAAS,EAAE,MAAM;IAapD,eAAe,IAAI,eAAe;IAIlC,UAAU;IAIV,UAAU,CAAC,aAAa,CAAC,EAAE,uBAAuB,GAAG,uBAAuB;IAQ5E,cAAc,CAAC,CAAC,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,EAAE,IAAI,EAAG,MAAM,GAAG,MAAM,EAAE,GAAI,QAAQ,CAAC,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CAiBpJ;AAED;;GAEG;AACH,qBAAa,qBAAqB;IAUb,SAAS,EAAE,MAAM;IATpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,aAAa,CAAa;gBAEf,SAAS,EAAE,MAAM;IAoBpC,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,qBAAqB,IAAI,MAAM,CAElC;IAED,IAAI,kBAAkB,IAAI,MAAM,CAE/B;IAED,IAAI,qBAAqB,IAAI,MAAM,CAElC;IAED,IAAI,qBAAqB,IAAI,MAAM,CAElC;IAED,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,oBAAoB;IAI/D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAC,OAAO,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB;IAOjH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAC,GAAG,EAAE,MAAM,EAAG,iBAAiB,EAAE,MAAM,GAAG,0BAAoE,GAAG,oBAAoB;IAQ9K,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,cAAc,EAAG,oBAAoB,GAAI,oBAAoB;IAOxG,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAG,GAAG,EAAE,UAAU,UAAQ,GAAG,oBAAoB;IAQhG,UAAU,CAAC,IAAI,EAAG,MAAM,GAAG,MAAM,EAAE,EAAE,SAAS,CAAC,EAAG,OAAO,GAAG,oBAAoB;IAOhF,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB;IAOpH;;;;OAIG;IACI,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,oBAAoB;CAO1F"}
1
+ {"version":3,"file":"fs-adapter.d.ts","sourceRoot":"","sources":["../../../../src/impl/fs/core/fs-adapter.ts"],"names":[],"mappings":"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"}
@@ -128,6 +128,12 @@ export class FileSystemNodeActions {
128
128
  writable: true,
129
129
  value: void 0
130
130
  });
131
+ Object.defineProperty(this, "_setPermissionsType", {
132
+ enumerable: true,
133
+ configurable: true,
134
+ writable: true,
135
+ value: void 0
136
+ });
131
137
  Object.defineProperty(this, "actionTypeSet", {
132
138
  enumerable: true,
133
139
  configurable: true,
@@ -141,6 +147,7 @@ export class FileSystemNodeActions {
141
147
  this._setFileContentType = `${this.sliceName}/setFileContent`;
142
148
  this._setExtensionStateType = `${this.sliceName}/setExtensionState`;
143
149
  this._setContentLoadingType = `${this.sliceName}/setContentLoading`;
150
+ this._setPermissionsType = `${this.sliceName}/setPermissions`;
144
151
  this.actionTypeSet = new Set([
145
152
  this._mkdirType,
146
153
  this._setFileType,
@@ -148,7 +155,8 @@ export class FileSystemNodeActions {
148
155
  this._updateFileContentType,
149
156
  this._setFileContentType,
150
157
  this._setExtensionStateType,
151
- this._setContentLoadingType
158
+ this._setContentLoadingType,
159
+ this._setPermissionsType
152
160
  ]);
153
161
  }
154
162
  get mkdirType() {
@@ -172,6 +180,9 @@ export class FileSystemNodeActions {
172
180
  get setContentLoadingType() {
173
181
  return this._setContentLoadingType;
174
182
  }
183
+ get setPermissionsType() {
184
+ return this._setPermissionsType;
185
+ }
175
186
  isFileSystemNodeAction(action) {
176
187
  return this.actionTypeSet.has(action.type);
177
188
  }
@@ -223,4 +234,15 @@ export class FileSystemNodeActions {
223
234
  command: { name: 'set-content-loading', path, loading }
224
235
  };
225
236
  }
237
+ /**
238
+ * Set (merge) client-side permissions on a node. Absent permissions mean a
239
+ * node is fully permissive; providers use this to reflect a source's ACL
240
+ * (e.g. a read-only listing: `{ write: false, reason: 'Query result' }`).
241
+ */
242
+ setPermissions(path, permissions) {
243
+ return {
244
+ type: this.setPermissionsType,
245
+ command: { name: 'set-permissions', path, permissions }
246
+ };
247
+ }
226
248
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hamak/ui-store",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Redux store management for microkernel-based applications",