@specific.dev/cli 0.1.92 → 0.1.93

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/dist/admin/404/index.html +1 -1
  2. package/dist/admin/404.html +1 -1
  3. package/dist/admin/__next.!KGRlZmF1bHQp.__PAGE__.txt +2 -2
  4. package/dist/admin/__next.!KGRlZmF1bHQp.txt +5 -5
  5. package/dist/admin/__next._full.txt +8 -8
  6. package/dist/admin/__next._head.txt +1 -1
  7. package/dist/admin/__next._index.txt +3 -3
  8. package/dist/admin/__next._tree.txt +1 -1
  9. package/dist/admin/_next/static/chunks/42de6b5004222d9f.js +1 -0
  10. package/dist/admin/_next/static/chunks/{091449dbc4d3eb97.js → df799a08b7ff15f9.js} +2 -2
  11. package/dist/admin/_not-found/__next._full.txt +3 -3
  12. package/dist/admin/_not-found/__next._head.txt +1 -1
  13. package/dist/admin/_not-found/__next._index.txt +3 -3
  14. package/dist/admin/_not-found/__next._not-found.__PAGE__.txt +1 -1
  15. package/dist/admin/_not-found/__next._not-found.txt +1 -1
  16. package/dist/admin/_not-found/__next._tree.txt +1 -1
  17. package/dist/admin/_not-found/index.html +1 -1
  18. package/dist/admin/_not-found/index.txt +3 -3
  19. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.__PAGE__.txt +2 -2
  20. package/dist/admin/databases/__next.!KGRlZmF1bHQp.databases.txt +1 -1
  21. package/dist/admin/databases/__next.!KGRlZmF1bHQp.txt +5 -5
  22. package/dist/admin/databases/__next._full.txt +8 -8
  23. package/dist/admin/databases/__next._head.txt +1 -1
  24. package/dist/admin/databases/__next._index.txt +3 -3
  25. package/dist/admin/databases/__next._tree.txt +1 -1
  26. package/dist/admin/databases/index.html +1 -1
  27. package/dist/admin/databases/index.txt +8 -8
  28. package/dist/admin/fullscreen/__next._full.txt +4 -4
  29. package/dist/admin/fullscreen/__next._head.txt +1 -1
  30. package/dist/admin/fullscreen/__next._index.txt +3 -3
  31. package/dist/admin/fullscreen/__next._tree.txt +1 -1
  32. package/dist/admin/fullscreen/__next.fullscreen.__PAGE__.txt +2 -2
  33. package/dist/admin/fullscreen/__next.fullscreen.txt +1 -1
  34. package/dist/admin/fullscreen/databases/__next._full.txt +4 -4
  35. package/dist/admin/fullscreen/databases/__next._head.txt +1 -1
  36. package/dist/admin/fullscreen/databases/__next._index.txt +3 -3
  37. package/dist/admin/fullscreen/databases/__next._tree.txt +1 -1
  38. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.__PAGE__.txt +2 -2
  39. package/dist/admin/fullscreen/databases/__next.fullscreen.databases.txt +1 -1
  40. package/dist/admin/fullscreen/databases/__next.fullscreen.txt +1 -1
  41. package/dist/admin/fullscreen/databases/index.html +1 -1
  42. package/dist/admin/fullscreen/databases/index.txt +4 -4
  43. package/dist/admin/fullscreen/index.html +1 -1
  44. package/dist/admin/fullscreen/index.txt +4 -4
  45. package/dist/admin/index.html +1 -1
  46. package/dist/admin/index.txt +8 -8
  47. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.__PAGE__.txt +2 -2
  48. package/dist/admin/mail/__next.!KGRlZmF1bHQp.mail.txt +1 -1
  49. package/dist/admin/mail/__next.!KGRlZmF1bHQp.txt +5 -5
  50. package/dist/admin/mail/__next._full.txt +8 -8
  51. package/dist/admin/mail/__next._head.txt +1 -1
  52. package/dist/admin/mail/__next._index.txt +3 -3
  53. package/dist/admin/mail/__next._tree.txt +1 -1
  54. package/dist/admin/mail/index.html +1 -1
  55. package/dist/admin/mail/index.txt +8 -8
  56. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.txt +5 -5
  57. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.__PAGE__.txt +2 -2
  58. package/dist/admin/workflows/__next.!KGRlZmF1bHQp.workflows.txt +1 -1
  59. package/dist/admin/workflows/__next._full.txt +8 -8
  60. package/dist/admin/workflows/__next._head.txt +1 -1
  61. package/dist/admin/workflows/__next._index.txt +3 -3
  62. package/dist/admin/workflows/__next._tree.txt +1 -1
  63. package/dist/admin/workflows/index.html +1 -1
  64. package/dist/admin/workflows/index.txt +8 -8
  65. package/dist/cli.js +489 -2062
  66. package/dist/docs/services.md +49 -5
  67. package/package.json +1 -2
  68. package/dist/admin/_next/static/chunks/153355cea359ee0f.js +0 -1
  69. package/dist/postinstall.js +0 -182912
  70. /package/dist/admin/_next/static/{b7lxofBl6HLcSJDobJJzv → bHtcCLWKGqkBj4NJ2_XcY}/_buildManifest.js +0 -0
  71. /package/dist/admin/_next/static/{b7lxofBl6HLcSJDobJJzv → bHtcCLWKGqkBj4NJ2_XcY}/_clientMiddlewareManifest.json +0 -0
  72. /package/dist/admin/_next/static/{b7lxofBl6HLcSJDobJJzv → bHtcCLWKGqkBj4NJ2_XcY}/_ssgManifest.js +0 -0
