@ic-reactor/core 1.16.0 → 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.
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.ActorManager = void 0;
13
4
  /* eslint-disable no-console */
@@ -19,181 +10,59 @@ const ACTOR_INITIAL_STATE = {
19
10
  version: 0,
20
11
  methodState: {},
21
12
  initializing: false,
13
+ isInitializing: false,
22
14
  initialized: false,
15
+ isInitialized: false,
23
16
  error: undefined,
24
17
  };
25
18
  class ActorManager {
26
- constructor(actorConfig) {
27
- this._actor = null;
28
- this._subscribers = [];
29
- this.updateState = (newState, action) => {
30
- this.actorStore.setState((state) => (Object.assign(Object.assign({}, state), newState)), false, action);
31
- };
32
- this.updateMethodState = (method, hash, newState) => {
33
- const actionName = `${method}:${newState.error ? "error" : newState.loading ? "loading" : "loaded"}`;
34
- this.actorStore.setState((state) => {
35
- const methodState = state.methodState[method] || {};
36
- const currentMethodState = methodState[hash] || DEFAULT_STATE;
37
- const updatedMethodState = Object.assign(Object.assign({}, methodState), { [hash]: Object.assign(Object.assign({}, currentMethodState), newState) });
38
- return Object.assign(Object.assign({}, state), { methodState: Object.assign(Object.assign({}, state.methodState), { [method]: updatedMethodState }) });
39
- }, false, actionName);
40
- };
41
- this.initialize = (options) => __awaiter(this, void 0, void 0, function* () {
42
- yield this._agentManager.updateAgent(options);
43
- });
44
- this.extractInterface = () => {
45
- return this._idlFactory({ IDL: candid_1.IDL });
46
- };
47
- this.extractMethodAttributes = () => {
48
- const iface = this.extractInterface();
49
- const methodAttributesArray = iface._fields.map(([name, func]) => ({
50
- name: name,
51
- attributes: {
52
- numberOfArgs: func.argTypes.length,
53
- type: ((0, helper_1.isQuery)(func) ? "query" : "update"),
54
- validate: (arg) => func.argTypes.some((t, i) => t.covariant(arg[i])),
19
+ _actor = null;
20
+ _idlFactory;
21
+ _agentManager;
22
+ _unsubscribeAgent;
23
+ _subscribers = [];
24
+ canisterId;
25
+ actorStore;
26
+ visitFunction;
27
+ methodAttributes;
28
+ updateState = (newState, action) => {
29
+ this.actorStore.setState((state) => ({ ...state, ...newState }), false, action);
30
+ };
31
+ updateMethodState = (method, hash, newState) => {
32
+ const actionName = `${method}:${newState.error ? "error" : newState.isLoading ? "loading..." : "loaded"}`;
33
+ this.actorStore.setState((state) => {
34
+ const methodState = state.methodState[method] || {};
35
+ const currentMethodState = methodState[hash] || DEFAULT_STATE;
36
+ const updatedMethodState = {
37
+ ...methodState,
38
+ [hash]: { ...currentMethodState, ...newState },
39
+ };
40
+ return {
41
+ ...state,
42
+ methodState: {
43
+ ...state.methodState,
44
+ [method]: updatedMethodState,
55
45
  },
56
- }));
57
- methodAttributesArray.sort((a, b) => {
58
- if (a.attributes.type === b.attributes.type) {
59
- return a.attributes.numberOfArgs - b.attributes.numberOfArgs;
60
- }
61
- return a.attributes.type === "query" ? -1 : 1;
62
- });
63
- return methodAttributesArray.reduce((acc, { name, attributes }) => {
64
- acc[name] = attributes;
65
- return acc;
66
- }, {});
67
- };
68
- this.extractVisitor = () => {
69
- const iface = this.extractInterface();
70
- return iface._fields.reduce((acc, service) => {
71
- const functionName = service[0];
72
- const type = service[1];
73
- const visit = ((extractorClass, data) => {
74
- return type.accept(extractorClass, data);
75
- });
76
- acc[functionName] = visit;
77
- return acc;
78
- }, {});
79
- };
80
- this.initializeActor = (agent) => {
81
- const network = this._agentManager.getNetwork();
82
- console.info(`Initializing actor ${this.canisterId} on ${network} network`);
83
- const { _idlFactory, canisterId } = this;
84
- this.updateState({
85
- initializing: true,
86
- initialized: false,
87
- methodState: {},
88
- }, "initializing");
89
- try {
90
- if (!agent) {
91
- throw new Error("Agent not initialized");
92
- }
93
- this._actor = agent_1.Actor.createActor(_idlFactory, {
94
- agent,
95
- canisterId,
96
- });
97
- if (!this._actor) {
98
- throw new Error("Failed to initialize actor");
99
- }
100
- this.updateState({
101
- initializing: false,
102
- initialized: true,
103
- }, "initialized");
104
- }
105
- catch (error) {
106
- console.error("Error in initializeActor:", error);
107
- this.updateState({ error: error, initializing: false }, "error");
108
- }
109
- };
110
- this._getActorMethod = (functionName) => {
111
- if (!this._actor) {
112
- throw new Error("Actor not initialized");
113
- }
114
- if (!this._actor[functionName] ||
115
- typeof this._actor[functionName] !== "function") {
116
- throw new Error(`Method ${String(functionName)} not found`);
117
- }
118
- return this._actor[functionName];
119
- };
120
- this.callMethod = (functionName, ...args) => __awaiter(this, void 0, void 0, function* () {
121
- const method = this._getActorMethod(functionName);
122
- const data = yield method(...args);
123
- return data;
124
- });
125
- this.callMethodWithOptions = (options) => {
126
- return (functionName, ...args) => __awaiter(this, void 0, void 0, function* () {
127
- const method = this._getActorMethod(functionName);
128
- const data = yield method.withOptions(options)(...args);
129
- return data;
130
- });
131
- };
132
- this.call = (functionName, ...args) => __awaiter(this, void 0, void 0, function* () {
133
- const requestHash = (0, helper_1.generateRequestHash)(args);
134
- try {
135
- this.updateMethodState(functionName, requestHash, {
136
- loading: true,
137
- error: undefined,
138
- });
139
- const data = yield this.callMethod(functionName, ...args);
140
- this.updateMethodState(functionName, requestHash, {
141
- loading: false,
142
- data,
143
- });
144
- return data;
145
- }
146
- catch (error) {
147
- this.updateMethodState(functionName, requestHash, {
148
- loading: false,
149
- error: error,
150
- data: undefined,
151
- });
152
- throw error;
153
- }
154
- });
155
- // actor store
156
- this.getActor = () => {
157
- return this._actor;
158
- };
159
- this.getState = () => {
160
- return this.actorStore.getState();
161
- };
162
- // @ts-expect-error: Overrides subscribe method signature
163
- this.subscribeActorState = (selectorOrListener, listener, options) => {
164
- let unsubscribe = () => { };
165
- if (listener) {
166
- unsubscribe = this.actorStore.subscribe(selectorOrListener, listener, options);
167
- }
168
- else {
169
- unsubscribe = this.actorStore.subscribe(selectorOrListener);
170
- }
171
- this._subscribers.push(unsubscribe);
172
- return unsubscribe;
173
- };
174
- this.setState = (updater) => {
175
- return this.actorStore.setState(updater);
176
- };
177
- this.cleanup = () => {
178
- this._unsubscribeAgent();
179
- this._subscribers.forEach((unsubscribe) => unsubscribe());
180
- };
46
+ };
47
+ }, false, actionName);
48
+ };
49
+ constructor(actorConfig) {
181
50
  const { agentManager, idlFactory, canisterId, name = canisterId.toString(), withVisitor = false, withDevtools = false, initializeOnCreate = true, } = actorConfig;
182
51
  if (!canisterId) {
183
- throw new Error("CanisterId is required!");
52
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("CanisterId is required!"), agent_1.ErrorKindEnum.Unknown);
184
53
  }
185
54
  this.canisterId = canisterId.toString();
186
55
  if (!idlFactory) {
187
- throw new Error("IDLFactory is required!");
56
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("IDLFactory is required!"), agent_1.ErrorKindEnum.Unknown);
188
57
  }
189
58
  this._idlFactory = idlFactory;
190
59
  this.methodAttributes = this.extractMethodAttributes();
191
60
  if (!agentManager) {
192
- throw new Error("AgentManager is required!");
61
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("AgentManager is required!"), agent_1.ErrorKindEnum.Unknown);
193
62
  }
194
63
  this._agentManager = agentManager;
195
64
  // Initialize stores
196
- this.actorStore = (0, helper_1.createStoreWithOptionalDevtools)(Object.assign(Object.assign({}, ACTOR_INITIAL_STATE), { name }), {
65
+ this.actorStore = (0, helper_1.createStoreWithOptionalDevtools)({ ...ACTOR_INITIAL_STATE, name }, {
197
66
  withDevtools,
198
67
  name: "reactor-actor",
199
68
  store: canisterId.toString(),
@@ -206,15 +75,171 @@ class ActorManager {
206
75
  this.visitFunction = emptyVisitor;
207
76
  }
208
77
  }
78
+ initialize = async (options) => {
79
+ await this._agentManager.updateAgent(options);
80
+ };
81
+ extractInterface = () => {
82
+ return this._idlFactory({ IDL: candid_1.IDL });
83
+ };
84
+ extractMethodAttributes = () => {
85
+ const iface = this.extractInterface();
86
+ const methodAttributesArray = iface._fields.map(([name, func]) => ({
87
+ name: name,
88
+ attributes: {
89
+ numberOfArgs: func.argTypes.length,
90
+ type: ((0, helper_1.isQuery)(func) ? "query" : "update"),
91
+ validate: (arg) => func.argTypes.some((t, i) => t.covariant(arg[i])),
92
+ },
93
+ }));
94
+ methodAttributesArray.sort((a, b) => {
95
+ if (a.attributes.type === b.attributes.type) {
96
+ return a.attributes.numberOfArgs - b.attributes.numberOfArgs;
97
+ }
98
+ return a.attributes.type === "query" ? -1 : 1;
99
+ });
100
+ return methodAttributesArray.reduce((acc, { name, attributes }) => {
101
+ acc[name] = attributes;
102
+ return acc;
103
+ }, {});
104
+ };
105
+ extractVisitor = () => {
106
+ const iface = this.extractInterface();
107
+ return iface._fields.reduce((acc, service) => {
108
+ const functionName = service[0];
109
+ const type = service[1];
110
+ const visit = ((extractorClass, data) => {
111
+ return type.accept(extractorClass, data);
112
+ });
113
+ acc[functionName] = visit;
114
+ return acc;
115
+ }, {});
116
+ };
117
+ initializeActor = (agent) => {
118
+ const network = this._agentManager.getNetwork();
119
+ console.info(`Initializing actor ${this.canisterId} on ${network} network`);
120
+ const { _idlFactory, canisterId } = this;
121
+ this.updateState({
122
+ initializing: true,
123
+ isInitializing: true,
124
+ initialized: false,
125
+ isInitialized: false,
126
+ methodState: {},
127
+ }, "initializing");
128
+ try {
129
+ if (!agent) {
130
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("Agent not initialized"), agent_1.ErrorKindEnum.Unknown);
131
+ }
132
+ this._actor = agent_1.Actor.createActor(_idlFactory, {
133
+ agent,
134
+ canisterId,
135
+ });
136
+ if (!this._actor) {
137
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("Failed to initialize actor"), agent_1.ErrorKindEnum.Unknown);
138
+ }
139
+ this.updateState({
140
+ initializing: false,
141
+ isInitializing: false,
142
+ initialized: true,
143
+ isInitialized: true,
144
+ }, "initialized");
145
+ }
146
+ catch (error) {
147
+ console.error("Error in initializeActor:", error);
148
+ this.updateState({
149
+ error: error,
150
+ initializing: false,
151
+ isInitializing: false,
152
+ }, "error");
153
+ }
154
+ };
155
+ _getActorMethod = (functionName) => {
156
+ if (!this._actor) {
157
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode("Actor not initialized"), agent_1.ErrorKindEnum.Unknown);
158
+ }
159
+ if (!this._actor[functionName] ||
160
+ typeof this._actor[functionName] !== "function") {
161
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode(`Method ${String(functionName)} not found`), agent_1.ErrorKindEnum.Unknown);
162
+ }
163
+ return this._actor[functionName];
164
+ };
165
+ callMethod = async (functionName, ...args) => {
166
+ const method = this._getActorMethod(functionName);
167
+ const data = await method(...args);
168
+ return data;
169
+ };
170
+ callMethodWithOptions = (options) => {
171
+ return async (functionName, ...args) => {
172
+ const method = this._getActorMethod(functionName);
173
+ const data = await method.withOptions(options)(...args);
174
+ return data;
175
+ };
176
+ };
177
+ call = async (functionName, ...args) => {
178
+ const requestHash = (0, helper_1.generateRequestHash)(args);
179
+ try {
180
+ this.updateMethodState(functionName, requestHash, {
181
+ loading: true,
182
+ isLoading: true,
183
+ error: undefined,
184
+ });
185
+ const data = await this.callMethod(functionName, ...args);
186
+ this.updateMethodState(functionName, requestHash, {
187
+ loading: false,
188
+ isLoading: false,
189
+ data,
190
+ });
191
+ return data;
192
+ }
193
+ catch (error) {
194
+ this.updateMethodState(functionName, requestHash, {
195
+ loading: false,
196
+ isLoading: false,
197
+ error: error,
198
+ data: undefined,
199
+ });
200
+ throw error;
201
+ }
202
+ };
209
203
  // agent store
