@rivinia/toast 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -8,13 +8,14 @@ dedupe, overflow policies — zero DOM, zero styles, zero router dependency.
8
8
  A future `@rivinia/toast/ui` entry point will render this state; Core never
9
9
  imports UI.
10
10
 
11
- - Version: **0.1.0**
11
+ - Version: **0.2.0**
12
12
  - Requires: **Angular `^22.0.0`**, `tslib`
13
13
 
14
14
  ## Install
15
15
 
16
16
  ```bash
17
17
  npm install @rivinia/toast
18
+ ng add @rivinia/toast # wires provideRiviniaToast() into app.config.ts
18
19
  ```
19
20
 
20
21
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivinia/toast",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Headless toast queue for Angular with optional UI outlet: signals, pause-on-hover timers, actions.",
5
5
  "keywords": [
6
6
  "angular",
@@ -17,6 +17,7 @@
17
17
  "tslib": "^2.3.0"
18
18
  },
19
19
  "sideEffects": false,
20
+ "schematics": "./schematics/collection.json",
20
21
  "module": "fesm2022/rivinia-toast.mjs",
21
22
  "typings": "types/rivinia-toast.d.ts",
22
23
  "exports": {
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
3
+ "schematics": {
4
+ "ng-add": {
5
+ "description": "Add provideRiviniaToast() to the application config.",
6
+ "factory": "./ng-add/index.cjs#ngAdd",
7
+ "schema": "./ng-add/schema.json"
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ngAdd = ngAdd;
4
+ const schematics_1 = require("@angular-devkit/schematics");
5
+ const PROVIDE_IMPORT = `import { provideRiviniaToast } from '@rivinia/toast';`;
6
+ /**
7
+ * `ng add @rivinia/toast` — wires the library into a standalone app config.
8
+ *
9
+ * - Never overwrites user files; only inserts one import + one provider.
10
+ * - Idempotent: safe to run twice (existing entries are detected and skipped).
11
+ * - No prompts by design: duration/maxVisible are one-line edits, and every
12
+ * extra question is a papercut. Pass `--duration` / `--max-visible` flags
13
+ * or edit the emitted call afterwards.
14
+ */
15
+ function ngAdd(options) {
16
+ return (tree, context) => {
17
+ let configPath;
18
+ try {
19
+ configPath = findAppConfig(tree, options.project);
20
+ }
21
+ catch (error) {
22
+ context.logger.warn(`[rivinia/toast] workspace lookup failed (${error instanceof Error ? error.message : error}) — skipping. ` +
23
+ `Add provideRiviniaToast() manually (see README).`);
24
+ return tree;
25
+ }
26
+ if (!configPath || !tree.exists(configPath)) {
27
+ context.logger.warn(`[rivinia/toast] app.config.ts not found — skipping. ` +
28
+ `Add provideRiviniaToast() manually (see README).`);
29
+ return tree;
30
+ }
31
+ let content = tree.read(configPath)?.toString('utf-8') ?? '';
32
+ if (!content) {
33
+ throw new schematics_1.SchematicsException(`[rivinia/toast] ${configPath} is empty.`);
34
+ }
35
+ const parts = [];
36
+ if (options.duration !== undefined)
37
+ parts.push(`duration: ${options.duration}`);
38
+ if (options.maxVisible !== undefined)
39
+ parts.push(`maxVisible: ${options.maxVisible}`);
40
+ const provideCall = `provideRiviniaToast(${parts.length > 0 ? `{ ${parts.join(', ')} }` : ''})`;
41
+ let changed = false;
42
+ if (!content.includes(PROVIDE_IMPORT)) {
43
+ content = insertAfterLastImport(content, PROVIDE_IMPORT);
44
+ changed = true;
45
+ }
46
+ if (!content.includes('provideRiviniaToast(')) {
47
+ content = insertProvider(content, provideCall);
48
+ changed = true;
49
+ }
50
+ else {
51
+ context.logger.info('[rivinia/toast] provideRiviniaToast() already present — skipped.');
52
+ }
53
+ if (changed) {
54
+ tree.overwrite(configPath, content);
55
+ context.logger.info(`[rivinia/toast] wired into ${configPath}.`);
56
+ }
57
+ return tree;
58
+ };
59
+ }
60
+ function defaultProjectName(tree, requested) {
61
+ if (requested)
62
+ return requested;
63
+ const angularJson = tree.read('/angular.json')?.toString('utf-8');
64
+ if (!angularJson) {
65
+ throw new schematics_1.SchematicsException('[rivinia/toast] angular.json not found.');
66
+ }
67
+ const workspace = JSON.parse(angularJson);
68
+ if (workspace.defaultProject && typeof workspace.defaultProject === 'string') {
69
+ return workspace.defaultProject;
70
+ }
71
+ const names = Object.keys(workspace.projects ?? {});
72
+ if (names.length === 0) {
73
+ throw new schematics_1.SchematicsException('[rivinia/toast] no projects in angular.json.');
74
+ }
75
+ return names[0];
76
+ }
77
+ function findAppConfig(tree, requestedProject) {
78
+ const angularJson = tree.read('/angular.json')?.toString('utf-8');
79
+ if (!angularJson)
80
+ return null;
81
+ const workspace = JSON.parse(angularJson);
82
+ const name = defaultProjectName(tree, requestedProject);
83
+ const project = workspace.projects?.[name];
84
+ if (!project)
85
+ return null;
86
+ const sourceRoot = project.sourceRoot ?? (project.root ? `${project.root}/src` : 'src');
87
+ return `/${sourceRoot}/app/app.config.ts`;
88
+ }
89
+ function insertAfterLastImport(content, line) {
90
+ const lines = content.split('\n');
91
+ let idx = -1;
92
+ for (let i = 0; i < lines.length; i++) {
93
+ if (/^\s*import\s/.test(lines[i]))
94
+ idx = i;
95
+ }
96
+ lines.splice(idx + 1, 0, line);
97
+ return lines.join('\n');
98
+ }
99
+ function insertProvider(content, call) {
100
+ const match = /providers\s*:\s*\[/.exec(content);
101
+ if (!match) {
102
+ throw new schematics_1.SchematicsException('[rivinia/toast] no `providers: [` array found in app.config.ts — add providers manually.');
103
+ }
104
+ const at = match.index + match[0].length;
105
+ return `${content.slice(0, at)}\n ${call},${content.slice(at)}`;
106
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "rivinia-toast-ng-add",
4
+ "title": "Rivinia Toast ng-add options",
5
+ "type": "object",
6
+ "properties": {
7
+ "duration": {
8
+ "type": "number",
9
+ "description": "Global default auto-dismiss delay in milliseconds for provideRiviniaToast({ duration }). Omit to keep the 5000 default."
10
+ },
11
+ "maxVisible": {
12
+ "type": "number",
13
+ "description": "Maximum simultaneously visible toasts for provideRiviniaToast({ maxVisible }). Omit to keep the 5 default."
14
+ },
15
+ "project": {
16
+ "type": "string",
17
+ "description": "Angular CLI project name — only for multi-app workspaces. Defaults to the workspace default project.",
18
+ "default": ""
19
+ }
20
+ },
21
+ "required": []
22
+ }