or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-utilities.mddependency-management.mdindex.mdschematics.mdstandalone-utilities.mdworkspace-utilities.md

standalone-utilities.mddocs/

0

# Standalone Utilities

1

2

Utilities for working with Angular's standalone components and bootstrap configuration, supporting the modern Angular application architecture without NgModules.

3

4

## Capabilities

5

6

### Root Import Management

7

8

Functions for adding imports to the root application configuration in standalone applications.

9

10

```typescript { .api }

11

/**

12

* Adds an import to the root of the project

13

* @param options - Options for the root import

14

* @returns Rule that adds the import

15

*/

16

function addRootImport(options: AddRootImportOptions): Rule;

17

```

18

19

**Usage Example:**

20

21

```typescript

22

import { addRootImport } from '@schematics/angular/utility';

23

24

// Add router import to standalone app

25

export function addRouter(): Rule {

26

return addRootImport({

27

import: 'RouterModule.forRoot(routes)',

28

from: '@angular/router'

29

});

30

}

31

32

// Add HTTP client import

33

export function addHttpClient(): Rule {

34

return addRootImport({

35

import: 'HttpClientModule',

36

from: '@angular/common/http'

37

});

38

}

39

```

40

41

### Root Provider Management

42

43

Functions for adding providers to the root application configuration.

44

45

```typescript { .api }

46

/**

47

* Adds a provider to the root of the project

48

* @param options - Options for the root provider

49

* @returns Rule that adds the provider

50

*/

51

function addRootProvider(options: AddRootProviderOptions): Rule;

52

```

53

54

**Usage Examples:**

55

56

```typescript

57

import { addRootProvider } from '@schematics/angular/utility';

58

59

// Add router provider

60

export function addRouterProvider(): Rule {

61

return addRootProvider({

62

expression: 'provideRouter(routes)',

63

import: 'provideRouter',

64

from: '@angular/router'

65

});

66

}

67

68

// Add HTTP client provider

69

export function addHttpClientProvider(): Rule {

70

return addRootProvider({

71

expression: 'provideHttpClient()',

72

import: 'provideHttpClient',

73

from: '@angular/common/http'

74

});

75

}

76

77

// Add custom service provider

78

export function addCustomProvider(): Rule {

79

return addRootProvider({

80

expression: 'provideMyService({ apiUrl: "https://api.example.com" })',

81

import: 'provideMyService',

82

from: './my-service'

83

});

84

}

85

```

86

87

### Code Block Management

88

89

Low-level utilities for managing code blocks and pending code modifications.

90

91

```typescript { .api }

92

/**

93

* Generated code that hasn't been interpolated yet

94

*/

95

interface PendingCode {

96

/** Code that will be inserted */

97

expression: string;

98

/** Imports that need to be added to the file in which the code is inserted */

99

imports: Map<string, Map<string, string>>;

100

}

101

102

/**

103

* Callback invoked by a Rule that produces the code that needs to be inserted somewhere in the app

104

* @param block - CodeBlock instance for generating code

105

* @returns PendingCode object with expression and imports

106

*/

107

type CodeBlockCallback = (block: CodeBlock) => PendingCode;

108

109

/**

110

* Utility class used to generate blocks of code that can be inserted by the devkit into a user's app

111

*/

112

class CodeBlock {

113

/**

114

* Function used to tag a code block in order to produce a PendingCode object

115

* @param strings - Template strings array

116

* @param params - Template parameters

117

* @returns PendingCode object

118

*/

119

code(strings: TemplateStringsArray, ...params: unknown[]): PendingCode;

120

121

/**

122

* Function used to reference an external symbol that should be imported

123

* @param name - Name of the symbol to import

124

* @param moduleSpecifier - Module to import from

125

* @returns String reference to the symbol

126

*/

127

external(name: string, moduleSpecifier: string): string;

128

129

/**

130

* Transforms a PendingCode object into a format that can be inserted into a file

131

* @param pendingCode - Code to transform

132

* @param filePath - Target file path

133

* @returns Transformed PendingCode

134

*/

135

static transformPendingCode(pendingCode: PendingCode, filePath: string): PendingCode;

136

}

137

```

