repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

commit
c0517ee
parent
c0208b3
author
Eric Bower
date
2026-03-28 23:12:36 -0400 EDT
docs: rm auto form
5 files changed,  +6, -135
D AUTO_FORM.md
+0, -124
  1@@ -1,124 +0,0 @@
  2-# Auto-Form Feature for pgs.sh
  3-
  4-## Overview
  5-
  6-The auto-form feature allows users to create HTML forms on their pgs.sh sites that automatically submit data to the pgs database. Form submissions can then be retrieved via the pgs CLI in JSON format.
  7-
  8-## How It Works
  9-
 10-1. Form submissions are automatically captured and stored in PostgreSQL
 11-2. Users can retrieve form data via the pgs CLI
 12-
 13-## Database Schema
 14-
 15-```sql
 16-CREATE TABLE form_entries (
 17-  id uuid NOT NULL DEFAULT uuid_generate_v4(),
 18-  user_id uuid NOT NULL,
 19-  name VARCHAR(255) NOT NULL,
 20-  data jsonb NOT NULL,
 21-  created_at timestamp without time zone NOT NULL DEFAULT NOW(),
 22-  CONSTRAINT form_entries_pkey PRIMARY KEY (id),
 23-  CONSTRAINT fk_form_entries_users
 24-    FOREIGN KEY(user_id)
 25-    REFERENCES app_users(id)
 26-    ON DELETE CASCADE
 27-);
 28-
 29-CREATE INDEX IF NOT EXISTS idx_form_entries_user ON form_entries(user_id);
 30-CREATE INDEX IF NOT EXISTS idx_form_entries_name ON form_entries(name);
 31-```
 32-
 33-### Migration
 34-
 35-Run the migration:
 36-```bash
 37-make latest
 38-```
 39-
 40-Or run all migrations:
 41-```bash
 42-make migrate
 43-```
 44-
 45-## HTML Form Example
 46-
 47-```html
 48-<form method="POST" action="/forms/example" data-pgs="true">
 49-  <p>
 50-    <label>Your Name: <input type="text" name="name" /></label>
 51-  </p>
 52-  <p>
 53-    <label>Your Email: <input type="email" name="email" /></label>
 54-  </p>
 55-  <p>
 56-    <label>Your Role: <select name="role[]" multiple>
 57-      <option value="leader">Leader</option>
 58-      <option value="follower">Follower</option>
 59-    </select></label>
 60-  </p>
 61-  <p>
 62-    <label>Message: <textarea name="message"></textarea></label>
 63-  </p>
 64-  <p>
 65-    <button type="submit">Send</button>
 66-  </p>
 67-</form>
 68-```
 69-
 70-## CLI Commands
 71-
 72-### List all form names for a user
 73-```bash
 74-ssh pgs.sh forms ls
 75-```
 76-
 77-### Get form submissions for a specific form
 78-```bash
 79-ssh pgs.sh forms show example
 80-```
 81-
 82-Output (JSON):
 83-```json
 84-[
 85-  {
 86-    "id": "uuid",
 87-    "name": "contact",
 88-    "data": {
 89-      "name": "John Doe",
 90-      "email": "john@example.com",
 91-      "role": ["leader", "follower"],
 92-      "message": "Hello!"
 93-    },
 94-    "created_at": "2026-03-05T12:00:00Z"
 95-  }
 96-]
 97-```
 98-
 99-### Delete all submissions for a form
100-```bash
101-ssh pgs.sh forms rm example --write
102-```
103-
104-## Data Storage
105-
106-- Form data is stored in PostgreSQL `form_entries` table
107-- Each submission is a JSON object with form field names as keys
108-- Data is associated with the user, not the project
109-- Form data is deleted when the user account is deleted (CASCADE)
110-
111-## Implementation Details
112-
113-### Database Methods
114-
115-```go
116-InsertFormEntry(userID, name string, data map[string]interface{}) error
117-FindFormEntriesByUserAndName(userID, name string) ([]*db.FormEntry, error)
118-FindFormNamesByUser(userID string) ([]string, error)
119-RemoveFormEntriesByUserAndName(userID, name string) error
120-```
121-
122-## More features
123-
124-- Form validation and confirmation pages
125-- CSRF token in form and validated in post handler
M pkg/apps/pgs/uploader.go
+1, -3
 1@@ -144,9 +144,7 @@ func (h *UploadAssetHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils
 2 	fileInfo.FSize = info.Size
 3 	fileInfo.FModTime = info.LastModified
 4 
 5-	reader := storage.NewAllReaderAt(contents)
 6-
 7-	return fileInfo, reader, nil
 8+	return fileInfo, contents, nil
 9 }
10 
11 func (h *UploadAssetHandler) List(s *pssh.SSHServerConnSession, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {
M pkg/filehandlers/imgs/handler.go
+1, -2
 1@@ -123,7 +123,6 @@ func (h *UploadImgHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils.F
 2 	if err != nil {
 3 		return nil, nil, err
 4 	}
 5-	reader := storage.NewAllReaderAt(contents)
 6 
 7 	fileInfo := &sendutils.VirtualFile{
 8 		FName:    cleanFilename,
 9@@ -132,7 +131,7 @@ func (h *UploadImgHandler) Read(s *pssh.SSHServerConnSession, entry *sendutils.F
10 		FModTime: info.LastModified,
11 	}
12 
13-	return fileInfo, reader, nil
14+	return fileInfo, contents, nil
15 }
16 
17 func (h *UploadImgHandler) Write(s *pssh.SSHServerConnSession, entry *sendutils.FileEntry) (string, error) {
M pkg/send/utils/io.go
+3, -3
 1@@ -10,9 +10,8 @@ type ReadAndReaderAt interface {
 2 }
 3 
 4 type ReadAndReaderAtCloser interface {
 5-	io.Reader
 6 	io.ReaderAt
 7-	io.ReadCloser
 8+	io.ReadSeekCloser
 9 }
10 
11 func NopReadAndReaderAtCloser(r ReadAndReaderAt) ReadAndReaderAtCloser {
12@@ -23,4 +22,5 @@ type nopReadAndReaderAt struct {
13 	ReadAndReaderAt
14 }
15 
16-func (nopReadAndReaderAt) Close() error { return nil }
17+func (nopReadAndReaderAt) Close() error                   { return nil }
18+func (nopReadAndReaderAt) Seek(int64, int) (int64, error) { return 0, nil }
M pkg/storage/handler.go
+1, -3
 1@@ -109,9 +109,7 @@ func (h *UploadAssetHandler) Read(s *pssh.SSHServerConnSession, entry *utils.Fil
 2 	fileInfo.FSize = info.Size
 3 	fileInfo.FModTime = info.LastModified
 4 
 5-	reader := NewAllReaderAt(contents)
 6-
 7-	return fileInfo, reader, nil
 8+	return fileInfo, contents, nil
 9 }
10 
11 func (h *UploadAssetHandler) List(s *pssh.SSHServerConnSession, fpath string, isDir bool, recursive bool) ([]os.FileInfo, error) {