devchain-cli 0.9.0 → 0.9.1

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 (52) hide show
  1. package/dist/drizzle/0041_community_skill_sources.sql +12 -0
  2. package/dist/drizzle/meta/0041_snapshot.json +4102 -0
  3. package/dist/drizzle/meta/_journal.json +8 -1
  4. package/dist/server/modules/seeders/seeders/0003_seed_preseed_jeffallan_claude_skills.d.ts +3 -0
  5. package/dist/server/modules/seeders/seeders/0003_seed_preseed_jeffallan_claude_skills.js +41 -0
  6. package/dist/server/modules/seeders/seeders/0003_seed_preseed_jeffallan_claude_skills.js.map +1 -0
  7. package/dist/server/modules/seeders/seeders/0004_seed_disable_microsoft_source_default.d.ts +3 -0
  8. package/dist/server/modules/seeders/seeders/0004_seed_disable_microsoft_source_default.js +48 -0
  9. package/dist/server/modules/seeders/seeders/0004_seed_disable_microsoft_source_default.js.map +1 -0
  10. package/dist/server/modules/seeders/services/data-seeder.service.js +4 -0
  11. package/dist/server/modules/seeders/services/data-seeder.service.js.map +1 -1
  12. package/dist/server/modules/skills/adapters/community-skill-source.adapter.d.ts +11 -0
  13. package/dist/server/modules/skills/adapters/community-skill-source.adapter.js +181 -0
  14. package/dist/server/modules/skills/adapters/community-skill-source.adapter.js.map +1 -0
  15. package/dist/server/modules/skills/controllers/community-sources.controller.d.ts +12 -0
  16. package/dist/server/modules/skills/controllers/community-sources.controller.js +71 -0
  17. package/dist/server/modules/skills/controllers/community-sources.controller.js.map +1 -0
  18. package/dist/server/modules/skills/dtos/community-sources.dto.d.ts +100 -0
  19. package/dist/server/modules/skills/dtos/community-sources.dto.js +138 -0
  20. package/dist/server/modules/skills/dtos/community-sources.dto.js.map +1 -0
  21. package/dist/server/modules/skills/services/community-sources.service.d.ts +11 -0
  22. package/dist/server/modules/skills/services/community-sources.service.js +99 -0
  23. package/dist/server/modules/skills/services/community-sources.service.js.map +1 -0
  24. package/dist/server/modules/skills/services/skill-source-registry.service.d.ts +9 -0
  25. package/dist/server/modules/skills/services/skill-source-registry.service.js +46 -0
  26. package/dist/server/modules/skills/services/skill-source-registry.service.js.map +1 -0
  27. package/dist/server/modules/skills/services/skill-sync.service.d.ts +3 -3
  28. package/dist/server/modules/skills/services/skill-sync.service.js +9 -11
  29. package/dist/server/modules/skills/services/skill-sync.service.js.map +1 -1
  30. package/dist/server/modules/skills/services/skills.service.d.ts +3 -3
  31. package/dist/server/modules/skills/services/skills.service.js +21 -18
  32. package/dist/server/modules/skills/services/skills.service.js.map +1 -1
  33. package/dist/server/modules/skills/skills.module.js +7 -1
  34. package/dist/server/modules/skills/skills.module.js.map +1 -1
  35. package/dist/server/modules/storage/db/schema.d.ts +140 -0
  36. package/dist/server/modules/storage/db/schema.js +12 -1
  37. package/dist/server/modules/storage/db/schema.js.map +1 -1
  38. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +6 -1
  39. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  40. package/dist/server/modules/storage/local/local-storage.service.d.ts +11 -1
  41. package/dist/server/modules/storage/local/local-storage.service.js +159 -0
  42. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  43. package/dist/server/modules/storage/models/domain.models.d.ts +12 -0
  44. package/dist/server/tsconfig.tsbuildinfo +1 -1
  45. package/dist/server/ui/assets/{ReviewDetailPage-D_-bS1MK.js → ReviewDetailPage-D13dH7Wh.js} +1 -1
  46. package/dist/server/ui/assets/{ReviewsPage-BE1gxYlC.js → ReviewsPage-C98ST0lf.js} +1 -1
  47. package/dist/server/ui/assets/{index-C094CE5I.js → index-C8Dc1yQf.js} +175 -175
  48. package/dist/server/ui/assets/index-DZkJ40z9.css +32 -0
  49. package/dist/server/ui/assets/{useReviewSubscription-Bs-17h-m.js → useReviewSubscription-CmLuF45Z.js} +1 -1
  50. package/dist/server/ui/index.html +2 -2
  51. package/package.json +4 -1
  52. package/dist/server/ui/assets/index-CbtpBUHu.css +0 -32
