@peterseibel/hug 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,6 +54,47 @@ hug fork
54
54
 
55
55
  Creates a new Apps Script project from the current local code. Useful with git branches — fork on a branch to get a separate Apps Script project you can develop against independently. If you're using `hug config` to manage resources like spreadsheet IDs, you'll probably want to update them after forking so the new project points at its own resources.
56
56
 
57
+ #### Forking a container-bound project
58
+
59
+ If your project is a container-bound script (created via Extensions > Apps Script inside a Google Sheet, Doc, etc.), `hug fork` will refuse by default since the forked standalone copy can't call `getActiveSpreadsheet()` and similar container APIs.
60
+
61
+ Use `--detach` to fork anyway and automatically save the original container's ID to `config.js`:
62
+
63
+ ```bash
64
+ hug fork --detach
65
+ ```
66
+
67
+ This sets `CONTAINER_ID` in `config.js` to the original container's ID. You'll then need to update your code to open the container explicitly instead of relying on the bound context. For example:
68
+
69
+ ```javascript
70
+ // Before (container-bound only)
71
+ const ss = SpreadsheetApp.getActiveSpreadsheet();
72
+ const sheet = SpreadsheetApp.getActiveSheet();
73
+ const range = SpreadsheetApp.getActiveRange();
74
+
75
+ // After (works in standalone fork)
76
+ const ss = SpreadsheetApp.openById(CONFIG.CONTAINER_ID);
77
+ const sheet = ss.getActiveSheet(); // or ss.getSheetByName("Sheet1")
78
+ const range = sheet.getActiveRange(); // or sheet.getRange(...)
79
+ ```
80
+
81
+ Similarly for other container types:
82
+
83
+ ```javascript
84
+ // Google Doc
85
+ const doc = DocumentApp.openById(CONFIG.CONTAINER_ID);
86
+
87
+ // Google Form
88
+ const form = FormApp.openById(CONFIG.CONTAINER_ID);
89
+ ```
90
+
91
+ After updating the code, push it and optionally set up a fresh deployment:
92
+
93
+ ```bash
94
+ hug push
95
+ hug deploy "detach from container"
96
+ ```
97
+
57
98
  ### Configure
58
99
 
