or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcomponent-utilities.mdcomputed.mddependency-injection.mdindex.mdlifecycle.mdreactive-state.mdtypes.mdwatchers.md

advanced-features.mddocs/

0

# Advanced Features

1

2

Effect scopes, app instances, and other advanced composition features for complex state management and application architecture patterns.

3

4

## Capabilities

5

6

### Effect Scopes

7

8

Advanced effect management system for organizing and cleaning up reactive effects in groups.

9

10

```typescript { .api }

11

/**

12

* Creates a new effect scope for organizing effects

13

* @param detached - Whether the scope runs independently of parent scope

14

* @returns Effect scope instance

15

*/

16

function effectScope(detached?: boolean): EffectScope;

17

18

/**

19

* Gets the currently active effect scope

20

* @returns Current effect scope or undefined

21

*/

22

function getCurrentScope(): EffectScope | undefined;

23

24

/**

25

* Registers a disposal callback for the current effect scope

26

* @param fn - Cleanup function to run when scope is disposed

27

*/

28

function onScopeDispose(fn: () => void): void;

29

30

class EffectScope {

31

/**

32

* Runs a function within this effect scope

33

* @param fn - Function to run in scope

34

* @returns Result of the function

35

*/

36

run<T>(fn: () => T): T | undefined;

37

38

/**

39

* Stops and cleans up all effects in this scope

40

*/

41

stop(): void;

42

}

43

```

44

45

**Usage Examples:**

46

47

```typescript

48

import { effectScope, watchEffect, watch, ref, onScopeDispose } from "@vue/composition-api";

49

50

// Basic effect scope usage

51

const scope = effectScope();

52

53

scope.run(() => {

54

const count = ref(0);

55

56

// This watcher will be collected by the scope

57

watchEffect(() => {

58

console.log("Count:", count.value);

59

});

60

61

// Cleanup when scope is disposed

62

onScopeDispose(() => {

63

console.log("Scope disposed");

64

});

65

});

66

67

// Later, stop all effects in the scope

68

scope.stop();

69

70

// Detached scope (won't be stopped when parent stops)

71

const detachedScope = effectScope(true);

72

73

detachedScope.run(() => {

74

// Effects here won't be cleaned up by parent scope

75

const timer = setInterval(() => {

76

console.log("Timer tick");

77

}, 1000);

78

79

onScopeDispose(() => {

80

clearInterval(timer);

81

});

82

});

83

```

84

85

**Advanced Scope Patterns:**

86

87

```typescript

88

import { effectScope, ref, watch, onScopeDispose } from "@vue/composition-api";

89

90

// Scope-based service management

91

class DataService {

92

private scope = effectScope();

93

private data = ref([]);

94

private loading = ref(false);

95

96

constructor(private apiUrl: string) {

97

this.scope.run(() => {

98

// Set up reactive data fetching

99

watch(

100

() => this.apiUrl,

101

async (url) => {

102

this.loading.value = true;

103

try {

104

const response = await fetch(url);

105

this.data.value = await response.json();

106

} finally {

107

this.loading.value = false;

108

}

109

},

110

{ immediate: true }

111

);

112

113

// Cleanup on dispose

114

onScopeDispose(() => {

115

console.log("DataService disposed");

116

});

117

});

118

}

119

120

getData() {

121

return readonly(this.data);

122

}

123

124

isLoading() {

125

return readonly(this.loading);

126

}

127

128

dispose() {

129

this.scope.stop();

130

}

131

}

132

133

// Usage

134

const service = new DataService("/api/users");

135

const users = service.getData();

136

const loading = service.isLoading();

137

138

// Later cleanup

139

service.dispose();

140

```

141

142

### App Instance (Vue 3 Compatibility)

143

144

Vue 3-like app instance creation for better migration compatibility.

145

146

