percher 1.2.0 → 1.3.0

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.
@@ -4850,7 +4850,7 @@ var package_default;
4850
4850
  var init_package = __esm(() => {
4851
4851
  package_default = {
4852
4852
  name: "@percher/client",
4853
- version: "1.2.0",
4853
+ version: "1.3.0",
4854
4854
  description: "Official TypeScript SDK for Percher: deploy apps, manage env vars, stream logs, and automate hosting workflows.",
4855
4855
  keywords: [
4856
4856
  "percher",
@@ -4891,7 +4891,7 @@ var init_package = __esm(() => {
4891
4891
  typecheck: "tsc --noEmit"
4892
4892
  },
4893
4893
  dependencies: {
4894
- "@percher/toml": "^1.0.3"
4894
+ "@percher/toml": "^1.0.4"
4895
4895
  },
4896
4896
  devDependencies: {
4897
4897
  "bun-types": "^1.1.0",
@@ -5663,6 +5663,58 @@ class BillingResource {
5663
5663
  }
5664
5664
  }
5665
5665
 
5666
+ // ../client/dist/resources/data-records.js
5667
+ function dataPathSegment(kind, value) {
5668
+ const re = kind === "collection" ? COLLECTION_RE : RECORD_ID_RE;
5669
+ if (!re.test(value))
5670
+ throw new TypeError(`invalid data ${kind}`);
5671
+ return encodeURIComponent(value);
5672
+ }
5673
+ function outcomeUnknown(cause, observed) {
5674
+ const answered = cause instanceof PercherApiError;
5675
+ return new PercherApiError(OUTCOME_UNKNOWN_MESSAGE, {
5676
+ status: answered ? cause.status : 0,
5677
+ code: "DATA_WRITE_OUTCOME_UNKNOWN",
5678
+ requestId: answered ? cause.requestId : undefined,
5679
+ cause,
5680
+ extra: { observed }
5681
+ });
5682
+ }
5683
+ function isRecordReply(reply) {
5684
+ return typeof reply === "object" && reply !== null && !Array.isArray(reply) && typeof reply.id === "string" && reply.id.length > 0;
5685
+ }
5686
+ function isDeleteReply(reply) {
5687
+ return reply === undefined || typeof reply === "object" && reply !== null && !Array.isArray(reply);
5688
+ }
5689
+ async function writeOnce(run, usable) {
5690
+ let reply;
5691
+ try {
5692
+ reply = await run();
5693
+ } catch (err) {
5694
+ if (err instanceof SunsetError)
5695
+ throw err;
5696
+ if (err instanceof PercherApiError) {
5697
+ if (err.code === "DATA_WRITE_OUTCOME_UNKNOWN")
5698
+ throw err;
5699
+ if (err.status >= 400 && err.status < 500)
5700
+ throw err;
5701
+ if (err.status >= 500 && WRITE_NOT_SENT.has(err.code))
5702
+ throw err;
5703
+ }
5704
+ throw outcomeUnknown(err, err instanceof PercherApiError ? "error_response" : "no_usable_response");
5705
+ }
5706
+ if (!usable(reply))
5707
+ throw outcomeUnknown(undefined, "unusable_reply");
5708
+ return reply;
5709
+ }
5710
+ var COLLECTION_RE, RECORD_ID_RE, WRITE_NOT_SENT, OUTCOME_UNKNOWN_MESSAGE = "No usable answer arrived for this write, so it may or may not have been saved.";
5711
+ var init_data_records = __esm(() => {
5712
+ init_errors();
5713
+ COLLECTION_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
5714
+ RECORD_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
5715
+ WRITE_NOT_SENT = new Set(["PB_NOT_RUNNING", "PB_AUTH_FAILED", "PB_VERSION_UNSUPPORTED"]);
5716
+ });
5717
+
5666
5718
  // ../client/dist/resources/data.js
5667
5719
  class DataResource {
5668
5720
  http;
@@ -5699,7 +5751,37 @@ class DataResource {
5699
5751
  removeOAuthProvider(appRef, provider) {
5700
5752
  return this.http.delete(`/apps/${encodeURIComponent(appRef)}/data/oauth/${encodeURIComponent(provider)}`);
5701
5753
  }
5754
+ getSchema(appRef) {
5755
+ return this.http.get(`/apps/${encodeURIComponent(appRef)}/data/schema`);
5756
+ }
5757
+ queryRecords(appRef, collection, query = {}) {
5758
+ return this.http.post(`${this.records(appRef, collection)}/query`, query);
5759
+ }
5760
+ getRecord(appRef, collection, id) {
5761
+ return this.http.get(this.record(appRef, collection, id));
5762
+ }
5763
+ createRecord(appRef, collection, input) {
5764
+ const path = this.records(appRef, collection);
5765
+ return writeOnce(() => this.http.post(path, input), isRecordReply);
5766
+ }
5767
+ updateRecord(appRef, collection, id, input) {
5768
+ const path = this.record(appRef, collection, id);
5769
+ return writeOnce(() => this.http.patch(path, input), isRecordReply);
5770
+ }
5771
+ async deleteRecord(appRef, collection, id) {
5772
+ const path = this.record(appRef, collection, id);
5773
+ await writeOnce(() => this.http.deleteJson(path), isDeleteReply);
5774
+ }
5775
+ records(appRef, collection) {
5776
+ return `/apps/${encodeURIComponent(appRef)}/data/collections/${dataPathSegment("collection", collection)}/records`;
5777
+ }
5778
+ record(appRef, collection, id) {
5779
+ return `${this.records(appRef, collection)}/${dataPathSegment("id", id)}`;
5780
+ }
5702
5781
  }
5782
+ var init_data = __esm(() => {
5783
+ init_data_records();
5784
+ });
5703
5785
 
5704
5786
  // ../client/dist/resources/env.js
5705
5787
  function scopeQuery(opts) {
@@ -6163,6 +6245,7 @@ var init_client = __esm(() => {
6163
6245
  init_http();
6164
6246
  init_apps();
6165
6247
  init_auth();
6248
+ init_data();
6166
6249
  init_logs();
6167
6250
  });
6168
6251
 
@@ -6341,6 +6424,7 @@ var init_dist = __esm(() => {
6341
6424
  init_errors();
6342
6425
  init_apps();
6343
6426
  init_auth();
6427
+ init_data();
6344
6428
  init_logs();
6345
6429
  init_telemetry_consent();
6346
6430
  });
@@ -6789,19 +6873,19 @@ var require_tslib = __commonJS((exports, module) => {
6789
6873
  }
6790
6874
  return t;
6791
6875
  };
6792
- __decorate = function(decorators, target, key, desc) {
6793
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
6876
+ __decorate = function(decorators, target2, key, desc) {
6877
+ var c = arguments.length, r = c < 3 ? target2 : desc === null ? desc = Object.getOwnPropertyDescriptor(target2, key) : desc, d;
6794
6878
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
6795
- r = Reflect.decorate(decorators, target, key, desc);
6879
+ r = Reflect.decorate(decorators, target2, key, desc);
6796
6880
  else
6797
6881
  for (var i = decorators.length - 1;i >= 0; i--)
6798
6882
  if (d = decorators[i])
6799
- r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6800
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6883
+ r = (c < 3 ? d(r) : c > 3 ? d(target2, key, r) : d(target2, key)) || r;
6884
+ return c > 3 && r && Object.defineProperty(target2, key, r), r;
6801
6885
  };
6802
6886
  __param = function(paramIndex, decorator) {
6803
- return function(target, key) {
6804
- decorator(target, key, paramIndex);
6887
+ return function(target2, key) {
6888
+ decorator(target2, key, paramIndex);
6805
6889
  };
6806
6890
  };
6807
6891
  __esDecorate = function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
@@ -6811,8 +6895,8 @@ var require_tslib = __commonJS((exports, module) => {
6811
6895
  return f;
6812
6896
  }
6813
6897
  var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
6814
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6815
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6898
+ var target2 = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6899
+ var descriptor = descriptorIn || (target2 ? Object.getOwnPropertyDescriptor(target2, contextIn.name) : {});
6816
6900
  var _, done = false;
6817
6901
  for (var i = decorators.length - 1;i >= 0; i--) {
6818
6902
  var context = {};
@@ -6844,8 +6928,8 @@ var require_tslib = __commonJS((exports, module) => {
6844
6928
  descriptor[key] = _;
6845
6929
  }
6846
6930
  }
6847
- if (target)
6848
- Object.defineProperty(target, contextIn.name, descriptor);
6931
+ if (target2)
6932
+ Object.defineProperty(target2, contextIn.name, descriptor);
6849
6933
  done = true;
6850
6934
  };
6851
6935
  __runInitializers = function(thisArg, initializers, value) {
@@ -9022,13 +9106,13 @@ var require_path_visitor = __commonJS((exports, module) => {
9022
9106
  isFunction.assert(Visitor.visit);
9023
9107
  return new Visitor;
9024
9108
  };
9025
- function extend2(target, source) {
9109
+ function extend2(target2, source) {
9026
9110
  for (var property in source) {
9027
9111
  if (hasOwn.call(source, property)) {
9028
- target[property] = source[property];
9112
+ target2[property] = source[property];
9029
9113
  }
9030
9114
  }
9031
- return target;
9115
+ return target2;
9032
9116
  }
9033
9117
  PathVisitor.visit = function visit(node, methods) {
9034
9118
  return PathVisitor.fromMethodsObject(methods).visit(node);
@@ -12603,27 +12687,27 @@ var require_esprima2 = __commonJS((exports, module) => {
12603
12687
  };
12604
12688
  CommentHandler2.prototype.findLeadingComments = function(metadata) {
12605
12689
  var leadingComments = [];
12606
- var target;
12690
+ var target2;
12607
12691
  while (this.stack.length > 0) {
12608
12692
  var entry = this.stack[this.stack.length - 1];
12609
12693
  if (entry && entry.start >= metadata.start.offset) {
12610
- target = entry.node;
12694
+ target2 = entry.node;
12611
12695
  this.stack.pop();
12612
12696
  } else {
12613
12697
  break;
12614
12698
  }
12615
12699
  }
12616
- if (target) {
12617
- var count = target.leadingComments ? target.leadingComments.length : 0;
12700
+ if (target2) {
12701
+ var count = target2.leadingComments ? target2.leadingComments.length : 0;
12618
12702
  for (var i = count - 1;i >= 0; --i) {
12619
- var comment = target.leadingComments[i];
12703
+ var comment = target2.leadingComments[i];
12620
12704
  if (comment.range[1] <= metadata.start.offset) {
12621
12705
  leadingComments.unshift(comment);
12622
- target.leadingComments.splice(i, 1);
12706
+ target2.leadingComments.splice(i, 1);
12623
12707
  }
12624
12708
  }
12625
- if (target.leadingComments && target.leadingComments.length === 0) {
12626
- delete target.leadingComments;
12709
+ if (target2.leadingComments && target2.leadingComments.length === 0) {
12710
+ delete target2.leadingComments;
12627
12711
  }
12628
12712
  return leadingComments;
12629
12713
  }
@@ -13109,9 +13193,9 @@ var require_esprima2 = __commonJS((exports, module) => {
13109
13193
  if (this.match("}")) {
13110
13194
  this.tolerateError("JSX attributes must only be assigned a non-empty expression");
13111
13195
  }
13112
- var expression = this.parseAssignmentExpression();
13196
+ var expression2 = this.parseAssignmentExpression();
13113
13197
  this.reenterJSX();
13114
- return this.finalize(node, new JSXNode.JSXExpressionContainer(expression));
13198
+ return this.finalize(node, new JSXNode.JSXExpressionContainer(expression2));
13115
13199
  };
13116
13200
  JSXParser2.prototype.parseJSXAttributeValue = function() {
13117
13201
  return this.matchJSX("{") ? this.parseJSXExpressionAttribute() : this.matchJSX("<") ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute();
@@ -13184,16 +13268,16 @@ var require_esprima2 = __commonJS((exports, module) => {
13184
13268
  JSXParser2.prototype.parseJSXExpressionContainer = function() {
13185
13269
  var node = this.createJSXNode();
13186
13270
  this.expectJSX("{");
13187
- var expression;
13271
+ var expression2;
13188
13272
  if (this.matchJSX("}")) {
13189
- expression = this.parseJSXEmptyExpression();
13273
+ expression2 = this.parseJSXEmptyExpression();
13190
13274
  this.expectJSX("}");
13191
13275
  } else {
13192
13276
  this.finishJSX();
13193
- expression = this.parseAssignmentExpression();
13277
+ expression2 = this.parseAssignmentExpression();
13194
13278
  this.reenterJSX();
13195
13279
  }
13196
- return this.finalize(node, new JSXNode.JSXExpressionContainer(expression));
13280
+ return this.finalize(node, new JSXNode.JSXExpressionContainer(expression2));
13197
13281
  };
13198
13282
  JSXParser2.prototype.parseJSXChildren = function() {
13199
13283
  var children = [];
@@ -13339,9 +13423,9 @@ var require_esprima2 = __commonJS((exports, module) => {
13339
13423
  }();
13340
13424
  exports2.JSXEmptyExpression = JSXEmptyExpression;
13341
13425
  var JSXExpressionContainer = function() {
13342
- function JSXExpressionContainer2(expression) {
13426
+ function JSXExpressionContainer2(expression2) {
13343
13427
  this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer;
13344
- this.expression = expression;
13428
+ this.expression = expression2;
13345
13429
  }
13346
13430
  return JSXExpressionContainer2;
13347
13431
  }();
@@ -13445,13 +13529,13 @@ var require_esprima2 = __commonJS((exports, module) => {
13445
13529
  }();
13446
13530
  exports2.ArrayPattern = ArrayPattern;
13447
13531
  var ArrowFunctionExpression = function() {
13448
- function ArrowFunctionExpression2(params, body, expression) {
13532
+ function ArrowFunctionExpression2(params, body, expression2) {
13449
13533
  this.type = syntax_1.Syntax.ArrowFunctionExpression;
13450
13534
  this.id = null;
13451
13535
  this.params = params;
13452
13536
  this.body = body;
13453
13537
  this.generator = false;
13454
- this.expression = expression;
13538
+ this.expression = expression2;
13455
13539
  this.async = false;
13456
13540
  }
13457
13541
  return ArrowFunctionExpression2;
@@ -13477,13 +13561,13 @@ var require_esprima2 = __commonJS((exports, module) => {
13477
13561
  }();
13478
13562
  exports2.AssignmentPattern = AssignmentPattern;
13479
13563
  var AsyncArrowFunctionExpression = function() {
13480
- function AsyncArrowFunctionExpression2(params, body, expression) {
13564
+ function AsyncArrowFunctionExpression2(params, body, expression2) {
13481
13565
  this.type = syntax_1.Syntax.ArrowFunctionExpression;
13482
13566
  this.id = null;
13483
13567
  this.params = params;
13484
13568
  this.body = body;
13485
13569
  this.generator = false;
13486
- this.expression = expression;
13570
+ this.expression = expression2;
13487
13571
  this.async = true;
13488
13572
  }
13489
13573
  return AsyncArrowFunctionExpression2;
@@ -13632,9 +13716,9 @@ var require_esprima2 = __commonJS((exports, module) => {
13632
13716
  }();
13633
13717
  exports2.DebuggerStatement = DebuggerStatement;
13634
13718
  var Directive = function() {
13635
- function Directive2(expression, directive) {
13719
+ function Directive2(expression2, directive) {
13636
13720
  this.type = syntax_1.Syntax.ExpressionStatement;
13637
- this.expression = expression;
13721
+ this.expression = expression2;
13638
13722
  this.directive = directive;
13639
13723
  }
13640
13724
  return Directive2;
@@ -13692,9 +13776,9 @@ var require_esprima2 = __commonJS((exports, module) => {
13692
13776
  }();
13693
13777
  exports2.ExportSpecifier = ExportSpecifier;
13694
13778
  var ExpressionStatement = function() {
13695
- function ExpressionStatement2(expression) {
13779
+ function ExpressionStatement2(expression2) {
13696
13780
  this.type = syntax_1.Syntax.ExpressionStatement;
13697
- this.expression = expression;
13781
+ this.expression = expression2;
13698
13782
  }
13699
13783
  return ExpressionStatement2;
13700
13784
  }();
@@ -15428,14 +15512,14 @@ var require_esprima2 = __commonJS((exports, module) => {
15428
15512
  } else {
15429
15513
  body = this.isolateCoverGrammar(this.parseAssignmentExpression);
15430
15514
  }
15431
- var expression = body.type !== syntax_1.Syntax.BlockStatement;
15515
+ var expression2 = body.type !== syntax_1.Syntax.BlockStatement;
15432
15516
  if (this.context.strict && list.firstRestricted) {
15433
15517
  this.throwUnexpectedToken(list.firstRestricted, list.message);
15434
15518
  }
15435
15519
  if (this.context.strict && list.stricted) {
15436
15520
  this.tolerateUnexpectedToken(list.stricted, list.message);
15437
15521
  }
15438
- expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression));
15522
+ expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression2)) : this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression2));
15439
15523
  this.context.strict = previousStrict;
15440
15524
  this.context.allowStrictDirective = previousAllowStrictDirective;
15441
15525
  this.context.allowYield = previousAllowYield;
@@ -19985,7 +20069,7 @@ var require_fast_path = __commonJS((exports) => {
19985
20069
  }
19986
20070
  return s[0];
19987
20071
  };
19988
- FPp.call = function call(callback) {
20072
+ FPp.call = function call2(callback) {
19989
20073
  var s = this.stack;
19990
20074
  var origLen = s.length;
19991
20075
  var value = s[origLen - 1];
@@ -22228,8 +22312,8 @@ while`);
22228
22312
  return (0, lines_1.concat)([path.call(print, "left"), ".", path.call(print, "right")]);
22229
22313
  case "TSAsExpression":
22230
22314
  case "TSSatisfiesExpression": {
22231
- var expression = path.call(print, "expression");
22232
- parts.push(expression, n.type === "TSSatisfiesExpression" ? " satisfies " : " as ", path.call(print, "typeAnnotation"));
22315
+ var expression2 = path.call(print, "expression");
22316
+ parts.push(expression2, n.type === "TSSatisfiesExpression" ? " satisfies " : " as ", path.call(print, "typeAnnotation"));
22233
22317
  return (0, lines_1.concat)(parts);
22234
22318
  }
22235
22319
  case "TSTypeCastExpression":
@@ -23864,9 +23948,9 @@ var require_lib = __commonJS((exports) => {
23864
23948
  UnsupportedDefaultExport: "Only expressions, functions or classes are allowed as the `default` export.",
23865
23949
  UnsupportedImport: "`import` can only be used in `import()` or `import.meta`.",
23866
23950
  UnsupportedMetaProperty: ({
23867
- target,
23951
+ target: target2,
23868
23952
  onlyValidPropertyName
23869
- }) => `The only valid meta property for ${target} is ${target}.${onlyValidPropertyName}.`,
23953
+ }) => `The only valid meta property for ${target2} is ${target2}.${onlyValidPropertyName}.`,
23870
23954
  UnsupportedParameterDecorator: "Decorators cannot be used to decorate parameters.",
23871
23955
  UnsupportedPropertyDecorator: "Decorators cannot be used to decorate object literal properties.",
23872
23956
  UnsupportedSuper: "'super' can only be used with function calls (i.e. super()) or in property accesses (i.e. super.prop or super[prop]).",
@@ -24154,15 +24238,15 @@ var require_lib = __commonJS((exports) => {
24154
24238
  return this.finishNodeAt(chain, "ChainExpression", endLoc);
24155
24239
  }
24156
24240
  directiveToStmt(directive) {
24157
- const expression = directive.value;
24241
+ const expression2 = directive.value;
24158
24242
  delete directive.value;
24159
- this.castNodeTo(expression, "Literal");
24160
- expression.raw = expression.extra.raw;
24161
- expression.value = expression.extra.expressionValue;
24243
+ this.castNodeTo(expression2, "Literal");
24244
+ expression2.raw = expression2.extra.raw;
24245
+ expression2.value = expression2.extra.expressionValue;
24162
24246
  const stmt = this.castNodeTo(directive, "ExpressionStatement");
24163
- stmt.expression = expression;
24164
- stmt.directive = expression.extra.rawValue;
24165
- delete expression.extra;
24247
+ stmt.expression = expression2;
24248
+ stmt.directive = expression2.extra.rawValue;
24249
+ delete expression2.extra;
24166
24250
  return stmt;
24167
24251
  }
24168
24252
  fillOptionalPropertiesForTSESLint(node) {}
@@ -27113,14 +27197,14 @@ var require_lib = __commonJS((exports) => {
27113
27197
  this.resetEndLocation(decl.id);
27114
27198
  }
27115
27199
  }
27116
- parseAsyncArrowFromCallExpression(node, call) {
27200
+ parseAsyncArrowFromCallExpression(node, call2) {
27117
27201
  if (this.match(14)) {
27118
27202
  const oldNoAnonFunctionType = this.state.noAnonFunctionType;
27119
27203
  this.state.noAnonFunctionType = true;
27120
27204
  node.returnType = this.flowParseTypeAnnotation();
27121
27205
  this.state.noAnonFunctionType = oldNoAnonFunctionType;
27122
27206
  }
27123
- return super.parseAsyncArrowFromCallExpression(node, call);
27207
+ return super.parseAsyncArrowFromCallExpression(node, call2);
27124
27208
  }
27125
27209
  shouldParseAsyncArrow() {
27126
27210
  return this.match(14) || super.shouldParseAsyncArrow();
@@ -28274,8 +28358,8 @@ var require_lib = __commonJS((exports) => {
28274
28358
  if (this.match(8)) {
28275
28359
  node.expression = this.jsxParseEmptyExpression();
28276
28360
  } else {
28277
- const expression = this.parseExpression();
28278
- node.expression = expression;
28361
+ const expression2 = this.parseExpression();
28362
+ node.expression = expression2;
28279
28363
  }
28280
28364
  this.setContext(previousContext);
28281
28365
  this.state.canStartJSXElement = true;
@@ -31211,53 +31295,53 @@ var require_lib = __commonJS((exports) => {
31211
31295
  }
31212
31296
  return false;
31213
31297
  }
31214
- isOptionalMemberExpression(expression) {
31215
- return expression.type === "OptionalMemberExpression";
31298
+ isOptionalMemberExpression(expression2) {
31299
+ return expression2.type === "OptionalMemberExpression";
31216
31300
  }
31217
- checkLVal(expression, ancestor, binding = 64, checkClashes = false, strictModeChanged = false, hasParenthesizedAncestor = false, disallowCallExpression = false) {
31301
+ checkLVal(expression2, ancestor, binding = 64, checkClashes = false, strictModeChanged = false, hasParenthesizedAncestor = false, disallowCallExpression = false) {
31218
31302
  var _expression$extra;
31219
- const type = expression.type;
31220
- if (this.isObjectMethod(expression))
31303
+ const type = expression2.type;
31304
+ if (this.isObjectMethod(expression2))
31221
31305
  return;
31222
- const isOptionalMemberExpression = this.isOptionalMemberExpression(expression);
31306
+ const isOptionalMemberExpression = this.isOptionalMemberExpression(expression2);
31223
31307
  if (isOptionalMemberExpression || type === "MemberExpression") {
31224
31308
  if (isOptionalMemberExpression) {
31225
- this.expectPlugin("optionalChainingAssign", expression.loc.start);
31309
+ this.expectPlugin("optionalChainingAssign", expression2.loc.start);
31226
31310
  if (ancestor.type !== "AssignmentExpression") {
31227
- this.raise(Errors.InvalidLhsOptionalChaining, expression, {
31311
+ this.raise(Errors.InvalidLhsOptionalChaining, expression2, {
31228
31312
  ancestor
31229
31313
  });
31230
31314
  }
31231
31315
  }
31232
31316
  if (binding !== 64) {
31233
- this.raise(Errors.InvalidPropertyBindingPattern, expression);
31317
+ this.raise(Errors.InvalidPropertyBindingPattern, expression2);
31234
31318
  }
31235
31319
  return;
31236
31320
  }
31237
31321
  if (type === "Identifier") {
31238
- this.checkIdentifier(expression, binding, strictModeChanged);
31322
+ this.checkIdentifier(expression2, binding, strictModeChanged);
31239
31323
  const {
31240
31324
  name
31241
- } = expression;
31325
+ } = expression2;
31242
31326
  if (checkClashes) {
31243
31327
  if (checkClashes.has(name)) {
31244
- this.raise(Errors.ParamDupe, expression);
31328
+ this.raise(Errors.ParamDupe, expression2);
31245
31329
  } else {
31246
31330
  checkClashes.add(name);
31247
31331
  }
31248
31332
  }
31249
31333
  return;
31250
31334
  } else if (type === "VoidPattern" && ancestor.type === "CatchClause") {
31251
- this.raise(Errors.VoidPatternCatchClauseParam, expression);
31335
+ this.raise(Errors.VoidPatternCatchClauseParam, expression2);
31252
31336
  }
31253
- const unwrappedExpression = unwrapParenthesizedExpression(expression);
31337
+ const unwrappedExpression = unwrapParenthesizedExpression(expression2);
31254
31338
  disallowCallExpression || (disallowCallExpression = unwrappedExpression.type === "CallExpression" && (unwrappedExpression.callee.type === "Import" || unwrappedExpression.callee.type === "Super"));
31255
- const validity = this.isValidLVal(type, disallowCallExpression, !(hasParenthesizedAncestor || (_expression$extra = expression.extra) != null && _expression$extra.parenthesized) && ancestor.type === "AssignmentExpression", binding);
31339
+ const validity = this.isValidLVal(type, disallowCallExpression, !(hasParenthesizedAncestor || (_expression$extra = expression2.extra) != null && _expression$extra.parenthesized) && ancestor.type === "AssignmentExpression", binding);
31256
31340
  if (validity === true)
31257
31341
  return;
31258
31342
  if (validity === false) {
31259
31343
  const ParseErrorClass = binding === 64 ? Errors.InvalidLhs : Errors.InvalidLhsBinding;
31260
- this.raise(ParseErrorClass, expression, {
31344
+ this.raise(ParseErrorClass, expression2, {
31261
31345
  ancestor
31262
31346
  });
31263
31347
  return;
@@ -31272,7 +31356,7 @@ var require_lib = __commonJS((exports) => {
31272
31356
  const nextAncestor = type === "ArrayPattern" || type === "ObjectPattern" ? {
31273
31357
  type
31274
31358
  } : ancestor;
31275
- const val = expression[key];
31359
+ const val = expression2[key];
31276
31360
  if (Array.isArray(val)) {
31277
31361
  for (const child of val) {
31278
31362
  if (child) {
@@ -33530,11 +33614,11 @@ var require_lib = __commonJS((exports) => {
33530
33614
  this.resetEndLocation(decl.id);
33531
33615
  }
33532
33616
  }
33533
- parseAsyncArrowFromCallExpression(node, call) {
33617
+ parseAsyncArrowFromCallExpression(node, call2) {
33534
33618
  if (this.match(14)) {
33535
33619
  node.returnType = this.tsParseTypeAnnotation();
33536
33620
  }
33537
- return super.parseAsyncArrowFromCallExpression(node, call);
33621
+ return super.parseAsyncArrowFromCallExpression(node, call2);
33538
33622
  }
33539
33623
  parseMaybeAssign(refExpressionErrors, afterLeftParse) {
33540
33624
  var _jsx, _jsx2, _typeCast, _jsx3, _typeCast2;
@@ -33725,9 +33809,9 @@ var require_lib = __commonJS((exports) => {
33725
33809
  if (this.match(47) || this.match(51)) {
33726
33810
  const typeArguments = this.tsParseTypeArgumentsInExpression();
33727
33811
  if (this.match(10)) {
33728
- const call = super.parseMaybeDecoratorArguments(expr, startLoc);
33729
- call.typeParameters = typeArguments;
33730
- return call;
33812
+ const call2 = super.parseMaybeDecoratorArguments(expr, startLoc);
33813
+ call2.typeParameters = typeArguments;
33814
+ return call2;
33731
33815
  }
33732
33816
  this.unexpected(null, 10);
33733
33817
  }
@@ -34117,31 +34201,31 @@ var require_lib = __commonJS((exports) => {
34117
34201
  return this.chStartsBindingIdentifier(nextCh, next) || nextCh === 34 || nextCh === 39;
34118
34202
  }
34119
34203
  };
34120
- function isPossiblyLiteralEnum(expression) {
34121
- if (expression.type !== "MemberExpression")
34204
+ function isPossiblyLiteralEnum(expression2) {
34205
+ if (expression2.type !== "MemberExpression")
34122
34206
  return false;
34123
34207
  const {
34124
34208
  computed,
34125
34209
  property
34126
- } = expression;
34210
+ } = expression2;
34127
34211
  if (computed && property.type !== "StringLiteral" && (property.type !== "TemplateLiteral" || property.expressions.length > 0)) {
34128
34212
  return false;
34129
34213
  }
34130
- return isUncomputedMemberExpressionChain(expression.object);
34214
+ return isUncomputedMemberExpressionChain(expression2.object);
34131
34215
  }
34132
- function isValidAmbientConstInitializer(expression, estree2) {
34216
+ function isValidAmbientConstInitializer(expression2, estree2) {
34133
34217
  var _expression$extra;
34134
34218
  const {
34135
34219
  type
34136
- } = expression;
34137
- if ((_expression$extra = expression.extra) != null && _expression$extra.parenthesized) {
34220
+ } = expression2;
34221
+ if ((_expression$extra = expression2.extra) != null && _expression$extra.parenthesized) {
34138
34222
  return false;
34139
34223
  }
34140
34224
  if (estree2) {
34141
34225
  if (type === "Literal") {
34142
34226
  const {
34143
34227
  value
34144
- } = expression;
34228
+ } = expression2;
34145
34229
  if (typeof value === "string" || typeof value === "boolean") {
34146
34230
  return true;
34147
34231
  }
@@ -34151,42 +34235,42 @@ var require_lib = __commonJS((exports) => {
34151
34235
  return true;
34152
34236
  }
34153
34237
  }
34154
- if (isNumber(expression, estree2) || isNegativeNumber(expression, estree2)) {
34238
+ if (isNumber(expression2, estree2) || isNegativeNumber(expression2, estree2)) {
34155
34239
  return true;
34156
34240
  }
34157
- if (type === "TemplateLiteral" && expression.expressions.length === 0) {
34241
+ if (type === "TemplateLiteral" && expression2.expressions.length === 0) {
34158
34242
  return true;
34159
34243
  }
34160
- if (isPossiblyLiteralEnum(expression)) {
34244
+ if (isPossiblyLiteralEnum(expression2)) {
34161
34245
  return true;
34162
34246
  }
34163
34247
  return false;
34164
34248
  }
34165
- function isNumber(expression, estree2) {
34249
+ function isNumber(expression2, estree2) {
34166
34250
  if (estree2) {
34167
- return expression.type === "Literal" && (typeof expression.value === "number" || ("bigint" in expression));
34251
+ return expression2.type === "Literal" && (typeof expression2.value === "number" || ("bigint" in expression2));
34168
34252
  }
34169
- return expression.type === "NumericLiteral" || expression.type === "BigIntLiteral";
34253
+ return expression2.type === "NumericLiteral" || expression2.type === "BigIntLiteral";
34170
34254
  }
34171
- function isNegativeNumber(expression, estree2) {
34172
- if (expression.type === "UnaryExpression") {
34255
+ function isNegativeNumber(expression2, estree2) {
34256
+ if (expression2.type === "UnaryExpression") {
34173
34257
  const {
34174
34258
  operator,
34175
34259
  argument
34176
- } = expression;
34260
+ } = expression2;
34177
34261
  if (operator === "-" && isNumber(argument, estree2)) {
34178
34262
  return true;
34179
34263
  }
34180
34264
  }
34181
34265
  return false;
34182
34266
  }
34183
- function isUncomputedMemberExpressionChain(expression) {
34184
- if (expression.type === "Identifier")
34267
+ function isUncomputedMemberExpressionChain(expression2) {
34268
+ if (expression2.type === "Identifier")
34185
34269
  return true;
34186
- if (expression.type !== "MemberExpression" || expression.computed) {
34270
+ if (expression2.type !== "MemberExpression" || expression2.computed) {
34187
34271
  return false;
34188
34272
  }
34189
- return isUncomputedMemberExpressionChain(expression.object);
34273
+ return isUncomputedMemberExpressionChain(expression2.object);
34190
34274
  }
34191
34275
  var PlaceholderErrors = ParseErrorEnum`placeholders`({
34192
34276
  ClassNameIsRequired: "A class name is required.",
@@ -35048,16 +35132,16 @@ var require_lib = __commonJS((exports) => {
35048
35132
  shouldParseAsyncArrow() {
35049
35133
  return this.match(19) && !this.canInsertSemicolon();
35050
35134
  }
35051
- parseAsyncArrowFromCallExpression(node, call) {
35135
+ parseAsyncArrowFromCallExpression(node, call2) {
35052
35136
  var _call$extra;
35053
- this.resetPreviousNodeTrailingComments(call);
35137
+ this.resetPreviousNodeTrailingComments(call2);
35054
35138
  this.expect(19);
35055
- this.parseArrowExpression(node, call.arguments, true, (_call$extra = call.extra) == null ? undefined : _call$extra.trailingCommaLoc);
35056
- if (call.innerComments) {
35057
- setInnerComments(node, call.innerComments);
35139
+ this.parseArrowExpression(node, call2.arguments, true, (_call$extra = call2.extra) == null ? undefined : _call$extra.trailingCommaLoc);
35140
+ if (call2.innerComments) {
35141
+ setInnerComments(node, call2.innerComments);
35058
35142
  }
35059
- if (call.callee.trailingComments) {
35060
- setInnerComments(node, call.callee.trailingComments);
35143
+ if (call2.callee.trailingComments) {
35144
+ setInnerComments(node, call2.callee.trailingComments);
35061
35145
  }
35062
35146
  return node;
35063
35147
  }
@@ -35485,15 +35569,15 @@ var require_lib = __commonJS((exports) => {
35485
35569
  }
35486
35570
  return this.wrapParenthesis(startLoc, val);
35487
35571
  }
35488
- wrapParenthesis(startLoc, expression) {
35572
+ wrapParenthesis(startLoc, expression2) {
35489
35573
  if (!(this.optionFlags & 1024)) {
35490
- this.addExtra(expression, "parenthesized", true);
35491
- this.addExtra(expression, "parenStart", startLoc.index);
35492
- this.takeSurroundingComments(expression, startLoc.index, this.state.lastTokEndLoc.index);
35493
- return expression;
35574
+ this.addExtra(expression2, "parenthesized", true);
35575
+ this.addExtra(expression2, "parenStart", startLoc.index);
35576
+ this.takeSurroundingComments(expression2, startLoc.index, this.state.lastTokEndLoc.index);
35577
+ return expression2;
35494
35578
  }
35495
35579
  const parenExpression = this.startNodeAt(startLoc);
35496
- parenExpression.expression = expression;
35580
+ parenExpression.expression = expression2;
35497
35581
  return this.finishNode(parenExpression, "ParenthesizedExpression");
35498
35582
  }
35499
35583
  shouldParseArrow(params) {
@@ -36141,10 +36225,10 @@ var require_lib = __commonJS((exports) => {
36141
36225
  return this.finishNode(bodyNode, "PipelineTopicExpression");
36142
36226
  }
36143
36227
  }
36144
- isSimpleReference(expression) {
36145
- switch (expression.type) {
36228
+ isSimpleReference(expression2) {
36229
+ switch (expression2.type) {
36146
36230
  case "MemberExpression":
36147
- return !expression.computed && this.isSimpleReference(expression.object);
36231
+ return !expression2.computed && this.isSimpleReference(expression2.object);
36148
36232
  case "Identifier":
36149
36233
  return true;
36150
36234
  default:
@@ -86915,17 +86999,17 @@ var require_template = __commonJS((exports, module) => {
86915
86999
  function statement() {
86916
87000
  return statements.apply(null, arguments)[0];
86917
87001
  }
86918
- function expression(template) {
87002
+ function expression2(template) {
86919
87003
  template = Array.from(template);
86920
87004
  if (template.length > 0) {
86921
87005
  template[0] = "(" + template[0];
86922
87006
  template[template.length - 1] += ")";
86923
87007
  }
86924
- const expression2 = statement.apply(null, [template].concat(Array.from(arguments).slice(1))).expression;
86925
- if (expression2.extra) {
86926
- expression2.extra.parenthesized = false;
87008
+ const expression3 = statement.apply(null, [template].concat(Array.from(arguments).slice(1))).expression;
87009
+ if (expression3.extra) {
87010
+ expression3.extra.parenthesized = false;
86927
87011
  }
86928
- return expression2;
87012
+ return expression3;
86929
87013
  }
86930
87014
  function asyncExpression(template) {
86931
87015
  template = Array.from(template);
@@ -86933,13 +87017,13 @@ var require_template = __commonJS((exports, module) => {
86933
87017
  template[0] = "async () => (" + template[0];
86934
87018
  template[template.length - 1] += ")";
86935
87019
  }
86936
- const expression2 = statement.apply(null, [template].concat(Array.from(arguments).slice(1))).expression.body;
86937
- if (expression2.extra) {
86938
- expression2.extra.parenthesized = false;
87020
+ const expression3 = statement.apply(null, [template].concat(Array.from(arguments).slice(1))).expression.body;
87021
+ if (expression3.extra) {
87022
+ expression3.extra.parenthesized = false;
86939
87023
  }
86940
- return expression2;
87024
+ return expression3;
86941
87025
  }
86942
- return { statements, statement, expression, asyncExpression };
87026
+ return { statements, statement, expression: expression2, asyncExpression };
86943
87027
  };
86944
87028
  });
86945
87029
 
@@ -92736,6 +92820,152 @@ function iconColourHex(token) {
92736
92820
  return BRAND.green;
92737
92821
  return ICON_COLOURS[token] ?? BRAND.green;
92738
92822
  }
92823
+ // ../shared/dist/data-records.js
92824
+ var DATA_COLLECTION_RE = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
92825
+ var DATA_RECORD_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
92826
+ var DATA_LIMITS = {
92827
+ bodyBytes: 262144,
92828
+ responseBytes: 1048576,
92829
+ maxPage: 1000,
92830
+ maxPerPage: 100,
92831
+ expressionChars: 1024,
92832
+ filterMaxDepth: 16,
92833
+ filterMaxComparisons: 64,
92834
+ accessMaxApps: 50,
92835
+ schemaPerPage: 200,
92836
+ schemaMaxPages: 10,
92837
+ sortMaxItems: 8,
92838
+ actAsTokenSeconds: 900,
92839
+ actAsCacheMaxSeconds: 600,
92840
+ identityCandidatesPerPage: 20
92841
+ };
92842
+ var DATA_IDENTITY_KINDS = ["user", "visitor", "superuser"];
92843
+ var DATA_ACTING_AS = [...DATA_IDENTITY_KINDS, "unset"];
92844
+ var DATA_RECORD_ERROR_STATUS = {
92845
+ PB_VERSION_UNSUPPORTED: 503,
92846
+ PB_RECORD_NOT_FOUND: 404,
92847
+ PB_VALIDATION: 400,
92848
+ PB_CONFLICT: 409,
92849
+ PB_CONFLICT_UNSUPPORTED: 400,
92850
+ DATA_COLLECTION_FORBIDDEN: 403,
92851
+ DATA_FIELD_UNSUPPORTED: 400,
92852
+ DATA_RATE_LIMITED: 429,
92853
+ DATA_RESPONSE_TOO_LARGE: 413,
92854
+ OAUTH_DATA_ACCESS_REQUIRED: 403,
92855
+ DATA_TOOLS_NOT_ENABLED: 403,
92856
+ PB_AUTH_FAILED: 503,
92857
+ PB_NOT_RUNNING: 503,
92858
+ PB_BRIDGE_UNAVAILABLE: 502,
92859
+ NOT_POCKETBASE: 400,
92860
+ DATA_QUERY_INVALID: 400,
92861
+ DATA_SCHEMA_TOO_LARGE: 413,
92862
+ DATA_QUERY_TIMEOUT: 504,
92863
+ DATA_WRITE_OUTCOME_UNKNOWN: 502,
92864
+ PB_RULE_DENIED: 403,
92865
+ DATA_ACT_AS_REQUIRED: 403,
92866
+ DATA_ACT_AS_UNAVAILABLE: 403
92867
+ };
92868
+
92869
+ // ../shared/dist/data-filter.js
92870
+ class ExpressionError extends Error {
92871
+ reason;
92872
+ at;
92873
+ constructor(reason, at) {
92874
+ super(reason);
92875
+ this.reason = reason;
92876
+ this.at = at;
92877
+ }
92878
+ }
92879
+ var RESERVED = new Set(["true", "false", "null"]);
92880
+ class SchemaIndex {
92881
+ visible = new Set;
92882
+ hidden = new Set;
92883
+ lowered = new Set;
92884
+ constructor(fields) {
92885
+ for (const f of fields) {
92886
+ (f.hidden ? this.hidden : this.visible).add(f.name);
92887
+ this.lowered.add(f.name.toLowerCase());
92888
+ }
92889
+ }
92890
+ checkField(name, at) {
92891
+ if (RESERVED.has(name.toLowerCase()))
92892
+ throw new ExpressionError("reserved_word", at);
92893
+ if (this.visible.has(name))
92894
+ return;
92895
+ throw new ExpressionError(this.hidden.has(name) ? "hidden_field" : "unknown_field", at);
92896
+ }
92897
+ checkKeywordLiteral(word, at) {
92898
+ if (this.lowered.has(word))
92899
+ throw new ExpressionError("shadowed_literal", at);
92900
+ }
92901
+ }
92902
+ // ../shared/dist/disposable-email-domains.js
92903
+ var DISPOSABLE_DOMAINS = new Set([
92904
+ "mailinator.com",
92905
+ "mailinator.net",
92906
+ "mailinator2.com",
92907
+ "binkmail.com",
92908
+ "bobmail.info",
92909
+ "chammy.info",
92910
+ "devnullmail.com",
92911
+ "letthemeatspam.com",
92912
+ "mailnesia.com",
92913
+ "mailtothis.com",
92914
+ "notmailinator.com",
92915
+ "reallymymail.com",
92916
+ "safetymail.info",
92917
+ "thisisnotmyrealemail.com",
92918
+ "tradermail.info",
92919
+ "veryrealemail.com",
92920
+ "zippymail.info",
92921
+ "guerrillamail.com",
92922
+ "guerrillamail.net",
92923
+ "guerrillamail.org",
92924
+ "guerrillamail.biz",
92925
+ "guerrillamail.de",
92926
+ "guerrillamailblock.com",
92927
+ "sharklasers.com",
92928
+ "grr.la",
92929
+ "spam4.me",
92930
+ "10minutemail.com",
92931
+ "10minutemail.net",
92932
+ "20minutemail.com",
92933
+ "30minutemail.com",
92934
+ "tempmail.com",
92935
+ "temp-mail.org",
92936
+ "temp-mail.io",
92937
+ "tempmailaddress.com",
92938
+ "tempmailo.com",
92939
+ "tempinbox.com",
92940
+ "throwawaymail.com",
92941
+ "yopmail.com",
92942
+ "yopmail.fr",
92943
+ "yopmail.net",
92944
+ "maildrop.cc",
92945
+ "trashmail.com",
92946
+ "trashmail.de",
92947
+ "trashmail.net",
92948
+ "trash-mail.com",
92949
+ "dispostable.com",
92950
+ "fakeinbox.com",
92951
+ "getnada.com",
92952
+ "mintemail.com",
92953
+ "mohmal.com",
92954
+ "moakt.cc",
92955
+ "formtests.info",
92956
+ "mailcatch.com",
92957
+ "mailnull.com",
92958
+ "spambog.com",
92959
+ "spambox.us",
92960
+ "spamgourmet.com",
92961
+ "emailondeck.com",
92962
+ "fakemailgenerator.com",
92963
+ "jetable.org",
92964
+ "mytrashmail.com",
92965
+ "owlpic.com",
92966
+ "rcpt.at",
92967
+ "trbvm.com"
92968
+ ]);
92739
92969
  // ../shared/dist/legal.js
92740
92970
  var LEGAL_DOCUMENT_VERSIONS = {
92741
92971
  terms: "1.0.3",
@@ -92759,6 +92989,12 @@ var UPLOAD_SESSION_TTL_MS = 6 * 60 * 60 * 1000;
92759
92989
  var UPLOAD_SESSION_MAX_LIFETIME_MS = 24 * 60 * 60 * 1000;
92760
92990
  // ../shared/dist/logs.js
92761
92991
  var MAX_LOG_SEARCH_LENGTH = 256;
92992
+ // ../shared/dist/oauth-scopes.js
92993
+ var DATA_ACCESS_SUFFIX = "records in your apps' databases, including data your app's users entered. Every record the assistant reads is sent to it and may be processed by its provider under the provider's terms. Revoke in Settings → Connections; copies already sent are not recalled.";
92994
+ var DATA_ACCESS_MODE_LABELS = {
92995
+ readwrite: `Read, create, change and delete ${DATA_ACCESS_SUFFIX}`,
92996
+ read: `Read ${DATA_ACCESS_SUFFIX}`
92997
+ };
92762
92998
  // ../shared/dist/platform-env.js
92763
92999
  var PERCHER_INJECTED_ENV_KEYS = new Set([
92764
93000
  "NODE_ENV",
@@ -92784,6 +93020,23 @@ var PROXY_LOWERCASE_ALIASES = new Set([
92784
93020
  // ../shared/dist/runtime.js
92785
93021
  var DEFAULT_NODE_VERSION_MAJOR = "24";
92786
93022
  var DEFAULT_NODE_VERSION_LABEL = `${DEFAULT_NODE_VERSION_MAJOR} LTS`;
93023
+ // ../shared/dist/signup-day.js
93024
+ var stockholmDate = new Intl.DateTimeFormat("sv-SE", {
93025
+ timeZone: "Europe/Stockholm",
93026
+ year: "numeric",
93027
+ month: "2-digit",
93028
+ day: "2-digit"
93029
+ });
93030
+ var stockholmClock = new Intl.DateTimeFormat("en-GB", {
93031
+ timeZone: "Europe/Stockholm",
93032
+ year: "numeric",
93033
+ month: "2-digit",
93034
+ day: "2-digit",
93035
+ hour: "2-digit",
93036
+ minute: "2-digit",
93037
+ second: "2-digit",
93038
+ hourCycle: "h23"
93039
+ });
92787
93040
  // ../shared/dist/switches.js
92788
93041
  var ONE = ["1"];
92789
93042
  var TRUE = ["true"];
@@ -107210,7 +107463,7 @@ var LEGACY_AUDIT_REQUIRED_CONJUNCTS = [
107210
107463
  "volumes_attributed",
107211
107464
  "scans_complete",
107212
107465
  "runtime_evidence_complete",
107213
- "clabbe_attestation_complete",
107466
+ "security_attestation_complete",
107214
107467
  "launch_gate_ready"
107215
107468
  ];
107216
107469
  function legacyAuditIsGreen(result) {
@@ -108056,7 +108309,7 @@ import { join as join9, resolve as resolve5 } from "node:path";
108056
108309
  // ../core/dist/templates.js
108057
108310
  import { existsSync as existsSync5, mkdirSync as mkdirSync6, readdirSync, readFileSync as readFileSync6, statSync, writeFileSync as writeFileSync6 } from "node:fs";
108058
108311
  import { basename as basename2, join as join8, normalize, relative as relative2, resolve as resolve4 } from "node:path";
108059
- var __dirname = "D:\\dev\\Percher-codex-clone\\packages\\core\\dist";
108312
+ var __dirname = "C:\\dev\\Percher-npm-final-release-20261018\\packages\\core\\dist";
108060
108313
  var TEMPLATES_DIR = resolve4(import.meta.dirname ?? __dirname, "../templates");
108061
108314
  var PLACEHOLDER = "__APP_NAME__";
108062
108315
  function listTemplates() {
@@ -108437,115 +108690,11 @@ async function dataOauth(ctx, input = { provider: "google" }) {
108437
108690
  redirectUri: status.redirectUri
108438
108691
  };
108439
108692
  }
108440
- // ../core/dist/commands/delete.js
108441
- var deleteInputSchema = exports_external.object({
108442
- app: exports_external.string().optional().describe("App name to delete (defaults to percher.toml app name)"),
108443
- confirm: exports_external.boolean().describe("Must be true to confirm deletion. This is a destructive operation that permanently removes the app, its container, database, domains, env vars, and deploy history.")
108444
- });
108445
- async function deleteApp(ctx, input) {
108446
- const name = input.app ?? readPercherTomlAppName(ctx.cwd);
108447
- if (!name) {
108448
- throw new PercherCoreError("No app specified and no percher.toml found", {
108449
- code: "env.no-app",
108450
- hint: "Pass an app name or run from a directory with percher.toml."
108451
- });
108452
- }
108453
- if (!input.confirm) {
108454
- throw new PercherCoreError(`Deletion requires explicit confirmation. Set confirm: true to delete "${name}" permanently.`, {
108455
- code: "delete.confirmation-required",
108456
- hint: `This will permanently delete the app "${name}" and all its data. Pass confirm: true to proceed.`
108457
- });
108458
- }
108459
- await ctx.client.apps.delete(name);
108460
- }
108461
- // ../core/dist/commands/deploy-repo.js
108693
+ // ../core/dist/commands/data-records.js
108462
108694
  init_dist();
108463
108695
 
108464
- // ../core/dist/poll-deployment.js
108696
+ // ../core/dist/data-recovery.js
108465
108697
  init_dist();
108466
- class DeployPollLostContactError extends PercherCoreError {
108467
- deploymentId;
108468
- constructor(message, deploymentId, appName, options) {
108469
- super(message, {
108470
- code: "push.lost-contact",
108471
- hint: `The deploy may already be live. Check with: percher deploys ${appName}`,
108472
- cause: options?.cause
108473
- });
108474
- this.deploymentId = deploymentId;
108475
- this.name = "DeployPollLostContactError";
108476
- }
108477
- }
108478
- function isTransientPollError(err) {
108479
- if (isTransientNetworkError(err))
108480
- return true;
108481
- if (err instanceof PercherApiError)
108482
- return err.status === 429 || err.status === 502 || err.status === 503 || err.status === 504;
108483
- return err instanceof TypeError && /terminated/i.test(err.message);
108484
- }
108485
- async function pollDeployment(opts) {
108486
- const terminal = opts.terminal ?? ["live", "failed"];
108487
- const intervalMs = opts.intervalMs ?? 2000;
108488
- const timeoutMs = opts.timeoutMs ?? TIMEOUTS.clientPublishPoll;
108489
- const maxRetries = opts.maxRetries ?? Number.POSITIVE_INFINITY;
108490
- const retryBudgetMs = opts.retryBudgetMs ?? 5 * 60000;
108491
- let deployment = opts.initial;
108492
- const startedAt = Date.now();
108493
- const seenEventIds = new Set;
108494
- if (opts.onEvent) {
108495
- await drainNewEvents(opts, deployment.id, seenEventIds);
108496
- }
108497
- while (!terminal.includes(deployment.status)) {
108498
- if (Date.now() - startedAt > timeoutMs) {
108499
- opts.onTimeout(deployment);
108500
- }
108501
- opts.onTick?.(deployment);
108502
- await new Promise((r) => setTimeout(r, intervalMs));
108503
- let attempt = 0;
108504
- let streakStartedAt = 0;
108505
- let polled = false;
108506
- while (!polled) {
108507
- try {
108508
- deployment = await opts.ctx.client.apps.getDeployment(opts.appId, deployment.id);
108509
- polled = true;
108510
- } catch (err) {
108511
- attempt++;
108512
- if (!isTransientPollError(err))
108513
- throw err;
108514
- if (attempt === 1) {
108515
- streakStartedAt = Date.now();
108516
- opts.ctx.status(err instanceof PercherApiError && err.status === 429 ? "Percher asked this client to slow down; retrying while the deploy continues..." : "Lost contact with Percher; retrying while the deploy continues...");
108517
- }
108518
- if (Date.now() - startedAt > timeoutMs)
108519
- opts.onTimeout(deployment);
108520
- if (attempt >= maxRetries || Date.now() - streakStartedAt >= retryBudgetMs) {
108521
- const msg = err.message ?? String(err);
108522
- throw new DeployPollLostContactError(`${msg}
108523
-
108524
- The deploy may already be live — contact with Percher was lost mid-poll. Check with: percher deploys ${opts.appName}`, deployment.id, opts.appName, { cause: err });
108525
- }
108526
- const backoff = (opts.backoffMs ?? ((n) => Math.min(1000 * 2 ** (n - 1), 15000)))(attempt);
108527
- await new Promise((r) => setTimeout(r, backoff));
108528
- }
108529
- }
108530
- if (opts.onEvent) {
108531
- await drainNewEvents(opts, deployment.id, seenEventIds);
108532
- }
108533
- }
108534
- return deployment;
108535
- }
108536
- async function drainNewEvents(opts, deployId, seenEventIds) {
108537
- if (!opts.onEvent)
108538
- return;
108539
- try {
108540
- const { events } = await opts.ctx.client.apps.getDeployEvents(opts.appId, deployId);
108541
- for (const event of events) {
108542
- if (seenEventIds.has(event.id))
108543
- continue;
108544
- seenEventIds.add(event.id);
108545
- opts.onEvent(event);
108546
- }
108547
- } catch {}
108548
- }
108549
108698
 
108550
108699
  // ../core/dist/structured-error-codes.js
108551
108700
  var MAPPINGS = {
@@ -109084,6 +109233,277 @@ function recoveryFromErrorClass(errorClass, failure) {
109084
109233
  }
109085
109234
  }
109086
109235
 
109236
+ // ../core/dist/data-recovery.js
109237
+ var WRITES = new Set(["create", "update", "delete"]);
109238
+ function isDataRecordErrorCode(code) {
109239
+ return typeof code === "string" && Object.hasOwn(DATA_RECORD_ERROR_STATUS, code);
109240
+ }
109241
+
109242
+ class DataRecordError extends PercherApiError {
109243
+ target;
109244
+ constructor(err, target) {
109245
+ super(err.message, {
109246
+ status: err.status,
109247
+ code: err.code,
109248
+ requestId: err.requestId,
109249
+ extra: err.extra,
109250
+ cause: err
109251
+ });
109252
+ this.name = "DataRecordError";
109253
+ this.target = target;
109254
+ }
109255
+ }
109256
+
109257
+ // ../core/dist/commands/data-records.js
109258
+ var appArg = exports_external.string().min(1).optional().describe("App name or id. Defaults to the app in ./percher.toml.");
109259
+ var collectionArg = exports_external.string().regex(DATA_COLLECTION_RE, "a collection name: a letter, then letters, digits or _ (max 64)").describe("Collection name, exactly as percher_data_schema lists it (case-sensitive).");
109260
+ var recordIdArg = exports_external.string().regex(DATA_RECORD_ID_RE, "a record id: letters, digits, _ or - (max 64)").describe("Record id.");
109261
+ var expression = (what) => exports_external.string().max(DATA_LIMITS.expressionChars).optional().describe(what);
109262
+ var recordData = exports_external.record(exports_external.string(), exports_external.unknown()).describe("Field values keyed by field name (see percher_data_schema). File fields, hidden fields and unknown fields are refused.");
109263
+ var dataSchemaInputSchema = exports_external.object({ app: appArg });
109264
+ var dataQueryInputSchema = exports_external.object({
109265
+ app: appArg,
109266
+ collection: collectionArg,
109267
+ filter: expression("PocketBase-style filter over the collection's own fields, e.g. status = 'open' && priority >= 2. Operators = != > >= < <= ~ !~ and their ?-prefixed any-of forms; && || and parentheses. No @-variables, dotted paths, functions or backslashes."),
109268
+ sort: expression("Comma-separated fields, - for descending, e.g. -created,title (max 8)."),
109269
+ page: exports_external.number().int().min(1).max(DATA_LIMITS.maxPage).optional(),
109270
+ perPage: exports_external.number().int().min(1).max(DATA_LIMITS.maxPerPage).optional(),
109271
+ fields: expression("Comma-separated field names to return (default: every non-hidden field).")
109272
+ });
109273
+ var dataGetInputSchema = exports_external.object({
109274
+ app: appArg,
109275
+ collection: collectionArg,
109276
+ id: recordIdArg
109277
+ });
109278
+ var dataCreateInputSchema = exports_external.object({
109279
+ app: appArg,
109280
+ collection: collectionArg,
109281
+ data: recordData,
109282
+ id: recordIdArg.optional().describe("Optional id for the new record. With one, a create whose outcome is unknown can be checked with percher_data_get instead of searched for.")
109283
+ });
109284
+ var dataUpdateInputSchema = exports_external.object({
109285
+ app: appArg,
109286
+ collection: collectionArg,
109287
+ id: recordIdArg,
109288
+ data: recordData,
109289
+ ifUpdated: exports_external.string().min(1).max(64).optional().describe("The record's `updated` value as last read. The update is refused if it changed since. A best-effort timestamp check, not a lock: timestamp collisions and the app's own concurrent writes can defeat it.")
109290
+ });
109291
+ var dataDeleteInputSchema = exports_external.object({
109292
+ app: appArg,
109293
+ collection: collectionArg,
109294
+ id: recordIdArg
109295
+ });
109296
+ function resolveApp(ctx, app) {
109297
+ const name = app ?? readPercherTomlAppName(ctx.cwd);
109298
+ if (!name) {
109299
+ throw new PercherCoreError("No app specified and no percher.toml found", {
109300
+ code: "data.no-app",
109301
+ hint: "Pass an app name or run from a directory with percher.toml."
109302
+ });
109303
+ }
109304
+ return name;
109305
+ }
109306
+ async function call(target, run) {
109307
+ try {
109308
+ return await run();
109309
+ } catch (err) {
109310
+ if (err instanceof PercherApiError && isDataRecordErrorCode(err.code)) {
109311
+ throw new DataRecordError(err, target);
109312
+ }
109313
+ throw err;
109314
+ }
109315
+ }
109316
+ function target(op, app, collection, id) {
109317
+ return {
109318
+ op,
109319
+ app,
109320
+ ...collection !== undefined ? { collection } : {},
109321
+ ...id !== undefined ? { id } : {}
109322
+ };
109323
+ }
109324
+ var SCHEMA_MAX_COLLECTIONS = DATA_LIMITS.schemaPerPage * DATA_LIMITS.schemaMaxPages;
109325
+ function omittedByRulesNote(omitted) {
109326
+ if (typeof omitted !== "number" || !Number.isSafeInteger(omitted) || omitted < 1 || omitted > SCHEMA_MAX_COLLECTIONS) {
109327
+ return;
109328
+ }
109329
+ const subject = omitted === 1 ? "1 collection in this app is" : `${omitted} collections in this app are`;
109330
+ return `${subject} reachable only with full access, which the app's own server code may use. The owner can choose full access for this app in Settings → Connections.`;
109331
+ }
109332
+ async function dataSchema2(ctx, input) {
109333
+ const app = resolveApp(ctx, input.app);
109334
+ const schema = await call(target("schema", app), () => ctx.client.data.getSchema(app));
109335
+ const { note: _fromApi, ...rest } = schema;
109336
+ const note = omittedByRulesNote(rest.omittedByRules);
109337
+ return note === undefined ? rest : { ...rest, note };
109338
+ }
109339
+ async function dataQuery(ctx, input) {
109340
+ const { app: rawApp, collection, ...query } = input;
109341
+ const app = resolveApp(ctx, rawApp);
109342
+ return call(target("query", app, collection), () => ctx.client.data.queryRecords(app, collection, query));
109343
+ }
109344
+ async function dataGet(ctx, input) {
109345
+ const app = resolveApp(ctx, input.app);
109346
+ return call(target("get", app, input.collection, input.id), () => ctx.client.data.getRecord(app, input.collection, input.id));
109347
+ }
109348
+ async function dataCreate(ctx, input) {
109349
+ const app = resolveApp(ctx, input.app);
109350
+ const body = {
109351
+ data: input.data,
109352
+ ...input.id !== undefined ? { id: input.id } : {}
109353
+ };
109354
+ return call(target("create", app, input.collection, input.id), () => ctx.client.data.createRecord(app, input.collection, body));
109355
+ }
109356
+ async function dataUpdate(ctx, input) {
109357
+ const app = resolveApp(ctx, input.app);
109358
+ const body = {
109359
+ data: input.data,
109360
+ ...input.ifUpdated !== undefined ? { ifUpdated: input.ifUpdated } : {}
109361
+ };
109362
+ return call(target("update", app, input.collection, input.id), () => ctx.client.data.updateRecord(app, input.collection, input.id, body));
109363
+ }
109364
+ async function dataDelete(ctx, input) {
109365
+ const app = resolveApp(ctx, input.app);
109366
+ await call(target("delete", app, input.collection, input.id), () => ctx.client.data.deleteRecord(app, input.collection, input.id));
109367
+ return { deleted: true, collection: input.collection, id: input.id };
109368
+ }
109369
+ // ../core/dist/commands/delete.js
109370
+ var deleteInputSchema = exports_external.object({
109371
+ app: exports_external.string().optional().describe("App name to delete (defaults to percher.toml app name)"),
109372
+ confirm: exports_external.boolean().describe("Must be true to confirm deletion. This is a destructive operation that permanently removes the app, its container, database, domains, env vars, and deploy history.")
109373
+ });
109374
+ async function deleteApp(ctx, input) {
109375
+ const name = input.app ?? readPercherTomlAppName(ctx.cwd);
109376
+ if (!name) {
109377
+ throw new PercherCoreError("No app specified and no percher.toml found", {
109378
+ code: "env.no-app",
109379
+ hint: "Pass an app name or run from a directory with percher.toml."
109380
+ });
109381
+ }
109382
+ if (!input.confirm) {
109383
+ throw new PercherCoreError(`Deletion requires explicit confirmation. Set confirm: true to delete "${name}" permanently.`, {
109384
+ code: "delete.confirmation-required",
109385
+ hint: `This will permanently delete the app "${name}" and all its data. Pass confirm: true to proceed.`
109386
+ });
109387
+ }
109388
+ await ctx.client.apps.delete(name);
109389
+ }
109390
+ // ../core/dist/commands/deploy-repo.js
109391
+ init_dist();
109392
+
109393
+ // ../core/dist/deployment-replaced.js
109394
+ var summary = "This deployment is no longer active. Inspect the app's current state before deploying again.";
109395
+ function recovery(app, deployId) {
109396
+ return recoveryDoctor({ app, deployId, mode: "deploy", reasonCode: "replaced_by_newer" });
109397
+ }
109398
+ function throwIfDeploymentReplaced(app, deployment) {
109399
+ if (deployment.status !== "replaced")
109400
+ return;
109401
+ throw new PercherCoreError(summary, {
109402
+ code: "push.deploy-replaced",
109403
+ hint: `Run \`percher doctor --app ${app}\` to inspect the current state.`,
109404
+ recovery: { ...recovery(app, deployment.id) }
109405
+ });
109406
+ }
109407
+ function replacedDeploymentResult(app, deployment) {
109408
+ return {
109409
+ status: "replaced",
109410
+ app,
109411
+ deployment,
109412
+ summary,
109413
+ recovery: recovery(app.name, deployment.id),
109414
+ fileCount: 0,
109415
+ bytes: 0,
109416
+ configPath: "",
109417
+ bundle: { fileCount: 0, bytes: 0 }
109418
+ };
109419
+ }
109420
+
109421
+ // ../core/dist/poll-deployment.js
109422
+ init_dist();
109423
+ class DeployPollLostContactError extends PercherCoreError {
109424
+ deploymentId;
109425
+ constructor(message, deploymentId, appName, options) {
109426
+ super(message, {
109427
+ code: "push.lost-contact",
109428
+ hint: `The deploy may already be live. Check with: percher deploys ${appName}`,
109429
+ cause: options?.cause
109430
+ });
109431
+ this.deploymentId = deploymentId;
109432
+ this.name = "DeployPollLostContactError";
109433
+ }
109434
+ }
109435
+ function isTransientPollError(err) {
109436
+ if (isTransientNetworkError(err))
109437
+ return true;
109438
+ if (err instanceof PercherApiError)
109439
+ return err.status === 429 || err.status === 502 || err.status === 503 || err.status === 504;
109440
+ return err instanceof TypeError && /terminated/i.test(err.message);
109441
+ }
109442
+ async function pollDeployment(opts) {
109443
+ const terminal = opts.terminal ?? ["live", "failed", "replaced"];
109444
+ const intervalMs = opts.intervalMs ?? 2000;
109445
+ const timeoutMs = opts.timeoutMs ?? TIMEOUTS.clientPublishPoll;
109446
+ const maxRetries = opts.maxRetries ?? Number.POSITIVE_INFINITY;
109447
+ const retryBudgetMs = opts.retryBudgetMs ?? 5 * 60000;
109448
+ let deployment = opts.initial;
109449
+ const startedAt = Date.now();
109450
+ const seenEventIds = new Set;
109451
+ if (opts.onEvent) {
109452
+ await drainNewEvents(opts, deployment.id, seenEventIds);
109453
+ }
109454
+ while (!terminal.includes(deployment.status)) {
109455
+ if (Date.now() - startedAt > timeoutMs) {
109456
+ opts.onTimeout(deployment);
109457
+ }
109458
+ opts.onTick?.(deployment);
109459
+ await new Promise((r) => setTimeout(r, intervalMs));
109460
+ let attempt = 0;
109461
+ let streakStartedAt = 0;
109462
+ let polled = false;
109463
+ while (!polled) {
109464
+ try {
109465
+ deployment = await opts.ctx.client.apps.getDeployment(opts.appId, deployment.id);
109466
+ polled = true;
109467
+ } catch (err) {
109468
+ attempt++;
109469
+ if (!isTransientPollError(err))
109470
+ throw err;
109471
+ if (attempt === 1) {
109472
+ streakStartedAt = Date.now();
109473
+ opts.ctx.status(err instanceof PercherApiError && err.status === 429 ? "Percher asked this client to slow down; retrying while the deploy continues..." : "Lost contact with Percher; retrying while the deploy continues...");
109474
+ }
109475
+ if (Date.now() - startedAt > timeoutMs)
109476
+ opts.onTimeout(deployment);
109477
+ if (attempt >= maxRetries || Date.now() - streakStartedAt >= retryBudgetMs) {
109478
+ const msg = err.message ?? String(err);
109479
+ throw new DeployPollLostContactError(`${msg}
109480
+
109481
+ The deploy may already be live — contact with Percher was lost mid-poll. Check with: percher deploys ${opts.appName}`, deployment.id, opts.appName, { cause: err });
109482
+ }
109483
+ const backoff = (opts.backoffMs ?? ((n) => Math.min(1000 * 2 ** (n - 1), 15000)))(attempt);
109484
+ await new Promise((r) => setTimeout(r, backoff));
109485
+ }
109486
+ }
109487
+ if (opts.onEvent) {
109488
+ await drainNewEvents(opts, deployment.id, seenEventIds);
109489
+ }
109490
+ }
109491
+ return deployment;
109492
+ }
109493
+ async function drainNewEvents(opts, deployId, seenEventIds) {
109494
+ if (!opts.onEvent)
109495
+ return;
109496
+ try {
109497
+ const { events } = await opts.ctx.client.apps.getDeployEvents(opts.appId, deployId);
109498
+ for (const event of events) {
109499
+ if (seenEventIds.has(event.id))
109500
+ continue;
109501
+ seenEventIds.add(event.id);
109502
+ opts.onEvent(event);
109503
+ }
109504
+ } catch {}
109505
+ }
109506
+
109087
109507
  // ../core/dist/commands/publish-failure.js
109088
109508
  init_dist();
109089
109509
  import { join as join10 } from "node:path";
@@ -109559,7 +109979,7 @@ async function classifyDeploymentFailure(opts) {
109559
109979
  error48.suggestion = `${error48.suggestion}
109560
109980
  To return to the last version that ran cleanly: \`bunx percher rollback --last-good\`.`;
109561
109981
  }
109562
- const recovery = error48.errorClass ? recoveryFromErrorClass(error48.errorClass, {
109982
+ const recovery2 = error48.errorClass ? recoveryFromErrorClass(error48.errorClass, {
109563
109983
  missingEnvVars: error48.missingEnvVars,
109564
109984
  deployId: deployment.id,
109565
109985
  appName: app.name,
@@ -109573,13 +109993,13 @@ To return to the last version that ran cleanly: \`bunx percher rollback --last-g
109573
109993
  });
109574
109994
  return {
109575
109995
  error: error48,
109576
- recovery,
109996
+ recovery: recovery2,
109577
109997
  summary: `${error48.title} (${app.name}, deploy ${deployment.id}).`
109578
109998
  };
109579
109999
  }
109580
110000
  async function buildFailureResult(opts) {
109581
110001
  const { ctx, app, deployment, tarball, input } = opts;
109582
- const { error: error48, recovery, summary } = await classifyDeploymentFailure({
110002
+ const { error: error48, recovery: recovery2, summary: summary2 } = await classifyDeploymentFailure({
109583
110003
  ctx,
109584
110004
  app,
109585
110005
  deployment,
@@ -109592,8 +110012,8 @@ async function buildFailureResult(opts) {
109592
110012
  fileCount: tarball.fileCount,
109593
110013
  bytes: tarball.bytes,
109594
110014
  error: error48,
109595
- recovery,
109596
- summary,
110015
+ recovery: recovery2,
110016
+ summary: summary2,
109597
110017
  configPath: tomlPathFor(ctx.cwd),
109598
110018
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
109599
110019
  };
@@ -110169,7 +110589,7 @@ async function waitForDeploy(ctx, input, opts) {
110169
110589
  }
110170
110590
  }
110171
110591
  if (deployment.status === "failed") {
110172
- const { error: error48, recovery, summary } = await classifyDeploymentFailure({
110592
+ const { error: error48, recovery: recovery2, summary: summary2 } = await classifyDeploymentFailure({
110173
110593
  ctx,
110174
110594
  app,
110175
110595
  deployment,
@@ -110182,8 +110602,8 @@ async function waitForDeploy(ctx, input, opts) {
110182
110602
  elapsedSeconds: Math.round((Date.now() - startedAt) / 1000),
110183
110603
  totalElapsedSeconds: secondsSinceCreated(deployment),
110184
110604
  error: error48,
110185
- recovery,
110186
- summary
110605
+ recovery: recovery2,
110606
+ summary: summary2
110187
110607
  };
110188
110608
  }
110189
110609
  if (deployment.isCheck && deployment.checkPassed) {
@@ -110404,7 +110824,7 @@ async function doctor(ctx, input = {}) {
110404
110824
  tomlProblems = tomlErrorToRecoveryProblems(err);
110405
110825
  }
110406
110826
  if (err instanceof PercherTomlError && err.issues && err.issues.length > 0) {
110407
- const summary = err.issues.slice(0, 3).map((i) => {
110827
+ const summary2 = err.issues.slice(0, 3).map((i) => {
110408
110828
  const where = i.path.length > 0 ? `[${i.path.join(".")}]` : "(root)";
110409
110829
  return `${where} ${i.message}`;
110410
110830
  }).join("; ");
@@ -110412,7 +110832,7 @@ async function doctor(ctx, input = {}) {
110412
110832
  checks3.push({
110413
110833
  name: "percher.toml",
110414
110834
  status: "fail",
110415
- message: `${summary}${more}`
110835
+ message: `${summary2}${more}`
110416
110836
  });
110417
110837
  } else {
110418
110838
  checks3.push({
@@ -110899,7 +111319,7 @@ var VERDICT_RULES = [
110899
111319
  const reasonCode = vctx.lastDeployStatus === "queued" ? "deploy_queued" : vctx.lastDeployStatus === "building" ? "deploy_building" : vctx.lastDeployStatus === "deploying" ? "deploy_deploying" : "deploy_queued";
110900
111320
  const what = inTransitionalApp ? `App ${vctx.appName ?? ""} is provisioning` : `Last deploy is ${vctx.lastDeployStatus}`;
110901
111321
  const waiting = inTransitionalApp ? "This app is still provisioning" : reasonCode === "deploy_building" ? "The last deploy is still building" : reasonCode === "deploy_deploying" ? "The last deploy is being rolled out" : "The last deploy is still queued";
110902
- const recovery = vctx.lastDeployId && vctx.appName ? recoveryWait({
111322
+ const recovery2 = vctx.lastDeployId && vctx.appName ? recoveryWait({
110903
111323
  app: vctx.appName,
110904
111324
  deployId: vctx.lastDeployId,
110905
111325
  reasonCode
@@ -110915,7 +111335,7 @@ var VERDICT_RULES = [
110915
111335
  reasonCode,
110916
111336
  phase: "deploy"
110917
111337
  },
110918
- recovery,
111338
+ recovery: recovery2,
110919
111339
  summary: vctx.lastDeployId ? `${what.trim()} — wait for deploy ${vctx.lastDeployId}.` : `${what.trim()} — wait a moment and re-run.`
110920
111340
  };
110921
111341
  }
@@ -111183,7 +111603,7 @@ var domainRemoveInputSchema = exports_external.object({
111183
111603
  app: exports_external.string().optional(),
111184
111604
  domain: exports_external.string().min(1, "Domain is required")
111185
111605
  });
111186
- function resolveApp(ctx, app) {
111606
+ function resolveApp2(ctx, app) {
111187
111607
  const name = app ?? readPercherTomlAppName(ctx.cwd);
111188
111608
  if (!name) {
111189
111609
  throw new PercherCoreError("No app specified and no percher.toml found", {
@@ -111194,19 +111614,19 @@ function resolveApp(ctx, app) {
111194
111614
  return name;
111195
111615
  }
111196
111616
  async function domainAdd(ctx, input) {
111197
- const appRef2 = resolveApp(ctx, input.app);
111617
+ const appRef2 = resolveApp2(ctx, input.app);
111198
111618
  return ctx.client.apps.addDomain(appRef2, input.domain);
111199
111619
  }
111200
111620
  async function domainVerify(ctx, input) {
111201
- const appRef2 = resolveApp(ctx, input.app);
111621
+ const appRef2 = resolveApp2(ctx, input.app);
111202
111622
  return ctx.client.apps.verifyDomain(appRef2, input.domain);
111203
111623
  }
111204
111624
  async function domainList(ctx, input = {}) {
111205
- const appRef2 = resolveApp(ctx, input.app);
111625
+ const appRef2 = resolveApp2(ctx, input.app);
111206
111626
  return ctx.client.apps.listDomains(appRef2);
111207
111627
  }
111208
111628
  async function domainRemove(ctx, input) {
111209
- const appRef2 = resolveApp(ctx, input.app);
111629
+ const appRef2 = resolveApp2(ctx, input.app);
111210
111630
  await ctx.client.apps.removeDomain(appRef2, input.domain);
111211
111631
  }
111212
111632
  // ../core/dist/commands/env.js
@@ -111554,7 +111974,7 @@ var githubConnectInputSchema = exports_external.object({
111554
111974
  branch: exports_external.string().optional().describe("Branch to deploy and track (default: main)"),
111555
111975
  autoPreviews: exports_external.boolean().optional().describe("Opt-in: push to a non-tracked branch creates a preview deploy at <app>--p-<branch-slug>.percher.run. Default false.")
111556
111976
  });
111557
- function resolveApp2(ctx, app) {
111977
+ function resolveApp3(ctx, app) {
111558
111978
  const name = app ?? readPercherTomlAppName(ctx.cwd);
111559
111979
  if (!name) {
111560
111980
  throw new PercherCoreError("No app specified and no percher.toml found", {
@@ -111565,7 +111985,7 @@ function resolveApp2(ctx, app) {
111565
111985
  return name;
111566
111986
  }
111567
111987
  async function githubConnect(ctx, input) {
111568
- const appRef2 = resolveApp2(ctx, input.app);
111988
+ const appRef2 = resolveApp3(ctx, input.app);
111569
111989
  const branch = input.branch ?? "main";
111570
111990
  let deployment;
111571
111991
  let created;
@@ -111645,7 +112065,7 @@ var githubSetupWebhookInputSchema = exports_external.object({
111645
112065
  app: exports_external.string().optional().describe("App name (overrides percher.toml)")
111646
112066
  });
111647
112067
  async function githubSetupWebhook(ctx, input) {
111648
- const appRef2 = resolveApp2(ctx, input.app);
112068
+ const appRef2 = resolveApp3(ctx, input.app);
111649
112069
  const webhook = await ctx.client.apps.setupWebhook(appRef2);
111650
112070
  const repoBase = webhook.instructions.repo.replace(/\.git$/, "");
111651
112071
  return {
@@ -112360,12 +112780,12 @@ ${serialize(extras)}`;
112360
112780
  }
112361
112781
  ];
112362
112782
  for (const { name, content } of targets) {
112363
- const target = join16(ctx.cwd, name);
112364
- if (existsSync11(target)) {
112783
+ const target2 = join16(ctx.cwd, name);
112784
+ if (existsSync11(target2)) {
112365
112785
  result.warnings.push(`${name} already exists — left untouched. The imported config expects a multi-stage static build; merge by hand if needed.`);
112366
112786
  continue;
112367
112787
  }
112368
- writeFileSync8(target, content, "utf-8");
112788
+ writeFileSync8(target2, content, "utf-8");
112369
112789
  scaffoldedFiles.push(name);
112370
112790
  }
112371
112791
  }
@@ -112610,7 +113030,24 @@ function configFromDetection(name, detected, dataMode) {
112610
113030
  }
112611
113031
 
112612
113032
  // ../core/dist/validation/blocked-names.js
113033
+ var SENSITIVE_BRANDS = new Set([
113034
+ "paypal",
113035
+ "bankid",
113036
+ "swish",
113037
+ "swedbank",
113038
+ "handelsbanken",
113039
+ "nordea",
113040
+ "seb",
113041
+ "danskebank",
113042
+ "mitid",
113043
+ "nemid",
113044
+ "mobilepay",
113045
+ "vipps",
113046
+ "klarna",
113047
+ "skatteverket"
113048
+ ]);
112613
113049
  var BLOCKED_APP_NAMES = new Set([
113050
+ ...SENSITIVE_BRANDS,
112614
113051
  "api",
112615
113052
  "app",
112616
113053
  "admin",
@@ -112669,6 +113106,8 @@ var BLOCKED_APP_NAMES = new Set([
112669
113106
  function isBlockedName(name) {
112670
113107
  if (BLOCKED_APP_NAMES.has(name))
112671
113108
  return true;
113109
+ if (name.split("-").some((part) => SENSITIVE_BRANDS.has(part)))
113110
+ return true;
112672
113111
  const prefixes = [
112673
113112
  "login-",
112674
113113
  "signin-",
@@ -112706,6 +113145,8 @@ function adjustReservedName(name) {
112706
113145
  let adjusted = `app-${name}`;
112707
113146
  if (adjusted.length > 40)
112708
113147
  adjusted = adjusted.slice(0, 40).replace(/-+$/g, "");
113148
+ if (isBlockedName(adjusted))
113149
+ return `app-${crypto.randomUUID().slice(0, 8)}`;
112709
113150
  return adjusted;
112710
113151
  }
112711
113152
  function detectInteractive() {
@@ -112782,10 +113223,10 @@ async function init(ctx, input = {}) {
112782
113223
  }
112783
113224
  ];
112784
113225
  for (const { name: name2, content } of targets) {
112785
- const target = join18(ctx.cwd, name2);
112786
- if (existsSync13(target) && !input.force)
113226
+ const target2 = join18(ctx.cwd, name2);
113227
+ if (existsSync13(target2) && !input.force)
112787
113228
  continue;
112788
- writeFileSync9(target, content, "utf8");
113229
+ writeFileSync9(target2, content, "utf8");
112789
113230
  scaffoldedFiles.push(name2);
112790
113231
  }
112791
113232
  }
@@ -113319,7 +113760,7 @@ async function inspectSupabase(ctx, input) {
113319
113760
  const storageBuckets = normalizeBuckets(schemaBlob.storageBuckets);
113320
113761
  const authUsersCount = toFiniteNumber(schemaBlob.authUsersCount);
113321
113762
  const warnings = collectWarnings(tables, storageBuckets, authUsersCount);
113322
- const summary = renderSummary({
113763
+ const summary2 = renderSummary({
113323
113764
  projectRef: input.projectRef,
113324
113765
  tables,
113325
113766
  authUsersCount,
@@ -113334,7 +113775,7 @@ async function inspectSupabase(ctx, input) {
113334
113775
  storageBuckets,
113335
113776
  warnings,
113336
113777
  recovery: recoveryNone(),
113337
- summary
113778
+ summary: summary2
113338
113779
  };
113339
113780
  }
113340
113781
  function failure(args) {
@@ -114345,12 +114786,12 @@ function isSupabaseFromTerminal(path, supabaseNames) {
114345
114786
  let fromCall = null;
114346
114787
  let cursor = path.node;
114347
114788
  while (cursor.type === "CallExpression") {
114348
- const call = cursor;
114349
- if (call.callee.type !== "MemberExpression")
114789
+ const call2 = cursor;
114790
+ if (call2.callee.type !== "MemberExpression")
114350
114791
  break;
114351
- const callee = call.callee;
114792
+ const callee = call2.callee;
114352
114793
  if (callee.property.type === "Identifier" && callee.property.name === "from") {
114353
- fromCall = call;
114794
+ fromCall = call2;
114354
114795
  break;
114355
114796
  }
114356
114797
  cursor = callee.object;
@@ -114405,15 +114846,15 @@ function decomposeFromChain(outer) {
114405
114846
  const reversedSteps = [];
114406
114847
  let node = outer;
114407
114848
  while (node.type === "CallExpression") {
114408
- const call = node;
114409
- if (call.callee.type !== "MemberExpression")
114849
+ const call2 = node;
114850
+ if (call2.callee.type !== "MemberExpression")
114410
114851
  break;
114411
- const callee = call.callee;
114852
+ const callee = call2.callee;
114412
114853
  const method = callee.property.type === "Identifier" ? callee.property.name : null;
114413
114854
  if (method === null)
114414
114855
  return null;
114415
114856
  if (method === "from") {
114416
- const arg = call.arguments[0];
114857
+ const arg = call2.arguments[0];
114417
114858
  if (!arg || arg.type !== "Literal" && arg.type !== "StringLiteral")
114418
114859
  return null;
114419
114860
  const table = arg.value;
@@ -114421,7 +114862,7 @@ function decomposeFromChain(outer) {
114421
114862
  return null;
114422
114863
  return { table, steps: reversedSteps.reverse() };
114423
114864
  }
114424
- reversedSteps.push({ method, args: call.arguments });
114865
+ reversedSteps.push({ method, args: call2.arguments });
114425
114866
  node = callee.object;
114426
114867
  }
114427
114868
  return null;
@@ -114846,14 +115287,14 @@ function readChainSteps(outer) {
114846
115287
  let cursor = outer;
114847
115288
  while (true) {
114848
115289
  if (cursor.type === "CallExpression") {
114849
- const call = cursor;
114850
- if (call.callee.type !== "MemberExpression")
115290
+ const call2 = cursor;
115291
+ if (call2.callee.type !== "MemberExpression")
114851
115292
  break;
114852
- const callee = call.callee;
115293
+ const callee = call2.callee;
114853
115294
  if (callee.property.type === "Identifier") {
114854
115295
  reversed.push({
114855
115296
  method: callee.property.name,
114856
- call
115297
+ call: call2
114857
115298
  });
114858
115299
  }
114859
115300
  cursor = callee.object;
@@ -114874,8 +115315,8 @@ function readChainSteps(outer) {
114874
115315
  }
114875
115316
  return reversed.reverse();
114876
115317
  }
114877
- function readFirstStringArg(call) {
114878
- const a = call.arguments[0];
115318
+ function readFirstStringArg(call2) {
115319
+ const a = call2.arguments[0];
114879
115320
  if (!a)
114880
115321
  return null;
114881
115322
  if (a.type === "Literal" || a.type === "StringLiteral") {
@@ -115620,11 +116061,11 @@ async function migrationStatus(ctx, input) {
115620
116061
  const warning = analysis.checks.filter((c) => c.status === "warn");
115621
116062
  const buildFailed = build?.ran === true && !build.passed;
115622
116063
  const allGreen = failing.length === 0 && warning.length === 0 && !buildFailed;
115623
- const recovery = allGreen ? recoveryNone() : recoveryAsk({
116064
+ const recovery2 = allGreen ? recoveryNone() : recoveryAsk({
115624
116065
  prompt: buildPrompt(analysis.state, failing, warning, build),
115625
116066
  reasonCode: "unknown"
115626
116067
  });
115627
- const summary = `${STATE_SUMMARY[analysis.state]}${build ? ` Build: ${build.ran ? build.passed ? "passed" : "FAILED" : "skipped"}.` : ""}`;
116068
+ const summary2 = `${STATE_SUMMARY[analysis.state]}${build ? ` Build: ${build.ran ? build.passed ? "passed" : "FAILED" : "skipped"}.` : ""}`;
115628
116069
  return {
115629
116070
  status: "ok",
115630
116071
  rootDir: rootAbs,
@@ -115632,8 +116073,8 @@ async function migrationStatus(ctx, input) {
115632
116073
  migrationComplete: analysis.migrationComplete,
115633
116074
  checks: analysis.checks,
115634
116075
  ...build ? { build } : {},
115635
- recovery,
115636
- summary,
116076
+ recovery: recovery2,
116077
+ summary: summary2,
115637
116078
  checklist
115638
116079
  };
115639
116080
  }
@@ -115886,7 +116327,7 @@ async function rewriteSupabaseClient(ctx, input) {
115886
116327
  for (const flag of flags) {
115887
116328
  flagsByPattern[flag.pattern] = (flagsByPattern[flag.pattern] ?? 0) + 1;
115888
116329
  }
115889
- const recovery = reportNeeded ? recoveryAsk({
116330
+ const recovery2 = reportNeeded ? recoveryAsk({
115890
116331
  prompt: buildPrompt2(flags, walk2.skipped.length, hadRewrites, clientModuleWritten),
115891
116332
  reasonCode: "unknown"
115892
116333
  }) : recoveryNone();
@@ -115904,7 +116345,7 @@ async function rewriteSupabaseClient(ctx, input) {
115904
116345
  envFilesChanged: walk2.summary.envFilesChanged,
115905
116346
  clientModule: clientModuleWritten,
115906
116347
  skipped: walk2.skipped,
115907
- recovery,
116348
+ recovery: recovery2,
115908
116349
  summary: renderSummary2({
115909
116350
  mode,
115910
116351
  changed: changed.length,
@@ -116146,13 +116587,13 @@ function topologicalSort(collections) {
116146
116587
  for (const field of c.schema) {
116147
116588
  if (field.type !== "relation")
116148
116589
  continue;
116149
- const target = field.options.collectionName;
116150
- if (target === c.name)
116590
+ const target2 = field.options.collectionName;
116591
+ if (target2 === c.name)
116151
116592
  continue;
116152
- if (!byName.has(target))
116593
+ if (!byName.has(target2))
116153
116594
  continue;
116154
- dependsOn.get(c.name)?.add(target);
116155
- dependents.get(target)?.add(c.name);
116595
+ dependsOn.get(c.name)?.add(target2);
116596
+ dependents.get(target2)?.add(c.name);
116156
116597
  }
116157
116598
  }
116158
116599
  const inputOrder = collections.map((c) => c.name);
@@ -116393,7 +116834,7 @@ function renderRowTransform(collection) {
116393
116834
  }
116394
116835
  for (const rel of relations) {
116395
116836
  const fieldName = rel.name;
116396
- const target = rel.options.collectionName;
116837
+ const target2 = rel.options.collectionName;
116397
116838
  const isAuthUsersRef = rel.source.flag === "auth_users_reference";
116398
116839
  if (isAuthUsersRef) {
116399
116840
  parts.push(` if (rest[${JSON.stringify(fieldName)}] != null) {`);
@@ -116403,9 +116844,9 @@ function renderRowTransform(collection) {
116403
116844
  continue;
116404
116845
  }
116405
116846
  parts.push(` if (rest[${JSON.stringify(fieldName)}] != null) {`);
116406
- parts.push(` const mapped = lookupId(${JSON.stringify(target)}, rest[${JSON.stringify(fieldName)}]);`);
116847
+ parts.push(` const mapped = lookupId(${JSON.stringify(target2)}, rest[${JSON.stringify(fieldName)}]);`);
116407
116848
  parts.push(" if (mapped === undefined) {");
116408
- parts.push(` throw new Error(\`[${collection.name}.${fieldName}] no PB id for source value '\${rest[${JSON.stringify(fieldName)}]}' in ${target} map — was ${target} migrated first?\`);`);
116849
+ parts.push(` throw new Error(\`[${collection.name}.${fieldName}] no PB id for source value '\${rest[${JSON.stringify(fieldName)}]}' in ${target2} map — was ${target2} migrated first?\`);`);
116409
116850
  parts.push(" }");
116410
116851
  parts.push(` rest[${JSON.stringify(fieldName)}] = mapped;`);
116411
116852
  parts.push(" }");
@@ -116608,7 +117049,7 @@ async function migrateSupabaseSchema(ctx, input) {
116608
117049
  }
116609
117050
  };
116610
117051
  }
116611
- const summary = renderSummary3({
117052
+ const summary2 = renderSummary3({
116612
117053
  projectRef: input.projectRef,
116613
117054
  outputDirRel,
116614
117055
  inspection,
@@ -116621,7 +117062,7 @@ async function migrateSupabaseSchema(ctx, input) {
116621
117062
  filesWritten,
116622
117063
  preview,
116623
117064
  recovery: recoveryNone(),
116624
- summary
117065
+ summary: summary2
116625
117066
  };
116626
117067
  }
116627
117068
  function resolveOutputDir(cwd, requested) {
@@ -116721,8 +117162,8 @@ function renderMigrationNotes(preview) {
116721
117162
  lines.push("| Field | Type | Required | Postgres source | Flag |");
116722
117163
  lines.push("|---|---|---|---|---|");
116723
117164
  for (const field of collection.schema) {
116724
- const target = field.type === "relation" ? `relation → \`${field.options.collectionName}\`` : field.type;
116725
- lines.push(`| \`${field.name}\` | ${target} | ${field.required ? "yes" : "no"} | \`${field.source.postgresType}\` | ${field.source.flag ? `\`${field.source.flag}\`` : "—"} |`);
117165
+ const target2 = field.type === "relation" ? `relation → \`${field.options.collectionName}\`` : field.type;
117166
+ lines.push(`| \`${field.name}\` | ${target2} | ${field.required ? "yes" : "no"} | \`${field.source.postgresType}\` | ${field.source.flag ? `\`${field.source.flag}\`` : "—"} |`);
116726
117167
  }
116727
117168
  lines.push("");
116728
117169
  }
@@ -116830,7 +117271,7 @@ var previewBranchSetInputSchema = exports_external.object({
116830
117271
  var previewBranchInputSchema = exports_external.object({
116831
117272
  app: exports_external.string().optional()
116832
117273
  });
116833
- function resolveApp3(ctx, app) {
117274
+ function resolveApp4(ctx, app) {
116834
117275
  const name = app ?? readPercherTomlAppName(ctx.cwd);
116835
117276
  if (!name) {
116836
117277
  throw new PercherCoreError("No app specified and no percher.toml found", {
@@ -116841,11 +117282,11 @@ function resolveApp3(ctx, app) {
116841
117282
  return name;
116842
117283
  }
116843
117284
  async function previewBranchSet(ctx, input) {
116844
- const appRef2 = resolveApp3(ctx, input.app);
117285
+ const appRef2 = resolveApp4(ctx, input.app);
116845
117286
  return ctx.client.apps.setPreviewBranch(appRef2, input.branch);
116846
117287
  }
116847
117288
  async function previewBranchUnset(ctx, input = {}) {
116848
- const appRef2 = resolveApp3(ctx, input.app);
117289
+ const appRef2 = resolveApp4(ctx, input.app);
116849
117290
  return ctx.client.apps.unsetPreviewBranch(appRef2);
116850
117291
  }
116851
117292
  var setPreviewBranchToolInputSchema = exports_external.object({
@@ -116853,7 +117294,7 @@ var setPreviewBranchToolInputSchema = exports_external.object({
116853
117294
  branch: exports_external.string().nullable().describe("Branch to pin as the preview address; pass null to clear it.")
116854
117295
  });
116855
117296
  async function previewBranchShow(ctx, input = {}) {
116856
- const appRef2 = resolveApp3(ctx, input.app);
117297
+ const appRef2 = resolveApp4(ctx, input.app);
116857
117298
  const app = await ctx.client.apps.get(appRef2);
116858
117299
  return {
116859
117300
  previewBranch: app.previewBranch ?? null,
@@ -116862,7 +117303,7 @@ async function previewBranchShow(ctx, input = {}) {
116862
117303
  };
116863
117304
  }
116864
117305
  async function previewList(ctx, input = {}) {
116865
- const appRef2 = resolveApp3(ctx, input.app);
117306
+ const appRef2 = resolveApp4(ctx, input.app);
116866
117307
  const app = await ctx.client.apps.get(appRef2);
116867
117308
  return { app: app.name, previews: app.previews ?? [] };
116868
117309
  }
@@ -118401,7 +118842,6 @@ async function finalizeDeploy(opts) {
118401
118842
  intervalMs: 2000,
118402
118843
  timeoutMs,
118403
118844
  appName: app.name,
118404
- terminal: ["live", "failed", "replaced"],
118405
118845
  onTick: (d) => {
118406
118846
  const elapsedMs = Date.now() - buildStart;
118407
118847
  if (d.status !== lastStatus) {
@@ -118458,8 +118898,8 @@ async function finalizeDeploy(opts) {
118458
118898
  const buildMs = Date.now() - buildStart;
118459
118899
  if (deployment.isCheck && deployment.checkPassed) {
118460
118900
  const totalSeconds2 = (Date.now() - t0) / 1000;
118461
- const summary = `${app.name} check passed (${Math.round(totalSeconds2)}s) — would build and boot. The live app was not changed.`;
118462
- ctx.status(summary);
118901
+ const summary2 = `${app.name} check passed (${Math.round(totalSeconds2)}s) — would build and boot. The live app was not changed.`;
118902
+ ctx.status(summary2);
118463
118903
  return {
118464
118904
  status: "check_passed",
118465
118905
  app,
@@ -118476,7 +118916,7 @@ async function finalizeDeploy(opts) {
118476
118916
  missingBuildEnvKeys: missingBuildEnvKeys.length > 0 ? missingBuildEnvKeys : undefined,
118477
118917
  traceId: deployment.id,
118478
118918
  recovery: RECOVERY_NONE,
118479
- summary,
118919
+ summary: summary2,
118480
118920
  configPath: tomlPathFor2(ctx.cwd),
118481
118921
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
118482
118922
  };
@@ -118644,6 +119084,7 @@ async function handleUnauthorized(ctx, config2, tarball, input) {
118644
119084
  async function handleAnonymousPublish(ctx, config2, input, tarball) {
118645
119085
  const anonClient = new PercherClient({
118646
119086
  apiUrl: ctx.client.apiUrl,
119087
+ token: null,
118647
119088
  sessionId: ctx.client.sessionId
118648
119089
  });
118649
119090
  let created;
@@ -118656,7 +119097,8 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
118656
119097
  created = await anonClient.anon.createAnonApp({
118657
119098
  name: config2.app.name,
118658
119099
  powChallengeId: ch.challengeId,
118659
- powSolution: solution
119100
+ powSolution: solution,
119101
+ ...ctx.syntheticFixture ? { testFixturePermit: ctx.syntheticFixture.permit } : {}
118660
119102
  });
118661
119103
  } catch (err) {
118662
119104
  const httpStatus = err.status;
@@ -118697,13 +119139,15 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
118697
119139
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
118698
119140
  };
118699
119141
  }
118700
- if (!hasPersistedToken())
118701
- saveConfig({ token: created.token });
118702
- setAnonClaim({
118703
- app: created.app.name,
118704
- claimToken: created.claimToken,
118705
- expiresAt: created.expiresAt
118706
- });
119142
+ if (!ctx.syntheticFixture) {
119143
+ if (!hasPersistedToken())
119144
+ saveConfig({ token: created.token });
119145
+ setAnonClaim({
119146
+ app: created.app.name,
119147
+ claimToken: created.claimToken,
119148
+ expiresAt: created.expiresAt
119149
+ });
119150
+ }
118707
119151
  const newClient = new PercherClient({
118708
119152
  apiUrl: ctx.client.apiUrl,
118709
119153
  token: created.token,
@@ -118711,6 +119155,10 @@ async function handleAnonymousPublish(ctx, config2, input, tarball) {
118711
119155
  });
118712
119156
  ctx.client = newClient;
118713
119157
  ctx.setClient?.(newClient);
119158
+ if (ctx.syntheticFixture) {
119159
+ ctx.syntheticFixture.appId = created.app.id;
119160
+ ctx.syntheticFixture.created(created.app);
119161
+ }
118714
119162
  config2.app.name = created.app.name;
118715
119163
  const t0 = Date.now();
118716
119164
  const freshTarball = await createTarball({ cwd: ctx.cwd, config: config2 });
@@ -118756,14 +119204,22 @@ async function loadOrGenerate(ctx, preParsed) {
118756
119204
  async function ensureApp2(ctx, config2) {
118757
119205
  try {
118758
119206
  const app = await ctx.client.apps.get(config2.app.name);
119207
+ if (ctx.syntheticFixture && app.id !== ctx.syntheticFixture.appId) {
119208
+ throw new Error("Disposable fixture publishing requires a new app.");
119209
+ }
118759
119210
  return { app, firstDeploy: false };
118760
119211
  } catch (err) {
118761
119212
  if (err.code === "APP_NOT_FOUND") {
118762
119213
  const app = await ctx.client.apps.create({
118763
119214
  name: config2.app.name,
118764
119215
  runtime: config2.app.runtime,
118765
- framework: config2.app.framework
119216
+ framework: config2.app.framework,
119217
+ ...ctx.syntheticFixture ? { testFixturePermit: ctx.syntheticFixture.permit } : {}
118766
119218
  });
119219
+ if (ctx.syntheticFixture) {
119220
+ ctx.syntheticFixture.appId = app.id;
119221
+ ctx.syntheticFixture.created(app);
119222
+ }
118767
119223
  return { app, firstDeploy: true };
118768
119224
  }
118769
119225
  throw err;
@@ -119074,12 +119530,13 @@ async function push(ctx, input = {}, internals = {}) {
119074
119530
  });
119075
119531
  }
119076
119532
  });
119533
+ throwIfDeploymentReplaced(app.name, deployment);
119077
119534
  if (deployment.status === "failed") {
119078
119535
  const errorDetail = deployment.errorMessage ? `
119079
119536
  ${deployment.errorMessage}` : "";
119080
119537
  const fromCode = classifyByErrorCode(deployment.errorCode, deployment.errorMessage ?? "");
119081
119538
  const classified = fromCode ?? classifyError(deployment.errorMessage ?? "", "");
119082
- const recovery = classified ? recoveryFromErrorClass(classified.errorClass, {
119539
+ const recovery2 = classified ? recoveryFromErrorClass(classified.errorClass, {
119083
119540
  missingEnvVars: classified.missingEnvVars,
119084
119541
  deployId: deployment.id,
119085
119542
  appName: app.name,
@@ -119093,7 +119550,7 @@ ${deployment.errorMessage}` : "";
119093
119550
  throw new PercherCoreError(`Deployment failed (deploy ${deployment.id})${errorDetail}`, {
119094
119551
  code: "push.deploy-failed",
119095
119552
  hint: `Run \`percher deploys inspect ${deployment.id}\` to see the full build log and error. ${deployment.errorMessage ? "Fix the issue above and re-run." : "Look for the failing step in the build log."}`,
119096
- recovery
119553
+ recovery: recovery2
119097
119554
  });
119098
119555
  }
119099
119556
  const totalSec = ((Date.now() - startedAt) / 1000).toFixed(0);
@@ -119101,7 +119558,7 @@ ${deployment.errorMessage}` : "";
119101
119558
  ctx.status(displayUrl ? `Preview at ${displayUrl} (${totalSec}s)` : `Live at ${deployment.url ?? app.url} (${totalSec}s)`);
119102
119559
  const finalUrl = displayUrl ?? deployment.url ?? app.url;
119103
119560
  const fwSuffix = config2.app.framework ? ` (${config2.app.framework}, ${totalSec}s)` : ` (${totalSec}s)`;
119104
- const summary = `${app.name} ${displayUrl ? "preview deployed" : "deployed"}${fwSuffix} → ${finalUrl}`;
119561
+ const summary2 = `${app.name} ${displayUrl ? "preview deployed" : "deployed"}${fwSuffix} → ${finalUrl}`;
119105
119562
  return {
119106
119563
  app,
119107
119564
  deployment,
@@ -119109,7 +119566,7 @@ ${deployment.errorMessage}` : "";
119109
119566
  bytes: tarball.bytes,
119110
119567
  fileCount: tarball.fileCount,
119111
119568
  recovery: RECOVERY_NONE,
119112
- summary,
119569
+ summary: summary2,
119113
119570
  configPath: join26(ctx.cwd, "percher.toml"),
119114
119571
  bundle: { fileCount: tarball.fileCount, bytes: tarball.bytes }
119115
119572
  };
@@ -119381,9 +119838,11 @@ async function redeploy(ctx, input = {}) {
119381
119838
  });
119382
119839
  }
119383
119840
  const totalSeconds = (Date.now() - t0) / 1000;
119841
+ if (deployment.status === "replaced")
119842
+ return replacedDeploymentResult(app, deployment);
119384
119843
  const url2 = deployment.previewUrl ?? deployment.url ?? app.url;
119385
119844
  if (deployment.status === "failed") {
119386
- const { error: error48, recovery, summary } = await classifyDeploymentFailure({
119845
+ const { error: error48, recovery: recovery2, summary: summary2 } = await classifyDeploymentFailure({
119387
119846
  ctx,
119388
119847
  app,
119389
119848
  deployment
@@ -119395,8 +119854,8 @@ async function redeploy(ctx, input = {}) {
119395
119854
  fileCount: 0,
119396
119855
  bytes: 0,
119397
119856
  error: error48,
119398
- recovery,
119399
- summary,
119857
+ recovery: recovery2,
119858
+ summary: summary2,
119400
119859
  configPath: "",
119401
119860
  bundle: { fileCount: 0, bytes: 0 }
119402
119861
  };
@@ -119794,19 +120253,19 @@ function versionAge(iso, now = Date.now()) {
119794
120253
  return `${d}d ago`;
119795
120254
  return `${Math.floor(d / 30)}mo ago`;
119796
120255
  }
119797
- function rollbackTargetMarker(target, isLive) {
119798
- if (isLive || !target)
120256
+ function rollbackTargetMarker(target2, isLive) {
120257
+ if (isLive || !target2)
119799
120258
  return "";
119800
- if (target.mode === "rebuild")
120259
+ if (target2.mode === "rebuild")
119801
120260
  return " [rebuild required]";
119802
- if (target.mode === "none")
120261
+ if (target2.mode === "none")
119803
120262
  return " [not a rollback target]";
119804
120263
  return "";
119805
120264
  }
119806
- function rollbackTargetDetail(target, isLive) {
119807
- if (isLive || !target || target.mode === "in-window")
120265
+ function rollbackTargetDetail(target2, isLive) {
120266
+ if (isLive || !target2 || target2.mode === "in-window")
119808
120267
  return [];
119809
- const explanation = target.explanation?.trim();
120268
+ const explanation = target2.explanation?.trim();
119810
120269
  return explanation ? [` ${explanation}`] : [];
119811
120270
  }
119812
120271
  async function writeLine(ctx, line) {
@@ -119841,14 +120300,15 @@ async function resolveCommitSha(ctx, name, input) {
119841
120300
  const pick2 = versions2.slice(0, BARE_PICK_LIMIT);
119842
120301
  if (!ctx.stdinIsInteractive) {
119843
120302
  const appFlag = ` --app ${name}`;
119844
- const lines = pick2.flatMap((v, i) => {
120303
+ const lines = pick2.flatMap((v) => {
120304
+ const isLive = v.rollbackTarget?.reason === "ALREADY_LIVE";
119845
120305
  const note = v.message.split(`
119846
120306
  `)[0]?.trim() || "Published";
119847
- const marker = rollbackTargetMarker(v.rollbackTarget, i === 0);
119848
- const detail = rollbackTargetDetail(v.rollbackTarget, i === 0);
120307
+ const marker = isLive ? " (live now)" : rollbackTargetMarker(v.rollbackTarget, false);
120308
+ const detail = rollbackTargetDetail(v.rollbackTarget, isLive);
119849
120309
  const git = v.remoteSha ? ` git ${v.remoteSha.slice(0, 7)}` : "";
119850
120310
  const suffix = ` # ${note}${git} (${versionAge(v.timestamp)})${marker}`;
119851
- if (v.rollbackTarget?.mode === "none" && i !== 0) {
120311
+ if (v.rollbackTarget?.mode === "none") {
119852
120312
  return [` ${v.sha}${suffix}`, ...detail];
119853
120313
  }
119854
120314
  const rebuildFlag = v.rollbackTarget?.mode === "rebuild" ? " --rebuild" : "";
@@ -119866,10 +120326,11 @@ ${lines.join(`
119866
120326
  const note = v.message.split(`
119867
120327
  `)[0]?.trim() || "Published";
119868
120328
  const git = v.remoteSha ? ` git ${v.remoteSha.slice(0, 7)}` : "";
119869
- const live = i === 0 ? " (live now)" : "";
119870
- const marker = rollbackTargetMarker(v.rollbackTarget, i === 0);
120329
+ const isLive = v.rollbackTarget?.reason === "ALREADY_LIVE";
120330
+ const live = isLive ? " (live now)" : "";
120331
+ const marker = rollbackTargetMarker(v.rollbackTarget, isLive);
119871
120332
  await writeLine(ctx, ` ${i + 1}. ${v.sha.slice(0, 10)} ${versionAge(v.timestamp)} ${note}${git}${live}${marker}`);
119872
- for (const detail of rollbackTargetDetail(v.rollbackTarget, i === 0)) {
120333
+ for (const detail of rollbackTargetDetail(v.rollbackTarget, isLive)) {
119873
120334
  await writeLine(ctx, detail);
119874
120335
  }
119875
120336
  }
@@ -119922,6 +120383,7 @@ async function rollback(ctx, input, internals = {}) {
119922
120383
  });
119923
120384
  }
119924
120385
  });
120386
+ throwIfDeploymentReplaced(name, deployment);
119925
120387
  if (deployment.status === "failed") {
119926
120388
  throw new PercherCoreError("Rollback failed", {
119927
120389
  code: "push.deploy-failed",
@@ -119932,7 +120394,7 @@ async function rollback(ctx, input, internals = {}) {
119932
120394
  }
119933
120395
  // ../core/dist/commands/sharing.js
119934
120396
  var ShareRoleSchema = exports_external.enum(["viewer", "admin"]);
119935
- function resolveApp4(ctx, app) {
120397
+ function resolveApp5(ctx, app) {
119936
120398
  const name = app ?? readPercherTomlAppName(ctx.cwd);
119937
120399
  if (!name) {
119938
120400
  throw new PercherCoreError("No app specified and no percher.toml found", {
@@ -119960,19 +120422,19 @@ var shareRevokeInputSchema = exports_external.object({
119960
120422
  shareId: exports_external.string().min(1, "shareId is required")
119961
120423
  });
119962
120424
  async function shareList(ctx, input = {}) {
119963
- const appRef2 = resolveApp4(ctx, input.app);
120425
+ const appRef2 = resolveApp5(ctx, input.app);
119964
120426
  return ctx.client.sharing.list(appRef2);
119965
120427
  }
119966
120428
  async function shareInvite(ctx, input) {
119967
- const appRef2 = resolveApp4(ctx, input.app);
120429
+ const appRef2 = resolveApp5(ctx, input.app);
119968
120430
  return ctx.client.sharing.create(appRef2, { email: input.email, role: input.role });
119969
120431
  }
119970
120432
  async function shareSetRole(ctx, input) {
119971
- const appRef2 = resolveApp4(ctx, input.app);
120433
+ const appRef2 = resolveApp5(ctx, input.app);
119972
120434
  return ctx.client.sharing.setRole(appRef2, input.shareId, input.role);
119973
120435
  }
119974
120436
  async function shareRevoke(ctx, input) {
119975
- const appRef2 = resolveApp4(ctx, input.app);
120437
+ const appRef2 = resolveApp5(ctx, input.app);
119976
120438
  await ctx.client.sharing.revoke(appRef2, input.shareId);
119977
120439
  }
119978
120440
  var invitesListInputSchema = exports_external.object({});
@@ -120080,7 +120542,7 @@ async function tokenRevoke(ctx, input) {
120080
120542
  await ctx.client.account.revokeToken(input.id);
120081
120543
  }
120082
120544
  // ../core/dist/commands/transfers.js
120083
- function resolveApp5(ctx, app) {
120545
+ function resolveApp6(ctx, app) {
120084
120546
  const name = app ?? readPercherTomlAppName(ctx.cwd);
120085
120547
  if (!name) {
120086
120548
  throw new PercherCoreError("No app specified and no percher.toml found", {
@@ -120102,15 +120564,15 @@ var transferListForAppInputSchema = exports_external.object({
120102
120564
  app: exports_external.string().optional()
120103
120565
  });
120104
120566
  async function transferInitiate(ctx, input) {
120105
- const appRef2 = resolveApp5(ctx, input.app);
120567
+ const appRef2 = resolveApp6(ctx, input.app);
120106
120568
  return ctx.client.transfers.initiate(appRef2, { email: input.email });
120107
120569
  }
120108
120570
  async function transferCancel(ctx, input) {
120109
- const appRef2 = resolveApp5(ctx, input.app);
120571
+ const appRef2 = resolveApp6(ctx, input.app);
120110
120572
  await ctx.client.transfers.cancel(appRef2, input.transferId);
120111
120573
  }
120112
120574
  async function transferListForApp(ctx, input = {}) {
120113
- const appRef2 = resolveApp5(ctx, input.app);
120575
+ const appRef2 = resolveApp6(ctx, input.app);
120114
120576
  return ctx.client.transfers.listForApp(appRef2);
120115
120577
  }
120116
120578
  var transfersIncomingInputSchema = exports_external.object({});
@@ -120958,8 +121420,8 @@ function registerAdminCommands(cli, ctx) {
120958
121420
  if (topology?.topologyReady !== true) {
120959
121421
  await writeLine2(ctx, `${import_picocolors3.default.red("✗")} tenant topology audit is red or unavailable — no launch all-clear.`);
120960
121422
  for (const finding of topology?.findings ?? []) {
120961
- const target = finding.network ?? finding.containerId ?? finding.appId ?? "fleet";
120962
- await writeLine2(ctx, ` ${import_picocolors3.default.red("✗")} ${finding.code} [${target}] — ${finding.detail}`);
121423
+ const target2 = finding.network ?? finding.containerId ?? finding.appId ?? "fleet";
121424
+ await writeLine2(ctx, ` ${import_picocolors3.default.red("✗")} ${finding.code} [${target2}] — ${finding.detail}`);
120963
121425
  }
120964
121426
  }
120965
121427
  if (options.app || options.appId) {
@@ -120973,8 +121435,8 @@ function registerAdminCommands(cli, ctx) {
120973
121435
  await writeLine2(ctx, `${import_picocolors3.default.yellow("!")} drift: ${missing} missing route(s), ${hostDrift} missing host(s), ${extra} extra route(s)`);
120974
121436
  for (const d of drift) {
120975
121437
  const label = d.kind === "missing_route" ? import_picocolors3.default.red("MISSING") : d.kind === "missing_host" ? import_picocolors3.default.yellow("HOST_DRIFT") : import_picocolors3.default.dim("EXTRA");
120976
- const target = d.appName ? `[${d.appName}] ` : "";
120977
- await writeLine2(ctx, ` ${label} ${target}${d.routeId} (${d.routeType}) — ${d.hosts.join(", ")}`);
121438
+ const target2 = d.appName ? `[${d.appName}] ` : "";
121439
+ await writeLine2(ctx, ` ${label} ${target2}${d.routeId} (${d.routeType}) — ${d.hosts.join(", ")}`);
120978
121440
  }
120979
121441
  }
120980
121442
  await writeLine2(ctx, import_picocolors3.default.dim(`Repair: percher admin reconcile-routes${options.app ? ` --app ${options.app}` : ""}`));
@@ -121050,8 +121512,8 @@ async function printList(ctx, title, rows) {
121050
121512
 
121051
121513
  // src/commands/apps.ts
121052
121514
  var import_picocolors5 = __toESM(require_picocolors(), 1);
121053
- function assertNever2(status2, summary) {
121054
- throw new Error(`Unhandled publish status: ${JSON.stringify(status2)}${summary ? ` (${summary})` : ""}`);
121515
+ function assertNever2(status2, summary2) {
121516
+ throw new Error(`Unhandled publish status: ${JSON.stringify(status2)}${summary2 ? ` (${summary2})` : ""}`);
121055
121517
  }
121056
121518
  async function handlePublishResult(ctx, result, options = {}) {
121057
121519
  switch (result.status) {
@@ -121290,6 +121752,10 @@ function registerAppsCommands(cli, ctx) {
121290
121752
  deployId,
121291
121753
  noCache: options.cache === false
121292
121754
  });
121755
+ if (result.status === "replaced") {
121756
+ await handlePublishResult(ctx, result);
121757
+ throw new SilentExitError;
121758
+ }
121293
121759
  if (result.status === "needs_login") {
121294
121760
  await writeLine2(ctx, `${import_picocolors5.default.red("✗")} Not logged in. Run: percher login`);
121295
121761
  throw new SilentExitError;
@@ -121607,6 +122073,154 @@ function registerAuthCommands(cli, ctx) {
121607
122073
 
121608
122074
  // src/commands/data.ts
121609
122075
  var import_picocolors7 = __toESM(require_picocolors(), 1);
122076
+
122077
+ // src/commands/data-records.ts
122078
+ var DATA_RECORD_SUBCOMMANDS = new Set([
122079
+ "schema",
122080
+ "query",
122081
+ "get",
122082
+ "create",
122083
+ "update",
122084
+ "delete"
122085
+ ]);
122086
+
122087
+ class DataArgumentError extends PercherCoreError {
122088
+ constructor(message) {
122089
+ super(message, { code: "data.missing-argument" });
122090
+ }
122091
+ }
122092
+ function cacKey(name) {
122093
+ return name.replaceAll(/([a-z])-([a-z])/g, (_, a, b) => a + b.toUpperCase());
122094
+ }
122095
+ function textOption(argv, options, key, flag) {
122096
+ const parsed = options[key];
122097
+ if (parsed === undefined)
122098
+ return;
122099
+ if (typeof parsed === "string")
122100
+ return parsed;
122101
+ if (typeof parsed !== "number") {
122102
+ throw new DataArgumentError(`${flag} needs exactly one value`);
122103
+ }
122104
+ const end = argv.includes("--") ? argv.indexOf("--") : argv.length;
122105
+ let raw;
122106
+ for (let i = 0;i < end; i++) {
122107
+ const m = /^--([^=]+)(?:=(.*))?$/s.exec(argv[i] ?? "");
122108
+ if (!m || cacKey(m[1] ?? "") !== key)
122109
+ continue;
122110
+ raw = m[2] ?? argv[i + 1];
122111
+ }
122112
+ if (raw === undefined || Number(raw) !== parsed) {
122113
+ throw new DataArgumentError(`${flag} could not be read as typed`);
122114
+ }
122115
+ return raw;
122116
+ }
122117
+ function intOption(options, key, flag) {
122118
+ const parsed = options[key];
122119
+ if (parsed === undefined)
122120
+ return;
122121
+ if (typeof parsed === "number")
122122
+ return parsed;
122123
+ if (typeof parsed === "string")
122124
+ return Number(parsed);
122125
+ throw new DataArgumentError(`${flag} needs exactly one value`);
122126
+ }
122127
+ function recordPositionals(rest, options) {
122128
+ const after = Array.isArray(options["--"]) ? options["--"] : [];
122129
+ const all = [...rest, ...after];
122130
+ if (!all.every((v) => typeof v === "string")) {
122131
+ throw new DataArgumentError("Could not read the collection or record id as typed; put boolean flags after them");
122132
+ }
122133
+ return all;
122134
+ }
122135
+ function recordData2(value) {
122136
+ let parsed;
122137
+ try {
122138
+ parsed = JSON.parse(value ?? "");
122139
+ } catch {
122140
+ parsed = undefined;
122141
+ }
122142
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
122143
+ throw new PercherCoreError("--data must be a JSON object of field values", {
122144
+ code: "data.invalid-json",
122145
+ hint: `Example: --data '{"title":"Buy milk","done":false}'`
122146
+ });
122147
+ }
122148
+ return parsed;
122149
+ }
122150
+ function missing(usage) {
122151
+ throw new PercherCoreError(`Missing arguments. Usage: percher ${usage}`, {
122152
+ code: "data.missing-argument"
122153
+ });
122154
+ }
122155
+ async function runDataRecordCommand(ctx, argv, sub, rest, options) {
122156
+ const [collection, id] = recordPositionals(rest, options);
122157
+ const text = (key, flag) => textOption(argv, options, key, flag);
122158
+ const app = text("app", "--app");
122159
+ let result;
122160
+ switch (sub) {
122161
+ case "schema":
122162
+ result = await dataSchema2(ctx, dataSchemaInputSchema.parse({ app }));
122163
+ break;
122164
+ case "query":
122165
+ if (!collection)
122166
+ missing("data query <collection> [--filter …] [--app <name>]");
122167
+ result = await dataQuery(ctx, dataQueryInputSchema.parse({
122168
+ app,
122169
+ collection,
122170
+ filter: text("filter", "--filter"),
122171
+ sort: text("sort", "--sort"),
122172
+ page: intOption(options, "page", "--page"),
122173
+ perPage: intOption(options, "perPage", "--per-page"),
122174
+ fields: text("fields", "--fields")
122175
+ }));
122176
+ break;
122177
+ case "get":
122178
+ if (!collection || !id)
122179
+ missing("data get <collection> <id> [--app <name>]");
122180
+ result = await dataGet(ctx, dataGetInputSchema.parse({ app, collection, id }));
122181
+ break;
122182
+ case "create":
122183
+ if (!collection)
122184
+ missing("data create <collection> --data '<json>' [--id <id>]");
122185
+ result = await dataCreate(ctx, dataCreateInputSchema.parse({
122186
+ app,
122187
+ collection,
122188
+ data: recordData2(text("data", "--data")),
122189
+ id: text("id", "--id")
122190
+ }));
122191
+ break;
122192
+ case "update":
122193
+ if (!collection || !id)
122194
+ missing("data update <collection> <id> --data '<json>'");
122195
+ result = await dataUpdate(ctx, dataUpdateInputSchema.parse({
122196
+ app,
122197
+ collection,
122198
+ id,
122199
+ data: recordData2(text("data", "--data")),
122200
+ ifUpdated: text("ifUpdated", "--if-updated")
122201
+ }));
122202
+ break;
122203
+ case "delete":
122204
+ if (!collection || !id)
122205
+ missing("data delete <collection> <id> [--app <name>]");
122206
+ result = await dataDelete(ctx, dataDeleteInputSchema.parse({ app, collection, id }));
122207
+ break;
122208
+ default:
122209
+ return;
122210
+ }
122211
+ await writeLine2(ctx, JSON.stringify(result, null, 2));
122212
+ }
122213
+ function registerDataRecordHelp(cli) {
122214
+ const none = async () => {};
122215
+ cli.command("data schema", "List the collections and fields the data tools can use").action(none);
122216
+ cli.command("data query <collection>", "Query records (--filter, --sort, --page, --per-page, --fields)").action(none);
122217
+ cli.command("data get <collection> <id>", "Get one record").action(none);
122218
+ cli.command("data create <collection>", "Create a record from --data '<json>' (optional --id)").action(none);
122219
+ cli.command("data update <collection> <id>", "Change fields from --data '<json>' (optional --if-updated)").action(none);
122220
+ cli.command("data delete <collection> <id>", "Delete one record").action(none);
122221
+ }
122222
+
122223
+ // src/commands/data.ts
121610
122224
  var DATA_VALUE_FLAGS = new Set([
121611
122225
  "--out",
121612
122226
  "--app",
@@ -121615,7 +122229,11 @@ var DATA_VALUE_FLAGS = new Set([
121615
122229
  "--client-secret"
121616
122230
  ]);
121617
122231
  function registerDataCommands(cli, ctx, argv) {
121618
- cli.command("data [app] [...rest]", "Show app data status and collections").option("--json", "Output as JSON").option("--reveal", "(reset-superuser only) also print the plaintext password once").option("--out <path>", "(export only) Output file (default: ./<app>-pb-<timestamp>.tar.gz)").option("--provider <name>", "(oauth only) OAuth provider (default: google)").option("--app <name>", "(export, oauth) target app (default: read percher.toml)").option("--client-id <id>", "(oauth only) OAuth client id").option("--client-secret <secret>", "(oauth only) OAuth client secret (a command-line value lands in shell history)").option("--remove", "(oauth only) remove the provider instead of setting it").action(async (app, _rest, options) => {
122232
+ cli.command("data [app] [...rest]", "Show app data status and collections").option("--json", "Output as JSON").option("--reveal", "(reset-superuser only) also print the plaintext password once").option("--out <path>", "(export only) Output file (default: ./<app>-pb-<timestamp>.tar.gz)").option("--provider <name>", "(oauth only) OAuth provider (default: google)").option("--app <name>", "Target app (default: read percher.toml); names an app called like a subcommand, e.g. `data --app get`").option("--client-id <id>", "(oauth only) OAuth client id").option("--client-secret <secret>", "(oauth only) OAuth client secret (a command-line value lands in shell history)").option("--remove", "(oauth only) remove the provider instead of setting it").option("--filter <expr>", "(query only) filter over the collection's fields").option("--sort <fields>", "(query only) comma-separated fields, - for descending (write --sort=-field)").option("--page <n>", "(query only) page number").option("--per-page <n>", "(query only) records per page (max 100)").option("--fields <fields>", "(query only) comma-separated fields to return").option("--data <json>", "(create, update) field values as a JSON object").option("--id <id>", "(create only) id for the new record").option("--if-updated <timestamp>", "(update only) refuse if the record changed since").action(async (app, _rest, options) => {
122233
+ if (app !== undefined && DATA_RECORD_SUBCOMMANDS.has(app)) {
122234
+ await runDataRecordCommand(ctx, argv, app, _rest, options);
122235
+ return;
122236
+ }
121619
122237
  if (app === "reset-superuser") {
121620
122238
  const idx = argv.indexOf("reset-superuser");
121621
122239
  const realApp = idx >= 0 ? firstNonFlagAfter(argv, idx) : undefined;
@@ -121666,7 +122284,7 @@ function registerDataCommands(cli, ctx, argv) {
121666
122284
  }
121667
122285
  return;
121668
122286
  }
121669
- const result = await data(ctx, { app, json: options.json });
122287
+ const result = await data(ctx, { app: app ?? options.app, json: options.json });
121670
122288
  if (options.json) {
121671
122289
  await writeLine2(ctx, JSON.stringify(result, null, 2));
121672
122290
  } else {
@@ -121691,6 +122309,7 @@ function registerDataCommands(cli, ctx, argv) {
121691
122309
  }
121692
122310
  }
121693
122311
  });
122312
+ registerDataRecordHelp(cli);
121694
122313
  cli.command("data reset-superuser [app]", "Reset PocketBase superuser and inject new credentials").option("--reveal", "Also print the plaintext password once (default: hidden)").action(async (app, options) => {
121695
122314
  const result = await resetSuperuser(ctx, { app, reveal: options.reveal });
121696
122315
  await printSuperuserResetResult(ctx, result);
@@ -121877,10 +122496,10 @@ function registerDeploysCommands(cli, ctx, argv) {
121877
122496
  const label = v.channel ? channelLabels[v.channel] ?? v.channel : null;
121878
122497
  const git = v.remoteSha ? ` · git ${v.remoteSha.slice(0, 7)}` : "";
121879
122498
  const suffix = `${label ? ` · via ${label}` : ""}${git}`;
121880
- const target = v.rollbackTarget;
121881
- const marker = target && target.mode !== "in-window" ? target.mode === "rebuild" ? "[rebuild required]" : "[not a rollback target]" : null;
121882
- if (marker && target)
121883
- reasons.set(marker, target.explanation);
122499
+ const target2 = v.rollbackTarget;
122500
+ const marker = target2 && target2.mode !== "in-window" ? target2.mode === "rebuild" ? "[rebuild required]" : "[not a rollback target]" : null;
122501
+ if (marker && target2)
122502
+ reasons.set(marker, target2.explanation);
121884
122503
  await writeLine2(ctx, `${v.sha} ${v.timestamp} ${message}${noteLabel ? ` · ${noteLabel}` : ""}${suffix}${marker ? ` ${marker}` : ""}`);
121885
122504
  }
121886
122505
  for (const [marker, explanation] of reasons) {
@@ -121895,8 +122514,8 @@ ${marker} ${explanation}`);
121895
122514
  head,
121896
122515
  patch: options.patch
121897
122516
  });
121898
- const { summary, files } = result;
121899
- await writeLine2(ctx, `${summary.filesChanged} file${summary.filesChanged === 1 ? "" : "s"} changed · ${import_picocolors8.default.green(`+${summary.additions}`)} ${import_picocolors8.default.red(`−${summary.deletions}`)} (${result.base.slice(0, 10)} → ${result.head.slice(0, 10)})`);
122517
+ const { summary: summary2, files } = result;
122518
+ await writeLine2(ctx, `${summary2.filesChanged} file${summary2.filesChanged === 1 ? "" : "s"} changed · ${import_picocolors8.default.green(`+${summary2.additions}`)} ${import_picocolors8.default.red(`−${summary2.deletions}`)} (${result.base.slice(0, 10)} → ${result.head.slice(0, 10)})`);
121900
122519
  for (const f of files) {
121901
122520
  const stat3 = f.binary ? import_picocolors8.default.dim("binary") : `${import_picocolors8.default.green(`+${f.additions}`)} ${import_picocolors8.default.red(`−${f.deletions}`)}`;
121902
122521
  await writeLine2(ctx, ` ${f.status} ${f.path} ${stat3}${f.truncated ? import_picocolors8.default.dim(" (truncated)") : ""}`);
@@ -122597,7 +123216,7 @@ import { createInterface } from "node:readline";
122597
123216
  // package.json
122598
123217
  var package_default2 = {
122599
123218
  name: "percher",
122600
- version: "1.2.0",
123219
+ version: "1.3.0",
122601
123220
  description: "CLI for the Percher hosting platform — publish apps with one command",
122602
123221
  type: "module",
122603
123222
  bin: {
@@ -122625,9 +123244,9 @@ var package_default2 = {
122625
123244
  typecheck: "tsc --noEmit"
122626
123245
  },
122627
123246
  dependencies: {
122628
- "@percher/client": "^1.2.0",
122629
- "@percher/core": "^1.2.0",
122630
- "@percher/toml": "^1.0.3",
123247
+ "@percher/client": "^1.3.0",
123248
+ "@percher/core": "^1.3.0",
123249
+ "@percher/toml": "^1.0.4",
122631
123250
  cac: "^7.0.0",
122632
123251
  picocolors: "^1.1.1"
122633
123252
  },