138

139

## Advanced Usage

140

141

### Complex Provider Setup

142

143

```typescript

144

import { addRootProvider } from '@schematics/angular/utility';

145

import { chain } from '@angular-devkit/schematics';

146

147

export function setupCompleteApp(): Rule {

148

return chain([

149

// Add router

150

addRootProvider('default', ({code, external}) => {

151

return code`${external('provideRouter', '@angular/router')}(routes)`;

152

}),

153

154

// Add HTTP client with features

155

addRootProvider('default', ({code, external}) => {

156

return code`${external('provideHttpClient', '@angular/common/http')}(

157

${external('withFetch', '@angular/common/http')}(),

158

${external('withInterceptors', '@angular/common/http')}([loggingInterceptor])

159

)`;

160

}),

161

162

// Add animations

163

addRootProvider('default', ({code, external}) => {

164

return code`${external('provideAnimations', '@angular/platform-browser/animations')}()`;

165

})

166

]);

167

}

168

```

169

170

### Conditional Provider Addition

171

172

```typescript

173

import { addRootProvider } from '@schematics/angular/utility';

174

175

export function conditionalProvider(): Rule {

176

return async (tree: Tree, context: SchematicContext) => {

177

// Check if app uses standalone architecture

178

const mainPath = '/src/main.ts';

179

const mainContent = tree.readText(mainPath);

180

181

if (mainContent.includes('bootstrapApplication')) {

182

return addRootProvider('default', ({code, external}) => {

183

return code`${external('provideMyFeature', './my-feature')}()`;

184

});

185

}

186

187

// Handle module-based app differently

188

context.logger.info('Module-based app detected, skipping standalone provider');

189

return noop();

190

};

191

}

192

```

193

194

### Custom Provider with Configuration

195

196

```typescript

197

import { addRootProvider } from '@schematics/angular/utility';

198

199

export function addConfiguredProvider(): Rule {

200

return addRootProvider('default', ({code, external}) => {

201

return code`${external('provideMyService', '@my-org/my-service')}({

202

apiUrl: 'https://api.example.com',

203

timeout: 5000,

204

retries: 3

205

})`;

206

});

207

}

208

```

209

210

### Multiple Providers

211

212

```typescript

213

import { addRootProvider } from '@schematics/angular/utility';

214

215

export function addMultipleProviders(): Rule {

216

return addRootProvider('default', ({code, external}) => {

217

return code`

218

${external('provideStore', '@ngrx/store')}(reducers),

219

${external('provideEffects', '@ngrx/effects')}([UserEffects, ProductEffects])

220

`;

221

});

222

}

223

```

224

225

## Integration with Module-based Apps

226

227

For applications that haven't migrated to standalone, these utilities will gracefully handle the differences:

228

229

```typescript

230

import { addRootProvider } from '@schematics/angular/utility';

231

232

// This will work in both standalone and module-based apps

233

export function universalProvider(): Rule {

234

return (tree: Tree, context: SchematicContext) => {

235

const mainPath = '/src/main.ts';

236

const mainContent = tree.readText(mainPath);

237

238

if (mainContent.includes('bootstrapApplication')) {

239

// Standalone app - add to providers array

240

return addRootProvider({

241

expression: 'provideMyFeature()',

242

import: 'provideMyFeature',

243

from: './my-feature'

244

});

245

} else {

246

// Module-based app - would need to use module utilities instead

247

context.logger.warn('Module-based app detected. Consider migrating to standalone.');

248

return noop();

249

}

250

};

251

}

252

```

253

254

## Error Handling

255

256

The standalone utilities include built-in error handling for common scenarios:

257

258

- **Missing main.ts**: Utilities will log appropriate errors if the main application file is not found

259

- **Non-standalone apps**: Functions will detect module-based applications and provide appropriate warnings

260

- **Invalid syntax**: Code parsing errors are caught and reported with helpful messages

261

- **Duplicate providers**: The utilities can detect and handle duplicate provider registrations