@shipfox/client-projects 12.0.2 → 14.0.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.
Files changed (111) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +64 -0
  3. package/dist/chrome.d.ts +5 -1
  4. package/dist/chrome.d.ts.map +1 -1
  5. package/dist/chrome.js +18 -26
  6. package/dist/chrome.js.map +1 -1
  7. package/dist/components/model-provider-reminder-banner.d.ts.map +1 -1
  8. package/dist/components/model-provider-reminder-banner.js +4 -2
  9. package/dist/components/model-provider-reminder-banner.js.map +1 -1
  10. package/dist/components/project-crumb.d.ts +3 -1
  11. package/dist/components/project-crumb.d.ts.map +1 -1
  12. package/dist/components/project-crumb.js +7 -5
  13. package/dist/components/project-crumb.js.map +1 -1
  14. package/dist/components/project-switcher.d.ts +2 -1
  15. package/dist/components/project-switcher.d.ts.map +1 -1
  16. package/dist/components/project-switcher.js +10 -8
  17. package/dist/components/project-switcher.js.map +1 -1
  18. package/dist/core/definition.d.ts +6 -0
  19. package/dist/core/definition.d.ts.map +1 -1
  20. package/dist/core/definition.js.map +1 -1
  21. package/dist/core/project.d.ts +7 -0
  22. package/dist/core/project.d.ts.map +1 -1
  23. package/dist/core/project.js.map +1 -1
  24. package/dist/feature.d.ts +29 -5
  25. package/dist/feature.d.ts.map +1 -1
  26. package/dist/feature.js +26 -5
  27. package/dist/feature.js.map +1 -1
  28. package/dist/hooks/api/mappers.d.ts.map +1 -1
  29. package/dist/hooks/api/mappers.js +9 -1
  30. package/dist/hooks/api/mappers.js.map +1 -1
  31. package/dist/hooks/api/projects.d.ts +21 -2
  32. package/dist/hooks/api/projects.d.ts.map +1 -1
  33. package/dist/hooks/api/projects.js +175 -2
  34. package/dist/hooks/api/projects.js.map +1 -1
  35. package/dist/index.d.ts +3 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/pages/create-project-page.d.ts.map +1 -1
  40. package/dist/pages/create-project-page.js +97 -21
  41. package/dist/pages/create-project-page.js.map +1 -1
  42. package/dist/pages/create-project-page.stories.js +5 -3
  43. package/dist/pages/create-project-page.stories.js.map +1 -1
  44. package/dist/pages/project-settings-form-errors.d.ts +11 -0
  45. package/dist/pages/project-settings-form-errors.d.ts.map +1 -0
  46. package/dist/pages/project-settings-form-errors.js +16 -0
  47. package/dist/pages/project-settings-form-errors.js.map +1 -0
  48. package/dist/pages/project-settings-page.d.ts +2 -0
  49. package/dist/pages/project-settings-page.d.ts.map +1 -0
  50. package/dist/pages/project-settings-page.js +225 -0
  51. package/dist/pages/project-settings-page.js.map +1 -0
  52. package/dist/pages/project-settings-page.stories.d.ts +23 -0
  53. package/dist/pages/project-settings-page.stories.d.ts.map +1 -0
  54. package/dist/pages/project-settings-page.stories.js +206 -0
  55. package/dist/pages/project-settings-page.stories.js.map +1 -0
  56. package/dist/pages/projects-hub-page.js +11 -11
  57. package/dist/pages/projects-hub-page.js.map +1 -1
  58. package/dist/project-error.d.ts +1 -0
  59. package/dist/project-error.d.ts.map +1 -1
  60. package/dist/project-error.js +7 -0
  61. package/dist/project-error.js.map +1 -1
  62. package/dist/routes/inputs.d.ts +2 -2
  63. package/dist/routes/inputs.d.ts.map +1 -1
  64. package/dist/routes/inputs.js +5 -5
  65. package/dist/routes/inputs.js.map +1 -1
  66. package/dist/routes/project-index.d.ts +2 -2
  67. package/dist/routes/project-index.d.ts.map +1 -1
  68. package/dist/routes/project-index.js +3 -3
  69. package/dist/routes/project-index.js.map +1 -1
  70. package/dist/routes/project-settings-index.d.ts +10 -0
  71. package/dist/routes/project-settings-index.d.ts.map +1 -0
  72. package/dist/routes/project-settings-index.js +12 -0
  73. package/dist/routes/project-settings-index.js.map +1 -0
  74. package/dist/routes/project-settings.d.ts +6 -0
  75. package/dist/routes/project-settings.d.ts.map +1 -0
  76. package/dist/routes/project-settings.js +7 -0
  77. package/dist/routes/project-settings.js.map +1 -0
  78. package/dist/tsconfig.test.tsbuildinfo +1 -1
  79. package/package.json +11 -10
  80. package/src/chrome.tsx +27 -19
  81. package/src/components/model-provider-reminder-banner.tsx +3 -1
  82. package/src/components/project-crumb.tsx +18 -5
  83. package/src/components/project-switcher.test.tsx +7 -4
  84. package/src/components/project-switcher.tsx +16 -5
  85. package/src/core/definition.ts +7 -0
  86. package/src/core/project.ts +8 -0
  87. package/src/feature.ts +26 -4
  88. package/src/hooks/api/mappers.test.ts +19 -0
  89. package/src/hooks/api/mappers.ts +6 -0
  90. package/src/hooks/api/projects.test.ts +247 -1
  91. package/src/hooks/api/projects.ts +227 -2
  92. package/src/index.ts +9 -1
  93. package/src/pages/create-project-page.stories.tsx +5 -4
  94. package/src/pages/create-project-page.test.tsx +191 -12
  95. package/src/pages/create-project-page.tsx +102 -15
  96. package/src/pages/home-router.test.tsx +2 -2
  97. package/src/pages/project-settings-form-errors.ts +17 -0
  98. package/src/pages/project-settings-page.stories.tsx +216 -0
  99. package/src/pages/project-settings-page.test.tsx +74 -0
  100. package/src/pages/project-settings-page.tsx +220 -0
  101. package/src/pages/projects-hub-page.test.tsx +17 -11
  102. package/src/pages/projects-hub-page.tsx +9 -9
  103. package/src/project-error.test.ts +1 -0
  104. package/src/project-error.ts +8 -0
  105. package/src/routes/inputs.test.ts +8 -6
  106. package/src/routes/inputs.ts +7 -6
  107. package/src/routes/project-index.tsx +3 -3
  108. package/src/routes/project-settings-index.tsx +11 -0
  109. package/src/routes/project-settings.tsx +4 -0
  110. package/test/pages.tsx +26 -22
  111. package/tsconfig.build.tsbuildinfo +1 -1
package/dist/feature.js CHANGED
@@ -4,31 +4,52 @@ export const projectsNavigation = [
4
4
  id: 'nav.projects',
5
5
  scope: 'workspace',
6
6
  label: 'Projects',
7
- to: '/workspaces/$wid',
7
+ to: '/w/$workspaceSlug',
8
8
  exact: true,
9
9
  order: 100
10
10
  }
11
11
  ];
12
+ export const projectSettingsSections = [
13
+ {
14
+ id: 'settings.project-general',
15
+ scope: 'project',
16
+ pathSegment: 'general',
17
+ label: 'General',
18
+ icon: 'settings3Line',
19
+ order: 50
20
+ }
21
+ ];
12
22
  export const projectsFeature = defineClientFeature({
13
23
  id: 'shipfox.projects',
14
24
  routes: [
15
25
  {
16
- path: '/workspaces/$wid',
26
+ path: '/w/$workspaceSlug',
17
27
  parent: 'workspaceLayout',
18
28
  impl: '@shipfox/client-projects/routes/home'
19
29
  },
20
30
  {
21
- path: '/workspaces/$wid/projects/new',
31
+ path: '/w/$workspaceSlug/projects/new',
22
32
  parent: 'workspaceLayout',
23
33
  impl: '@shipfox/client-projects/routes/create-project'
24
34
  },
25
35
  {
26
- path: '/workspaces/$wid/projects/$pid',
36
+ path: '/w/$workspaceSlug/p/$projectSlug',
27
37
  parent: 'projectLayout',
28
38
  impl: '@shipfox/client-projects/routes/project-index'
39
+ },
40
+ {
41
+ path: '/w/$workspaceSlug/p/$projectSlug/settings',
42
+ parent: 'projectSettings',
43
+ impl: '@shipfox/client-projects/routes/project-settings-index'
44
+ },
45
+ {
46
+ path: '/w/$workspaceSlug/p/$projectSlug/settings/general',
47
+ parent: 'projectSettings',
48
+ impl: '@shipfox/client-projects/routes/project-settings'
29
49
  }
30
50
  ],
31
- navigation: projectsNavigation
51
+ navigation: projectsNavigation,
52
+ settingsSections: projectSettingsSections
32
53
  });
33
54
 