@@ -22,7 +22,13 @@ service "web" {
22
22
 
23
23
  env = {
24
24
  PORT = port
25
- API_URL = service.api.public_url
25
+ API_URL = "https://${service.api.public_url}"
26
+ }
27
+
28
+ dev {
29
+ env = {
30
+ API_URL = "http://${service.api.public_url}"
31
+ }
26
32
  }
27
33
  }
28
34
 
@@ -143,10 +149,34 @@ service "worker" {
143
149
 
144
150
  Available service reference attributes:
145
151
 
146
- - `service.<name>.private_url` - Internal URL without scheme (host and port)
152
+ - `service.<name>.private_url` - Internal URL without scheme (e.g., `localhost:3001`). Does NOT include `http://` or `https://`.
147
153
  - `service.<name>.host` - Host only (e.g., `localhost`)
148
- - `service.<name>.port` - Port only (e.g., `3000`)
149
- - `service.<name>.public_url` - Public URL without scheme (host and port). Only available for endpoints with `public = true`. Served over HTTPS.
154
+ - `service.<name>.port` - Port only (e.g., `3001`)
155
+ - `service.<name>.public_url` - Public URL without scheme (e.g., `my-app.specific.app` in production, `localhost:3001` in dev). Does NOT include `http://` or `https://`. Only available for endpoints with `public = true`.
156
+
157
+ **Important:** `public_url` and `private_url` do NOT include a scheme. In production, services are served over HTTPS. In local development, services use plain HTTP. When you need to construct a full URL, use string interpolation with the correct scheme for each environment. Use the `dev { env = {} }` block to override with `http://` locally:
158
+
159
+ ```hcl
160
+ service "web" {
161
+ build = build.web
162
+ command = "npm start"
163
+
164
+ endpoint {
165
+ public = true
166
+ }
167
+
168
+ env = {
169
+ PORT = port
170
+ API_URL = "https://${service.api.public_url}"
171
+ }
172
+
173
+ dev {
174
+ env = {
175
+ API_URL = "http://${service.api.public_url}"
176
+ }
177
+ }
178
+ }
179
+ ```
150
180
 
151
181
  For services with multiple named endpoints, you must specify the endpoint:
152
182
 
@@ -186,7 +216,13 @@ service "api" {
186
216
 
187
217
  env = {
188
218
  PORT = port
189
- CORS_ORIGIN = service.web.public_url
219
+ CORS_ORIGIN = "https://${service.web.public_url}"
220
+ }
221
+
222
+ dev {
223
+ env = {
224
+ CORS_ORIGIN = "http://${service.web.public_url}"
225
+ }
190
226
  }
191
227
  }
192
228
  ```
@@ -315,11 +351,19 @@ service "worker" {
315
351
  CUSTOM_DB = "host=${postgres.main.host} port=${postgres.main.port}"
316
352
  PUBLIC_API = "https://${service.api.public_url}/v1"
317
353
  }
354
+
355
+ dev {
356
+ env = {
357
+ PUBLIC_API = "http://${service.api.public_url}/v1"
358
+ }
359
+ }
318
360
  }
319
361
  ```
320
362
 
321
363
  All resource references (services, postgres, redis, storage, port, endpoint) can be used inside interpolated strings. Secret and config references cannot be interpolated — they must be used as standalone values.
322
364
 
365
+ Since `public_url` and `private_url` do not include a scheme, you should use `https://` in the top-level `env` (for production) and override with `http://` in the `dev { env = {} }` block (for local development). The `dev` env block is merged with the top-level env, so you only need to override the variables that differ.
366
+
323
367
  ## Service dev configuration
324
368
 
325
369
  Override how a service runs in development. If the referenced build has no `dev` block, it is skipped.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specific.dev/cli",
3
- "version": "0.1.92",
3
+ "version": "0.1.93",
4
4
  "description": "CLI for Specific infrastructure-as-code",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",
@@ -17,7 +17,6 @@
17
17
  "link:dev": "npm run build:dev && npm link",
18
18
  "link:staging": "npm run build:staging && npm link",
19
19
  "link:prod": "npm run build && npm link",
20
- "postinstall": "node dist/postinstall.js || true",
21
20
  "build:binary": "npx tsx scripts/build-binary.ts"
22
21
  },