```typescript { .api }

147

/**

148

* Creates a Vue 3-like app instance for compatibility

149

* @param rootComponent - Root component definition

150

* @param rootProps - Props for root component

151

* @returns App instance with Vue 3-like API

152

*/

153

function createApp(rootComponent: any, rootProps?: any): App;

154

155

interface App<T = any> {

156

/**

157

* Mounts the app to a DOM element

158

* @param rootContainer - DOM element or selector

159

* @returns Component instance

160

*/

161

mount(rootContainer: Element | string): T;

162

163

/**

164

* Unmounts the app

165

*/

166

unmount(): void;

167

168

/**

169

* Provides a value for the entire app

170

* @param key - Injection key

171

* @param value - Value to provide

172

* @returns App instance for chaining

173

*/

174

provide<T>(key: InjectionKey<T> | string, value: T): this;

175

176

/**

177

* Registers a global component

178

* @param name - Component name

179

* @param component - Component definition

180

* @returns App instance for chaining

181

*/

182

component(name: string, component: Component): this;

183

184

/**

185

* Registers a global directive

186

* @param name - Directive name

187

* @param directive - Directive definition

188

* @returns App instance for chaining

189

*/

190

directive(name: string, directive: Directive): this;

191

192

/**

193

* Installs a plugin

194

* @param plugin - Plugin to install

195

* @param options - Plugin options

196

* @returns App instance for chaining

197

*/

198

use(plugin: Plugin, ...options: any[]): this;

199

200

/**

201

* Sets a global property

202

* @param key - Property key

203

* @param value - Property value

204

* @returns App instance for chaining

205

*/

206

config: {

207

globalProperties: Record<string, any>;

208

};

209

}

210

```

211

212

**Usage Examples:**

213

214

```typescript

215

import { createApp, defineComponent, ref } from "@vue/composition-api";

216

217

const RootComponent = defineComponent({

218

setup() {

219

const message = ref("Hello Vue 3 App!");

220

221

return {

222

message,

223

};

224

},

225

template: `<h1>{{ message }}</h1>`,

226

});

227

228

// Create and configure app

229

const app = createApp(RootComponent);

230

231

// Global provide

232

app.provide("appName", "My Vue App");

233

234

// Global component

235

app.component("GlobalButton", {

236

template: `<button><slot /></button>`,

237

});

238

239

// Global directive

240

app.directive("focus", {

241

inserted(el) {

242

el.focus();

243

},

244

});

245

246

// Install plugin

247

app.use(SomePlugin, { option: "value" });

248

249

// Mount app

250

const vm = app.mount("#app");

251

252

// Later unmount

253

app.unmount();

254

```

255

256

### Advanced Reactive Utilities

257

258

Advanced reactive programming utilities for complex state management scenarios.

259

260

```typescript { .api }

261

/**

262

* Gets the current scope's Vue instance for internal operations

263

* @returns Vue instance or null

264

*/

265

function getCurrentScopeVM(): ComponentInstance | null;

266

267

/**

268

* Records effect scope for tracking (internal utility)

269

* @param effect - Effect to record

270

* @param scope - Target scope

271

*/

272

function recordEffectScope(effect: ReactiveEffect, scope?: EffectScope): void;

273

```

274

275

**Advanced Reactive Patterns:**

276

277

```typescript

278

import { effectScope, ref, computed, watch, onScopeDispose } from "@vue/composition-api";

279

280

// Advanced store pattern with scoped effects

281

class ReactiveStore<T> {

282

private scope = effectScope();

283

private state = ref<T>({} as T);

284

private computedCache = new Map();

285

private watchers = new Set<() => void>();

286

287

constructor(initialState: T) {

288

this.scope.run(() => {

289

this.state.value = initialState;

290

291

onScopeDispose(() => {

292

this.watchers.forEach(stop => stop());

293

this.computedCache.clear();

294

});

295

});

296

}

297

298

getState(): Readonly<Ref<T>> {

299

return readonly(this.state);

300

}

301

302

setState(updater: (state: T) => T): void {

303

this.state.value = updater(this.state.value);

304

}

305

306

select<R>(selector: (state: T) => R): ComputedRef<R> {

307

const key = selector.toString();

308

309

if (!this.computedCache.has(key)) {

310

const computed = this.scope.run(() =>

311

computed(() => selector(this.state.value))

312

);

313

this.computedCache.set(key, computed);

314

}

315

316

return this.computedCache.get(key);

317

}

318

319

subscribe(callback: (state: T) => void): () => void {

320

const stop = this.scope.run(() =>

321

watch(this.state, callback, { deep: true })

322

);

323

324

if (stop) {

325

this.watchers.add(stop);

326

return () => {

327

stop();

328

this.watchers.delete(stop);

329

};

330

}

331

332

return () => {};

333

}

334

335

destroy(): void {

336

this.scope.stop();

337

}

338

}

339

340

// Usage

341

interface AppState {

342

user: { name: string; id: number } | null;

343

theme: "light" | "dark";

344

notifications: Array<{ id: string; message: string }>;

345

}

346

347

const store = new ReactiveStore<AppState>({

348

user: null,

349

theme: "light",

350

notifications: [],

351

});

352

353

// Select derived state

354

const isAuthenticated = store.select(state => !!state.user);

355

const notificationCount = store.select(state => state.notifications.length);

356

357

// Subscribe to changes

358

const unsubscribe = store.subscribe(state => {

359

console.log("State changed:", state);

360

});

361

362

// Update state

363

store.setState(state => ({

364

...state,

365

user: { name: "Alice", id: 1 },

366

}));

367

```