@@ -54,6 +54,14 @@ const logger_1 = require("../../../common/logging/logger");
54
54
  const sqlite_raw_1 = require("../db/sqlite-raw");
55
55
  const feature_flags_1 = require("../../../common/config/feature-flags");
56
56
  const logger = (0, logger_1.createLogger)('LocalStorageService');
57
+ const COMMUNITY_SOURCE_NAME_PATTERN = /^[a-z0-9-]+$/;
58
+ const RESERVED_COMMUNITY_SOURCE_NAMES = new Set([
59
+ 'anthropic',
60
+ 'openai',
61
+ 'microsoft',
62
+ 'trailofbits',
63
+ 'vercel',
64
+ ]);
57
65
  let LocalStorageService = class LocalStorageService {
58
66
  constructor(db) {
59
67
  this.db = db;
@@ -121,6 +129,57 @@ let LocalStorageService = class LocalStorageService {
121
129
  }
122
130
  return JSON.stringify(skillsRequired);
123
131
  }
132
+ normalizeCommunitySourceName(name) {
133
+ const normalized = name.trim().toLowerCase();
134
+ if (!normalized) {
135
+ throw new error_types_1.ValidationError('name is required.', { fieldName: 'name' });
136
+ }
137
+ if (!COMMUNITY_SOURCE_NAME_PATTERN.test(normalized)) {
138
+ throw new error_types_1.ValidationError('Invalid community source name. Use lowercase letters, numbers, and hyphens only.', { name: normalized });
139
+ }
140
+ if (RESERVED_COMMUNITY_SOURCE_NAMES.has(normalized)) {
141
+ throw new error_types_1.ValidationError('Community source name conflicts with a built-in source.', {
142
+ name: normalized,
143
+ });
144
+ }
145
+ return normalized;
146
+ }
147
+ normalizeCommunitySourceNameForLookup(name) {
148
+ const normalized = name.trim().toLowerCase();
149
+ if (!normalized) {
150
+ throw new error_types_1.ValidationError('name is required.', { fieldName: 'name' });
151
+ }
152
+ if (!COMMUNITY_SOURCE_NAME_PATTERN.test(normalized)) {
153
+ throw new error_types_1.ValidationError('Invalid community source name. Use lowercase letters, numbers, and hyphens only.', { name: normalized });
154
+ }
155
+ return normalized;
156
+ }
157
+ normalizeCommunityRepoPart(value, fieldName) {
158
+ const normalized = value.trim().toLowerCase();
159
+ if (!normalized) {
160
+ throw new error_types_1.ValidationError(`${fieldName} is required.`, { fieldName });
161
+ }
162
+ return normalized;
163
+ }
164
+ normalizeCommunityBranch(branch) {
165
+ const normalized = (branch ?? 'main').trim();
166
+ if (!normalized) {
167
+ throw new error_types_1.ValidationError('branch is required.', { fieldName: 'branch' });
168
+ }
169
+ return normalized;
170
+ }
171
+ isSqliteUniqueConstraint(error) {
172
+ if (typeof error !== 'object' || error === null) {
173
+ return false;
174
+ }
175
+ const code = 'code' in error ? error.code : undefined;
176
+ const message = 'message' in error ? error.message : undefined;
177
+ const normalizedMessage = typeof message === 'string' ? message : '';
178
+ return (code === 'SQLITE_CONSTRAINT' ||
179
+ code === 'SQLITE_CONSTRAINT_UNIQUE' ||
180
+ code === 19 ||
181
+ normalizedMessage.includes('UNIQUE constraint failed'));
182
+ }
124
183
  async ensureValidEpicParent(projectId, parentId, childId) {
125
184
  if (!parentId) {
126
185
  return;
@@ -1901,6 +1960,106 @@ let LocalStorageService = class LocalStorageService {
1901
1960
  }
1902
1961
  return this.updateProvider(id, update);
1903
1962
  }
1963
+ async listCommunitySkillSources() {
1964
+ const { communitySkillSources } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1965
+ const { asc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1966
+ const rows = await this.db
1967
+ .select()
1968
+ .from(communitySkillSources)
1969
+ .orderBy(asc(communitySkillSources.name));
1970
+ return rows;
1971
+ }
1972
+ async getCommunitySkillSource(id) {
1973
+ const normalizedId = id.trim();
1974
+ if (!normalizedId) {
1975
+ throw new error_types_1.ValidationError('id is required.', { fieldName: 'id' });
1976
+ }
1977
+ const { communitySkillSources } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1978
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1979
+ const rows = await this.db
1980
+ .select()
1981
+ .from(communitySkillSources)
1982
+ .where(eq(communitySkillSources.id, normalizedId))
1983
+ .limit(1);
1984
+ if (!rows[0]) {
1985
+ throw new error_types_1.NotFoundError('Community skill source', normalizedId);
1986
+ }
1987
+ return rows[0];
1988
+ }
1989
+ async getCommunitySkillSourceByName(name) {
1990
+ const normalizedName = this.normalizeCommunitySourceNameForLookup(name);
1991
+ const { communitySkillSources } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1992
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1993
+ const rows = await this.db
1994
+ .select()
1995
+ .from(communitySkillSources)
1996
+ .where(eq(communitySkillSources.name, normalizedName))
1997
+ .limit(1);
1998
+ return rows[0] ?? null;
1999
+ }
2000
+ async createCommunitySkillSource(data) {
2001
+ const normalizedName = this.normalizeCommunitySourceName(data.name);
2002
+ const normalizedRepoOwner = this.normalizeCommunityRepoPart(data.repoOwner, 'repoOwner');
2003
+ const normalizedRepoName = this.normalizeCommunityRepoPart(data.repoName, 'repoName');
2004
+ const normalizedBranch = this.normalizeCommunityBranch(data.branch);
2005
+ const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
2006
+ const now = new Date().toISOString();
2007
+ const record = {
2008
+ id: randomUUID(),
2009
+ name: normalizedName,
2010
+ repoOwner: normalizedRepoOwner,
2011
+ repoName: normalizedRepoName,
2012
+ branch: normalizedBranch,
2013
+ createdAt: now,
2014
+ updatedAt: now,
2015
+ };
2016
+ const { communitySkillSources } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2017
+ try {
2018
+ await this.db.insert(communitySkillSources).values({
2019
+ id: record.id,
2020
+ name: record.name,
2021
+ repoOwner: record.repoOwner,
2022
+ repoName: record.repoName,
2023
+ branch: record.branch,
2024
+ createdAt: record.createdAt,
2025
+ updatedAt: record.updatedAt,
2026
+ });
2027
+ }
2028
+ catch (error) {
2029
+ if (this.isSqliteUniqueConstraint(error)) {
2030
+ const rawMessage = typeof error === 'object' && error !== null && 'message' in error
2031
+ ? String(error.message ?? '')
2032
+ : '';
2033
+ if (rawMessage.includes('community_skill_sources.name')) {
2034
+ throw new error_types_1.ConflictError('Community skill source name already exists.', {
2035
+ name: normalizedName,
2036
+ });
2037
+ }
2038
+ throw new error_types_1.ConflictError('Community skill source repository already exists.', {
2039
+ repoOwner: normalizedRepoOwner,
2040
+ repoName: normalizedRepoName,
2041
+ });
2042
+ }
2043
+ throw new error_types_1.StorageError('Failed to create community skill source.', {
2044
+ name: normalizedName,
2045
+ repoOwner: normalizedRepoOwner,
2046
+ repoName: normalizedRepoName,
2047
+ cause: error instanceof Error ? error.message : String(error),
2048
+ });
2049
+ }
2050
+ logger.info({ communitySkillSourceId: record.id, name: record.name }, 'Created community skill source');
2051
+ return record;
2052
+ }
2053
+ async deleteCommunitySkillSource(id) {
2054
+ const source = await this.getCommunitySkillSource(id);
2055
+ const { communitySkillSources, skills } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2056
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2057
+ await this.db.transaction(async (tx) => {
2058
+ await tx.delete(skills).where(eq(skills.source, source.name));
2059
+ await tx.delete(communitySkillSources).where(eq(communitySkillSources.id, source.id));
2060
+ });
2061
+ logger.info({ communitySkillSourceId: source.id, sourceName: source.name }, 'Deleted community skill source and related skills');
2062
+ }
1904
2063
  async createAgentProfile(data) {
1905
2064
  const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
1906
2065
  const now = new Date().toISOString();