angular-grab 0.1.1 → 0.1.3

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.
Files changed (138) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.playwright-mcp/console-2026-03-07T02-49-38-061Z.log +37 -0
  3. package/.playwright-mcp/console-2026-03-07T02-51-03-493Z.log +26 -0
  4. package/.playwright-mcp/console-2026-03-07T02-51-25-431Z.log +15 -0
  5. package/.playwright-mcp/console-2026-03-07T02-52-02-980Z.log +199 -0
  6. package/.playwright-mcp/page-2026-03-07T02-52-09-791Z.png +0 -0
  7. package/README.md +215 -0
  8. package/examples/angular-19-app/.editorconfig +17 -0
  9. package/examples/angular-19-app/.vscode/extensions.json +4 -0
  10. package/examples/angular-19-app/.vscode/launch.json +20 -0
  11. package/examples/angular-19-app/.vscode/mcp.json +9 -0
  12. package/examples/angular-19-app/.vscode/tasks.json +42 -0
  13. package/examples/angular-19-app/README.md +59 -0
  14. package/examples/angular-19-app/angular.json +79 -0
  15. package/examples/angular-19-app/package.json +42 -0
  16. package/examples/angular-19-app/public/favicon.ico +0 -0
  17. package/examples/angular-19-app/src/app/app.config.ts +13 -0
  18. package/examples/angular-19-app/src/app/app.css +37 -0
  19. package/examples/angular-19-app/src/app/app.html +25 -0
  20. package/examples/angular-19-app/src/app/app.routes.ts +3 -0
  21. package/examples/angular-19-app/src/app/app.spec.ts +23 -0
  22. package/examples/angular-19-app/src/app/app.ts +12 -0
  23. package/examples/angular-19-app/src/app/button/button.component.ts +25 -0
  24. package/examples/angular-19-app/src/app/card/card.component.ts +33 -0
  25. package/examples/angular-19-app/src/app/header/header.component.ts +31 -0
  26. package/examples/angular-19-app/src/app/popover/popover.component.ts +133 -0
  27. package/examples/angular-19-app/src/index.html +13 -0
  28. package/examples/angular-19-app/src/main.ts +6 -0
  29. package/examples/angular-19-app/src/styles.css +1 -0
  30. package/examples/angular-19-app/tsconfig.app.json +15 -0
  31. package/examples/angular-19-app/tsconfig.json +33 -0
  32. package/examples/angular-19-app/tsconfig.spec.json +15 -0
  33. package/package.json +14 -111
  34. package/packages/angular-grab/package.json +96 -0
  35. package/packages/angular-grab/src/angular/__tests__/context-builder.test.ts +216 -0
  36. package/packages/angular-grab/src/angular/angular-grab.service.ts +62 -0
  37. package/packages/angular-grab/src/angular/index.ts +13 -0
  38. package/packages/angular-grab/src/angular/provide-angular-grab.ts +22 -0
  39. package/packages/angular-grab/src/angular/resolvers/component-resolver.ts +71 -0
  40. package/packages/angular-grab/src/angular/resolvers/context-builder.ts +86 -0
  41. package/packages/angular-grab/src/angular/resolvers/ng-utils.ts +14 -0
  42. package/packages/angular-grab/src/angular/resolvers/source-resolver.ts +61 -0
  43. package/packages/angular-grab/src/builder/__tests__/builder.test.ts +72 -0
  44. package/packages/angular-grab/src/builder/builders/application/index.ts +13 -0
  45. package/packages/angular-grab/src/builder/builders/dev-server/index.ts +9 -0
  46. package/packages/angular-grab/src/builder/index.ts +3 -0
  47. package/packages/angular-grab/src/cli/__tests__/cli.test.ts +239 -0
  48. package/packages/angular-grab/src/cli/commands/init.ts +106 -0
  49. package/packages/angular-grab/src/cli/index.ts +15 -0
  50. package/packages/angular-grab/src/cli/utils/detect-project.ts +78 -0
  51. package/packages/angular-grab/src/cli/utils/modify-angular-json.ts +42 -0
  52. package/packages/angular-grab/src/cli/utils/modify-app-config.ts +42 -0
  53. package/packages/angular-grab/src/core/__tests__/generate-snippet.test.ts +149 -0
  54. package/packages/angular-grab/src/core/__tests__/plugin-registry.test.ts +286 -0
  55. package/packages/angular-grab/src/core/__tests__/store.test.ts +118 -0
  56. package/packages/angular-grab/src/core/__tests__/utils.test.ts +85 -0
  57. package/packages/angular-grab/src/core/clipboard/copy.ts +104 -0
  58. package/packages/angular-grab/src/core/clipboard/generate-snippet.ts +38 -0
  59. package/packages/angular-grab/src/core/constants.ts +10 -0
  60. package/packages/angular-grab/src/core/grab.ts +596 -0
  61. package/packages/angular-grab/src/core/index.global.ts +13 -0
  62. package/packages/angular-grab/src/core/index.ts +19 -0
  63. package/packages/angular-grab/src/core/keyboard/keyboard-handler.ts +163 -0
  64. package/packages/angular-grab/src/core/overlay/crosshair.ts +107 -0
  65. package/packages/angular-grab/src/core/overlay/freeze-overlay.ts +239 -0
  66. package/packages/angular-grab/src/core/overlay/overlay-renderer.ts +180 -0
  67. package/packages/angular-grab/src/core/overlay/select-feedback.ts +108 -0
  68. package/packages/angular-grab/src/core/overlay/toast.ts +175 -0
  69. package/packages/angular-grab/src/core/picker/element-picker.ts +114 -0
  70. package/packages/angular-grab/src/core/plugins/plugin-registry.ts +83 -0
  71. package/packages/angular-grab/src/core/store.ts +52 -0
  72. package/packages/angular-grab/src/core/toolbar/actions-menu.ts +178 -0
  73. package/packages/angular-grab/src/core/toolbar/comment-popover.ts +235 -0
  74. package/packages/angular-grab/src/core/toolbar/copy-actions.ts +98 -0
  75. package/packages/angular-grab/src/core/toolbar/history-popover.ts +245 -0
  76. package/packages/angular-grab/src/core/toolbar/theme-manager.ts +188 -0
  77. package/packages/angular-grab/src/core/toolbar/toolbar-icons.ts +29 -0
  78. package/packages/angular-grab/src/core/toolbar/toolbar-renderer.ts +239 -0
  79. package/packages/angular-grab/src/core/types.ts +139 -0
  80. package/packages/angular-grab/src/core/utils.ts +16 -0
  81. package/packages/angular-grab/src/esbuild-plugin/__tests__/transform.test.ts +174 -0
  82. package/packages/angular-grab/src/esbuild-plugin/index.ts +3 -0
  83. package/packages/angular-grab/src/esbuild-plugin/plugin.ts +29 -0
  84. package/packages/angular-grab/src/esbuild-plugin/scan.ts +105 -0
  85. package/packages/angular-grab/src/esbuild-plugin/transform.ts +152 -0
  86. package/packages/angular-grab/src/vite-plugin/__tests__/plugin.test.ts +84 -0
  87. package/packages/angular-grab/src/vite-plugin/index.ts +19 -0
  88. package/packages/angular-grab/src/webpack-plugin/__tests__/plugin.test.ts +72 -0
  89. package/packages/angular-grab/src/webpack-plugin/index.ts +2 -0
  90. package/packages/angular-grab/src/webpack-plugin/loader.ts +15 -0
  91. package/packages/angular-grab/src/webpack-plugin/plugin.ts +20 -0
  92. package/packages/angular-grab/tsconfig.json +15 -0
  93. package/packages/angular-grab/tsup.config.ts +119 -0
  94. package/pnpm-workspace.yaml +3 -0
  95. package/turbo.json +21 -0
  96. package/dist/angular/index.d.ts +0 -151
  97. package/dist/angular/index.js +0 -2811
  98. package/dist/angular/index.js.map +0 -1
  99. package/dist/builder/builders/application/index.js +0 -143
  100. package/dist/builder/builders/application/index.js.map +0 -1
  101. package/dist/builder/builders/dev-server/index.js +0 -139
  102. package/dist/builder/builders/dev-server/index.js.map +0 -1
  103. package/dist/builder/index.js +0 -2
  104. package/dist/builder/index.js.map +0 -1
  105. package/dist/builder/package.json +0 -1
  106. package/dist/cli/index.js +0 -223
  107. package/dist/cli/index.js.map +0 -1
  108. package/dist/core/index.cjs +0 -2589
  109. package/dist/core/index.cjs.map +0 -1
  110. package/dist/core/index.d.cts +0 -139
  111. package/dist/core/index.d.ts +0 -139
  112. package/dist/core/index.global.js +0 -542
  113. package/dist/core/index.js +0 -2560
  114. package/dist/core/index.js.map +0 -1
  115. package/dist/esbuild-plugin/index.cjs +0 -239
  116. package/dist/esbuild-plugin/index.cjs.map +0 -1
  117. package/dist/esbuild-plugin/index.d.cts +0 -26
  118. package/dist/esbuild-plugin/index.d.ts +0 -26
  119. package/dist/esbuild-plugin/index.js +0 -200
  120. package/dist/esbuild-plugin/index.js.map +0 -1
  121. package/dist/vite-plugin/index.d.ts +0 -7
  122. package/dist/vite-plugin/index.js +0 -128
  123. package/dist/vite-plugin/index.js.map +0 -1
  124. package/dist/webpack-plugin/index.cjs +0 -54
  125. package/dist/webpack-plugin/index.cjs.map +0 -1
  126. package/dist/webpack-plugin/index.d.cts +0 -5
  127. package/dist/webpack-plugin/index.d.ts +0 -5
  128. package/dist/webpack-plugin/index.js +0 -23
  129. package/dist/webpack-plugin/index.js.map +0 -1
  130. package/dist/webpack-plugin/loader.cjs +0 -155
  131. package/dist/webpack-plugin/loader.cjs.map +0 -1
  132. package/dist/webpack-plugin/loader.d.cts +0 -3
  133. package/dist/webpack-plugin/loader.d.ts +0 -3
  134. package/dist/webpack-plugin/loader.js +0 -122
  135. package/dist/webpack-plugin/loader.js.map +0 -1
  136. /package/{builders.json → packages/angular-grab/builders.json} +0 -0
  137. /package/{dist → packages/angular-grab/src}/builder/builders/application/schema.json +0 -0
  138. /package/{dist → packages/angular-grab/src}/builder/builders/dev-server/schema.json +0 -0
