checkpoint-cli 1.0.1 → 1.0.3

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/dist/index.js CHANGED
@@ -12,6 +12,8 @@ const chalk_1 = __importDefault(require("chalk"));
12
12
  const supabase_js_1 = require("@supabase/supabase-js");
13
13
  const config_js_1 = require("./config.js");
14
14
  const tracking_script_minimal_js_1 = require("./tracking-script-minimal.js");
15
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
16
+ const { version: cliVersion } = require('../package.json');
15
17
  /* ── Authenticated Supabase Client ── */
16
18
  function getSupabase() {
17
19
  const config = (0, config_js_1.loadConfig)();
@@ -104,10 +106,33 @@ async function getAuthenticatedClient() {
104
106
  }
105
107
  /* ── Injection Proxy ── */
106
108
  function startInjectionProxy(targetPort) {
107
- const scriptBody = (0, tracking_script_minimal_js_1.buildMinimalTrackingScript)().replace(/<\/script/gi, '<\\/script');
108
- const SCRIPT = `<script data-checkpoint-script="minimal-v1">\n${scriptBody}\n</script>`;
109
+ const AGENT_PATH = '/__checkpoint/agent.min.js';
110
+ const agentScript = (0, tracking_script_minimal_js_1.buildMinimalTrackingScript)();
111
+ const extractNonce = (html) => {
112
+ const nonceMatch = html.match(/<script\b[^>]*\bnonce=(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i);
113
+ return nonceMatch?.[1] ?? nonceMatch?.[2] ?? nonceMatch?.[3] ?? null;
114
+ };
115
+ const buildInjectionTag = (html) => {
116
+ const nonce = extractNonce(html);
117
+ const nonceAttr = nonce ? ` nonce="${nonce.replace(/"/g, '&quot;')}"` : '';
118
+ return `<script data-checkpoint-script="minimal-v1" src="${AGENT_PATH}"${nonceAttr} defer></script>`;
119
+ };
109
120
  return new Promise((resolve, reject) => {
110
121
  const server = http_1.default.createServer((req, res) => {
122
+ const pathname = new URL(req.url || '/', 'http://checkpoint.local').pathname;
123
+ if (pathname === AGENT_PATH) {
124
+ res.writeHead(200, {
125
+ 'content-type': 'application/javascript; charset=utf-8',
126
+ 'cache-control': 'no-store, max-age=0',
127
+ 'x-content-type-options': 'nosniff',
128
+ });
129
+ if (req.method === 'HEAD') {
130
+ res.end();
131
+ return;
132
+ }
133
+ res.end(agentScript);
134
+ return;
135
+ }
111
136
  const fwdHeaders = { ...req.headers, host: `localhost:${targetPort}` };
112
137
  delete fwdHeaders['accept-encoding'];
113
138
  const proxyReq = http_1.default.request({
@@ -128,15 +153,16 @@ function startInjectionProxy(targetPort) {
128
153
  proxyRes.on('data', (chunk) => chunks.push(chunk));
129
154
  proxyRes.on('end', () => {
130
155
  let body = Buffer.concat(chunks).toString('utf-8');
156
+ const scriptTag = buildInjectionTag(body);
131
157
  if (!body.includes('data-checkpoint-script="minimal-v1"')) {
132
158
  if (body.includes('</head>')) {
133
- body = body.replace('</head>', () => SCRIPT + '\n</head>');
159
+ body = body.replace('</head>', () => scriptTag + '\n</head>');
134
160
  }
135
161
  else if (body.includes('</body>')) {
136
- body = body.replace('</body>', () => SCRIPT + '\n</body>');
162
+ body = body.replace('</body>', () => scriptTag + '\n</body>');
137
163
  }
138
164
  else {
139
- body += SCRIPT;
165
+ body += scriptTag;
140
166
  }
141
167
  }
142
168
  const headers = { ...proxyRes.headers };
@@ -555,7 +581,7 @@ const program = new commander_1.Command();
555
581
  program
556
582
  .name('checkpoint')
557
583
  .description('Share your localhost with reviewers — get visual feedback directly on the page.\n\nQuick start:\n 1. checkpoint login Sign in to your Checkpoint account\n 2. checkpoint start -p 3000 Start tunneling and get a share link\n\nReuse a tunnel name to keep the same share URL and preserve all comments.')
558
- .version('0.5.2');
584
+ .version(cliVersion);
559
585
  // ── checkpoint login ──
560
586
  program
561
587
  .command('login')
@@ -18,6 +18,23 @@ function buildMinimalTrackingScript() {
18
18
  var lastPath='';
19
19
  var mutationTick=false;
20
20
  var pendingPickCommit=false;
21
+ var parentTargetOrigin='*';
22
+
23
+ function initParentOrigin(){
24
+ try{
25
+ if(!document.referrer) return;
26
+ var parsed=new URL(document.referrer);
27
+ if(parsed.protocol==='http:'||parsed.protocol==='https:') parentTargetOrigin=parsed.origin;
28
+ }catch(e){}
29
+ }
30
+
31
+ function postToParent(payload){
32
+ try{
33
+ window.parent.postMessage(payload,parentTargetOrigin);
34
+ return;
35
+ }catch(e){}
36
+ try{ window.parent.postMessage(payload,'*'); }catch(e){}
37
+ }
21
38
 
22
39
  function getMetrics(){
23
40
  var de=document.documentElement;
@@ -31,6 +48,27 @@ function buildMinimalTrackingScript() {
31
48
  };
32
49
  }
33
50
 
51
+ function reportReady(){
52
+ try{
53
+ postToParent({
54
+ type:'checkpoint:ready',
55
+ path:location.pathname+location.search+location.hash,
56
+ version:'minimal-v1',
57
+ capabilities:{ pickMode:true, resolveAnchors:true, sourceAnchors:true }
58
+ });
59
+ }catch(e){}
60
+ }
61
+
62
+ function reportDiagnostic(code,detail){
63
+ try{
64
+ postToParent({
65
+ type:'checkpoint:diagnostic',
66
+ code:code||'unknown',
67
+ detail:detail||''
68
+ });
69
+ }catch(e){}
70
+ }
71
+
34
72
  function clampPercent(v){
35
73
  if(v<0) return 0;
36
74
  if(v>100) return 100;
@@ -732,7 +770,7 @@ inspectBox.style.border='2px solid #F26522';
732
770
 
733
771
  function postPickResult(target,clientX,clientY){
734
772
  var payload=buildAnchorPayload(target,clientX,clientY);
735
- window.parent.postMessage({
773
+ postToParent({
736
774
  type:'checkpoint:pickResult',
737
775
  path:location.pathname+location.search+location.hash,
738
776
  anchorPayload:payload,
@@ -742,7 +780,7 @@ inspectBox.style.border='2px solid #F26522';
742
780
  scrollY:payload.coord_fallback&&typeof payload.coord_fallback.scroll_y==='number'?payload.coord_fallback.scroll_y:0,
743
781
  viewHeight:payload.coord_fallback&&typeof payload.coord_fallback.viewport_height==='number'?payload.coord_fallback.viewport_height:0
744
782
  }
745
- },'*');
783
+ });
746
784
  }
747
785
 
748
786
  function setPickMode(enabled){
@@ -854,7 +892,7 @@ inspectBox.style.border='2px solid #F26522';
854
892
  function reportScroll(){
855
893
  try{
856
894
  var m=getMetrics();
857
- window.parent.postMessage({
895
+ postToParent({
858
896
  type:'checkpoint:scroll',
859
897
  scrollX:m.scrollX,
860
898
  scrollY:m.scrollY,
@@ -862,7 +900,7 @@ inspectBox.style.border='2px solid #F26522';
862
900
  docHeight:m.docHeight,
863
901
  viewWidth:m.viewWidth,
864
902
  viewHeight:m.viewHeight
865
- },'*');
903
+ });
866
904
  }catch(e){}
867
905
  }
868
906
 
@@ -871,7 +909,7 @@ inspectBox.style.border='2px solid #F26522';
871
909
  var p=location.pathname+location.search+location.hash;
872
910
  if(p===lastPath) return;
873
911
  lastPath=p;
874
- window.parent.postMessage({ type:'checkpoint:navigate', path:p },'*');
912
+ postToParent({ type:'checkpoint:navigate', path:p });
875
913
  reportScroll();
876
914
  }catch(e){}
877
915
  }
@@ -881,11 +919,11 @@ inspectBox.style.border='2px solid #F26522';
881
919
  mutationTick=true;
882
920
  requestAnimationFrame(function(){
883
921
  mutationTick=false;
884
- window.parent.postMessage({
922
+ postToParent({
885
923
  type:'checkpoint:domMutation',
886
924
  reason:'mutation',
887
925
  path:location.pathname+location.search+location.hash
888
- },'*');
926
+ });
889
927
  });
890
928
  }
891
929
 
@@ -895,9 +933,13 @@ inspectBox.style.border='2px solid #F26522';
895
933
  var observer=new MutationObserver(function(){ reportDomMutation(); });
896
934
  observer.observe(document.documentElement,{ childList:true, subtree:true, attributes:true });
897
935
  window.addEventListener('beforeunload',function(){ try{observer.disconnect();}catch(e){}; });
898
- }catch(e){}
936
+ }catch(e){
937
+ reportDiagnostic('mutation_observer_failed',String(e&&e.message?e.message:e));
938
+ }
899
939
  }
900
940
 
941
+ initParentOrigin();
942
+ reportReady();
901
943
  reportNav();
902
944
  reportScroll();
903
945
  setupMutationObserver();
@@ -912,6 +954,7 @@ inspectBox.style.border='2px solid #F26522';
912
954
 
913
955
  window.addEventListener('message',function(e){
914
956
  try{
957
+ if(e.source!==window.parent) return;
915
958
  var d=e.data;
916
959
  if(!d||typeof d!=='object') return;
917
960
  if(d.type==='checkpoint:scrollTo'&&typeof d.y==='number'){
@@ -937,11 +980,11 @@ inspectBox.style.border='2px solid #F26522';
937
980
  coordFallback:result.coordFallback||null
938
981
  });
939
982
  }
940
- window.parent.postMessage({
983
+ postToParent({
941
984
  type:'checkpoint:anchorsResolved',
942
985
  path:location.pathname+location.search+location.hash,
943
986
  positions:positions
944
- },'*');
987
+ });
945
988
  }
946
989
  }catch(ex){}
947
990
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "checkpoint-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Share your localhost with reviewers — get visual feedback directly on the page",
5
5
  "keywords": [
6
6
  "checkpoint",