23
22
  "keywords": [
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,12283,35014,e=>{"use strict";var t=e.i(90795),r=e.i(59369);function o(){let e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e}function n(){let e=window.location.hostname,t=".spcf.localhost";if("localhost"===e||"127.0.0.1"===e||"spcf.localhost"===e)return"default";if(e.endsWith(t)){let r=e.slice(0,-t.length);if(r&&!r.includes("."))return r}return null}function s(e,t){return o()&&t?`http://localhost:${t}`:"default"===e?"https://__drizzle_gateway.spcf.localhost":`https://__drizzle_gateway.${e}.spcf.localhost`}function a(e,t){return o()&&t?`http://localhost:${t}`:"default"===e?"https://__temporal.spcf.localhost":`https://__temporal.${e}.spcf.localhost`}e.s(["getDrizzleGatewayUrl",()=>s,"getInstanceKey",()=>n,"getTemporalUiUrl",()=>a],35014);let l=(0,r.createContext)(void 0);function i({children:e}){let[o,i]=(0,r.useState)(null),[c,u]=(0,r.useState)(null),[m,d]=(0,r.useState)(!1),h=(0,r.useMemo)(()=>n(),[]);(0,r.useEffect)(()=>{async function e(){try{let e=await fetch("/api/state");if(!e.ok)throw Error("Failed to fetch state");let t=await e.json();i(t),d(!0),u(null)}catch(e){e instanceof TypeError&&"Failed to fetch"===e.message?u("specific dev is not running. Restart it to reconnect."):u(e instanceof Error?e.message:"Unknown error"),d(!1)}}e();let t=setInterval(e,2e3);return()=>clearInterval(t)},[]);let f=o?.resources.some(e=>"postgres"===e.type)??!1,p=(0,r.useMemo)(()=>h?s(h,o?.drizzleGatewayPort):null,[h,o?.drizzleGatewayPort]),y=o?.hasTemporal??!1,v=(0,r.useMemo)(()=>h?a(h,o?.temporalUiPort):null,[h,o?.temporalUiPort]),g=o?.hasMail??!1,w=o?.mailApiUrl??null,T=o?.projectId??null,b=(0,r.useMemo)(()=>({state:o,error:c,connected:m,instanceKey:h,hasDatabases:f,drizzleGatewayUrl:p,hasTemporal:y,temporalUiUrl:v,hasMail:g,mailApiUrl:w,projectId:T}),[o,c,m,h,f,p,y,v,g,w,T]);return(0,t.jsx)(l.Provider,{value:b,children:e})}function c(){let e=(0,r.useContext)(l);if(void 0===e)throw Error("useDevState must be used within a DevStateProvider");return e}e.s(["DevStateProvider",()=>i,"useDevState",()=>c],12283)},70932,e=>{"use strict";var t=e.i(59369),r=(e,t,r,o,n,s,a,l)=>{let i=document.documentElement,c=["light","dark"];function u(t){var r;(Array.isArray(e)?e:[e]).forEach(e=>{let r="class"===e,o=r&&s?n.map(e=>s[e]||e):n;r?(i.classList.remove(...o),i.classList.add(s&&s[t]?s[t]:t)):i.setAttribute(e,t)}),r=t,l&&c.includes(r)&&(i.style.colorScheme=r)}if(o)u(o);else try{let e=localStorage.getItem(t)||r,o=a&&"system"===e?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;u(o)}catch(e){}},o=["light","dark"],n="(prefers-color-scheme: dark)",s="u"<typeof window,a=t.createContext(void 0),l={setTheme:e=>{},themes:[]},i=()=>{var e;return null!=(e=t.useContext(a))?e:l},c=e=>t.useContext(a)?t.createElement(t.Fragment,null,e.children):t.createElement(m,{...e}),u=["light","dark"],m=({forcedTheme:e,disableTransitionOnChange:r=!1,enableSystem:s=!0,enableColorScheme:l=!0,storageKey:i="theme",themes:c=u,defaultTheme:m=s?"system":"light",attribute:y="data-theme",value:v,children:g,nonce:w,scriptProps:T})=>{let[b,S]=t.useState(()=>h(i,m)),[E,C]=t.useState(()=>"system"===b?p():b),P=v?Object.values(v):c,k=t.useCallback(e=>{let t=e;if(!t)return;"system"===e&&s&&(t=p());let n=v?v[t]:t,a=r?f(w):null,i=document.documentElement,c=e=>{"class"===e?(i.classList.remove(...P),n&&i.classList.add(n)):e.startsWith("data-")&&(n?i.setAttribute(e,n):i.removeAttribute(e))};if(Array.isArray(y)?y.forEach(c):c(y),l){let e=o.includes(m)?m:null,r=o.includes(t)?t:e;i.style.colorScheme=r}null==a||a()},[w]),_=t.useCallback(e=>{let t="function"==typeof e?e(b):e;S(t);try{localStorage.setItem(i,t)}catch(e){}},[b]),z=t.useCallback(t=>{C(p(t)),"system"===b&&s&&!e&&k("system")},[b,e]);t.useEffect(()=>{let e=window.matchMedia(n);return e.addListener(z),z(e),()=>e.removeListener(z)},[z]),t.useEffect(()=>{let e=e=>{e.key===i&&(e.newValue?S(e.newValue):_(m))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[_]),t.useEffect(()=>{k(null!=e?e:b)},[e,b]);let A=t.useMemo(()=>({theme:b,setTheme:_,forcedTheme:e,resolvedTheme:"system"===b?E:b,themes:s?[...c,"system"]:c,systemTheme:s?E:void 0}),[b,_,e,E,s,c]);return t.createElement(a.Provider,{value:A},t.createElement(d,{forcedTheme:e,storageKey:i,attribute:y,enableSystem:s,enableColorScheme:l,defaultTheme:m,value:v,themes:c,nonce:w,scriptProps:T}),g)},d=t.memo(({forcedTheme:e,storageKey:o,attribute:n,enableSystem:s,enableColorScheme:a,defaultTheme:l,value:i,themes:c,nonce:u,scriptProps:m})=>{let d=JSON.stringify([n,o,l,e,c,i,s,a]).slice(1,-1);return t.createElement("script",{...m,suppressHydrationWarning:!0,nonce:"u"<typeof window?u:"",dangerouslySetInnerHTML:{__html:`(${r.toString()})(${d})`}})}),h=(e,t)=>{let r;if(!s){try{r=localStorage.getItem(e)||void 0}catch(e){}return r||t}},f=e=>{let t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(t),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(t)},1)}},p=e=>(e||(e=window.matchMedia(n)),e.matches?"dark":"light");e.s(["ThemeProvider",()=>c,"useTheme",()=>i])},49311,e=>{"use strict";var t=e.i(90795),r=e.i(70932);function o({children:e,...o}){return(0,t.jsx)(r.ThemeProvider,{...o,children:e})}e.s(["ThemeProvider",()=>o])}]);