210
204
  get agentManager() {
211
205
  return this._agentManager;
212
206
  }
207
+ // actor store
208
+ getActor = () => {
209
+ return this._actor;
210
+ };
211
+ getState = () => {
212
+ return this.actorStore.getState();
213
+ };
214
+ // @ts-expect-error: Overrides subscribe method signature
215
+ subscribeActorState = (selectorOrListener, listener, options) => {
216
+ let unsubscribe = helper_1.noop;
217
+ if (listener) {
218
+ unsubscribe = this.actorStore.subscribe(selectorOrListener, listener, options);
219
+ }
220
+ else {
221
+ unsubscribe = this.actorStore.subscribe(selectorOrListener);
222
+ }
223
+ this._subscribers.push(unsubscribe);
224
+ return unsubscribe;
225
+ };
226
+ setState = (updater) => {
227
+ return this.actorStore.setState(updater);
228
+ };
229
+ cleanup = () => {
230
+ this._unsubscribeAgent();
231
+ this._subscribers.forEach((unsubscribe) => unsubscribe());
232
+ };
213
233
  }
214
234
  exports.ActorManager = ActorManager;
215
235
  const emptyVisitor = new Proxy({}, {
216
236
  get: function (_, prop) {
217
- throw new Error(`Cannot visit function "${String(prop)}" without initializing the actor with the visitor option, please set the withVisitor option to true when creating the actor manager.`);
237
+ throw new agent_1.AgentError(new agent_1.UnexpectedErrorCode(`Cannot visit function "${String(prop)}" without initializing the actor with the visitor option, please set the withVisitor option to true when creating the actor manager.`), agent_1.ErrorKindEnum.Unknown);
218
238
  },
219
239
  });