59
100
  ```bash
package/bin/hug CHANGED
@@ -22,7 +22,7 @@ Usage: hug <command> [options]
22
22
  Project commands:
23
23
  init [--template blank|webapp] [name] Create a new project from a template
24
24
  init --scriptId <id> [name] Import an existing Apps Script project
25
- fork Create a new Apps Script project from current code
25
+ fork [--detach] Create a new Apps Script project from current code
26
26
 
27
27
  Development commands:
28
28
  push Push local files to Apps Script
@@ -98,6 +98,7 @@ cmd_init() {
98
98
  # Import mode: clone an existing project
99
99
  echo "Importing project $script_id..."
100
100
  run_clasp "$clasp" clone "$script_id"
101
+ patch_parent_id
101
102
 
102
103
  echo ""
103
104
  echo "Project imported. Next steps:"
@@ -139,16 +140,23 @@ cmd_init() {
139
140
 
140
141
  cmd_fork() {
141
142
  local force=false
143
+ local detach=false
142
144
  while [ $# -gt 0 ]; do
143
145
  case "$1" in
144
146
  -f|--force) force=true; shift ;;
147
+ --detach) detach=true; shift ;;
145
148
  --help)
146
- echo "Usage: hug fork [-f|--force]"
149
+ echo "Usage: hug fork [-f|--force] [--detach]"
147
150
  echo ""
148
151
  echo "Creates a new Apps Script project from the current local code."
149
152
  echo "Replaces .clasp.json with a new project, then pushes code to it."
150
153
  echo ""
151
- echo "Refuses if the current project is container-bound (use -f to override)."
154
+ echo "Refuses if the current project is container-bound (use -f to override,"
155
+ echo "or --detach to fork and save the container ID to config)."
156
+ echo ""
157
+ echo " --detach Fork a container-bound project and set CONTAINER_ID in"
158
+ echo " config.js to the original container's ID, so code can"
159
+ echo " open it via SpreadsheetApp.openById() etc."
152
160
  echo ""
153
161
  echo "Useful with git branches: fork on a branch to get a separate"
154
162
  echo "Apps Script project for each branch."
@@ -162,16 +170,21 @@ cmd_fork() {
162
170
  return 1
163
171
  fi
164
172
 
165
- if [ "$force" = false ] && grep -q '"parentId"' .clasp.json 2>/dev/null; then
166
- local parent_id
173
+ # Capture parentId before we replace .clasp.json
174
+ local parent_id=""
175
+ if grep -q '"parentId"' .clasp.json 2>/dev/null; then
167
176
  parent_id=$(grep '"parentId"' .clasp.json | sed 's/.*"parentId"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
177
+ fi
178
+
179
+ if [ -n "$parent_id" ] && [ "$force" = false ] && [ "$detach" = false ]; then
168
180
  echo "Error: this is a container-bound script. Forking will create a standalone" >&2
169
181
  echo "project, but the code may depend on its container (e.g. by calling." >&2
170
182
  echo "getActiveSpreadsheet())." >&2
171
183
  echo "" >&2
172
184
  echo "Container: https://drive.google.com/file/d/$parent_id" >&2
173
185
  echo "" >&2
174
- echo "Use 'hug fork --force' to fork anyway." >&2
186
+ echo "Use 'hug fork --force' to fork anyway, or '--detach' to fork and" >&2
187
+ echo "save the container ID to config.js as CONTAINER_ID." >&2
175
188
  return 1
176
189
  fi
177
190
 
@@ -183,10 +196,30 @@ cmd_fork() {
183
196
 
184
197
  echo "Creating new Apps Script project '$title'..."
185
198
  rm -f .clasp.json
199
+ # Preserve appsscript.json because clasp create overwrites it with server defaults
200
+ local saved_manifest=""
201
+ if [ -f appsscript.json ]; then
202
+ saved_manifest=$(cat appsscript.json)
203
+ fi
186
204
  run_clasp "$clasp" create --type standalone --title "$title"
205
+ if [ -n "$saved_manifest" ]; then
206
+ echo "$saved_manifest" > appsscript.json
207
+ fi
187
208
 
188
209
  echo "Pushing code to new project..."
189
- run_clasp "$clasp" push
210
+ run_clasp "$clasp" push --force
211
+
212
+ # If detaching, save the original container ID to config
213
+ if [ "$detach" = true ] && [ -n "$parent_id" ]; then
214
+ local existing=""
215
+ if [ -f config.js ]; then
216
+ existing=$(_read_config)
217
+ fi
218
+ existing=$(echo "$existing" | grep -v "^CONTAINER_ID=" || true)
219
+ { printf '%s\nCONTAINER_ID=%s\n' "$existing" "$parent_id" | grep -v '^$' || true; } | _write_config
220
+ echo "Set CONTAINER_ID=$parent_id in config.js."
221
+ echo "Push will include config.js. Use SpreadsheetApp.openById(CONFIG.CONTAINER_ID) etc."
222
+ fi
190
223
 
191
224
  echo ""
192
225
  echo "Fork complete. This directory now points to a new Apps Script project."
package/lib/common.sh CHANGED
@@ -43,6 +43,41 @@ run_clasp() {
43
43
  return $exit_code
44
44
  }
45
45
 
46
+ # If the project is container-bound, patch parentId into .clasp.json
47
+ patch_parent_id() {
48
+ local script_id
49
+ script_id=$(grep '"scriptId"' .clasp.json | sed 's/.*"scriptId"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
50
+ if [ -z "$script_id" ]; then
51
+ return
52
+ fi
53
+
54
+ local token
55
+ token=$(sed -n 's/.*"access_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' ~/.clasprc.json 2>/dev/null)
56
+ if [ -z "$token" ]; then
57
+ return
58
+ fi
59
+
60
+ local response
61
+ response=$(curl -sf -H "Authorization: Bearer $token" \
62
+ "https://script.googleapis.com/v1/projects/$script_id" 2>/dev/null) || return 0
63
+
64
+ local parent_id
65
+ parent_id=$(echo "$response" | sed -n 's/.*"parentId"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
66
+ if [ -z "$parent_id" ]; then
67
+ return
68
+ fi
69
+
70
+ # Already has parentId
71
+ if grep -q '"parentId"' .clasp.json 2>/dev/null; then
72
+ return
73
+ fi
74
+
75
+ # Inject parentId into .clasp.json before the closing brace
76
+ local tmp
77
+ tmp=$(mktemp)
78
+ sed '$s/}$/,"parentId":"'"$parent_id"'"}/' .clasp.json > "$tmp" && mv "$tmp" .clasp.json
79
+ }
80
+
46
81
  # Resolve the hug package root (where templates/ lives)
47
82
  hug_root() {
48
83
  local source="${BASH_SOURCE[0]}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peterseibel/hug",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "A wrapper around clasp for managing Google Apps Script projects",
5
5
  "bin": {
6
6
  "hug": "bin/hug"