368

369

### Global Property Registration

370

371

Utilities for registering global properties and methods.

372

373

```typescript { .api }

374

/**

375

* Development warning utility (internal)

376

* @param message - Warning message

377

*/

378

function warn(message: string): void;

379

```

380

381

**Global Registration Patterns:**

382

383

```typescript { .api }

384

import Vue from "vue";

385

import { ref, reactive } from "@vue/composition-api";

386

387

// Extend Vue with global properties

388

declare module "vue/types/vue" {

389

interface Vue {

390

$api: ApiService;

391

$eventBus: EventBus;

392

}

393

}

394

395

// Global API service

396

class ApiService {

397

private baseUrl: string;

398

399

constructor(baseUrl: string) {

400

this.baseUrl = baseUrl;

401

}

402

403

async get<T>(endpoint: string): Promise<T> {

404

const response = await fetch(`${this.baseUrl}${endpoint}`);

405

return response.json();

406

}

407

}

408

409

// Global event bus

410

class EventBus {

411

private events = reactive<Record<string, Array<Function>>>({});

412

413

on(event: string, callback: Function): void {

414

if (!this.events[event]) {

415

this.events[event] = [];

416

}

417

this.events[event].push(callback);

418

}

419

420

emit(event: string, ...args: any[]): void {

421

if (this.events[event]) {

422

this.events[event].forEach(callback => callback(...args));

423

}

424

}

425

426

off(event: string, callback?: Function): void {

427

if (!this.events[event]) return;

428

429

if (callback) {

430

const index = this.events[event].indexOf(callback);

431

if (index > -1) {

432

this.events[event].splice(index, 1);

433

}

434

} else {

435

this.events[event] = [];

436

}

437

}

438

}

439

440

// Install globally

441

Vue.prototype.$api = new ApiService("/api");

442

Vue.prototype.$eventBus = new EventBus();

443

444

// Usage in composition API

445

export default defineComponent({

446

setup() {

447

const instance = getCurrentInstance();

448

const api = instance?.proxy?.$api;

449

const eventBus = instance?.proxy?.$eventBus;

450

451

onMounted(() => {

452

eventBus?.on("refresh", () => {

453

// Handle refresh event

454

});

455

});

456

457

onBeforeUnmount(() => {

458

eventBus?.off("refresh");

459

});

460

461

return {};

462

},

463

});

464

```

465

466

## Types

467

468

```typescript { .api }

469

interface EffectScope {

470

active: boolean;

471

effects: ReactiveEffect[];

472

cleanups: (() => void)[];

473

parent: EffectScope | undefined;

474

475

run<T>(fn: () => T): T | undefined;

476

stop(): void;

477

}

478

479

interface App<T = any> {

480

version: string;

481

config: AppConfig;

482

483

mount(rootContainer: Element | string): T;

484

unmount(): void;

485

provide<T>(key: InjectionKey<T> | string, value: T): this;

486

component(name: string, component?: Component): this | Component;

487

directive(name: string, directive?: Directive): this | Directive;

488

use(plugin: Plugin, ...options: any[]): this;

489

}

490

491

interface AppConfig {

492

errorHandler?: (err: Error, instance: ComponentPublicInstance | null, info: string) => void;

493

warnHandler?: (msg: string, instance: ComponentPublicInstance | null, trace: string) => void;

494

globalProperties: Record<string, any>;

495

isCustomElement?: (tag: string) => boolean;

496

}

497

498

interface ReactiveEffect<T = any> {

499

(): T;

500

_isEffect: true;

501

id: number;

502

active: boolean;

503

raw: () => T;

504

deps: Array<Dep>;

505

options: ReactiveEffectOptions;

506

allowRecurse: boolean;

507

}

508

509

interface ReactiveEffectOptions {

510

lazy?: boolean;

511

scheduler?: (job: ReactiveEffect) => void;

512

onTrack?: (event: DebuggerEvent) => void;

513

onTrigger?: (event: DebuggerEvent) => void;

514

onStop?: () => void;

515

allowRecurse?: boolean;

516

}

517

518

type Dep = Set<ReactiveEffect> & {

519

cleanup: () => void;

520

computed?: ComputedRef<any>;

521

};

522

523

interface DebuggerEvent {

524

effect: ReactiveEffect;

525

target: object;

526

type: TrackOpTypes | TriggerOpTypes;

527

key: any;

528

newValue?: any;

529

oldValue?: any;

530

oldTarget?: Map<any, any> | Set<any>;

531

}

532

```