@devwithbobby/loops 0.1.0 → 0.1.2

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 (72) hide show
  1. package/README.md +343 -375
  2. package/dist/client/index.d.ts +186 -0
  3. package/dist/client/index.d.ts.map +1 -0
  4. package/dist/client/index.js +396 -0
  5. package/dist/client/types.d.ts +24 -0
  6. package/dist/client/types.d.ts.map +1 -0
  7. package/dist/client/types.js +0 -0
  8. package/dist/component/convex.config.d.ts +3 -0
  9. package/dist/component/convex.config.d.ts.map +1 -0
  10. package/dist/component/convex.config.js +25 -0
  11. package/dist/component/lib.d.ts +103 -0
  12. package/dist/component/lib.d.ts.map +1 -0
  13. package/dist/component/lib.js +1000 -0
  14. package/dist/component/schema.d.ts +3 -0
  15. package/dist/component/schema.d.ts.map +1 -0
  16. package/dist/component/schema.js +16 -0
  17. package/dist/component/tables/contacts.d.ts +2 -0
  18. package/dist/component/tables/contacts.d.ts.map +1 -0
  19. package/dist/component/tables/contacts.js +14 -0
  20. package/dist/component/tables/emailOperations.d.ts +2 -0
  21. package/dist/component/tables/emailOperations.d.ts.map +1 -0
  22. package/dist/component/tables/emailOperations.js +20 -0
  23. package/dist/component/validators.d.ts +18 -0
  24. package/dist/component/validators.d.ts.map +1 -0
  25. package/dist/component/validators.js +34 -0
  26. package/dist/utils.d.ts +4 -0
  27. package/dist/utils.d.ts.map +1 -0
  28. package/dist/utils.js +5 -0
  29. package/package.json +11 -5
  30. package/.changeset/README.md +0 -8
  31. package/.changeset/config.json +0 -14
  32. package/.config/commitlint.config.ts +0 -11
  33. package/.config/lefthook.yml +0 -11
  34. package/.github/workflows/release.yml +0 -52
  35. package/.github/workflows/test-and-lint.yml +0 -39
  36. package/biome.json +0 -45
  37. package/bun.lock +0 -1166
  38. package/bunfig.toml +0 -7
  39. package/convex.json +0 -3
  40. package/example/CLAUDE.md +0 -106
  41. package/example/README.md +0 -21
  42. package/example/bun-env.d.ts +0 -17
  43. package/example/convex/_generated/api.d.ts +0 -53
  44. package/example/convex/_generated/api.js +0 -23
  45. package/example/convex/_generated/dataModel.d.ts +0 -60
  46. package/example/convex/_generated/server.d.ts +0 -149
  47. package/example/convex/_generated/server.js +0 -90
  48. package/example/convex/convex.config.ts +0 -7
  49. package/example/convex/example.ts +0 -76
  50. package/example/convex/schema.ts +0 -3
  51. package/example/convex/tsconfig.json +0 -34
  52. package/example/src/App.tsx +0 -185
  53. package/example/src/frontend.tsx +0 -39
  54. package/example/src/index.css +0 -15
  55. package/example/src/index.html +0 -12
  56. package/example/src/index.tsx +0 -19
  57. package/example/tsconfig.json +0 -28
  58. package/prds/CHANGELOG.md +0 -38
  59. package/prds/CLAUDE.md +0 -408
  60. package/prds/CONTRIBUTING.md +0 -274
  61. package/prds/ENV_SETUP.md +0 -222
  62. package/prds/MONITORING.md +0 -301
  63. package/prds/RATE_LIMITING.md +0 -412
  64. package/prds/SECURITY.md +0 -246
  65. package/renovate.json +0 -32
  66. package/test/client/_generated/_ignore.ts +0 -1
  67. package/test/client/index.test.ts +0 -65
  68. package/test/client/setup.test.ts +0 -54
  69. package/test/component/lib.test.ts +0 -225
  70. package/test/component/setup.test.ts +0 -21
  71. package/tsconfig.build.json +0 -20
  72. package/tsconfig.json +0 -22