220
- const DEFAULT_STATE = { data: undefined, error: undefined, loading: false };
240
+ const DEFAULT_STATE = {
241
+ data: undefined,
242
+ error: undefined,
243
+ loading: false,
244
+ isLoading: false,
245
+ };
@@ -1,6 +1,6 @@
1
1
  import type { AgentManager } from "../agent";
2
2
  import type { IDL, ActorMethod, ActorSubclass, Principal, StoreWithAllMiddleware } from "../../types";
3
- import { CallConfig } from "@dfinity/agent";
3
+ import type { AgentError, CallConfig } from "@dfinity/agent";
4
4
  export interface DefaultActorType {
5
5
  [key: string]: ActorMethod;
6
6
  }
@@ -26,11 +26,34 @@ export type VisitService<A = BaseActor, M extends FunctionName<A> = FunctionName
26
26
  };
27
27
  export type ActorMethodParameters<T> = T extends ActorMethod<infer Args, any> ? Args : never;
28
28
  export type ActorMethodReturnType<T> = T extends ActorMethod<any, infer Ret> ? Ret : never;
29
+ /**
30
+ * Interface representing the state of each actor method.
31
+ *
32
+ * @template A - The actor type, defaulting to `BaseActor`.
33
+ * @template M - A specific method name of the actor.
34
+ */
29
35
  export interface ActorMethodState<A = BaseActor, M extends FunctionName<A> = FunctionName<A>> {
36
+ /**
37
+ * The per-method state object, keyed by the method name.
38
+ */
30
39
  [key: string]: {
40
+ /**
41
+ * The data returned from the actor method call, if available.
42
+ */
31
43
  data: ActorMethodReturnType<A[M]> | undefined;
44
+ /**
45
+ * @deprecated Use `isLoading` instead.
46
+ * Flag indicating whether the actor method is in progress.
47
+ */
32
48
  loading: boolean;
33
- error: Error | undefined;
49
+ /**
50
+ * Flag indicating whether the actor method is in progress.
51
+ */
52
+ isLoading: boolean;
53
+ /**
54
+ * Error thrown during the actor method invocation, if any.
55
+ */
56
+ error: AgentError | undefined;
34
57
  };
35
58
  }
