@tanstack/cli 0.69.5 → 0.69.6

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.
@@ -0,0 +1,48 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ const partnerTierOrder = {
3
+ gold: 0,
4
+ silver: 1,
5
+ bronze: 2,
6
+ };
7
+ const cliSessionSeed = randomUUID();
8
+ function hashString(value) {
9
+ let hash = 2166136261;
10
+ for (let index = 0; index < value.length; index++) {
11
+ hash ^= value.charCodeAt(index);
12
+ hash = Math.imul(hash, 16777619);
13
+ }
14
+ return hash >>> 0;
15
+ }
16
+ function compareIdentity(left, right) {
17
+ const nameComparison = left.name.localeCompare(right.name);
18
+ return nameComparison || left.id.localeCompare(right.id);
19
+ }
20
+ function compareSeededPartnerOrder(left, right, seed) {
21
+ const leftWeight = left.partner.placementWeight ?? 1;
22
+ const rightWeight = right.partner.placementWeight ?? 1;
23
+ const leftRandom = (hashString(`${seed}:${left.partner.id}`) + 1) / 4294967297;
24
+ const rightRandom = (hashString(`${seed}:${right.partner.id}`) + 1) / 4294967297;
25
+ const seededComparison = -Math.log(leftRandom) / leftWeight + Math.log(rightRandom) / rightWeight;
26
+ return seededComparison || compareIdentity(left, right);
27
+ }
28
+ export function orderAddOnsForPartnerPlacement(addOns, surface, sessionSeed = cliSessionSeed) {
29
+ const rotationSeed = `${surface}:${sessionSeed}`;
30
+ const partners = addOns
31
+ .filter((addOn) => addOn.partner)
32
+ .sort((left, right) => {
33
+ const tierComparison = partnerTierOrder[left.partner.tier] -
34
+ partnerTierOrder[right.partner.tier];
35
+ if (tierComparison !== 0) {
36
+ return tierComparison;
37
+ }
38
+ if (surface === 'deployment' && left.partner.id === 'cloudflare') {
39
+ return -1;
40
+ }
41
+ if (surface === 'deployment' && right.partner.id === 'cloudflare') {
42
+ return 1;
43
+ }
44
+ return compareSeededPartnerOrder(left, right, rotationSeed);
45
+ });
46
+ const nonPartners = addOns.filter((addOn) => !addOn.partner);
47
+ return [...partners, ...nonPartners];
48
+ }
@@ -0,0 +1,2 @@
1
+ import type { AddOn } from '@tanstack/create';
2
+ export declare function orderAddOnsForPartnerPlacement(addOns: Array<AddOn>, surface: string, sessionSeed?: `${string}-${string}-${string}-${string}-${string}`): AddOn[];
@@ -1,6 +1,7 @@
1
1
  import { cancel, confirm, isCancel, multiselect, note, password, select, text, } from '@clack/prompts';
2
2
  import { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getAllAddOns, } from '@tanstack/create';
3
3
  import { isCurrentDirectoryProjectNameInput, validateProjectName, } from './utils.js';
4
+ import { orderAddOnsForPartnerPlacement } from './partner-placement.js';
4
5
  export async function selectFramework(frameworks, defaultFrameworkId) {
5
6
  const initialValue = (defaultFrameworkId &&
6
7
  frameworks.find((f) => f.id.toLowerCase() === defaultFrameworkId.toLowerCase())?.id) ||
@@ -101,7 +102,7 @@ export async function selectAddOns(framework, mode, type, message, forcedAddOns
101
102
  return [];
102
103
  }
103
104
  if (allowMultiple) {
104
- const selectableAddOns = addOns.filter((addOn) => !forcedAddOns.includes(addOn.id));
105
+ const selectableAddOns = orderAddOnsForPartnerPlacement(addOns.filter((addOn) => !forcedAddOns.includes(addOn.id)), 'add-ons');
105
106
  if (selectableAddOns.length === 0) {
106
107
  return [];
107
108
  }
@@ -272,20 +273,19 @@ export async function promptForEnvVars(addOns) {
272
273
  export async function selectDeployment(framework, deployment, forcedDeployment) {
273
274
  const deployments = new Set();
274
275
  let initialValue = undefined;
275
- for (const addOn of framework
276
+ for (const addOn of orderAddOnsForPartnerPlacement(framework
276
277
  .getAddOns()
277
- .sort((a, b) => a.name.localeCompare(b.name))) {
278
- if (addOn.type === 'deployment') {
279
- deployments.add(addOn);
280
- if (deployment && addOn.id === deployment) {
281
- return deployment;
282
- }
283
- if (forcedDeployment && addOn.id === forcedDeployment) {
284
- initialValue = addOn.id;
285
- }
286
- else if (!initialValue && addOn.default) {
287
- initialValue = addOn.id;
288
- }
278
+ .filter((addOn) => addOn.type === 'deployment')
279
+ .sort((a, b) => a.name.localeCompare(b.name)), 'deployment')) {
280
+ deployments.add(addOn);
281
+ if (deployment && addOn.id === deployment) {
282
+ return deployment;
283
+ }
284
+ if (forcedDeployment && addOn.id === forcedDeployment) {
285
+ initialValue = addOn.id;
286
+ }
287
+ else if (!initialValue && addOn.default) {
288
+ initialValue = addOn.id;
289
289
  }
290
290
  }
291
291
  if (deployments.size === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cli",
3
- "version": "0.69.5",
3
+ "version": "0.69.6",
4
4
  "description": "TanStack CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -44,7 +44,7 @@
44
44
  "tempy": "^3.1.0",
45
45
  "validate-npm-package-name": "^7.0.0",
46
46
  "zod": "^3.24.2",
47
- "@tanstack/create": "0.68.4"
47
+ "@tanstack/create": "0.68.5"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@playwright/test": "^1.58.2",