@@ -1,139 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/builder/builders/dev-server/index.ts
31
- var dev_server_exports = {};
32
- __export(dev_server_exports, {
33
- default: () => dev_server_default
34
- });
35
- module.exports = __toCommonJS(dev_server_exports);
36
- var import_architect = require("@angular-devkit/architect");
37
- var import_build = require("@angular/build");
38
-
39
- // src/esbuild-plugin/scan.ts
40
- var import_typescript = __toESM(require("typescript"), 1);
41
- var import_path = __toESM(require("path"), 1);
42
- var import_fs = __toESM(require("fs"), 1);
43
- function scanComponentSources(rootDir) {
44
- const sourceMap = {};
45
- const files = findComponentFiles(rootDir);
46
- for (const filePath of files) {
47
- const content = import_fs.default.readFileSync(filePath, "utf8");
48
- if (!content.includes("@Component")) continue;
49
- const relativePath = import_path.default.relative(rootDir, filePath).replace(/\\/g, "/");
50
- const components = extractComponents(content, filePath);
51
- for (const comp of components) {
52
- sourceMap[comp.name] = { file: relativePath, line: comp.line };
53
- }
54
- }
55
- return sourceMap;
56
- }
57
- function extractComponents(code, filePath) {
58
- const sourceFile = import_typescript.default.createSourceFile(
59
- filePath,
60
- code,
61
- import_typescript.default.ScriptTarget.Latest,
62
- true,
63
- import_typescript.default.ScriptKind.TS
64
- );
65
- const results = [];
66
- function visit(node) {
67
- if (import_typescript.default.isClassDeclaration(node) && node.name) {
68
- const decorators = import_typescript.default.getDecorators(node);
69
- if (!decorators) return;
70
- const hasComponent = decorators.some((d) => {
71
- if (!import_typescript.default.isCallExpression(d.expression)) return false;
72
- if (!import_typescript.default.isIdentifier(d.expression.expression)) return false;
73
- return d.expression.expression.text === "Component";
74
- });
75
- if (hasComponent) {
76
- const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
77
- results.push({ name: node.name.text, line: line + 1 });
78
- }
79
- }
80
- import_typescript.default.forEachChild(node, visit);
81
- }
82
- visit(sourceFile);
83
- return results;
84
- }
85
- function findComponentFiles(rootDir) {
86
- const results = [];
87
- const srcDir = import_path.default.join(rootDir, "src");
88
- if (!import_fs.default.existsSync(srcDir)) return results;
89
- walk(srcDir, results);
90
- return results;
91
- }
92
- function walk(dir, results) {
93
- let entries;
94
- try {
95
- entries = import_fs.default.readdirSync(dir, { withFileTypes: true });
96
- } catch {
97
- return;
98
- }
99
- for (const entry of entries) {
100
- if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
101
- const fullPath = import_path.default.join(dir, entry.name);
102
- if (entry.isDirectory()) {
103
- walk(fullPath, results);
104
- } else if (entry.name.endsWith(".component.ts")) {
105
- results.push(fullPath);
106
- }
107
- }
108
- }
109
-
110
- // src/esbuild-plugin/plugin.ts
111
- function angularGrabEsbuildPlugin(options) {
112
- return {
113
- name: "angular-grab",
114
- setup(build) {
115
- if (options?.enabled === false) return;
116
- const rootDir = options?.rootDir || process.cwd();
117
- const sourceMap = scanComponentSources(rootDir);
118
- if (Object.keys(sourceMap).length === 0) return;
119
- const json = JSON.stringify(sourceMap);
120
- const banner = build.initialOptions.banner || {};
121
- const existing = typeof banner === "object" ? banner.js || "" : "";
122
- build.initialOptions.banner = {
123
- ...typeof banner === "object" ? banner : {},
124
- js: `globalThis.__ANGULAR_GRAB_SOURCE_MAP__=${json};${existing}`
125
- };
126
- }
127
- };
128
- }
129
-
130
- // src/esbuild-plugin/transform.ts
131
- var import_typescript2 = __toESM(require("typescript"), 1);
132
-
133
- // src/builder/builders/dev-server/index.ts
134
- var dev_server_default = (0, import_architect.createBuilder)(async function* (options, context) {
135
- yield* (0, import_build.executeDevServerBuilder)(options, context, {
136
- buildPlugins: [angularGrabEsbuildPlugin({ rootDir: context.workspaceRoot })]
137
- });
138
- });
139
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/builder/builders/dev-server/index.ts","../../../../src/esbuild-plugin/scan.ts","../../../../src/esbuild-plugin/plugin.ts","../../../../src/esbuild-plugin/transform.ts"],"sourcesContent":["import { createBuilder } from '@angular-devkit/architect';\nimport { executeDevServerBuilder } from '@angular/build';\nimport { angularGrabEsbuildPlugin } from '../../../esbuild-plugin';\n\nexport default createBuilder(async function* (options: any, context) {\n yield* executeDevServerBuilder(options, context, {\n buildPlugins: [angularGrabEsbuildPlugin({ rootDir: context.workspaceRoot })],\n });\n});\n","import ts from 'typescript';\nimport path from 'path';\nimport fs from 'fs';\n\nexport interface ComponentSourceInfo {\n file: string;\n line: number;\n}\n\nexport type SourceMap = Record<string, ComponentSourceInfo>;\n\n/**\n * Scans the project for `.component.ts` files and extracts component\n * class names with their source locations. Returns a map of\n * `{ ComponentName: { file, line } }`.\n */\nexport function scanComponentSources(rootDir: string): SourceMap {\n const sourceMap: SourceMap = {};\n const files = findComponentFiles(rootDir);\n\n for (const filePath of files) {\n const content = fs.readFileSync(filePath, 'utf8');\n if (!content.includes('@Component')) continue;\n\n const relativePath = path.relative(rootDir, filePath).replace(/\\\\/g, '/');\n const components = extractComponents(content, filePath);\n\n for (const comp of components) {\n sourceMap[comp.name] = { file: relativePath, line: comp.line };\n }\n }\n\n return sourceMap;\n}\n\ninterface ComponentInfo {\n name: string;\n line: number;\n}\n\nfunction extractComponents(code: string, filePath: string): ComponentInfo[] {\n const sourceFile = ts.createSourceFile(\n filePath,\n code,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n\n const results: ComponentInfo[] = [];\n\n function visit(node: ts.Node): void {\n if (ts.isClassDeclaration(node) && node.name) {\n const decorators = ts.getDecorators(node);\n if (!decorators) return;\n\n const hasComponent = decorators.some((d) => {\n if (!ts.isCallExpression(d.expression)) return false;\n if (!ts.isIdentifier(d.expression.expression)) return false;\n return d.expression.expression.text === 'Component';\n });\n\n if (hasComponent) {\n const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n results.push({ name: node.name.text, line: line + 1 });\n }\n }\n\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return results;\n}\n\nfunction findComponentFiles(rootDir: string): string[] {\n const results: string[] = [];\n const srcDir = path.join(rootDir, 'src');\n\n if (!fs.existsSync(srcDir)) return results;\n\n walk(srcDir, results);\n return results;\n}\n\nfunction walk(dir: string, results: string[]): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue;\n\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n walk(fullPath, results);\n } else if (entry.name.endsWith('.component.ts')) {\n results.push(fullPath);\n }\n }\n}\n","import type { Plugin } from 'esbuild';\nimport { scanComponentSources } from './scan';\n\nexport function angularGrabEsbuildPlugin(options?: {\n rootDir?: string;\n /** Set to false to disable the transform (e.g., in production). Default: true */\n enabled?: boolean;\n}): Plugin {\n return {\n name: 'angular-grab',\n setup(build) {\n if (options?.enabled === false) return;\n\n const rootDir = options?.rootDir || process.cwd();\n const sourceMap = scanComponentSources(rootDir);\n\n if (Object.keys(sourceMap).length === 0) return;\n\n // Inject the source map as a global variable via banner\n const json = JSON.stringify(sourceMap);\n const banner = build.initialOptions.banner || {};\n const existing = typeof banner === 'object' ? (banner.js || '') : '';\n build.initialOptions.banner = {\n ...(typeof banner === 'object' ? banner : {}),\n js: `globalThis.__ANGULAR_GRAB_SOURCE_MAP__=${json};${existing}`,\n };\n },\n };\n}\n","import ts from 'typescript';\nimport path from 'path';\n\nexport interface TransformResult {\n code: string;\n}\n\ninterface Edit {\n pos: number;\n end: number;\n text: string;\n}\n\nexport function transformAngularComponent(\n code: string,\n filePath: string,\n rootDir: string,\n): TransformResult | null {\n const sourceFile = ts.createSourceFile(\n filePath,\n code,\n ts.ScriptTarget.Latest,\n true,\n ts.ScriptKind.TS,\n );\n\n const relativePath = path.relative(rootDir, filePath).replace(/\\\\/g, '/').replace(/'/g, \"\\\\'\");\n const edits: Edit[] = [];\n\n visitNode(sourceFile);\n\n if (edits.length === 0) return null;\n\n // Apply edits in reverse order to preserve positions\n edits.sort((a, b) => b.pos - a.pos);\n\n let result = code;\n for (const edit of edits) {\n result = result.slice(0, edit.pos) + edit.text + result.slice(edit.end);\n }\n\n return { code: result };\n\n function visitNode(node: ts.Node): void {\n if (ts.isClassDeclaration(node)) {\n processClassDeclaration(node);\n }\n ts.forEachChild(node, visitNode);\n }\n\n function processClassDeclaration(classNode: ts.ClassDeclaration): void {\n const decorators = ts.getDecorators(classNode);\n if (!decorators) return;\n\n for (const decorator of decorators) {\n if (!ts.isCallExpression(decorator.expression)) continue;\n\n const expr = decorator.expression;\n if (!ts.isIdentifier(expr.expression)) continue;\n if (expr.expression.text !== 'Component') continue;\n\n processComponentDecorator(expr);\n }\n }\n\n function processComponentDecorator(callExpr: ts.CallExpression): void {\n if (callExpr.arguments.length === 0) {\n // Empty decorator call: @Component() — add host arg\n const line = sourceFile.getLineAndCharacterOfPosition(callExpr.getStart()).line;\n const sourceAttr = `'data-ng-source': '${relativePath}:${line}:0'`;\n const insertText = `{ host: { ${sourceAttr} } }`;\n\n const openParen = callExpr.getStart() + callExpr.expression.getText().length;\n // Find the actual position of the opening paren\n const parenPos = code.indexOf('(', openParen);\n const closeParenPos = code.indexOf(')', parenPos);\n\n edits.push({\n pos: parenPos + 1,\n end: closeParenPos,\n text: insertText,\n });\n return;\n }\n\n const arg = callExpr.arguments[0];\n if (!ts.isObjectLiteralExpression(arg)) return;\n\n const line = sourceFile.getLineAndCharacterOfPosition(callExpr.getStart()).line;\n const sourceAttr = `'data-ng-source': '${relativePath}:${line}:0'`;\n\n // Check if host property already exists\n const hostProp = arg.properties.find(\n (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === 'host',\n ) as ts.PropertyAssignment | undefined;\n\n if (hostProp) {\n // Host property exists — inject into it\n if (!ts.isObjectLiteralExpression(hostProp.initializer)) return;\n\n const hostObj = hostProp.initializer;\n\n // Check for existing data-ng-source (idempotent)\n const hasExisting = hostObj.properties.some(\n (p) =>\n ts.isPropertyAssignment(p) &&\n ((ts.isStringLiteral(p.name) && p.name.text === 'data-ng-source') ||\n (ts.isIdentifier(p.name) && p.name.text === 'data-ng-source')),\n );\n\n if (hasExisting) return;\n\n // Insert into existing host object\n if (hostObj.properties.length > 0) {\n const lastProp = hostObj.properties[hostObj.properties.length - 1];\n edits.push({\n pos: lastProp.getEnd(),\n end: lastProp.getEnd(),\n text: `, ${sourceAttr}`,\n });\n } else {\n // Empty host object: host: {}\n const openBrace = hostObj.getStart();\n const closeBrace = hostObj.getEnd();\n edits.push({\n pos: openBrace + 1,\n end: closeBrace - 1,\n text: ` ${sourceAttr} `,\n });\n }\n } else {\n // No host property — add one\n if (arg.properties.length > 0) {\n const lastProp = arg.properties[arg.properties.length - 1];\n edits.push({\n pos: lastProp.getEnd(),\n end: lastProp.getEnd(),\n text: `, host: { ${sourceAttr} }`,\n });\n } else {\n // Empty object literal: @Component({})\n const openBrace = arg.getStart();\n const closeBrace = arg.getEnd();\n edits.push({\n pos: openBrace + 1,\n end: closeBrace - 1,\n text: ` host: { ${sourceAttr} } `,\n });\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA8B;AAC9B,mBAAwC;;;ACDxC,wBAAe;AACf,kBAAiB;AACjB,gBAAe;AAcR,SAAS,qBAAqB,SAA4B;AAC/D,QAAM,YAAuB,CAAC;AAC9B,QAAM,QAAQ,mBAAmB,OAAO;AAExC,aAAW,YAAY,OAAO;AAC5B,UAAM,UAAU,UAAAA,QAAG,aAAa,UAAU,MAAM;AAChD,QAAI,CAAC,QAAQ,SAAS,YAAY,EAAG;AAErC,UAAM,eAAe,YAAAC,QAAK,SAAS,SAAS,QAAQ,EAAE,QAAQ,OAAO,GAAG;AACxE,UAAM,aAAa,kBAAkB,SAAS,QAAQ;AAEtD,eAAW,QAAQ,YAAY;AAC7B,gBAAU,KAAK,IAAI,IAAI,EAAE,MAAM,cAAc,MAAM,KAAK,KAAK;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AACT;AAOA,SAAS,kBAAkB,MAAc,UAAmC;AAC1E,QAAM,aAAa,kBAAAC,QAAG;AAAA,IACpB;AAAA,IACA;AAAA,IACA,kBAAAA,QAAG,aAAa;AAAA,IAChB;AAAA,IACA,kBAAAA,QAAG,WAAW;AAAA,EAChB;AAEA,QAAM,UAA2B,CAAC;AAElC,WAAS,MAAM,MAAqB;AAClC,QAAI,kBAAAA,QAAG,mBAAmB,IAAI,KAAK,KAAK,MAAM;AAC5C,YAAM,aAAa,kBAAAA,QAAG,cAAc,IAAI;AACxC,UAAI,CAAC,WAAY;AAEjB,YAAM,eAAe,WAAW,KAAK,CAAC,MAAM;AAC1C,YAAI,CAAC,kBAAAA,QAAG,iBAAiB,EAAE,UAAU,EAAG,QAAO;AAC/C,YAAI,CAAC,kBAAAA,QAAG,aAAa,EAAE,WAAW,UAAU,EAAG,QAAO;AACtD,eAAO,EAAE,WAAW,WAAW,SAAS;AAAA,MAC1C,CAAC;AAED,UAAI,cAAc;AAChB,cAAM,EAAE,KAAK,IAAI,WAAW,8BAA8B,KAAK,SAAS,CAAC;AACzE,gBAAQ,KAAK,EAAE,MAAM,KAAK,KAAK,MAAM,MAAM,OAAO,EAAE,CAAC;AAAA,MACvD;AAAA,IACF;AAEA,sBAAAA,QAAG,aAAa,MAAM,KAAK;AAAA,EAC7B;AAEA,QAAM,UAAU;AAChB,SAAO;AACT;AAEA,SAAS,mBAAmB,SAA2B;AACrD,QAAM,UAAoB,CAAC;AAC3B,QAAM,SAAS,YAAAD,QAAK,KAAK,SAAS,KAAK;AAEvC,MAAI,CAAC,UAAAD,QAAG,WAAW,MAAM,EAAG,QAAO;AAEnC,OAAK,QAAQ,OAAO;AACpB,SAAO;AACT;AAEA,SAAS,KAAK,KAAa,SAAyB;AAClD,MAAI;AACJ,MAAI;AACF,cAAU,UAAAA,QAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,EACvD,QAAQ;AACN;AAAA,EACF;AAEA,aAAW,SAAS,SAAS;AAC3B,QAAI,MAAM,SAAS,kBAAkB,MAAM,KAAK,WAAW,GAAG,EAAG;AAEjE,UAAM,WAAW,YAAAC,QAAK,KAAK,KAAK,MAAM,IAAI;AAE1C,QAAI,MAAM,YAAY,GAAG;AACvB,WAAK,UAAU,OAAO;AAAA,IACxB,WAAW,MAAM,KAAK,SAAS,eAAe,GAAG;AAC/C,cAAQ,KAAK,QAAQ;AAAA,IACvB;AAAA,EACF;AACF;;;ACrGO,SAAS,yBAAyB,SAI9B;AACT,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,OAAO;AACX,UAAI,SAAS,YAAY,MAAO;AAEhC,YAAM,UAAU,SAAS,WAAW,QAAQ,IAAI;AAChD,YAAM,YAAY,qBAAqB,OAAO;AAE9C,UAAI,OAAO,KAAK,SAAS,EAAE,WAAW,EAAG;AAGzC,YAAM,OAAO,KAAK,UAAU,SAAS;AACrC,YAAM,SAAS,MAAM,eAAe,UAAU,CAAC;AAC/C,YAAM,WAAW,OAAO,WAAW,WAAY,OAAO,MAAM,KAAM;AAClE,YAAM,eAAe,SAAS;AAAA,QAC5B,GAAI,OAAO,WAAW,WAAW,SAAS,CAAC;AAAA,QAC3C,IAAI,0CAA0C,IAAI,IAAI,QAAQ;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AACF;;;AC5BA,IAAAE,qBAAe;;;AHIf,IAAO,yBAAQ,gCAAc,iBAAiB,SAAc,SAAS;AACnE,aAAO,sCAAwB,SAAS,SAAS;AAAA,IAC/C,cAAc,CAAC,yBAAyB,EAAE,SAAS,QAAQ,cAAc,CAAC,CAAC;AAAA,EAC7E,CAAC;AACH,CAAC;","names":["fs","path","ts","import_typescript"]}
@@ -1,2 +0,0 @@
1
- "use strict";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"type":"commonjs"}
package/dist/cli/index.js DELETED
@@ -1,223 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/cli/commands/init.ts
4
- import { execSync } from "child_process";
5
-
6
- // src/cli/utils/detect-project.ts
7
- import { existsSync, readFileSync } from "fs";
8
- import { join, dirname } from "path";
9
- function findAngularJson(startDir = process.cwd()) {
10
- let dir = startDir;
11
- while (true) {
12
- const candidate = join(dir, "angular.json");
13
- if (existsSync(candidate)) return candidate;
14
- const parent = dirname(dir);
15
- if (parent === dir) return null;
16
- dir = parent;
17
- }
18
- }
19
- function detectProject(angularJsonPath) {
20
- const projectRoot = dirname(angularJsonPath);
21
- const raw = readFileSync(angularJsonPath, "utf8");
22
- const angularJson = JSON.parse(raw);
23
- const projects = angularJson.projects || {};
24
- const projectNames = Object.keys(projects);
25
- if (projectNames.length === 0) {
26
- throw new Error("No projects found in angular.json");
27
- }
28
- const projectName = projectNames[0];
29
- const project = projects[projectName];
30
- if (!project) {
31
- throw new Error(`Project "${projectName}" not found in angular.json`);
32
- }
33
- const sourceRoot = project.sourceRoot || "src";
34
- const targets = project.architect || project.targets;
35
- const buildTarget = targets?.build;
36
- if (!buildTarget) {
37
- throw new Error(`No build target found for project "${projectName}"`);
38
- }
39
- const builder = buildTarget.builder || "";
40
- let builderType;
41
- if (builder.includes(":application") || builder.includes("angular-grab:application")) {
42
- builderType = "application";
43
- } else if (builder.includes(":browser-esbuild")) {
44
- builderType = "browser-esbuild";
45
- } else if (builder.includes(":browser")) {
46
- builderType = "browser";
47
- } else {
48
- builderType = "application";
49
- }
50
- const packageManager = detectPackageManager(projectRoot);
51
- return {
52
- angularJsonPath,
53
- projectRoot,
54
- projectName,
55
- sourceRoot,
56
- builderType,
57
- packageManager
58
- };
59
- }
60
- function detectPackageManager(root) {
61
- if (existsSync(join(root, "pnpm-lock.yaml"))) return "pnpm";
62
- if (existsSync(join(root, "yarn.lock"))) return "yarn";
63
- return "npm";
64
- }
65
-
66
- // src/cli/utils/modify-angular-json.ts
67
- import { readFileSync as readFileSync2, writeFileSync } from "fs";
68
- function modifyAngularJson(angularJsonPath, projectName) {
69
- const raw = readFileSync2(angularJsonPath, "utf8");
70
- const angularJson = JSON.parse(raw);
71
- const project = angularJson.projects?.[projectName];
72
- const targets = project?.architect || project?.targets;
73
- if (!targets) return false;
74
- let modified = false;
75
- const buildTarget = targets.build;
76
- if (buildTarget?.builder) {
77
- const currentBuilder = buildTarget.builder;
78
- if (currentBuilder === "@angular/build:application" || currentBuilder === "@angular-devkit/build-angular:application") {
79
- buildTarget.builder = "angular-grab:application";
80
- modified = true;
81
- }
82
- }
83
- const serveTarget = targets.serve;
84
- if (serveTarget?.builder) {
85
- const currentBuilder = serveTarget.builder;
86
- if (currentBuilder === "@angular/build:dev-server" || currentBuilder === "@angular-devkit/build-angular:dev-server") {
87
- serveTarget.builder = "angular-grab:dev-server";
88
- modified = true;
89
- }
90
- }
91
- if (modified) {
92
- writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + "\n", "utf8");
93
- }
94
- return modified;
95
- }
96
-
97
- // src/cli/utils/modify-app-config.ts
98
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
99
- import { join as join2 } from "path";
100
- function modifyAppConfig(projectRoot, sourceRoot) {
101
- const configPath = join2(projectRoot, sourceRoot, "app", "app.config.ts");
102
- if (!existsSync2(configPath)) return false;
103
- let content = readFileSync3(configPath, "utf8");
104
- if (content.includes("provideAngularGrab")) return false;
105
- const importStatement = "import { provideAngularGrab } from 'angular-grab/angular';";
106
- const lines = content.split("\n");
107
- let lastImportEndIndex = -1;
108
- for (let i = 0; i < lines.length; i++) {
109
- const trimmed = lines[i].trimStart();
110
- if (trimmed.startsWith("import ") || /\}\s*from\s+['"]/.test(trimmed) || /from\s+['"]/.test(trimmed)) {
111
- lastImportEndIndex = i;
112
- }
113
- }
114
- if (lastImportEndIndex >= 0) {
115
- lines.splice(lastImportEndIndex + 1, 0, importStatement);
116
- content = lines.join("\n");
117
- } else {
118
- content = importStatement + "\n" + content;
119
- }
120
- const providersMatch = content.match(/providers\s*:\s*\[/);
121
- if (providersMatch && providersMatch.index != null) {
122
- const insertPos = providersMatch.index + providersMatch[0].length;
123
- content = content.slice(0, insertPos) + "\n provideAngularGrab()," + content.slice(insertPos);
124
- }
125
- writeFileSync2(configPath, content, "utf8");
126
- return true;
127
- }
128
-
129
- // src/cli/commands/init.ts
130
- var PACKAGES = ["angular-grab"];
131
- function log(msg) {
132
- console.log(`\x1B[36m[angular-grab]\x1B[0m ${msg}`);
133
- }
134
- function warn(msg) {
135
- console.log(`\x1B[33m[angular-grab]\x1B[0m ${msg}`);
136
- }
137
- function getInstallCommand(pm) {
138
- const deps = PACKAGES.join(" ");
139
- switch (pm) {
140
- case "pnpm":
141
- return `pnpm add -D ${deps}`;
142
- case "yarn":
143
- return `yarn add -D ${deps}`;
144
- default:
145
- return `npm install -D ${deps}`;
146
- }
147
- }
148
- async function init() {
149
- log("Initializing angular-grab...\n");
150
- const angularJsonPath = findAngularJson();
151
- if (!angularJsonPath) {
152
- throw new Error(
153
- "Could not find angular.json. Are you in an Angular project directory?"
154
- );
155
- }
156
- const info = detectProject(angularJsonPath);
157
- log(`Found project: ${info.projectName}`);
158
- log(`Builder type: ${info.builderType}`);
159
- log(`Package manager: ${info.packageManager}`);
160
- console.log("");
161
- if (info.builderType === "browser") {
162
- throw new Error(
163
- 'angular-grab requires the "application" builder (Angular 17+).\nPlease migrate from "@angular-devkit/build-angular:browser" to "@angular/build:application".\nSee: https://angular.dev/tools/cli/build-system-migration'
164
- );
165
- }
166
- if (info.builderType === "browser-esbuild") {
167
- throw new Error(
168
- 'angular-grab requires the "application" builder, not the transitional "browser-esbuild" builder.\nPlease migrate from "@angular-devkit/build-angular:browser-esbuild" to "@angular/build:application".\nSee: https://angular.dev/tools/cli/build-system-migration'
169
- );
170
- }
171
- log("Installing packages...");
172
- const installCmd = getInstallCommand(info.packageManager);
173
- try {
174
- execSync(installCmd, {
175
- cwd: info.projectRoot,
176
- stdio: "inherit"
177
- });
178
- } catch {
179
- warn("Package installation failed. You may need to install manually:");
180
- warn(` ${installCmd}`);
181
- console.log("");
182
- }
183
- log("Updating angular.json...");
184
- const jsonModified = modifyAngularJson(info.angularJsonPath, info.projectName);
185
- if (jsonModified) {
186
- log(" Swapped builders to angular-grab");
187
- } else {
188
- warn(" angular.json builders were already configured or could not be modified");
189
- }
190
- log("Updating app.config.ts...");
191
- const configModified = modifyAppConfig(info.projectRoot, info.sourceRoot);
192
- if (configModified) {
193
- log(" Added provideAngularGrab() to providers");
194
- } else {
195
- warn(" Could not modify app.config.ts (already configured or not found)");
196
- warn(" Please add manually:");
197
- warn(" import { provideAngularGrab } from 'angular-grab/angular';");
198
- warn(" // then add provideAngularGrab() to your providers array");
199
- }
200
- console.log("");
201
- log("\x1B[32mDone!\x1B[0m angular-grab is ready.");
202
- console.log("");
203
- console.log(" Next steps:");
204
- console.log(" 1. Run \x1B[1mng serve\x1B[0m");
205
- console.log(" 2. Hold \x1B[1mCmd+C\x1B[0m (Mac) or \x1B[1mCtrl+C\x1B[0m (Windows) and hover over elements");
206
- console.log(" 3. Click to copy element context to clipboard");
207
- console.log("");
208
- }
209
-
210
- // src/cli/index.ts
211
- var args = process.argv.slice(2);
212
- var command = args[0];
213
- if (command === "init" || !command) {
214
- init().catch((err) => {
215
- console.error("\x1B[31mError:\x1B[0m", err.message);
216
- process.exit(1);
217
- });
218
- } else {
219
- console.error(`Unknown command: ${command}`);
220
- console.log("\nUsage: npx angular-grab init");
221
- process.exit(1);
222
- }
223
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/cli/commands/init.ts","../../src/cli/utils/detect-project.ts","../../src/cli/utils/modify-angular-json.ts","../../src/cli/utils/modify-app-config.ts","../../src/cli/index.ts"],"sourcesContent":["import { execSync } from 'child_process';\nimport { findAngularJson, detectProject, type ProjectInfo } from '../utils/detect-project';\nimport { modifyAngularJson } from '../utils/modify-angular-json';\nimport { modifyAppConfig } from '../utils/modify-app-config';\n\nconst PACKAGES = ['angular-grab'];\n\nfunction log(msg: string): void {\n console.log(`\\x1b[36m[angular-grab]\\x1b[0m ${msg}`);\n}\n\nfunction warn(msg: string): void {\n console.log(`\\x1b[33m[angular-grab]\\x1b[0m ${msg}`);\n}\n\nfunction getInstallCommand(pm: ProjectInfo['packageManager']): string {\n const deps = PACKAGES.join(' ');\n switch (pm) {\n case 'pnpm':\n return `pnpm add -D ${deps}`;\n case 'yarn':\n return `yarn add -D ${deps}`;\n default:\n return `npm install -D ${deps}`;\n }\n}\n\nexport async function init(): Promise<void> {\n log('Initializing angular-grab...\\n');\n\n // 1. Find angular.json\n const angularJsonPath = findAngularJson();\n if (!angularJsonPath) {\n throw new Error(\n 'Could not find angular.json. Are you in an Angular project directory?',\n );\n }\n\n // 2. Detect project info\n const info = detectProject(angularJsonPath);\n log(`Found project: ${info.projectName}`);\n log(`Builder type: ${info.builderType}`);\n log(`Package manager: ${info.packageManager}`);\n console.log('');\n\n // 3. Reject legacy builders\n if (info.builderType === 'browser') {\n throw new Error(\n 'angular-grab requires the \"application\" builder (Angular 17+).\\n' +\n 'Please migrate from \"@angular-devkit/build-angular:browser\" to \"@angular/build:application\".\\n' +\n 'See: https://angular.dev/tools/cli/build-system-migration',\n );\n }\n\n if (info.builderType === 'browser-esbuild') {\n throw new Error(\n 'angular-grab requires the \"application\" builder, not the transitional \"browser-esbuild\" builder.\\n' +\n 'Please migrate from \"@angular-devkit/build-angular:browser-esbuild\" to \"@angular/build:application\".\\n' +\n 'See: https://angular.dev/tools/cli/build-system-migration',\n );\n }\n\n // 4. Install packages\n log('Installing packages...');\n const installCmd = getInstallCommand(info.packageManager);\n try {\n execSync(installCmd, {\n cwd: info.projectRoot,\n stdio: 'inherit',\n });\n } catch {\n warn('Package installation failed. You may need to install manually:');\n warn(` ${installCmd}`);\n console.log('');\n }\n\n // 5. Modify angular.json\n log('Updating angular.json...');\n const jsonModified = modifyAngularJson(info.angularJsonPath, info.projectName);\n if (jsonModified) {\n log(' Swapped builders to angular-grab');\n } else {\n warn(' angular.json builders were already configured or could not be modified');\n }\n\n // 6. Try to add provideAngularGrab() to app config\n log('Updating app.config.ts...');\n const configModified = modifyAppConfig(info.projectRoot, info.sourceRoot);\n if (configModified) {\n log(' Added provideAngularGrab() to providers');\n } else {\n warn(' Could not modify app.config.ts (already configured or not found)');\n warn(' Please add manually:');\n warn(\" import { provideAngularGrab } from 'angular-grab/angular';\");\n warn(' // then add provideAngularGrab() to your providers array');\n }\n\n console.log('');\n log('\\x1b[32mDone!\\x1b[0m angular-grab is ready.');\n console.log('');\n console.log(' Next steps:');\n console.log(' 1. Run \\x1b[1mng serve\\x1b[0m');\n console.log(' 2. Hold \\x1b[1mCmd+C\\x1b[0m (Mac) or \\x1b[1mCtrl+C\\x1b[0m (Windows) and hover over elements');\n console.log(' 3. Click to copy element context to clipboard');\n console.log('');\n}\n","import { existsSync, readFileSync } from 'fs';\nimport { join, dirname } from 'path';\n\nexport interface ProjectInfo {\n angularJsonPath: string;\n projectRoot: string;\n projectName: string;\n sourceRoot: string;\n builderType: 'application' | 'browser-esbuild' | 'browser';\n packageManager: 'pnpm' | 'yarn' | 'npm';\n}\n\nexport function findAngularJson(startDir: string = process.cwd()): string | null {\n let dir = startDir;\n while (true) {\n const candidate = join(dir, 'angular.json');\n if (existsSync(candidate)) return candidate;\n\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nexport function detectProject(angularJsonPath: string): ProjectInfo {\n const projectRoot = dirname(angularJsonPath);\n const raw = readFileSync(angularJsonPath, 'utf8');\n const angularJson = JSON.parse(raw);\n\n const projects = angularJson.projects || {};\n const projectNames = Object.keys(projects);\n if (projectNames.length === 0) {\n throw new Error('No projects found in angular.json');\n }\n\n const projectName = projectNames[0];\n const project = projects[projectName];\n if (!project) {\n throw new Error(`Project \"${projectName}\" not found in angular.json`);\n }\n\n const sourceRoot = project.sourceRoot || 'src';\n const targets = project.architect || project.targets;\n const buildTarget = targets?.build;\n if (!buildTarget) {\n throw new Error(`No build target found for project \"${projectName}\"`);\n }\n\n const builder: string = buildTarget.builder || '';\n let builderType: ProjectInfo['builderType'];\n\n if (builder.includes(':application') || builder.includes('angular-grab:application')) {\n builderType = 'application';\n } else if (builder.includes(':browser-esbuild')) {\n builderType = 'browser-esbuild';\n } else if (builder.includes(':browser')) {\n builderType = 'browser';\n } else {\n builderType = 'application';\n }\n\n const packageManager = detectPackageManager(projectRoot);\n\n return {\n angularJsonPath,\n projectRoot,\n projectName,\n sourceRoot,\n builderType,\n packageManager,\n };\n}\n\nfunction detectPackageManager(root: string): 'pnpm' | 'yarn' | 'npm' {\n if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(root, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n","import { readFileSync, writeFileSync } from 'fs';\n\nexport function modifyAngularJson(angularJsonPath: string, projectName: string): boolean {\n const raw = readFileSync(angularJsonPath, 'utf8');\n const angularJson = JSON.parse(raw);\n\n const project = angularJson.projects?.[projectName];\n const targets = project?.architect || project?.targets;\n if (!targets) return false;\n\n let modified = false;\n\n const buildTarget = targets.build;\n if (buildTarget?.builder) {\n const currentBuilder: string = buildTarget.builder;\n if (\n currentBuilder === '@angular/build:application' ||\n currentBuilder === '@angular-devkit/build-angular:application'\n ) {\n buildTarget.builder = 'angular-grab:application';\n modified = true;\n }\n }\n\n const serveTarget = targets.serve;\n if (serveTarget?.builder) {\n const currentBuilder: string = serveTarget.builder;\n if (\n currentBuilder === '@angular/build:dev-server' ||\n currentBuilder === '@angular-devkit/build-angular:dev-server'\n ) {\n serveTarget.builder = 'angular-grab:dev-server';\n modified = true;\n }\n }\n\n if (modified) {\n writeFileSync(angularJsonPath, JSON.stringify(angularJson, null, 2) + '\\n', 'utf8');\n }\n\n return modified;\n}\n","import { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { join } from 'path';\n\nexport function modifyAppConfig(projectRoot: string, sourceRoot: string): boolean {\n const configPath = join(projectRoot, sourceRoot, 'app', 'app.config.ts');\n if (!existsSync(configPath)) return false;\n\n let content = readFileSync(configPath, 'utf8');\n\n // Skip if already has provideAngularGrab\n if (content.includes('provideAngularGrab')) return false;\n\n // Add import for provideAngularGrab\n const importStatement = \"import { provideAngularGrab } from 'angular-grab/angular';\";\n\n // Find the last import block end by matching `from '...'` or `from \"...\"` lines\n const lines = content.split('\\n');\n let lastImportEndIndex = -1;\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trimStart();\n if (trimmed.startsWith('import ') || /\\}\\s*from\\s+['\"]/.test(trimmed) || /from\\s+['\"]/.test(trimmed)) {\n lastImportEndIndex = i;\n }\n }\n\n if (lastImportEndIndex >= 0) {\n lines.splice(lastImportEndIndex + 1, 0, importStatement);\n content = lines.join('\\n');\n } else {\n content = importStatement + '\\n' + content;\n }\n\n // Try to add provideAngularGrab() to the providers array\n const providersMatch = content.match(/providers\\s*:\\s*\\[/);\n if (providersMatch && providersMatch.index != null) {\n const insertPos = providersMatch.index + providersMatch[0].length;\n content = content.slice(0, insertPos) + '\\n provideAngularGrab(),' + content.slice(insertPos);\n }\n\n writeFileSync(configPath, content, 'utf8');\n return true;\n}\n","import { init } from './commands/init';\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nif (command === 'init' || !command) {\n init().catch((err) => {\n console.error('\\x1b[31mError:\\x1b[0m', err.message);\n process.exit(1);\n });\n} else {\n console.error(`Unknown command: ${command}`);\n console.log('\\nUsage: npx angular-grab init');\n process.exit(1);\n}\n"],"mappings":"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","names":["readFileSync","readFileSync","writeFileSync","existsSync","join"]}