34
55
  //# sourceMappingURL=feature.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type NavTabEntry} from '@shipfox/client-shell';\n\nexport const projectsNavigation = [\n {\n id: 'nav.projects',\n scope: 'workspace',\n label: 'Projects',\n to: '/workspaces/$wid',\n exact: true,\n order: 100,\n },\n] as const satisfies readonly NavTabEntry[];\n\nexport const projectsFeature = defineClientFeature({\n id: 'shipfox.projects',\n routes: [\n {\n path: '/workspaces/$wid',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-projects/routes/home',\n },\n {\n path: '/workspaces/$wid/projects/new',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-projects/routes/create-project',\n },\n {\n path: '/workspaces/$wid/projects/$pid',\n parent: 'projectLayout',\n impl: '@shipfox/client-projects/routes/project-index',\n },\n ],\n navigation: projectsNavigation,\n});\n"],"names":["defineClientFeature","projectsNavigation","id","scope","label","to","exact","order","projectsFeature","routes","path","parent","impl","navigation"],"mappings":"AAAA,SAAQA,mBAAmB,QAAyB,wBAAwB;AAE5E,OAAO,MAAMC,qBAAqB;IAChC;QACEC,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;QACPC,OAAO;IACT;CACD,CAA2C;AAE5C,OAAO,MAAMC,kBAAkBR,oBAAoB;IACjDE,IAAI;IACJO,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,YAAYZ;AACd,GAAG"}