@@ -1,185 +0,0 @@
1
- import { useAction } from "convex/react";
2
- import { api } from "../convex/_generated/api";
3
- import { useState } from "react";
4
- import "./index.css";
5
-
6
- export function App() {
7
- const [email, setEmail] = useState("");
8
- const [firstName, setFirstName] = useState("");
9
- const [lastName, setLastName] = useState("");
10
- const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);
11
-
12
- const addContact = useAction(api.example.addContact);
13
- const sendEvent = useAction(api.example.sendEvent);
14
- const [isLoading, setIsLoading] = useState(false);
15
-
16
- const handleAddContact = async (e: React.FormEvent) => {
17
- e.preventDefault();
18
- setIsLoading(true);
19
- setMessage(null);
20
-
21
- try {
22
- await addContact({
23
- email,
24
- firstName: firstName || undefined,
25
- lastName: lastName || undefined,
26
- });
27
- setMessage({ type: "success", text: "Contact added successfully!" });
28
- setEmail("");
29
- setFirstName("");
30
- setLastName("");
31
- } catch (error) {
32
- setMessage({
33
- type: "error",
34
- text: error instanceof Error ? error.message : "Failed to add contact",
35
- });
36
- } finally {
37
- setIsLoading(false);
38
- }
39
- };
40
-
41
- const handleSendEvent = async () => {
42
- if (!email) {
43
- setMessage({ type: "error", text: "Please enter an email first" });
44
- return;
45
- }
46
-
47
- setIsLoading(true);
48
- setMessage(null);
49
-
50
- try {
51
- await sendEvent({
52
- email,
53
- eventName: "welcome",
54
- eventProperties: {
55
- firstName: firstName || undefined,
56
- lastName: lastName || undefined,
57
- },
58
- });
59
- setMessage({ type: "success", text: "Event sent successfully!" });
60
- } catch (error) {
61
- setMessage({
62
- type: "error",
63
- text: error instanceof Error ? error.message : "Failed to send event",
64
- });
65
- } finally {
66
- setIsLoading(false);
67
- }
68
- };
69
-
70
- return (
71
- <div className="min-h-screen bg-gray-50 w-full flex items-center justify-center p-4">
72
- <div className="container mx-auto max-w-md">
73
- <div className="bg-white rounded-lg shadow border border-gray-200 p-8">
74
- <div className="text-center mb-8">
75
- <h1 className="text-3xl font-bold text-gray-900 mb-2">
76
- Loops Component
77
- </h1>
78
- <p className="text-gray-600 text-sm">
79
- Powered by Convex Components & Loops.so
80
- </p>
81
- </div>
82
-
83
- <form onSubmit={handleAddContact} className="space-y-4 mb-6">
84
- <div>
85
- <label
86
- htmlFor="email"
87
- className="block text-sm font-medium text-gray-700 mb-1"
88
- >
89
- Email *
90
- </label>
91
- <input
92
- id="email"
93
- type="email"
94
- required
95
- value={email}
96
- onChange={(e) => setEmail(e.target.value)}
97
- className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
98
- placeholder="user@example.com"
99
- />
100
- </div>
101
-
102
- <div>
103
- <label
104
- htmlFor="firstName"
105
- className="block text-sm font-medium text-gray-700 mb-1"
106
- >
107
- First Name
108
- </label>
109
- <input
110
- id="firstName"
111
- type="text"
112
- value={firstName}
113
- onChange={(e) => setFirstName(e.target.value)}
114
- className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
115
- placeholder="John"
116
- />
117
- </div>
118
-
119
- <div>
120
- <label
121
- htmlFor="lastName"
122
- className="block text-sm font-medium text-gray-700 mb-1"
123
- >
124
- Last Name
125
- </label>
126
- <input
127
- id="lastName"
128
- type="text"
129
- value={lastName}
130
- onChange={(e) => setLastName(e.target.value)}
131
- className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
132
- placeholder="Doe"
133
- />
134
- </div>
135
-
136
- <button
137
- type="submit"
138
- disabled={isLoading}
139
- className="w-full bg-blue-600 text-white font-medium px-6 py-2 rounded-md hover:bg-blue-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
140
- >
141
- {isLoading ? "Adding..." : "Add Contact"}
142
- </button>
143
- </form>
144
-
145
- <div className="mb-6">
146
- <button
147
- type="button"
148
- onClick={handleSendEvent}
149
- disabled={isLoading || !email}
150
- className="w-full bg-green-600 text-white font-medium px-6 py-2 rounded-md hover:bg-green-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
151
- >
152
- Send Welcome Event
153
- </button>
154
- </div>
155
-
156
- {message && (
157
- <div
158
- className={`p-4 rounded-md mb-4 ${
159
- message.type === "success"
160
- ? "bg-green-50 border border-green-200 text-green-800"
161
- : "bg-red-50 border border-red-200 text-red-800"
162
- }`}
163
- >
164
- {message.text}
165
- </div>
166
- )}
167
-
168
- <div className="bg-blue-50 rounded-lg p-4 border border-blue-100">
169
- <p className="text-sm text-gray-700 text-center">
170
- <code className="text-blue-600 font-mono text-xs">
171
- example/convex/example.ts
172
- </code>
173
- <br />
174
- <span className="text-gray-500 text-xs">
175
- Check out the code to see all available features
176
- </span>
177
- </p>
178
- </div>
179
- </div>
180
- </div>
181
- </div>
182
- );
183
- }
184
-
185
- export default App;
@@ -1,39 +0,0 @@
1
- /**
2
- * This file is the entry point for the React app, it sets up the root
3
- * element and renders the App component to the DOM.
4
- *
5
- * It is included in `src/index.html`.
6
- */
7
-
8
- import { ConvexProvider, ConvexReactClient } from "convex/react";
9
- import { createRoot } from "react-dom/client";
10
- import { App } from "./App";
11
-
12
- const convexURL = process.env.CONVEX_URL;
13
-
14
- if (!convexURL) {
15
- throw new Error("No convex URL provided!");
16
- }
17
-
18
- const convex = new ConvexReactClient(convexURL);
19
-
20
- function start() {
21
- const rootElement = document.getElementById("root");
22
-
23
- if (!rootElement) {
24
- throw new Error("Could not find root");
25
- }
26
-
27
- const root = createRoot(rootElement);
28
- root.render(
29
- <ConvexProvider client={convex}>
30
- <App />
31
- </ConvexProvider>,
32
- );
33
- }
34
-
35
- if (document.readyState === "loading") {
36
- document.addEventListener("DOMContentLoaded", start);
37
- } else {
38
- start();
39
- }
@@ -1,15 +0,0 @@
1
- @import "tailwindcss";
2
-
3
- @layer base {
4
- :root {
5
- @apply font-sans;
6
- }
7
-
8
- body {
9
- @apply w-full min-h-screen m-0;
10
- }
11
-
12
- #root {
13
- @apply w-full;
14
- }
15
- }
@@ -1,12 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Loops Component Example</title>
7
- </head>
8
- <body>
9
- <div id="root"></div>
10
- <script type="module" src="./frontend.tsx"></script>
11
- </body>
12
- </html>
@@ -1,19 +0,0 @@
1
- import { serve } from "bun";
2
- import index from "./index.html";
3
-
4
- const server = serve({
5
- routes: {
6
- // Serve index.html for all unmatched routes.
7
- "/*": index,
8
- },
9
-
10
- development: process.env.NODE_ENV !== "production" && {
11
- // Enable browser hot reloading in development
12
- hmr: true,
13
-
14
- // Echo console logs from the browser to the server
15
- console: true,
16
- },
17
- });
18
-
19
- console.log(`🚀 Server running at ${server.url}`);
@@ -1,28 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "lib": ["ESNext", "DOM"],
4
- "target": "ESNext",
5
- "module": "Preserve",
6
- "moduleDetection": "force",
7
- "jsx": "react-jsx",
8
- "allowJs": true,
9
- "moduleResolution": "bundler",
10
- "allowImportingTsExtensions": true,
11
- "verbatimModuleSyntax": true,
12
- "noEmit": true,
13
- "strict": true,
14
- "skipLibCheck": true,
15
- "noFallthroughCasesInSwitch": true,
16
- "noUncheckedIndexedAccess": true,
17
- "noImplicitOverride": true,
18
- "baseUrl": ".",
19
- "paths": {
20
- "@/*": ["./src/*"]
21
- },
22
- "noUnusedLocals": false,
23
- "noUnusedParameters": false,
24
- "noPropertyAccessFromIndexSignature": false
25
- },
26
-
27
- "exclude": ["dist", "node_modules"]
28
- }
package/prds/CHANGELOG.md DELETED
@@ -1,38 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ### Changed
11
- - Moved `convex` and `react` to `peerDependencies` to prevent version conflicts
12
-
13
- ### Added
14
- - Added `@arethetypeswrong/cli` for package validation
15
- - Added `attw` script for validating package exports
16
-
17
- ## [0.1.0] - 2025-10-24
18
-
19
- ### Added
20
- - Initial release of the Convex component template
21
- - Sharded counter component implementation
22
- - React hooks for component integration (`useLoopsComponent`, `useIncrementCounter`, `useCounterValue`)
23
- - Complete Convex component architecture with example app
24
- - GitHub Actions workflow with `pkg.pr.new` integration
25
- - Lefthook for automated pre-commit checks
26
- - Biome for linting and formatting
27
- - Comprehensive test suite using `convex-test`
28
- - TypeScript support with strict mode
29
- - Bun-based development workflow
30
- - Live component sources for hot-reloading during development
31
-
32
- ### Documentation
33
- - README with setup and usage instructions
34
- - CLAUDE.md for AI-assisted development guidance
35
- - Example app demonstrating component usage
36
-
37
- [Unreleased]: https://github.com/robertalv/loops-component/compare/v0.1.0...HEAD
38
- [0.1.0]: https://github.com/robertalv/loops-component/releases/tag/v0.1.0