@popoverai/dotrequirements 0.11.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.
Files changed (127) hide show
  1. package/README.md +478 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.js +82 -0
  4. package/dist/commands/init.d.ts +6 -0
  5. package/dist/commands/init.js +355 -0
  6. package/dist/commands/link.d.ts +15 -0
  7. package/dist/commands/link.js +156 -0
  8. package/dist/commands/login.d.ts +12 -0
  9. package/dist/commands/login.js +117 -0
  10. package/dist/commands/logout.d.ts +5 -0
  11. package/dist/commands/logout.js +17 -0
  12. package/dist/commands/mcp-setup.d.ts +5 -0
  13. package/dist/commands/mcp-setup.js +367 -0
  14. package/dist/commands/mcp.d.ts +6 -0
  15. package/dist/commands/mcp.js +10 -0
  16. package/dist/commands/pull.d.ts +7 -0
  17. package/dist/commands/pull.js +171 -0
  18. package/dist/commands/push.d.ts +11 -0
  19. package/dist/commands/push.js +310 -0
  20. package/dist/commands/test.d.ts +6 -0
  21. package/dist/commands/test.js +78 -0
  22. package/dist/config.d.ts +5 -0
  23. package/dist/config.js +16 -0
  24. package/dist/convex.d.ts +56 -0
  25. package/dist/convex.js +58 -0
  26. package/dist/harness/cache.d.ts +135 -0
  27. package/dist/harness/cache.js +342 -0
  28. package/dist/harness/convexReporting.d.ts +15 -0
  29. package/dist/harness/convexReporting.js +136 -0
  30. package/dist/harness/coverageCache.d.ts +30 -0
  31. package/dist/harness/coverageCache.js +70 -0
  32. package/dist/harness/finalize.d.ts +48 -0
  33. package/dist/harness/finalize.js +299 -0
  34. package/dist/harness/index.d.ts +70 -0
  35. package/dist/harness/index.js +103 -0
  36. package/dist/harness/localReporting.d.ts +6 -0
  37. package/dist/harness/localReporting.js +49 -0
  38. package/dist/harness/prepare.d.ts +41 -0
  39. package/dist/harness/prepare.js +83 -0
  40. package/dist/harness/requirementsLoader.d.ts +45 -0
  41. package/dist/harness/requirementsLoader.js +201 -0
  42. package/dist/harness/tracking.d.ts +49 -0
  43. package/dist/harness/tracking.js +179 -0
  44. package/dist/harness/types.d.ts +12 -0
  45. package/dist/harness/types.js +6 -0
  46. package/dist/mcp/convexClient.d.ts +43 -0
  47. package/dist/mcp/convexClient.js +101 -0
  48. package/dist/mcp/grep.d.ts +24 -0
  49. package/dist/mcp/grep.js +261 -0
  50. package/dist/mcp/index.d.ts +3 -0
  51. package/dist/mcp/index.js +1758 -0
  52. package/dist/mcp/requirements.d.ts +47 -0
  53. package/dist/mcp/requirements.js +141 -0
  54. package/dist/mcp/testCodeExtractor.d.ts +22 -0
  55. package/dist/mcp/testCodeExtractor.js +152 -0
  56. package/dist/mcp/types.d.ts +27 -0
  57. package/dist/mcp/types.js +2 -0
  58. package/dist/schema/browser.d.ts +12 -0
  59. package/dist/schema/browser.js +24 -0
  60. package/dist/schema/builder.d.ts +25 -0
  61. package/dist/schema/builder.js +125 -0
  62. package/dist/schema/conversions.d.ts +69 -0
  63. package/dist/schema/conversions.js +201 -0
  64. package/dist/schema/index.d.ts +14 -0
  65. package/dist/schema/index.js +24 -0
  66. package/dist/schema/parser-core.d.ts +61 -0
  67. package/dist/schema/parser-core.js +247 -0
  68. package/dist/schema/parser.d.ts +44 -0
  69. package/dist/schema/parser.js +295 -0
  70. package/dist/schema/resolver.d.ts +66 -0
  71. package/dist/schema/resolver.js +185 -0
  72. package/dist/schema/schemas.d.ts +312 -0
  73. package/dist/schema/schemas.js +258 -0
  74. package/dist/schema/test-schema.d.ts +5 -0
  75. package/dist/schema/test-schema.js +81 -0
  76. package/dist/templates/antigravity-gemini.md +3 -0
  77. package/dist/templates/antigravity-overview-rule.md +3 -0
  78. package/dist/templates/antigravity-test-rule.md +3 -0
  79. package/dist/templates/behavioral-core.md +25 -0
  80. package/dist/templates/claude-code-overview-skill.md +6 -0
  81. package/dist/templates/claude-code-skill.md +6 -0
  82. package/dist/templates/claude-code-test-skill.md +6 -0
  83. package/dist/templates/codex-agents.md +3 -0
  84. package/dist/templates/codex-overview-agents.md +3 -0
  85. package/dist/templates/codex-test-agents.md +3 -0
  86. package/dist/templates/cursor-overview-rule.mdc +5 -0
  87. package/dist/templates/cursor-rule.mdc +5 -0
  88. package/dist/templates/cursor-test-rule.mdc +5 -0
  89. package/dist/templates/example-requirements.d.ts +8 -0
  90. package/dist/templates/example-requirements.js +88 -0
  91. package/dist/templates/example-requirements.ts +88 -0
  92. package/dist/templates/overview-core.md +27 -0
  93. package/dist/templates/requirements-readme.d.ts +5 -0
  94. package/dist/templates/requirements-readme.js +31 -0
  95. package/dist/templates/requirements-readme.ts +30 -0
  96. package/dist/templates/test-writing-core.md +72 -0
  97. package/dist/utils/brand.d.ts +5 -0
  98. package/dist/utils/brand.js +8 -0
  99. package/dist/utils/browser-launch.d.ts +19 -0
  100. package/dist/utils/browser-launch.js +36 -0
  101. package/dist/utils/detect-existing-project.d.ts +5 -0
  102. package/dist/utils/detect-existing-project.js +34 -0
  103. package/dist/utils/env.d.ts +19 -0
  104. package/dist/utils/env.js +56 -0
  105. package/dist/utils/gitignore.d.ts +7 -0
  106. package/dist/utils/gitignore.js +29 -0
  107. package/dist/utils/local-project.d.ts +31 -0
  108. package/dist/utils/local-project.js +33 -0
  109. package/dist/utils/oauth-callback-server.d.ts +28 -0
  110. package/dist/utils/oauth-callback-server.js +156 -0
  111. package/dist/utils/oauth-flow.d.ts +22 -0
  112. package/dist/utils/oauth-flow.js +120 -0
  113. package/dist/utils/project-discovery.d.ts +57 -0
  114. package/dist/utils/project-discovery.js +146 -0
  115. package/dist/utils/project-name.d.ts +8 -0
  116. package/dist/utils/project-name.js +48 -0
  117. package/dist/utils/project-selector.d.ts +25 -0
  118. package/dist/utils/project-selector.js +69 -0
  119. package/dist/utils/prompts.d.ts +33 -0
  120. package/dist/utils/prompts.js +60 -0
  121. package/dist/utils/templates.d.ts +29 -0
  122. package/dist/utils/templates.js +67 -0
  123. package/dist/utils/token-refresh.d.ts +24 -0
  124. package/dist/utils/token-refresh.js +69 -0
  125. package/dist/utils/token-storage.d.ts +31 -0
  126. package/dist/utils/token-storage.js +57 -0
  127. package/package.json +82 -0
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: dotreq-overview
3
+ description: Use this to understand what the system is supposed to do. ALWAYS use it when exploring expected behavior.
4
+ ---
5
+
6
+ {{OVERVIEW_CORE}}
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: dotreq-requirements
3
+ description: Use this when adding new expected behavior to the system. ALWAYS use it when implementing new functionality.
4
+ ---
5
+
6
+ {{BEHAVIORAL_CORE}}
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: dotreq-tests
3
+ description: Use this when validating expected behavior. ALWAYS use it when writing tests.
4
+ ---
5
+
6
+ {{TEST_WRITING_CORE}}
@@ -0,0 +1,3 @@
1
+ <!-- BEGIN dotreq-requirements -->
2
+ {{BEHAVIORAL_CORE}}
3
+ <!-- END dotreq-requirements -->
@@ -0,0 +1,3 @@
1
+ <!-- BEGIN dotreq-overview -->
2
+ {{OVERVIEW_CORE}}
3
+ <!-- END dotreq-overview -->
@@ -0,0 +1,3 @@
1
+ <!-- BEGIN dotreq-tests -->
2
+ {{TEST_WRITING_CORE}}
3
+ <!-- END dotreq-tests -->
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Use this to understand what the system is supposed to do. ALWAYS use it when exploring expected behavior.
3
+ ---
4
+
5
+ {{OVERVIEW_CORE}}
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Use this when adding new expected behavior to the system. ALWAYS use it when implementing new functionality.
3
+ ---
4
+
5
+ {{BEHAVIORAL_CORE}}
@@ -0,0 +1,5 @@
1
+ ---
2
+ description: Use this when validating expected behavior. ALWAYS use it when writing tests.
3
+ ---
4
+
5
+ {{TEST_WRITING_CORE}}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Template for example.requirements.md
3
+ *
4
+ * This template is used for both local-only and authenticated init flows.
5
+ * It demonstrates the dotrequirements markdown format with nested requirements.
6
+ */
7
+ export declare function generateExampleRequirements(projectId?: string): string;
8
+ //# sourceMappingURL=example-requirements.d.ts.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Template for example.requirements.md
3
+ *
4
+ * This template is used for both local-only and authenticated init flows.
5
+ * It demonstrates the dotrequirements markdown format with nested requirements.
6
+ */
7
+ export function generateExampleRequirements(projectId = 'local') {
8
+ const now = new Date().toISOString();
9
+ return `---
10
+ projectId: ${projectId}
11
+ pulledAt: ${now}
12
+ version: 1
13
+ document:
14
+ title: "Example Requirements"
15
+ ---
16
+
17
+ # Example Requirements
18
+
19
+ This file demonstrates the dotrequirements format. Feel free to edit or delete it.
20
+
21
+ ## HOW-TO: How to use dotrequirements
22
+
23
+ \`\`\`dotrequirements
24
+ HOW-TO: How to use dotrequirements
25
+ 0. → Requirements live here and are referenced by index, like requirement('HOW-TO.0')
26
+ 1. Labels → Anything before the arrow is a label. You can reference a requirement by its index or its label: requirement('HOW-TO.1') == requirement('HOW-TO.labels')
27
+ 2. Labels → Repeated labels can be referenced sequentially: requirement('HOW-TO.labels#2')
28
+ 2.0. Nesting → You can keep nesting. Label references don't need to be nested: requirement('HOW-TO.nesting').
29
+ 2.1. Several words → Reference multi-word labels using kebab-case. Label references are never case sensitive: requirement('HOW-TO.several-words')
30
+ 3. → While you _can_ write your requirements longhand in this format, there are a number of better ways.
31
+ 3.0. MCP → The dotrequirements MCP equips an AI assistant to develop requirements with you
32
+ 3.1. Your current tools → Dotrequirements has a composer for Jira, Confluence, and Notion
33
+ 3.2. Our composer → You can use our requirements composer at app.dotrequirements.io
34
+ 4. Have fun → Especially in the time you get back from having a more stable, transparent, and AI-friendly codebase
35
+ \`\`\`
36
+
37
+ ---
38
+
39
+ ## USER-AUTH: User authentication flow
40
+
41
+ **Implementation notes:** Use bcrypt for password hashing with work factor >= 12.
42
+
43
+ \`\`\`dotrequirements
44
+ USER-AUTH: User authentication flow
45
+ 0. AC → Login form accepts email and password
46
+ 1. AC → Invalid credentials show error message
47
+ 2. Edge-case → Rate limiting after 5 failed attempts
48
+ 2.0. Requirement → Lock account for 15 minutes
49
+ 2.1. Requirement → Display countdown timer to user
50
+ \`\`\`
51
+
52
+ ---
53
+
54
+ ## PERF-1: API endpoints respond within acceptable time limits
55
+
56
+ \`\`\`dotrequirements
57
+ PERF-1: API endpoints respond within acceptable time limits
58
+ 0. Benchmark → Tested with 1000 concurrent users
59
+ 1. Requirement → p95 latency under 200ms
60
+ 2. Requirement → p99 latency under 500ms
61
+ \`\`\`
62
+
63
+ ---
64
+
65
+ ## Referencing in Tests
66
+
67
+ You can reference these requirements in your tests:
68
+
69
+ \`\`\`javascript
70
+ import { requirement } from '@popoverai/dotrequirements/test';
71
+
72
+ test('login with valid credentials', () => {
73
+ // Reference by numeric path
74
+ const ac = requirement('USER-AUTH.0');
75
+ // Returns: "AC: Login form accepts email and password"
76
+
77
+ // Reference by label
78
+ const edgeCase = requirement('USER-AUTH.edge-case');
79
+ // Returns: "Edge-case: Rate limiting after 5 failed attempts"
80
+
81
+ // Your test implementation...
82
+ });
83
+ \`\`\`
84
+
85
+ See the [test harness documentation](https://docs.dotrequirements.io/harness) for more details.
86
+ `;
87
+ }
88
+ //# sourceMappingURL=example-requirements.js.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Template for example.requirements.md
3
+ *
4
+ * This template is used for both local-only and authenticated init flows.
5
+ * It demonstrates the dotrequirements markdown format with nested requirements.
6
+ */
7
+ export function generateExampleRequirements(projectId: string = 'local'): string {
8
+ const now = new Date().toISOString();
9
+
10
+ return `---
11
+ projectId: ${projectId}
12
+ pulledAt: ${now}
13
+ version: 1
14
+ document:
15
+ title: "Example Requirements"
16
+ ---
17
+
18
+ # Example Requirements
19
+
20
+ This file demonstrates the dotrequirements format. Feel free to edit or delete it.
21
+
22
+ ## HOW-TO: How to use dotrequirements
23
+
24
+ \`\`\`dotrequirements
25
+ HOW-TO: How to use dotrequirements
26
+ 0. → Requirements live here and are referenced by index, like requirement('HOW-TO.0')
27
+ 1. Labels → Anything before the arrow is a label. You can reference a requirement by its index or its label: requirement('HOW-TO.1') == requirement('HOW-TO.labels')
28
+ 2. Labels → Repeated labels can be referenced sequentially: requirement('HOW-TO.labels#2')
29
+ 2.0. Nesting → You can keep nesting. Label references don't need to be nested: requirement('HOW-TO.nesting').
30
+ 2.1. Several words → Reference multi-word labels using kebab-case. Label references are never case sensitive: requirement('HOW-TO.several-words')
31
+ 3. → While you _can_ write your requirements longhand in this format, there are a number of better ways.
32
+ 3.0. MCP → The dotrequirements MCP equips an AI assistant to develop requirements with you
33
+ 3.1. Your current tools → Dotrequirements has a composer for Jira, Confluence, and Notion
34
+ 3.2. Our composer → You can use our requirements composer at app.dotrequirements.io
35
+ 4. Have fun → Especially in the time you get back from having a more stable, transparent, and AI-friendly codebase
36
+ \`\`\`
37
+
38
+ ---
39
+
40
+ ## USER-AUTH: User authentication flow
41
+
42
+ **Implementation notes:** Use bcrypt for password hashing with work factor >= 12.
43
+
44
+ \`\`\`dotrequirements
45
+ USER-AUTH: User authentication flow
46
+ 0. AC → Login form accepts email and password
47
+ 1. AC → Invalid credentials show error message
48
+ 2. Edge-case → Rate limiting after 5 failed attempts
49
+ 2.0. Requirement → Lock account for 15 minutes
50
+ 2.1. Requirement → Display countdown timer to user
51
+ \`\`\`
52
+
53
+ ---
54
+
55
+ ## PERF-1: API endpoints respond within acceptable time limits
56
+
57
+ \`\`\`dotrequirements
58
+ PERF-1: API endpoints respond within acceptable time limits
59
+ 0. Benchmark → Tested with 1000 concurrent users
60
+ 1. Requirement → p95 latency under 200ms
61
+ 2. Requirement → p99 latency under 500ms
62
+ \`\`\`
63
+
64
+ ---
65
+
66
+ ## Referencing in Tests
67
+
68
+ You can reference these requirements in your tests:
69
+
70
+ \`\`\`javascript
71
+ import { requirement } from '@popoverai/dotrequirements/test';
72
+
73
+ test('login with valid credentials', () => {
74
+ // Reference by numeric path
75
+ const ac = requirement('USER-AUTH.0');
76
+ // Returns: "AC: Login form accepts email and password"
77
+
78
+ // Reference by label
79
+ const edgeCase = requirement('USER-AUTH.edge-case');
80
+ // Returns: "Edge-case: Rate limiting after 5 failed attempts"
81
+
82
+ // Your test implementation...
83
+ });
84
+ \`\`\`
85
+
86
+ See the [test harness documentation](https://docs.dotrequirements.io/harness) for more details.
87
+ `;
88
+ }
@@ -0,0 +1,27 @@
1
+ # Understanding Expected Behavior
2
+
3
+ ALWAYS use this when you want to understand what the system is supposed to do.
4
+
5
+ ## Where to Find Expected Behavior
6
+
7
+ This project uses **requirements as the source of truth** for expected behavior.
8
+
9
+ **Location:** `.requirements/` directory contains `*.requirements.md` files
10
+
11
+ **Format:** Requirements are structured as:
12
+ - Requirement IDs (e.g., `AUTH-1`, `LOGIN-2`)
13
+ - Descriptions of expected behavior
14
+ - Hierarchical structure (parent requirements with child criteria)
15
+
16
+ ## MCP Tools for Exploration
17
+
18
+ - `list_all_requirements` - Get overview of all requirements in the project
19
+ - `get_requirement` - Get detailed requirement tree with test coverage
20
+ - `search_requirements` - Search by text/regex across all requirements
21
+ - `get_requirements_by_test` - See what a test file validates
22
+
23
+ ## Next Steps
24
+
25
+ Once you understand the expected behavior:
26
+ - **Adding new behavior?** Use the `dotreq-requirements` skill
27
+ - **Writing tests?** Use the `dotreq-tests` skill
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Template for .requirements/README.md
3
+ */
4
+ export declare function generateRequirementsReadme(): string;
5
+ //# sourceMappingURL=requirements-readme.d.ts.map
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Template for .requirements/README.md
3
+ */
4
+ export function generateRequirementsReadme() {
5
+ return `# Requirements
6
+
7
+ This directory contains requirements for the project. Requirements can be:
8
+ - Hand-authored locally in Markdown files
9
+ - Generated via \`dotrequirements pull\` from dot•requirements cloud
10
+ - Synced bidirectionally with \`dotrequirements push\`
11
+
12
+ ## File Format
13
+
14
+ Requirements use the \`*.requirements.md\` naming pattern. See the [Markdown Schema](https://docs.dotrequirements.io/schema) for format details.
15
+
16
+ ## Getting Started
17
+
18
+ 1. Edit \`example.requirements.md\` or create new \`*.requirements.md\` files
19
+ 2. Reference requirements in tests using the test harness
20
+ 3. Run tests to track coverage
21
+
22
+ ## Commands
23
+
24
+ - \`dotrequirements pull\` - Sync requirements from cloud
25
+ - \`dotrequirements push\` - Push local requirements to cloud
26
+ - \`dotrequirements test\` - Validate requirement files
27
+
28
+ Learn more: https://dotrequirements.io
29
+ `;
30
+ }
31
+ //# sourceMappingURL=requirements-readme.js.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Template for .requirements/README.md
3
+ */
4
+ export function generateRequirementsReadme(): string {
5
+ return `# Requirements
6
+
7
+ This directory contains requirements for the project. Requirements can be:
8
+ - Hand-authored locally in Markdown files
9
+ - Generated via \`dotrequirements pull\` from dot•requirements cloud
10
+ - Synced bidirectionally with \`dotrequirements push\`
11
+
12
+ ## File Format
13
+
14
+ Requirements use the \`*.requirements.md\` naming pattern. See the [Markdown Schema](https://docs.dotrequirements.io/schema) for format details.
15
+
16
+ ## Getting Started
17
+
18
+ 1. Edit \`example.requirements.md\` or create new \`*.requirements.md\` files
19
+ 2. Reference requirements in tests using the test harness
20
+ 3. Run tests to track coverage
21
+
22
+ ## Commands
23
+
24
+ - \`dotrequirements pull\` - Sync requirements from cloud
25
+ - \`dotrequirements push\` - Push local requirements to cloud
26
+ - \`dotrequirements test\` - Validate requirement files
27
+
28
+ Learn more: https://dotrequirements.io
29
+ `;
30
+ }
@@ -0,0 +1,72 @@
1
+ # Test Writing with Requirements
2
+
3
+ ALWAYS use this guidance when writing tests based on requirements.
4
+
5
+ ## Core Principle
6
+
7
+ Use `requirement()` AS the test description, not in the body or comments.
8
+
9
+ ```typescript
10
+ // ✅ Good
11
+ test(requirement('AUTH-1'), () => { /* test */ });
12
+
13
+ // ❌ Bad
14
+ test("user can log in", () => { requirement('AUTH-1'); });
15
+ ```
16
+
17
+ ## Test Structure
18
+
19
+ **Match the requirement hierarchy:**
20
+
21
+ For structured requirements, nest describe/it blocks:
22
+
23
+ ```typescript
24
+ describe(requirement('LOGIN-1'), () => {
25
+ describe(requirement('LOGIN-1.given'), () => {
26
+ // Arrange
27
+ });
28
+ describe(requirement('LOGIN-1.when'), () => {
29
+ // Act
30
+ it(requirement('LOGIN-1.then'), () => {
31
+ // Assert
32
+ });
33
+ });
34
+ });
35
+ ```
36
+
37
+ For simple requirements, use a single test block.
38
+
39
+ ## Comments
40
+
41
+ Comments should describe the TEST implementation, not copy the requirement text verbatim.
42
+
43
+ **NEVER document coverage in comments.** Our MCP tools track coverage automatically.
44
+
45
+ ```typescript
46
+ // ❌ Bad - creates second source of truth
47
+ /**
48
+ * Requirements coverage:
49
+ * - AUTH-9.0: Backend creates project ✓
50
+ * - AUTH-9.1: CLI writes to .env.local ✓
51
+ */
52
+
53
+ // ✅ Good - use MCP tools instead
54
+ // Use get_requirement, get_requirements_by_test to see coverage
55
+ ```
56
+
57
+ ## Workflow
58
+
59
+ After writing tests:
60
+
61
+ 1. Run tests to ensure they don't throw errors
62
+ 2. **ALWAYS run `review_test`** on the test file to validate tests actually check what requirements specify
63
+ 3. Fix any issues identified by the review
64
+
65
+ ## MCP Tools for Test Writing
66
+
67
+ - `get_requirement` - Get requirement tree with existing coverage
68
+ - `get_requirements_by_test` - See requirements referenced in a test file
69
+ - `list_untested_requirements` - Find requirements without tests
70
+ - `review_test` - Validate test actually checks what requirement specifies (run after writing tests)
71
+
72
+ Note: Users can also explicitly trigger this workflow with `/write-tests`.
@@ -0,0 +1,5 @@
1
+ /** Branded name for terminal output (colored bullet) */
2
+ export declare const brand: string;
3
+ /** Branded name for plain text (MCP descriptions, etc) */
4
+ export declare const brandPlain = "dot\u2022requirements";
5
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1,8 @@
1
+ import chalk from 'chalk';
2
+ // Cyan color: rgb(8, 145, 178)
3
+ const bulletColor = chalk.rgb(8, 145, 178);
4
+ /** Branded name for terminal output (colored bullet) */
5
+ export const brand = `dot${bulletColor('•')}requirements`;
6
+ /** Branded name for plain text (MCP descriptions, etc) */
7
+ export const brandPlain = 'dot•requirements';
8
+ //# sourceMappingURL=brand.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Cross-platform browser launching utility for OAuth flows.
3
+ *
4
+ * Implements AUTH-23: Browser launch utility for OAuth flow
5
+ *
6
+ * Uses the `open` npm package for secure, cross-platform browser launching
7
+ * without shell command injection vulnerabilities.
8
+ */
9
+ /**
10
+ * Open a URL in the user's default browser
11
+ *
12
+ * Works cross-platform (macOS, Windows, Linux)
13
+ */
14
+ export declare function openBrowser(url: string): Promise<void>;
15
+ /**
16
+ * Open browser with fallback instructions if automatic launch fails
17
+ */
18
+ export declare function openBrowserWithFallback(url: string): Promise<void>;
19
+ //# sourceMappingURL=browser-launch.d.ts.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Cross-platform browser launching utility for OAuth flows.
3
+ *
4
+ * Implements AUTH-23: Browser launch utility for OAuth flow
5
+ *
6
+ * Uses the `open` npm package for secure, cross-platform browser launching
7
+ * without shell command injection vulnerabilities.
8
+ */
9
+ import open from 'open';
10
+ /**
11
+ * Open a URL in the user's default browser
12
+ *
13
+ * Works cross-platform (macOS, Windows, Linux)
14
+ */
15
+ export async function openBrowser(url) {
16
+ try {
17
+ await open(url);
18
+ }
19
+ catch (error) {
20
+ throw new Error(`Failed to open browser: ${error instanceof Error ? error.message : String(error)}`);
21
+ }
22
+ }
23
+ /**
24
+ * Open browser with fallback instructions if automatic launch fails
25
+ */
26
+ export async function openBrowserWithFallback(url) {
27
+ try {
28
+ await openBrowser(url);
29
+ console.log('Opening browser for authentication...');
30
+ }
31
+ catch (error) {
32
+ console.error('Could not automatically open browser.');
33
+ console.log(`\nPlease open this URL in your browser manually:\n${url}\n`);
34
+ }
35
+ }
36
+ //# sourceMappingURL=browser-launch.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Detect if .requirements/ directory exists and extract projectId from files
3
+ */
4
+ export declare function detectExistingProject(cwd: string): string | null;
5
+ //# sourceMappingURL=detect-existing-project.d.ts.map
@@ -0,0 +1,34 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { parseRequirementsFromFile } from '../schema/index.js';
4
+ /**
5
+ * Detect if .requirements/ directory exists and extract projectId from files
6
+ */
7
+ export function detectExistingProject(cwd) {
8
+ const requirementsDir = path.join(cwd, '.requirements');
9
+ if (!fs.existsSync(requirementsDir)) {
10
+ return null;
11
+ }
12
+ // Look for .requirements.md files
13
+ const files = fs.readdirSync(requirementsDir)
14
+ .filter(f => f.endsWith('.requirements.md'));
15
+ if (files.length === 0) {
16
+ return null;
17
+ }
18
+ // Try to parse first file to get projectId
19
+ for (const file of files) {
20
+ try {
21
+ const filePath = path.join(requirementsDir, file);
22
+ const parsed = parseRequirementsFromFile(filePath);
23
+ if (parsed.metadata.projectId) {
24
+ return parsed.metadata.projectId;
25
+ }
26
+ }
27
+ catch (error) {
28
+ // Skip files that can't be parsed
29
+ continue;
30
+ }
31
+ }
32
+ return null;
33
+ }
34
+ //# sourceMappingURL=detect-existing-project.js.map
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Load environment variables from .env.local file
3
+ * Merges with existing process.env (process.env takes precedence)
4
+ */
5
+ export declare function loadEnvFile(cwd?: string): void;
6
+ /**
7
+ * Get project credentials from environment
8
+ * Returns undefined if not found
9
+ */
10
+ export declare function getProjectCredentials(): {
11
+ projectId: string;
12
+ projectSecret: string;
13
+ } | undefined;
14
+ /**
15
+ * Get project ID from environment
16
+ * Returns undefined if not found
17
+ */
18
+ export declare function getProjectId(): string | undefined;
19
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1,56 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Load environment variables from .env.local file
5
+ * Merges with existing process.env (process.env takes precedence)
6
+ */
7
+ export function loadEnvFile(cwd = process.cwd()) {
8
+ const envPath = path.join(cwd, '.env.local');
9
+ if (!fs.existsSync(envPath)) {
10
+ return;
11
+ }
12
+ try {
13
+ const content = fs.readFileSync(envPath, 'utf-8');
14
+ const lines = content.split('\n');
15
+ for (const line of lines) {
16
+ // Skip empty lines and comments
17
+ if (!line.trim() || line.trim().startsWith('#')) {
18
+ continue;
19
+ }
20
+ // Parse KEY=VALUE format
21
+ const match = line.match(/^([^=]+)=(.*)$/);
22
+ if (match) {
23
+ const key = match[1].trim();
24
+ const value = match[2].trim();
25
+ // Only set if not already in process.env
26
+ if (!process.env[key]) {
27
+ process.env[key] = value;
28
+ }
29
+ }
30
+ }
31
+ }
32
+ catch (error) {
33
+ // Silently fail if we can't read the file
34
+ // The commands will error appropriately if env vars are missing
35
+ }
36
+ }
37
+ /**
38
+ * Get project credentials from environment
39
+ * Returns undefined if not found
40
+ */
41
+ export function getProjectCredentials() {
42
+ const projectId = process.env.DOTREQUIREMENTS_PROJECT_ID;
43
+ const projectSecret = process.env.DOTREQUIREMENTS_PROJECT_SECRET;
44
+ if (!projectId || !projectSecret) {
45
+ return undefined;
46
+ }
47
+ return { projectId, projectSecret };
48
+ }
49
+ /**
50
+ * Get project ID from environment
51
+ * Returns undefined if not found
52
+ */
53
+ export function getProjectId() {
54
+ return process.env.DOTREQUIREMENTS_PROJECT_ID;
55
+ }
56
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Ensure .env.local is in .gitignore
3
+ * Creates .gitignore if it doesn't exist
4
+ * Appends .env.local if not already present
5
+ */
6
+ export declare function ensureGitignore(cwd?: string): void;
7
+ //# sourceMappingURL=gitignore.d.ts.map
@@ -0,0 +1,29 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * Ensure .env.local is in .gitignore
5
+ * Creates .gitignore if it doesn't exist
6
+ * Appends .env.local if not already present
7
+ */
8
+ export function ensureGitignore(cwd = process.cwd()) {
9
+ const gitignorePath = path.join(cwd, '.gitignore');
10
+ const entryToAdd = '.env.local';
11
+ const comment = '# dotrequirements credentials';
12
+ // Check if .gitignore exists
13
+ if (!fs.existsSync(gitignorePath)) {
14
+ // Create new .gitignore
15
+ fs.writeFileSync(gitignorePath, `${comment}\n${entryToAdd}\n`);
16
+ return;
17
+ }
18
+ // Read existing .gitignore
19
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
20
+ // Check if .env.local is already present
21
+ if (content.includes(entryToAdd)) {
22
+ return; // Already present, nothing to do
23
+ }
24
+ // Append to .gitignore
25
+ const separator = content.endsWith('\n') ? '' : '\n';
26
+ const newContent = `${content}${separator}\n${comment}\n${entryToAdd}\n`;
27
+ fs.writeFileSync(gitignorePath, newContent);
28
+ }
29
+ //# sourceMappingURL=gitignore.js.map