1
+ {"version":3,"sources":["../src/feature.ts"],"sourcesContent":["import {defineClientFeature, type NavTabEntry} from '@shipfox/client-shell';\n\nexport const projectsNavigation = [\n {\n id: 'nav.projects',\n scope: 'workspace',\n label: 'Projects',\n to: '/w/$workspaceSlug',\n exact: true,\n order: 100,\n },\n] as const satisfies readonly NavTabEntry[];\n\nexport const projectSettingsSections = [\n {\n id: 'settings.project-general',\n scope: 'project',\n pathSegment: 'general',\n label: 'General',\n icon: 'settings3Line',\n order: 50,\n },\n] as const;\n\nexport const projectsFeature = defineClientFeature({\n id: 'shipfox.projects',\n routes: [\n {\n path: '/w/$workspaceSlug',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-projects/routes/home',\n },\n {\n path: '/w/$workspaceSlug/projects/new',\n parent: 'workspaceLayout',\n impl: '@shipfox/client-projects/routes/create-project',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug',\n parent: 'projectLayout',\n impl: '@shipfox/client-projects/routes/project-index',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/settings',\n parent: 'projectSettings',\n impl: '@shipfox/client-projects/routes/project-settings-index',\n },\n {\n path: '/w/$workspaceSlug/p/$projectSlug/settings/general',\n parent: 'projectSettings',\n impl: '@shipfox/client-projects/routes/project-settings',\n },\n ],\n navigation: projectsNavigation,\n settingsSections: projectSettingsSections,\n});\n"],"names":["defineClientFeature","projectsNavigation","id","scope","label","to","exact","order","projectSettingsSections","pathSegment","icon","projectsFeature","routes","path","parent","impl","navigation","settingsSections"],"mappings":"AAAA,SAAQA,mBAAmB,QAAyB,wBAAwB;AAE5E,OAAO,MAAMC,qBAAqB;IAChC;QACEC,IAAI;QACJC,OAAO;QACPC,OAAO;QACPC,IAAI;QACJC,OAAO;QACPC,OAAO;IACT;CACD,CAA2C;AAE5C,OAAO,MAAMC,0BAA0B;IACrC;QACEN,IAAI;QACJC,OAAO;QACPM,aAAa;QACbL,OAAO;QACPM,MAAM;QACNH,OAAO;IACT;CACD,CAAU;AAEX,OAAO,MAAMI,kBAAkBX,oBAAoB;IACjDE,IAAI;IACJU,QAAQ;QACN;YACEC,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;QACA;YACEF,MAAM;YACNC,QAAQ;YACRC,MAAM;QACR;KACD;IACDC,YAAYf;IACZgB,kBAAkBT;AACpB,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,wBAAwB,EAAC,MAAM,8BAA8B,CAAC;AAC1F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE3D,wBAAgB,SAAS,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAY1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IACjC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,GAAG,WAAW,CAEd;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAgB3D;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,wBAAwB,GAAG,qBAAqB,CAU5F;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE;IACpC,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,IAAI,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,GAAG,cAAc,CAMjB"}
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,wBAAwB,EAAC,MAAM,8BAA8B,CAAC;AAC1F,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAC,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE3D,wBAAgB,SAAS,CAAC,GAAG,EAAE,kBAAkB,GAAG,OAAO,CAa1D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE;IACjC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,GAAG,WAAW,CAEd;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,UAAU,CAgB3D;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,wBAAwB,GAAG,qBAAqB,CAe5F;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE;IACpC,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,IAAI,EAAE,wBAAwB,GAAG,IAAI,CAAC;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,GAAG,cAAc,CAMjB"}
@@ -3,6 +3,7 @@ export function toProject(dto) {
3
3
  id: dto.id,
4
4
  workspaceId: dto.workspace_id,
5
5
  name: dto.name,
6
+ slug: dto.slug,
6
7
  source: {
7
8
  connectionId: dto.source.connection_id,
8
9
  externalRepositoryId: dto.source.external_repository_id
@@ -42,7 +43,14 @@ export function toDefinitionSyncSummary(dto) {
42
43
  startedAt: dto.started_at,
43
44
  finishedAt: dto.finished_at,
44
45
  lastErrorCode: dto.last_error_code,
45
- lastErrorMessage: dto.last_error_message
46
+ lastErrorMessage: dto.last_error_message,
47
+ warnings: dto.warnings.map((warning)=>({
48
+ code: warning.code,
49
+ message: warning.message,
50
+ ...warning.path === undefined ? {} : {
51
+ path: warning.path
52
+ }
53
+ }))
46
54
  };
47
55
  }
48
56
  export function toDefinitionList(dto) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/api/mappers.ts"],"sourcesContent":["import type {DefinitionDto, DefinitionSyncSummaryDto} from '@shipfox/api-definitions-dto';\nimport type {ProjectResponseDto} from '@shipfox/api-projects-dto';\nimport type {Definition, DefinitionList, DefinitionSyncSummary} from '#core/definition.js';\nimport type {Project, ProjectList} from '#core/project.js';\n\nexport function toProject(dto: ProjectResponseDto): Project {\n return {\n id: dto.id,\n workspaceId: dto.workspace_id,\n name: dto.name,\n source: {\n connectionId: dto.source.connection_id,\n externalRepositoryId: dto.source.external_repository_id,\n },\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n };\n}\n\nexport function toProjectList(dto: {\n projects: ProjectResponseDto[];\n next_cursor: string | null;\n}): ProjectList {\n return {projects: dto.projects.map(toProject), nextCursor: dto.next_cursor};\n}\n\nexport function toDefinition(dto: DefinitionDto): Definition {\n return {\n id: dto.id,\n projectId: dto.project_id,\n configPath: dto.config_path,\n source: dto.source,\n sha: dto.sha,\n ref: dto.ref,\n name: dto.name,\n workflowDocument: dto.workflow_document,\n workflowModel: dto.workflow_model,\n manualTrigger: dto.manual_trigger,\n fetchedAt: dto.fetched_at,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n };\n}\n\nexport function toDefinitionSyncSummary(dto: DefinitionSyncSummaryDto): DefinitionSyncSummary {\n return {\n ref: dto.ref,\n status: dto.status,\n lastSyncAt: dto.last_sync_at,\n startedAt: dto.started_at,\n finishedAt: dto.finished_at,\n lastErrorCode: dto.last_error_code,\n lastErrorMessage: dto.last_error_message,\n };\n}\n\nexport function toDefinitionList(dto: {\n definitions: DefinitionDto[];\n sync: DefinitionSyncSummaryDto | null;\n next_cursor: string | null;\n}): DefinitionList {\n return {\n definitions: dto.definitions.map(toDefinition),\n sync: dto.sync && toDefinitionSyncSummary(dto.sync),\n nextCursor: dto.next_cursor,\n };\n}\n"],"names":["toProject","dto","id","workspaceId","workspace_id","name","source","connectionId","connection_id","externalRepositoryId","external_repository_id","createdAt","created_at","updatedAt","updated_at","toProjectList","projects","map","nextCursor","next_cursor","toDefinition","projectId","project_id","configPath","config_path","sha","ref","workflowDocument","workflow_document","workflowModel","workflow_model","manualTrigger","manual_trigger","fetchedAt","fetched_at","toDefinitionSyncSummary","status","lastSyncAt","last_sync_at","startedAt","started_at","finishedAt","finished_at","lastErrorCode","last_error_code","lastErrorMessage","last_error_message","toDefinitionList","definitions","sync"],"mappings":"AAKA,OAAO,SAASA,UAAUC,GAAuB;IAC/C,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,aAAaF,IAAIG,YAAY;QAC7BC,MAAMJ,IAAII,IAAI;QACdC,QAAQ;YACNC,cAAcN,IAAIK,MAAM,CAACE,aAAa;YACtCC,sBAAsBR,IAAIK,MAAM,CAACI,sBAAsB;QACzD;QACAC,WAAWV,IAAIW,UAAU;QACzBC,WAAWZ,IAAIa,UAAU;IAC3B;AACF;AAEA,OAAO,SAASC,cAAcd,GAG7B;IACC,OAAO;QAACe,UAAUf,IAAIe,QAAQ,CAACC,GAAG,CAACjB;QAAYkB,YAAYjB,IAAIkB,WAAW;IAAA;AAC5E;AAEA,OAAO,SAASC,aAAanB,GAAkB;IAC7C,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVmB,WAAWpB,IAAIqB,UAAU;QACzBC,YAAYtB,IAAIuB,WAAW;QAC3BlB,QAAQL,IAAIK,MAAM;QAClBmB,KAAKxB,IAAIwB,GAAG;QACZC,KAAKzB,IAAIyB,GAAG;QACZrB,MAAMJ,IAAII,IAAI;QACdsB,kBAAkB1B,IAAI2B,iBAAiB;QACvCC,eAAe5B,IAAI6B,cAAc;QACjCC,eAAe9B,IAAI+B,cAAc;QACjCC,WAAWhC,IAAIiC,UAAU;QACzBvB,WAAWV,IAAIW,UAAU;QACzBC,WAAWZ,IAAIa,UAAU;IAC3B;AACF;AAEA,OAAO,SAASqB,wBAAwBlC,GAA6B;IACnE,OAAO;QACLyB,KAAKzB,IAAIyB,GAAG;QACZU,QAAQnC,IAAImC,MAAM;QAClBC,YAAYpC,IAAIqC,YAAY;QAC5BC,WAAWtC,IAAIuC,UAAU;QACzBC,YAAYxC,IAAIyC,WAAW;QAC3BC,eAAe1C,IAAI2C,eAAe;QAClCC,kBAAkB5C,IAAI6C,kBAAkB;IAC1C;AACF;AAEA,OAAO,SAASC,iBAAiB9C,GAIhC;IACC,OAAO;QACL+C,aAAa/C,IAAI+C,WAAW,CAAC/B,GAAG,CAACG;QACjC6B,MAAMhD,IAAIgD,IAAI,IAAId,wBAAwBlC,IAAIgD,IAAI;QAClD/B,YAAYjB,IAAIkB,WAAW;IAC7B;AACF"}
1
+ {"version":3,"sources":["../../../src/hooks/api/mappers.ts"],"sourcesContent":["import type {DefinitionDto, DefinitionSyncSummaryDto} from '@shipfox/api-definitions-dto';\nimport type {ProjectResponseDto} from '@shipfox/api-projects-dto';\nimport type {Definition, DefinitionList, DefinitionSyncSummary} from '#core/definition.js';\nimport type {Project, ProjectList} from '#core/project.js';\n\nexport function toProject(dto: ProjectResponseDto): Project {\n return {\n id: dto.id,\n workspaceId: dto.workspace_id,\n name: dto.name,\n slug: dto.slug,\n source: {\n connectionId: dto.source.connection_id,\n externalRepositoryId: dto.source.external_repository_id,\n },\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n };\n}\n\nexport function toProjectList(dto: {\n projects: ProjectResponseDto[];\n next_cursor: string | null;\n}): ProjectList {\n return {projects: dto.projects.map(toProject), nextCursor: dto.next_cursor};\n}\n\nexport function toDefinition(dto: DefinitionDto): Definition {\n return {\n id: dto.id,\n projectId: dto.project_id,\n configPath: dto.config_path,\n source: dto.source,\n sha: dto.sha,\n ref: dto.ref,\n name: dto.name,\n workflowDocument: dto.workflow_document,\n workflowModel: dto.workflow_model,\n manualTrigger: dto.manual_trigger,\n fetchedAt: dto.fetched_at,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n };\n}\n\nexport function toDefinitionSyncSummary(dto: DefinitionSyncSummaryDto): DefinitionSyncSummary {\n return {\n ref: dto.ref,\n status: dto.status,\n lastSyncAt: dto.last_sync_at,\n startedAt: dto.started_at,\n finishedAt: dto.finished_at,\n lastErrorCode: dto.last_error_code,\n lastErrorMessage: dto.last_error_message,\n warnings: dto.warnings.map((warning) => ({\n code: warning.code,\n message: warning.message,\n ...(warning.path === undefined ? {} : {path: warning.path}),\n })),\n };\n}\n\nexport function toDefinitionList(dto: {\n definitions: DefinitionDto[];\n sync: DefinitionSyncSummaryDto | null;\n next_cursor: string | null;\n}): DefinitionList {\n return {\n definitions: dto.definitions.map(toDefinition),\n sync: dto.sync && toDefinitionSyncSummary(dto.sync),\n nextCursor: dto.next_cursor,\n };\n}\n"],"names":["toProject","dto","id","workspaceId","workspace_id","name","slug","source","connectionId","connection_id","externalRepositoryId","external_repository_id","createdAt","created_at","updatedAt","updated_at","toProjectList","projects","map","nextCursor","next_cursor","toDefinition","projectId","project_id","configPath","config_path","sha","ref","workflowDocument","workflow_document","workflowModel","workflow_model","manualTrigger","manual_trigger","fetchedAt","fetched_at","toDefinitionSyncSummary","status","lastSyncAt","last_sync_at","startedAt","started_at","finishedAt","finished_at","lastErrorCode","last_error_code","lastErrorMessage","last_error_message","warnings","warning","code","message","path","undefined","toDefinitionList","definitions","sync"],"mappings":"AAKA,OAAO,SAASA,UAAUC,GAAuB;IAC/C,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVC,aAAaF,IAAIG,YAAY;QAC7BC,MAAMJ,IAAII,IAAI;QACdC,MAAML,IAAIK,IAAI;QACdC,QAAQ;YACNC,cAAcP,IAAIM,MAAM,CAACE,aAAa;YACtCC,sBAAsBT,IAAIM,MAAM,CAACI,sBAAsB;QACzD;QACAC,WAAWX,IAAIY,UAAU;QACzBC,WAAWb,IAAIc,UAAU;IAC3B;AACF;AAEA,OAAO,SAASC,cAAcf,GAG7B;IACC,OAAO;QAACgB,UAAUhB,IAAIgB,QAAQ,CAACC,GAAG,CAAClB;QAAYmB,YAAYlB,IAAImB,WAAW;IAAA;AAC5E;AAEA,OAAO,SAASC,aAAapB,GAAkB;IAC7C,OAAO;QACLC,IAAID,IAAIC,EAAE;QACVoB,WAAWrB,IAAIsB,UAAU;QACzBC,YAAYvB,IAAIwB,WAAW;QAC3BlB,QAAQN,IAAIM,MAAM;QAClBmB,KAAKzB,IAAIyB,GAAG;QACZC,KAAK1B,IAAI0B,GAAG;QACZtB,MAAMJ,IAAII,IAAI;QACduB,kBAAkB3B,IAAI4B,iBAAiB;QACvCC,eAAe7B,IAAI8B,cAAc;QACjCC,eAAe/B,IAAIgC,cAAc;QACjCC,WAAWjC,IAAIkC,UAAU;QACzBvB,WAAWX,IAAIY,UAAU;QACzBC,WAAWb,IAAIc,UAAU;IAC3B;AACF;AAEA,OAAO,SAASqB,wBAAwBnC,GAA6B;IACnE,OAAO;QACL0B,KAAK1B,IAAI0B,GAAG;QACZU,QAAQpC,IAAIoC,MAAM;QAClBC,YAAYrC,IAAIsC,YAAY;QAC5BC,WAAWvC,IAAIwC,UAAU;QACzBC,YAAYzC,IAAI0C,WAAW;QAC3BC,eAAe3C,IAAI4C,eAAe;QAClCC,kBAAkB7C,IAAI8C,kBAAkB;QACxCC,UAAU/C,IAAI+C,QAAQ,CAAC9B,GAAG,CAAC,CAAC+B,UAAa,CAAA;gBACvCC,MAAMD,QAAQC,IAAI;gBAClBC,SAASF,QAAQE,OAAO;gBACxB,GAAIF,QAAQG,IAAI,KAAKC,YAAY,CAAC,IAAI;oBAACD,MAAMH,QAAQG,IAAI;gBAAA,CAAC;YAC5D,CAAA;IACF;AACF;AAEA,OAAO,SAASE,iBAAiBrD,GAIhC;IACC,OAAO;QACLsD,aAAatD,IAAIsD,WAAW,CAACrC,GAAG,CAACG;QACjCmC,MAAMvD,IAAIuD,IAAI,IAAIpB,wBAAwBnC,IAAIuD,IAAI;QAClDrC,YAAYlB,IAAImB,WAAW;IAC7B;AACF"}
@@ -1,16 +1,19 @@
1
- import { type InfiniteData, type UseInfiniteQueryOptions, type UseQueryOptions } from '@tanstack/react-query';
2
- import type { CreateProjectCommand, Project, ProjectList } from '#core/project.js';
1
+ import { type InfiniteData, type QueryClient, type UseInfiniteQueryOptions, type UseQueryOptions } from '@tanstack/react-query';
2
+ import type { CreateProjectCommand, Project, ProjectList, UpdateProjectCommand } from '#core/project.js';
3
3
  export declare const projectsQueryKeys: {
4
4
  all: readonly ["projects"];
5
5
  list: (workspaceId: string, search?: string) => readonly ["projects", "list", string, string];
6
+ slug: (workspaceId: string, projectSlug: string) => readonly ["projects", "slug", string, string];
6
7
  exists: (workspaceId: string) => readonly ["projects", "exists", string];
7
8
  detail: (projectId: string) => readonly ["projects", "detail", string];
8
9
  };
9
10
  type ProjectListQueryKey = ReturnType<typeof projectsQueryKeys.list> | readonly ['projects', 'list'];
10
11
  type ProjectExistenceQueryKey = ReturnType<typeof projectsQueryKeys.exists> | readonly ['projects', 'exists'];
12
+ type ProjectSlugQueryKey = ReturnType<typeof projectsQueryKeys.slug> | readonly ['projects', 'slug'];
11
13
  type ProjectDetailQueryKey = ReturnType<typeof projectsQueryKeys.detail> | readonly ['projects', 'detail'];
12
14
  type ProjectListInfiniteQueryOptions = UseInfiniteQueryOptions<ProjectList, Error, InfiniteData<ProjectList, string | undefined>, ProjectListQueryKey, string | undefined>;
13
15
  type ProjectExistenceQueryOptions = UseQueryOptions<ProjectList, Error, ProjectList, ProjectExistenceQueryKey>;
16
+ type ProjectSlugQueryOptions = UseQueryOptions<Project | null, Error, Project | null, ProjectSlugQueryKey>;
14
17
  type ProjectDetailQueryOptions = UseQueryOptions<Project, Error, Project, ProjectDetailQueryKey>;
15
18
  export declare function listProjects({ workspaceId, limit, cursor, search, signal, }: {
16
19
  workspaceId: string;
@@ -19,13 +22,29 @@ export declare function listProjects({ workspaceId, limit, cursor, search, signa
19
22
  search?: string | undefined;
20
23
  signal?: AbortSignal | undefined;
21
24
  }): Promise<ProjectList>;
25
+ export declare function resolveProjectSlug({ queryClient, workspaceId, projectSlug, }: {
26
+ queryClient: QueryClient;
27
+ workspaceId: string;
28
+ projectSlug: string;
29
+ }): Promise<string | undefined>;
22
30
  export declare function getProject(projectId: string): Promise<Project>;
23
31
  export declare function createProject(command: CreateProjectCommand): Promise<Project>;
32
+ export declare function updateProject(command: UpdateProjectCommand): Promise<Project>;
33
+ export declare function isProjectSlugAvailable({ queryClient, workspaceId, projectSlug, currentProjectId, }: {
34
+ queryClient: QueryClient;
35
+ workspaceId: string;
36
+ projectSlug: string;
37
+ currentProjectId?: string | undefined;
38
+ }): boolean;
39
+ export declare function useProjectSlugAvailability(workspaceId: string | undefined, currentProjectId?: string): (projectSlug: string) => Promise<boolean>;
24
40
  export declare function projectsInfiniteQueryOptions(workspaceId: string | undefined, search?: string, limit?: number): ProjectListInfiniteQueryOptions;
25
41
  export declare function projectExistenceQueryOptions(workspaceId: string | undefined): ProjectExistenceQueryOptions;
26
42
  export declare function projectQueryOptions(projectId: string | undefined): ProjectDetailQueryOptions;
43
+ export declare function projectSlugQueryOptions(workspaceId: string | undefined, projectSlug: string | undefined): ProjectSlugQueryOptions;
27
44
  export declare function useProjectsInfiniteQuery(workspaceId: string | undefined, search?: string, limit?: number): import("@tanstack/react-query").UseInfiniteQueryResult<InfiniteData<ProjectList, string | undefined>, Error>;
28
45
  export declare function useProjectQuery(projectId: string | undefined): import("@tanstack/react-query").UseQueryResult<NoInfer<Project>, Error>;
46
+ export declare function useProjectSlugQuery(workspaceId: string | undefined, projectSlug: string | undefined): import("@tanstack/react-query").UseQueryResult<NoInfer<Project | null>, Error>;
29
47
  export declare function useCreateProjectMutation(): import("@tanstack/react-query").UseMutationResult<Project, Error, CreateProjectCommand, unknown>;
48
+ export declare function useUpdateProjectMutation(): import("@tanstack/react-query").UseMutationResult<Project, Error, UpdateProjectCommand, unknown>;
30
49
  export {};
31
50
  //# sourceMappingURL=projects.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/projects.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,KAAK,YAAY,EAGjB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EAKrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,oBAAoB,EAAE,OAAO,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAGjF,eAAO,MAAM,iBAAiB;;wBAER,MAAM;0BAEJ,MAAM;wBACR,MAAM;CAC3B,CAAC;AAEF,KAAK,mBAAmB,GACpB,UAAU,CAAC,OAAO,iBAAiB,CAAC,IAAI,CAAC,GACzC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAClC,KAAK,wBAAwB,GACzB,UAAU,CAAC,OAAO,iBAAiB,CAAC,MAAM,CAAC,GAC3C,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AACpC,KAAK,qBAAqB,GACtB,UAAU,CAAC,OAAO,iBAAiB,CAAC,MAAM,CAAC,GAC3C,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAEpC,KAAK,+BAA+B,GAAG,uBAAuB,CAC5D,WAAW,EACX,KAAK,EACL,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC,EAC7C,mBAAmB,EACnB,MAAM,GAAG,SAAS,CACnB,CAAC;AACF,KAAK,4BAA4B,GAAG,eAAe,CACjD,WAAW,EACX,KAAK,EACL,WAAW,EACX,wBAAwB,CACzB,CAAC;AACF,KAAK,yBAAyB,GAAG,eAAe,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,qBAAqB,CAAC,CAAC;AAEjG,wBAAsB,YAAY,CAAC,EACjC,WAAW,EACX,KAAU,EACV,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC,GAAG,OAAO,CAAC,WAAW,CAAC,CAOvB;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEpE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAYnF;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,SAAK,GACT,+BAA+B,CAmBjC;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,GAC9B,4BAA4B,CAS9B;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,yBAAyB,CAQ5F;AAED,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,MAAM,CAAC,EAAE,MAAM,EACf,KAAK,SAAK,gHAGX;AACD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,2EAE5D;AAED,wBAAgB,wBAAwB,qGAoBvC"}
1
+ {"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../../src/hooks/api/projects.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
- import { createProjectBodySchema, listProjectsResponseSchema, projectResponseSchema } from '@shipfox/api-projects-dto';
1
+ import { createProjectBodySchema, listProjectsResponseSchema, projectResponseSchema, updateProjectBodySchema } from '@shipfox/api-projects-dto';
2
2
  import { checkedApiRequest } from '@shipfox/client-api';
3
3
  import { keepPreviousData, queryOptions, useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
4
+ import { useCallback } from 'react';
4
5
  import { toProject, toProjectList } from './mappers.js';
6
+ const PROJECT_LIST_STALE_TIME = 30_000;
5
7
  export const projectsQueryKeys = {
6
8
  all: [
7
9
  'projects'
@@ -12,6 +14,12 @@ export const projectsQueryKeys = {
12
14
  workspaceId,
13
15
  search
14
16
  ],
17
+ slug: (workspaceId, projectSlug)=>[
18
+ ...projectsQueryKeys.all,
19
+ 'slug',
20
+ workspaceId,
21
+ projectSlug
22
+ ],
15
23
  exists: (workspaceId)=>[
16
24
  ...projectsQueryKeys.all,
17
25
  'exists',
@@ -34,6 +42,79 @@ export async function listProjects({ workspaceId, limit = 50, cursor, search, si
34
42
  signal
35
43
  }));
36
44
  }
45
+ export async function resolveProjectSlug({ queryClient, workspaceId, projectSlug }) {
46
+ const queryKey = projectsQueryKeys.list(workspaceId);
47
+ let data = queryClient.getQueryData(queryKey);
48
+ if (!data) {
49
+ await queryClient.fetchInfiniteQuery(projectsInfiniteQueryOptions(workspaceId));
50
+ data = queryClient.getQueryData(queryKey);
51
+ }
52
+ if (data) {
53
+ const project = data.pages.flatMap((page)=>page.projects).find((candidate)=>candidate.slug === projectSlug);
54
+ const dataUpdatedAt = queryClient.getQueryState(queryKey)?.dataUpdatedAt ?? 0;
55
+ if (project && Date.now() - dataUpdatedAt < PROJECT_LIST_STALE_TIME) {
56
+ cacheResolvedProject(queryClient, workspaceId, projectSlug, project);
57
+ return project.id;
58
+ }
59
+ const cursor = data.pages.at(-1)?.nextCursor;
60
+ if (project || !cursor) {
61
+ return await refetchAndResolveProjectSlug(queryClient, queryKey, workspaceId, projectSlug);
62
+ }
63
+ return await resolveProjectSlugBySearch(queryClient, workspaceId, projectSlug);
64
+ }
65
+ return undefined;
66
+ }
67
+ async function refetchAndResolveProjectSlug(queryClient, queryKey, workspaceId, projectSlug) {
68
+ await queryClient.refetchQueries({
69
+ queryKey,
70
+ type: 'all'
71
+ });
72
+ const data = queryClient.getQueryData(queryKey);
73
+ if (!data) return undefined;
74
+ const project = data.pages.flatMap((page)=>page.projects).find((candidate)=>candidate.slug === projectSlug);
75
+ if (project) {
76
+ cacheResolvedProject(queryClient, workspaceId, projectSlug, project);
77
+ return project.id;
78
+ }
79
+ if (!data.pages.at(-1)?.nextCursor) return undefined;
80
+ return await resolveProjectSlugBySearch(queryClient, workspaceId, projectSlug);
81
+ }
82
+ function cacheResolvedProject(queryClient, workspaceId, projectSlug, project) {
83
+ queryClient.setQueryData(projectsQueryKeys.slug(workspaceId, projectSlug), project);
84
+ queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);
85
+ }
86
+ async function resolveProjectSlugBySearch(queryClient, workspaceId, projectSlug, signal) {
87
+ const project = await findProjectBySlug({
88
+ workspaceId,
89
+ projectSlug,
90
+ signal
91
+ });
92
+ if (project) {
93
+ cacheResolvedProject(queryClient, workspaceId, projectSlug, project);
94
+ return project.id;
95
+ }
96
+ return undefined;
97
+ }
98
+ async function findProjectBySlug({ workspaceId, projectSlug, signal }) {
99
+ let result = await listProjects({
100
+ workspaceId,
101
+ search: projectSlug,
102
+ limit: 100,
103
+ signal
104
+ });
105
+ while(true){
106
+ const project = result.projects.find((candidate)=>candidate.slug === projectSlug);
107
+ if (project) return project;
108
+ if (!result.nextCursor) return undefined;
109
+ result = await listProjects({
110
+ workspaceId,
111
+ search: projectSlug,
112
+ limit: 100,
113
+ cursor: result.nextCursor,
114
+ signal
115
+ });
116
+ }
117
+ }
37
118
  export async function getProject(projectId) {
38
119
  return toProject(await checkedApiRequest(projectResponseSchema, `/projects/${projectId}`));
39
120
  }
@@ -41,6 +122,7 @@ export async function createProject(command) {
41
122
  const body = createProjectBodySchema.parse({
42
123
  workspace_id: command.workspaceId,
43
124
  name: command.name,
125
+ slug: command.slug,
44
126
  source: {
45
127
  connection_id: command.source.connectionId,
46
128
  external_repository_id: command.source.externalRepositoryId
@@ -51,6 +133,50 @@ export async function createProject(command) {
51
133
  body
52
134
  }));
53
135
  }
136
+ export async function updateProject(command) {
137
+ const body = updateProjectBodySchema.parse({
138
+ name: command.name,
139
+ slug: command.slug
140
+ });
141
+ return toProject(await checkedApiRequest(projectResponseSchema, `/projects/${command.projectId}`, {
142
+ method: 'PATCH',
143
+ body
144
+ }));
145
+ }
146
+ export function isProjectSlugAvailable({ queryClient, workspaceId, projectSlug, currentProjectId }) {
147
+ const cachedLists = queryClient.getQueriesData({
148
+ queryKey: [
149
+ ...projectsQueryKeys.all,
150
+ 'list',
151
+ workspaceId
152
+ ]
153
+ });
154
+ const conflict = cachedLists.flatMap(([, data])=>data?.pages.flatMap((page)=>page.projects) ?? []).some((project)=>project.slug === projectSlug && project.id !== currentProjectId);
155
+ return !conflict;
156
+ }
157
+ export function useProjectSlugAvailability(workspaceId, currentProjectId) {
158
+ const queryClient = useQueryClient();
159
+ return useCallback(async (projectSlug)=>{
160
+ if (!workspaceId) return false;
161
+ if (!isProjectSlugAvailable({
162
+ queryClient,
163
+ workspaceId,
164
+ projectSlug,
165
+ currentProjectId
166
+ })) {
167
+ return false;
168
+ }
169
+ const project = await findProjectBySlug({
170
+ workspaceId,
171
+ projectSlug
172
+ });
173
+ return project === undefined || project.id === currentProjectId;
174
+ }, [
175
+ currentProjectId,
176
+ queryClient,
177
+ workspaceId
178
+ ]);
179
+ }
54
180
  export function projectsInfiniteQueryOptions(workspaceId, search, limit = 50) {
55
181
  const normalizedSearch = search?.trim() ?? '';
56
182
  return {
@@ -68,7 +194,8 @@ export function projectsInfiniteQueryOptions(workspaceId, search, limit = 50) {
68
194
  signal
69
195
  }),
70
196
  getNextPageParam: (lastPage)=>lastPage.nextCursor ?? undefined,
71
- placeholderData: keepPreviousData
197
+ placeholderData: keepPreviousData,
198
+ staleTime: PROJECT_LIST_STALE_TIME
72
199
  };
73
200
  }
74
201
  export function projectExistenceQueryOptions(workspaceId) {
@@ -96,12 +223,38 @@ export function projectQueryOptions(projectId) {
96
223
  queryFn: ()=>getProject(projectId ?? '')
97
224
  });
98
225
  }
226
+ export function projectSlugQueryOptions(workspaceId, projectSlug) {
227
+ return queryOptions({
228
+ queryKey: workspaceId && projectSlug ? projectsQueryKeys.slug(workspaceId, projectSlug) : [
229
+ ...projectsQueryKeys.all,
230
+ 'slug'
231
+ ],
232
+ enabled: Boolean(workspaceId && projectSlug),
233
+ queryFn: async ({ signal, client })=>{
234
+ const resolvedWorkspaceId = workspaceId ?? '';
235
+ const resolvedProjectSlug = projectSlug ?? '';
236
+ const project = await findProjectBySlug({
237
+ workspaceId: resolvedWorkspaceId,
238
+ projectSlug: resolvedProjectSlug,
239
+ signal
240
+ });
241
+ if (project) {
242
+ cacheResolvedProject(client, resolvedWorkspaceId, resolvedProjectSlug, project);
243
+ }
244
+ return project ?? null;
245
+ },
246
+ staleTime: 30_000
247
+ });
248
+ }
99
249
  export function useProjectsInfiniteQuery(workspaceId, search, limit = 50) {
100
250
  return useInfiniteQuery(projectsInfiniteQueryOptions(workspaceId, search, limit));
101
251
  }
102
252
  export function useProjectQuery(projectId) {
103
253
  return useQuery(projectQueryOptions(projectId));
104
254
  }
255
+ export function useProjectSlugQuery(workspaceId, projectSlug) {
256
+ return useQuery(projectSlugQueryOptions(workspaceId, projectSlug));
257
+ }
105
258
  export function useCreateProjectMutation() {
106
259
  const queryClient = useQueryClient();
107
260
  return useMutation({
@@ -129,5 +282,25 @@ export function useCreateProjectMutation() {
129
282
  }
130
283
  });
131
284
  }
285
+ export function useUpdateProjectMutation() {
286
+ const queryClient = useQueryClient();
287
+ return useMutation({
288
+ mutationFn: updateProject,
289
+ onSuccess: async (project)=>{
290
+ queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);
291
+ queryClient.setQueryData(projectsQueryKeys.slug(project.workspaceId, project.slug), project);
292
+ await queryClient.invalidateQueries({
293
+ queryKey: [
294
+ ...projectsQueryKeys.all,
295
+ 'slug',
296
+ project.workspaceId
297
+ ]
298
+ });
299
+ await queryClient.invalidateQueries({
300
+ queryKey: projectsQueryKeys.list(project.workspaceId)
301
+ });
302
+ }
303
+ });
304
+ }
132
305
 
133
306
  //# sourceMappingURL=projects.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/api/projects.ts"],"sourcesContent":["import {\n createProjectBodySchema,\n listProjectsResponseSchema,\n projectResponseSchema,\n} from '@shipfox/api-projects-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {\n type InfiniteData,\n keepPreviousData,\n queryOptions,\n type UseInfiniteQueryOptions,\n type UseQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from '@tanstack/react-query';\nimport type {CreateProjectCommand, Project, ProjectList} from '#core/project.js';\nimport {toProject, toProjectList} from './mappers.js';\n\nexport const projectsQueryKeys = {\n all: ['projects'] as const,\n list: (workspaceId: string, search = '') =>\n [...projectsQueryKeys.all, 'list', workspaceId, search] as const,\n exists: (workspaceId: string) => [...projectsQueryKeys.all, 'exists', workspaceId] as const,\n detail: (projectId: string) => [...projectsQueryKeys.all, 'detail', projectId] as const,\n};\n\ntype ProjectListQueryKey =\n | ReturnType<typeof projectsQueryKeys.list>\n | readonly ['projects', 'list'];\ntype ProjectExistenceQueryKey =\n | ReturnType<typeof projectsQueryKeys.exists>\n | readonly ['projects', 'exists'];\ntype ProjectDetailQueryKey =\n | ReturnType<typeof projectsQueryKeys.detail>\n | readonly ['projects', 'detail'];\n\ntype ProjectListInfiniteQueryOptions = UseInfiniteQueryOptions<\n ProjectList,\n Error,\n InfiniteData<ProjectList, string | undefined>,\n ProjectListQueryKey,\n string | undefined\n>;\ntype ProjectExistenceQueryOptions = UseQueryOptions<\n ProjectList,\n Error,\n ProjectList,\n ProjectExistenceQueryKey\n>;\ntype ProjectDetailQueryOptions = UseQueryOptions<Project, Error, Project, ProjectDetailQueryKey>;\n\nexport async function listProjects({\n workspaceId,\n limit = 50,\n cursor,\n search,\n signal,\n}: {\n workspaceId: string;\n limit?: number;\n cursor?: string | undefined;\n search?: string | undefined;\n signal?: AbortSignal | undefined;\n}): Promise<ProjectList> {\n const params = new URLSearchParams({workspace_id: workspaceId, limit: String(limit)});\n if (cursor) params.set('cursor', cursor);\n if (search) params.set('search', search);\n return toProjectList(\n await checkedApiRequest(listProjectsResponseSchema, `/projects?${params.toString()}`, {signal}),\n );\n}\n\nexport async function getProject(projectId: string): Promise<Project> {\n return toProject(await checkedApiRequest(projectResponseSchema, `/projects/${projectId}`));\n}\n\nexport async function createProject(command: CreateProjectCommand): Promise<Project> {\n const body = createProjectBodySchema.parse({\n workspace_id: command.workspaceId,\n name: command.name,\n source: {\n connection_id: command.source.connectionId,\n external_repository_id: command.source.externalRepositoryId,\n },\n });\n return toProject(\n await checkedApiRequest(projectResponseSchema, '/projects', {method: 'POST', body}),\n );\n}\n\nexport function projectsInfiniteQueryOptions(\n workspaceId: string | undefined,\n search?: string,\n limit = 50,\n): ProjectListInfiniteQueryOptions {\n const normalizedSearch = search?.trim() ?? '';\n return {\n queryKey: workspaceId\n ? projectsQueryKeys.list(workspaceId, normalizedSearch)\n : ([...projectsQueryKeys.all, 'list'] as const),\n enabled: Boolean(workspaceId),\n initialPageParam: undefined as string | undefined,\n queryFn: ({pageParam, signal}: {pageParam: string | undefined; signal: AbortSignal}) =>\n listProjects({\n workspaceId: workspaceId ?? '',\n limit,\n cursor: pageParam,\n search: normalizedSearch || undefined,\n signal,\n }),\n getNextPageParam: (lastPage: ProjectList) => lastPage.nextCursor ?? undefined,\n placeholderData: keepPreviousData,\n };\n}\n\nexport function projectExistenceQueryOptions(\n workspaceId: string | undefined,\n): ProjectExistenceQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? projectsQueryKeys.exists(workspaceId)\n : ([...projectsQueryKeys.all, 'exists'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listProjects({workspaceId: workspaceId ?? '', limit: 1, signal}),\n staleTime: 30_000,\n });\n}\n\nexport function projectQueryOptions(projectId: string | undefined): ProjectDetailQueryOptions {\n return queryOptions({\n queryKey: projectId\n ? projectsQueryKeys.detail(projectId)\n : ([...projectsQueryKeys.all, 'detail'] as const),\n enabled: Boolean(projectId),\n queryFn: () => getProject(projectId ?? ''),\n });\n}\n\nexport function useProjectsInfiniteQuery(\n workspaceId: string | undefined,\n search?: string,\n limit = 50,\n) {\n return useInfiniteQuery(projectsInfiniteQueryOptions(workspaceId, search, limit));\n}\nexport function useProjectQuery(projectId: string | undefined) {\n return useQuery(projectQueryOptions(projectId));\n}\n\nexport function useCreateProjectMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: createProject,\n onSuccess: async (project) => {\n queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);\n queryClient.setQueryData<ProjectList>(projectsQueryKeys.exists(project.workspaceId), {\n projects: [project],\n nextCursor: null,\n });\n await queryClient.invalidateQueries({queryKey: projectsQueryKeys.list(project.workspaceId)});\n },\n onError: async (_error, command) => {\n await queryClient.invalidateQueries({\n queryKey: projectsQueryKeys.exists(command.workspaceId),\n refetchType: 'active',\n });\n await queryClient.invalidateQueries({queryKey: projectsQueryKeys.list(command.workspaceId)});\n },\n });\n}\n"],"names":["createProjectBodySchema","listProjectsResponseSchema","projectResponseSchema","checkedApiRequest","keepPreviousData","queryOptions","useInfiniteQuery","useMutation","useQuery","useQueryClient","toProject","toProjectList","projectsQueryKeys","all","list","workspaceId","search","exists","detail","projectId","listProjects","limit","cursor","signal","params","URLSearchParams","workspace_id","String","set","toString","getProject","createProject","command","body","parse","name","source","connection_id","connectionId","external_repository_id","externalRepositoryId","method","projectsInfiniteQueryOptions","normalizedSearch","trim","queryKey","enabled","Boolean","initialPageParam","undefined","queryFn","pageParam","getNextPageParam","lastPage","nextCursor","placeholderData","projectExistenceQueryOptions","staleTime","projectQueryOptions","useProjectsInfiniteQuery","useProjectQuery","useCreateProjectMutation","queryClient","mutationFn","onSuccess","project","setQueryData","id","projects","invalidateQueries","onError","_error","refetchType"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/hooks/api/projects.ts"],"sourcesContent":["import {\n createProjectBodySchema,\n listProjectsResponseSchema,\n projectResponseSchema,\n updateProjectBodySchema,\n} from '@shipfox/api-projects-dto';\nimport {checkedApiRequest} from '@shipfox/client-api';\nimport {\n type InfiniteData,\n keepPreviousData,\n type QueryClient,\n queryOptions,\n type UseInfiniteQueryOptions,\n type UseQueryOptions,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from '@tanstack/react-query';\nimport {useCallback} from 'react';\nimport type {\n CreateProjectCommand,\n Project,\n ProjectList,\n UpdateProjectCommand,\n} from '#core/project.js';\nimport {toProject, toProjectList} from './mappers.js';\n\nconst PROJECT_LIST_STALE_TIME = 30_000;\n\nexport const projectsQueryKeys = {\n all: ['projects'] as const,\n list: (workspaceId: string, search = '') =>\n [...projectsQueryKeys.all, 'list', workspaceId, search] as const,\n slug: (workspaceId: string, projectSlug: string) =>\n [...projectsQueryKeys.all, 'slug', workspaceId, projectSlug] as const,\n exists: (workspaceId: string) => [...projectsQueryKeys.all, 'exists', workspaceId] as const,\n detail: (projectId: string) => [...projectsQueryKeys.all, 'detail', projectId] as const,\n};\n\ntype ProjectListQueryKey =\n | ReturnType<typeof projectsQueryKeys.list>\n | readonly ['projects', 'list'];\ntype ProjectExistenceQueryKey =\n | ReturnType<typeof projectsQueryKeys.exists>\n | readonly ['projects', 'exists'];\ntype ProjectSlugQueryKey =\n | ReturnType<typeof projectsQueryKeys.slug>\n | readonly ['projects', 'slug'];\ntype ProjectDetailQueryKey =\n | ReturnType<typeof projectsQueryKeys.detail>\n | readonly ['projects', 'detail'];\n\ntype ProjectListInfiniteQueryOptions = UseInfiniteQueryOptions<\n ProjectList,\n Error,\n InfiniteData<ProjectList, string | undefined>,\n ProjectListQueryKey,\n string | undefined\n>;\ntype ProjectExistenceQueryOptions = UseQueryOptions<\n ProjectList,\n Error,\n ProjectList,\n ProjectExistenceQueryKey\n>;\ntype ProjectSlugQueryOptions = UseQueryOptions<\n Project | null,\n Error,\n Project | null,\n ProjectSlugQueryKey\n>;\ntype ProjectDetailQueryOptions = UseQueryOptions<Project, Error, Project, ProjectDetailQueryKey>;\n\nexport async function listProjects({\n workspaceId,\n limit = 50,\n cursor,\n search,\n signal,\n}: {\n workspaceId: string;\n limit?: number;\n cursor?: string | undefined;\n search?: string | undefined;\n signal?: AbortSignal | undefined;\n}): Promise<ProjectList> {\n const params = new URLSearchParams({workspace_id: workspaceId, limit: String(limit)});\n if (cursor) params.set('cursor', cursor);\n if (search) params.set('search', search);\n return toProjectList(\n await checkedApiRequest(listProjectsResponseSchema, `/projects?${params.toString()}`, {signal}),\n );\n}\n\nexport async function resolveProjectSlug({\n queryClient,\n workspaceId,\n projectSlug,\n}: {\n queryClient: QueryClient;\n workspaceId: string;\n projectSlug: string;\n}): Promise<string | undefined> {\n const queryKey = projectsQueryKeys.list(workspaceId);\n let data = queryClient.getQueryData<InfiniteData<ProjectList, string | undefined>>(queryKey);\n\n if (!data) {\n await queryClient.fetchInfiniteQuery(projectsInfiniteQueryOptions(workspaceId));\n data = queryClient.getQueryData<InfiniteData<ProjectList, string | undefined>>(queryKey);\n }\n\n if (data) {\n const project = data.pages\n .flatMap((page) => page.projects)\n .find((candidate) => candidate.slug === projectSlug);\n const dataUpdatedAt = queryClient.getQueryState(queryKey)?.dataUpdatedAt ?? 0;\n if (project && Date.now() - dataUpdatedAt < PROJECT_LIST_STALE_TIME) {\n cacheResolvedProject(queryClient, workspaceId, projectSlug, project);\n return project.id;\n }\n const cursor = data.pages.at(-1)?.nextCursor;\n if (project || !cursor) {\n return await refetchAndResolveProjectSlug(queryClient, queryKey, workspaceId, projectSlug);\n }\n return await resolveProjectSlugBySearch(queryClient, workspaceId, projectSlug);\n }\n\n return undefined;\n}\n\nasync function refetchAndResolveProjectSlug(\n queryClient: QueryClient,\n queryKey: ReturnType<typeof projectsQueryKeys.list>,\n workspaceId: string,\n projectSlug: string,\n): Promise<string | undefined> {\n await queryClient.refetchQueries({queryKey, type: 'all'});\n const data = queryClient.getQueryData<InfiniteData<ProjectList, string | undefined>>(queryKey);\n\n if (!data) return undefined;\n const project = data.pages\n .flatMap((page) => page.projects)\n .find((candidate) => candidate.slug === projectSlug);\n if (project) {\n cacheResolvedProject(queryClient, workspaceId, projectSlug, project);\n return project.id;\n }\n\n if (!data.pages.at(-1)?.nextCursor) return undefined;\n return await resolveProjectSlugBySearch(queryClient, workspaceId, projectSlug);\n}\n\nfunction cacheResolvedProject(\n queryClient: QueryClient,\n workspaceId: string,\n projectSlug: string,\n project: Project,\n): void {\n queryClient.setQueryData(projectsQueryKeys.slug(workspaceId, projectSlug), project);\n queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);\n}\n\nasync function resolveProjectSlugBySearch(\n queryClient: QueryClient,\n workspaceId: string,\n projectSlug: string,\n signal?: AbortSignal,\n): Promise<string | undefined> {\n const project = await findProjectBySlug({workspaceId, projectSlug, signal});\n if (project) {\n cacheResolvedProject(queryClient, workspaceId, projectSlug, project);\n return project.id;\n }\n return undefined;\n}\n\nasync function findProjectBySlug({\n workspaceId,\n projectSlug,\n signal,\n}: {\n workspaceId: string;\n projectSlug: string;\n signal?: AbortSignal | undefined;\n}): Promise<Project | undefined> {\n let result = await listProjects({workspaceId, search: projectSlug, limit: 100, signal});\n while (true) {\n const project = result.projects.find((candidate) => candidate.slug === projectSlug);\n if (project) return project;\n if (!result.nextCursor) return undefined;\n result = await listProjects({\n workspaceId,\n search: projectSlug,\n limit: 100,\n cursor: result.nextCursor,\n signal,\n });\n }\n}\n\nexport async function getProject(projectId: string): Promise<Project> {\n return toProject(await checkedApiRequest(projectResponseSchema, `/projects/${projectId}`));\n}\n\nexport async function createProject(command: CreateProjectCommand): Promise<Project> {\n const body = createProjectBodySchema.parse({\n workspace_id: command.workspaceId,\n name: command.name,\n slug: command.slug,\n source: {\n connection_id: command.source.connectionId,\n external_repository_id: command.source.externalRepositoryId,\n },\n });\n return toProject(\n await checkedApiRequest(projectResponseSchema, '/projects', {method: 'POST', body}),\n );\n}\n\nexport async function updateProject(command: UpdateProjectCommand): Promise<Project> {\n const body = updateProjectBodySchema.parse({name: command.name, slug: command.slug});\n return toProject(\n await checkedApiRequest(projectResponseSchema, `/projects/${command.projectId}`, {\n method: 'PATCH',\n body,\n }),\n );\n}\n\nexport function isProjectSlugAvailable({\n queryClient,\n workspaceId,\n projectSlug,\n currentProjectId,\n}: {\n queryClient: QueryClient;\n workspaceId: string;\n projectSlug: string;\n currentProjectId?: string | undefined;\n}): boolean {\n const cachedLists = queryClient.getQueriesData<InfiniteData<ProjectList, string | undefined>>({\n queryKey: [...projectsQueryKeys.all, 'list', workspaceId],\n });\n const conflict = cachedLists\n .flatMap(([, data]) => data?.pages.flatMap((page) => page.projects) ?? [])\n .some((project) => project.slug === projectSlug && project.id !== currentProjectId);\n return !conflict;\n}\n\nexport function useProjectSlugAvailability(\n workspaceId: string | undefined,\n currentProjectId?: string,\n): (projectSlug: string) => Promise<boolean> {\n const queryClient = useQueryClient();\n return useCallback(\n async (projectSlug: string) => {\n if (!workspaceId) return false;\n if (!isProjectSlugAvailable({queryClient, workspaceId, projectSlug, currentProjectId})) {\n return false;\n }\n const project = await findProjectBySlug({workspaceId, projectSlug});\n return project === undefined || project.id === currentProjectId;\n },\n [currentProjectId, queryClient, workspaceId],\n );\n}\n\nexport function projectsInfiniteQueryOptions(\n workspaceId: string | undefined,\n search?: string,\n limit = 50,\n): ProjectListInfiniteQueryOptions {\n const normalizedSearch = search?.trim() ?? '';\n return {\n queryKey: workspaceId\n ? projectsQueryKeys.list(workspaceId, normalizedSearch)\n : ([...projectsQueryKeys.all, 'list'] as const),\n enabled: Boolean(workspaceId),\n initialPageParam: undefined as string | undefined,\n queryFn: ({pageParam, signal}: {pageParam: string | undefined; signal: AbortSignal}) =>\n listProjects({\n workspaceId: workspaceId ?? '',\n limit,\n cursor: pageParam,\n search: normalizedSearch || undefined,\n signal,\n }),\n getNextPageParam: (lastPage: ProjectList) => lastPage.nextCursor ?? undefined,\n placeholderData: keepPreviousData,\n staleTime: PROJECT_LIST_STALE_TIME,\n };\n}\n\nexport function projectExistenceQueryOptions(\n workspaceId: string | undefined,\n): ProjectExistenceQueryOptions {\n return queryOptions({\n queryKey: workspaceId\n ? projectsQueryKeys.exists(workspaceId)\n : ([...projectsQueryKeys.all, 'exists'] as const),\n enabled: Boolean(workspaceId),\n queryFn: ({signal}) => listProjects({workspaceId: workspaceId ?? '', limit: 1, signal}),\n staleTime: 30_000,\n });\n}\n\nexport function projectQueryOptions(projectId: string | undefined): ProjectDetailQueryOptions {\n return queryOptions({\n queryKey: projectId\n ? projectsQueryKeys.detail(projectId)\n : ([...projectsQueryKeys.all, 'detail'] as const),\n enabled: Boolean(projectId),\n queryFn: () => getProject(projectId ?? ''),\n });\n}\n\nexport function projectSlugQueryOptions(\n workspaceId: string | undefined,\n projectSlug: string | undefined,\n): ProjectSlugQueryOptions {\n return queryOptions({\n queryKey:\n workspaceId && projectSlug\n ? projectsQueryKeys.slug(workspaceId, projectSlug)\n : ([...projectsQueryKeys.all, 'slug'] as const),\n enabled: Boolean(workspaceId && projectSlug),\n queryFn: async ({signal, client}) => {\n const resolvedWorkspaceId = workspaceId ?? '';\n const resolvedProjectSlug = projectSlug ?? '';\n const project = await findProjectBySlug({\n workspaceId: resolvedWorkspaceId,\n projectSlug: resolvedProjectSlug,\n signal,\n });\n if (project) {\n cacheResolvedProject(client, resolvedWorkspaceId, resolvedProjectSlug, project);\n }\n return project ?? null;\n },\n staleTime: 30_000,\n });\n}\n\nexport function useProjectsInfiniteQuery(\n workspaceId: string | undefined,\n search?: string,\n limit = 50,\n) {\n return useInfiniteQuery(projectsInfiniteQueryOptions(workspaceId, search, limit));\n}\nexport function useProjectQuery(projectId: string | undefined) {\n return useQuery(projectQueryOptions(projectId));\n}\nexport function useProjectSlugQuery(\n workspaceId: string | undefined,\n projectSlug: string | undefined,\n) {\n return useQuery(projectSlugQueryOptions(workspaceId, projectSlug));\n}\nexport function useCreateProjectMutation() {\n const queryClient = useQueryClient();\n return useMutation({\n mutationFn: createProject,\n onSuccess: async (project) => {\n queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);\n queryClient.setQueryData<ProjectList>(projectsQueryKeys.exists(project.workspaceId), {\n projects: [project],\n nextCursor: null,\n });\n await queryClient.invalidateQueries({queryKey: projectsQueryKeys.list(project.workspaceId)});\n },\n onError: async (_error, command) => {\n await queryClient.invalidateQueries({\n queryKey: projectsQueryKeys.exists(command.workspaceId),\n refetchType: 'active',\n });\n await queryClient.invalidateQueries({queryKey: projectsQueryKeys.list(command.workspaceId)});\n },\n });\n}\n\nexport function useUpdateProjectMutation() {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: updateProject,\n onSuccess: async (project) => {\n queryClient.setQueryData(projectsQueryKeys.detail(project.id), project);\n queryClient.setQueryData(projectsQueryKeys.slug(project.workspaceId, project.slug), project);\n await queryClient.invalidateQueries({\n queryKey: [...projectsQueryKeys.all, 'slug', project.workspaceId],\n });\n await queryClient.invalidateQueries({queryKey: projectsQueryKeys.list(project.workspaceId)});\n },\n });\n}\n"],"names":["createProjectBodySchema","listProjectsResponseSchema","projectResponseSchema","updateProjectBodySchema","checkedApiRequest","keepPreviousData","queryOptions","useInfiniteQuery","useMutation","useQuery","useQueryClient","useCallback","toProject","toProjectList","PROJECT_LIST_STALE_TIME","projectsQueryKeys","all","list","workspaceId","search","slug","projectSlug","exists","detail","projectId","listProjects","limit","cursor","signal","params","URLSearchParams","workspace_id","String","set","toString","resolveProjectSlug","queryClient","queryKey","data","getQueryData","fetchInfiniteQuery","projectsInfiniteQueryOptions","project","pages","flatMap","page","projects","find","candidate","dataUpdatedAt","getQueryState","Date","now","cacheResolvedProject","id","at","nextCursor","refetchAndResolveProjectSlug","resolveProjectSlugBySearch","undefined","refetchQueries","type","setQueryData","findProjectBySlug","result","getProject","createProject","command","body","parse","name","source","connection_id","connectionId","external_repository_id","externalRepositoryId","method","updateProject","isProjectSlugAvailable","currentProjectId","cachedLists","getQueriesData","conflict","some","useProjectSlugAvailability","normalizedSearch","trim","enabled","Boolean","initialPageParam","queryFn","pageParam","getNextPageParam","lastPage","placeholderData","staleTime","projectExistenceQueryOptions","projectQueryOptions","projectSlugQueryOptions","client","resolvedWorkspaceId","resolvedProjectSlug","useProjectsInfiniteQuery","useProjectQuery","useProjectSlugQuery","useCreateProjectMutation","mutationFn","onSuccess","invalidateQueries","onError","_error","refetchType","useUpdateProjectMutation"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export type { Definition, DefinitionList, DefinitionSyncSummary } from '#core/definition.js';
2
- export { type CreateProjectCommand, type Project, type ProjectList, type ProjectSource, projectNameFromRepository, selectProjectSource, } from '#core/project.js';
3
- export { ProjectBreadcrumb, ProjectLayoutGuard } from './chrome.js';
2
+ export { type CreateProjectCommand, type Project, type ProjectList, type ProjectSource, projectNameFromRepository, selectProjectSource, type UpdateProjectCommand, } from '#core/project.js';
3
+ export { ProjectBreadcrumb, resolveProjectSlug, useActiveProject, useMaybeActiveProject, useMaybeActiveProjectQuery, } from './chrome.js';
4
4
  export { ProjectCrumb, type ProjectCrumbProps } from './components/project-crumb.js';
5
5
  export { ProjectSwitcher, type ProjectSwitcherProps } from './components/project-switcher.js';
6
6
  export { SourceStrip } from './components/source-strip.js';
@@ -8,6 +8,7 @@ export * from './hooks/api/definitions.js';
8
8
  export * from './hooks/api/projects.js';
9
9
  export * from './pages/create-project-page.js';
10
10
  export * from './pages/home-router.js';
11
+ export { ProjectSettingsPage } from './pages/project-settings-page.js';
11
12
  export * from './pages/projects-hub-page.js';
12
13
  export * from './project-error.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAC,iBAAiB,EAAE,kBAAkB,EAAC,MAAM,aAAa,CAAC;AAClE,OAAO,EAAC,YAAY,EAAE,KAAK,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAC,eAAe,EAAE,KAAK,oBAAoB,EAAC,MAAM,kCAAkC,CAAC;AAC5F,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AACzD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAC,UAAU,EAAE,cAAc,EAAE,qBAAqB,EAAC,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,YAAY,EAAE,KAAK,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAC,eAAe,EAAE,KAAK,oBAAoB,EAAC,MAAM,kCAAkC,CAAC;AAC5F,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AACzD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AACrE,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { projectNameFromRepository, selectProjectSource } from '#core/project.js';
2
- export { ProjectBreadcrumb, ProjectLayoutGuard } from './chrome.js';
2
+ export { ProjectBreadcrumb, resolveProjectSlug, useActiveProject, useMaybeActiveProject, useMaybeActiveProjectQuery } from './chrome.js';
3
3
  export { ProjectCrumb } from './components/project-crumb.js';
4
4
  export { ProjectSwitcher } from './components/project-switcher.js';
5
5
  export { SourceStrip } from './components/source-strip.js';
@@ -7,6 +7,7 @@ export * from './hooks/api/definitions.js';
7
7
  export * from './hooks/api/projects.js';
8
8
  export * from './pages/create-project-page.js';
9
9
  export * from './pages/home-router.js';
10
+ export { ProjectSettingsPage } from './pages/project-settings-page.js';
10
11
  export * from './pages/projects-hub-page.js';
11
12
  export * from './project-error.js';
12
13
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type {Definition, DefinitionList, DefinitionSyncSummary} from '#core/definition.js';\nexport {\n type CreateProjectCommand,\n type Project,\n type ProjectList,\n type ProjectSource,\n projectNameFromRepository,\n selectProjectSource,\n} from '#core/project.js';\nexport {ProjectBreadcrumb, ProjectLayoutGuard} from './chrome.js';\nexport {ProjectCrumb, type ProjectCrumbProps} from './components/project-crumb.js';\nexport {ProjectSwitcher, type ProjectSwitcherProps} from './components/project-switcher.js';\nexport {SourceStrip} from './components/source-strip.js';\nexport * from './hooks/api/definitions.js';\nexport * from './hooks/api/projects.js';\nexport * from './pages/create-project-page.js';\nexport * from './pages/home-router.js';\nexport * from './pages/projects-hub-page.js';\nexport * from './project-error.js';\n"],"names":["projectNameFromRepository","selectProjectSource","ProjectBreadcrumb","ProjectLayoutGuard","ProjectCrumb","ProjectSwitcher","SourceStrip"],"mappings":"AACA,SAKEA,yBAAyB,EACzBC,mBAAmB,QACd,mBAAmB;AAC1B,SAAQC,iBAAiB,EAAEC,kBAAkB,QAAO,cAAc;AAClE,SAAQC,YAAY,QAA+B,gCAAgC;AACnF,SAAQC,eAAe,QAAkC,mCAAmC;AAC5F,SAAQC,WAAW,QAAO,+BAA+B;AACzD,cAAc,6BAA6B;AAC3C,cAAc,0BAA0B;AACxC,cAAc,iCAAiC;AAC/C,cAAc,yBAAyB;AACvC,cAAc,+BAA+B;AAC7C,cAAc,qBAAqB"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type {Definition, DefinitionList, DefinitionSyncSummary} from '#core/definition.js';\nexport {\n type CreateProjectCommand,\n type Project,\n type ProjectList,\n type ProjectSource,\n projectNameFromRepository,\n selectProjectSource,\n type UpdateProjectCommand,\n} from '#core/project.js';\nexport {\n ProjectBreadcrumb,\n resolveProjectSlug,\n useActiveProject,\n useMaybeActiveProject,\n useMaybeActiveProjectQuery,\n} from './chrome.js';\nexport {ProjectCrumb, type ProjectCrumbProps} from './components/project-crumb.js';\nexport {ProjectSwitcher, type ProjectSwitcherProps} from './components/project-switcher.js';\nexport {SourceStrip} from './components/source-strip.js';\nexport * from './hooks/api/definitions.js';\nexport * from './hooks/api/projects.js';\nexport * from './pages/create-project-page.js';\nexport * from './pages/home-router.js';\nexport {ProjectSettingsPage} from './pages/project-settings-page.js';\nexport * from './pages/projects-hub-page.js';\nexport * from './project-error.js';\n"],"names":["projectNameFromRepository","selectProjectSource","ProjectBreadcrumb","resolveProjectSlug","useActiveProject","useMaybeActiveProject","useMaybeActiveProjectQuery","ProjectCrumb","ProjectSwitcher","SourceStrip","ProjectSettingsPage"],"mappings":"AACA,SAKEA,yBAAyB,EACzBC,mBAAmB,QAEd,mBAAmB;AAC1B,SACEC,iBAAiB,EACjBC,kBAAkB,EAClBC,gBAAgB,EAChBC,qBAAqB,EACrBC,0BAA0B,QACrB,cAAc;AACrB,SAAQC,YAAY,QAA+B,gCAAgC;AACnF,SAAQC,eAAe,QAAkC,mCAAmC;AAC5F,SAAQC,WAAW,QAAO,+BAA+B;AACzD,cAAc,6BAA6B;AAC3C,cAAc,0BAA0B;AACxC,cAAc,iCAAiC;AAC/C,cAAc,yBAAyB;AACvC,SAAQC,mBAAmB,QAAO,mCAAmC;AACrE,cAAc,+BAA+B;AAC7C,cAAc,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-project-page.d.ts","sourceRoot":"","sources":["../../src/pages/create-project-page.tsx"],"names":[],"mappings":"AAyBA,wBAAgB,iBAAiB,gCAiShC"}
1
+ {"version":3,"file":"create-project-page.d.ts","sourceRoot":"","sources":["../../src/pages/create-project-page.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,iBAAiB,gCA+WhC"}