36
59
  export type ActorMethodStates<A = BaseActor> = {
@@ -40,12 +63,45 @@ export type ActorMethodType<A, M extends keyof A> = {
40
63
  (...args: ActorMethodParameters<A[M]>): Promise<ActorMethodReturnType<A[M]>>;
41
64
  withOptions: (options: CallConfig) => (...args: ActorMethodParameters<A[M]>) => Promise<ActorMethodReturnType<A[M]>>;
42
65
  };
66
+ /**
67
+ * Represents the state of an actor.
68
+ *
69
+ * @template A - The type of the actor, defaults to `BaseActor`.
70
+ */
43
71
  export type ActorState<A = BaseActor> = {
72
+ /**
73
+ * The name of the actor.
74
+ */
44
75
  name: string;
76
+ /**
77
+ * The version of the actor.
78
+ */
45
79
  version: number;
80
+ /**
81
+ * @deprecated Use `isInitialized` instead.
82
+ * Indicates whether the actor is initialized.
83
+ */
46
84
  initialized: boolean;
85
+ /**
86
+ * Indicates whether the actor is initialized.
87
+ */
88
+ isInitialized: boolean;
89
+ /**
90
+ * @deprecated Use `isInitializing` instead.
91
+ * Indicates whether the actor is in the process of initializing.
92
+ */
47
93
  initializing: boolean;
48
- error: Error | undefined;
94
+ /**
95
+ * Indicates whether the actor is in the process of initializing.
96
+ */
97
+ isInitializing: boolean;
98
+ /**
99
+ * The error associated with the actor, if any.
100
+ */
101
+ error: AgentError | undefined;
102
+ /**
103
+ * The state of the actor's methods.
104
+ */
49
105
  methodState: ActorMethodStates<A>;
50
106
  };
51
107
  export type ActorStore<A = BaseActor> = StoreWithAllMiddleware<ActorState<A>>;
@@ -12,7 +12,7 @@ export declare class CandidAdapter {
12
12
  getCandidDefinition(canisterId: CanisterId): Promise<CandidDefenition>;
13
13
  getFromMetadata(canisterId: CanisterId): Promise<string | undefined>;
14
14
  getFromTmpHack(canisterId: CanisterId): Promise<string>;
15
- dynamicEvalJs(data: string): Promise<CandidDefenition>;
15
+ evaluateCandidDefinition(data: string): Promise<CandidDefenition>;
16
16
  fetchDidTojs(candidSource: string, didjsCanisterId?: string): Promise<[string]>;
17
17
  parseDidToJs(candidSource: string): string;
18
18
  validateIDL(candidSource: string): boolean;