[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ESZPEVC141MQPEKK7RME9X":3,"skill-same:01M6ESZPEVC141MQPEKK7RME9X":64},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":26,"linkOnly":27,"markdownContent":28,"markdownBody":29,"frontMatter":30,"refName":31,"commitSha":32,"skillDirectory":33,"forksCount":34,"repositoryHtmlUrl":35,"repositoryHomepageUrl":36,"ownerHtmlUrl":37,"ownerBlogUrl":6,"ownerDescription":38,"updatedAt":39,"install":40,"resources":53},"01M6ESZPEVC141MQPEKK7RME9X","solid-principles",null,"SOLID principles adapted for functional and TypeScript-first development.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Fsolid-principles\u002FSKILL.md",[],[19,20,21,22,23,24,25],"solid","solid principles","principles","typescript","development","first","functional","2026-11-10 10:12:30",false,"---\nname: solid-principles\ndescription: SOLID principles adapted for functional and TypeScript-first development.\n---\n\n# SOLID Principles for Node.js\u002FTypeScript\n\n## Overview\nSOLID principles adapted for functional and TypeScript-first development.\n\n## S - Single Responsibility Principle\n\nA module\u002Ffunction should have only one reason to change.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Does validation, processing, and notification\nconst processOrder = async (order: Order) => {\n  \u002F\u002F Validation\n  if (!order.items.length) throw new Error('Empty order');\n  if (order.total \u003C 0) throw new Error('Invalid total');\n\n  \u002F\u002F Processing\n  const processed = { ...order, status: 'processed' };\n  await db.orders.save(processed);\n\n  \u002F\u002F Notification\n  await emailService.send(order.userId, 'Order confirmed');\n\n  return processed;\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Separate responsibilities\nconst validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n  if (!order.items.length) return Result.fail(emptyOrderError());\n  if (order.total \u003C 0) return Result.fail(invalidTotalError());\n  return Result.ok(order);\n};\n\nconst saveOrder = (db: Database) =>\n  async (order: Order): Promise\u003COrder> => {\n    const processed = { ...order, status: 'processed' };\n    await db.orders.save(processed);\n    return processed;\n  };\n\nconst notifyUser = (notifier: Notifier) =>\n  async (userId: string, message: string): Promise\u003Cvoid> => {\n    await notifier.send(userId, message);\n  };\n\n\u002F\u002F Compose in orchestrator\nconst processOrder = async (order: Order) => {\n  const validation = validateOrder(order);\n  if (validation.isFailure) return validation;\n\n  const saved = await saveOrder(db)(validation.value);\n  await notifyUser(emailService)(saved.userId, 'Order confirmed');\n\n  return Result.ok(saved);\n};\n```\n\n## O - Open\u002FClosed Principle\n\nOpen for extension, closed for modification.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Must modify function to add new discount types\nconst calculateDiscount = (type: string, amount: number): number => {\n  if (type === 'percentage') return amount * 0.1;\n  if (type === 'fixed') return 10;\n  if (type === 'loyalty') return amount * 0.15;\n  return 0;\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Extend via new strategies without modifying existing code\ntype DiscountStrategy = (amount: number) => number;\n\nconst discountStrategies: Record\u003Cstring, DiscountStrategy> = {\n  percentage: (amount) => amount * 0.1,\n  fixed: () => 10,\n  loyalty: (amount) => amount * 0.15,\n};\n\n\u002F\u002F Easy to extend\ndiscountStrategies.holiday = (amount) => amount * 0.25;\n\nconst calculateDiscount = (type: string, amount: number): number =>\n  discountStrategies[type]?.(amount) ?? 0;\n```\n\n## L - Liskov Substitution Principle\n\nSubtypes must be substitutable for their base types.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Square breaks Rectangle contract\nclass Rectangle {\n  constructor(public width: number, public height: number) {}\n  setWidth(w: number) { this.width = w; }\n  setHeight(h: number) { this.height = h; }\n  area() { return this.width * this.height; }\n}\n\nclass Square extends Rectangle {\n  setWidth(w: number) {\n    this.width = w;\n    this.height = w; \u002F\u002F Breaks expectation!\n  }\n}\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Use composition and explicit types\ntype Shape = {\n  area: () => number;\n};\n\nconst createRectangle = (width: number, height: number): Shape => ({\n  area: () => width * height,\n});\n\nconst createSquare = (side: number): Shape => ({\n  area: () => side * side,\n});\n```\n\n## I - Interface Segregation Principle\n\nClients should not depend on interfaces they don't use.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Fat interface\ninterface DataService {\n  read(id: string): Promise\u003CData>;\n  write(data: Data): Promise\u003Cvoid>;\n  delete(id: string): Promise\u003Cvoid>;\n  backup(): Promise\u003Cvoid>;\n  restore(): Promise\u003Cvoid>;\n  migrate(): Promise\u003Cvoid>;\n}\n\n\u002F\u002F Client only needs read\nconst reportGenerator = (service: DataService) => {\n  \u002F\u002F Only uses service.read(), but depends on entire interface\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Segregated interfaces\ntype Reader\u003CT> = {\n  read: (id: string) => Promise\u003CT>;\n};\n\ntype Writer\u003CT> = {\n  write: (data: T) => Promise\u003Cvoid>;\n};\n\ntype Deletable = {\n  delete: (id: string) => Promise\u003Cvoid>;\n};\n\n\u002F\u002F Client depends only on what it needs\nconst reportGenerator = (reader: Reader\u003CReportData>) => {\n  \u002F\u002F Only depends on read capability\n};\n\n\u002F\u002F Compose interfaces as needed\ntype DataService = Reader\u003CData> & Writer\u003CData> & Deletable;\n```\n\n## D - Dependency Inversion Principle\n\nDepend on abstractions, not concretions.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Direct dependency on implementation\nimport { PrismaClient } from '@prisma\u002Fclient';\n\nconst createUserService = () => {\n  const prisma = new PrismaClient(); \u002F\u002F Hardcoded!\n\n  return {\n    findUser: (id: string) => prisma.user.findFirst({ where: { id } }),\n  };\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Depend on abstraction\ntype UserRepository = {\n  findById: (id: string) => Promise\u003CUser | null>;\n  save: (user: User) => Promise\u003CUser>;\n};\n\nconst createUserService = (repo: UserRepository) => ({\n  findUser: (id: string) => repo.findById(id),\n  createUser: async (data: CreateUserData) => {\n    const user = { id: generateId(), ...data };\n    return repo.save(user);\n  },\n});\n\n\u002F\u002F Inject implementation\nconst prismaRepo: UserRepository = {\n  findById: (id) => prisma.user.findFirst({ where: { id } }),\n  save: (user) => prisma.user.create({ data: user }),\n};\n\nconst service = createUserService(prismaRepo);\n```\n\n## SOLID in Practice\n\n### Factory Function Pattern\n```typescript\n\u002F\u002F Follows all SOLID principles\ntype Dependencies = {\n  userRepo: UserRepository;\n  orderRepo: OrderRepository;\n  paymentGateway: PaymentGateway;\n  logger: Logger;\n};\n\nconst createOrderProcessor = (deps: Dependencies) => {\n  const validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n    \u002F\u002F Single responsibility: validation only\n  };\n\n  const processPayment = async (order: Order): Promise\u003CResult\u003CPayment, PaymentError>> => {\n    \u002F\u002F Single responsibility: payment only\n  };\n\n  return {\n    process: async (order: Order): Promise\u003CResult\u003CProcessedOrder, OrderError>> => {\n      const validation = validateOrder(order);\n      if (validation.isFailure) return validation;\n\n      const payment = await processPayment(validation.value);\n      if (payment.isFailure) return payment;\n\n      \u002F\u002F Compose results\n      return Result.ok({ order: validation.value, payment: payment.value });\n    },\n  };\n};\n```\n\n### Testing SOLID Code\n```typescript\ndescribe('OrderProcessor', () => {\n  it('should process valid order', async () => {\n    \u002F\u002F Easy to test due to dependency injection\n    const deps = {\n      userRepo: createFakeUserRepo(),\n      orderRepo: createFakeOrderRepo(),\n      paymentGateway: { charge: jest.fn().mockResolvedValue(Result.ok({})) },\n      logger: { info: jest.fn() },\n    };\n\n    const processor = createOrderProcessor(deps);\n    const result = await processor.process(createTestOrder());\n\n    expect(result.isSuccess).toBe(true);\n  });\n});\n```\n","# SOLID Principles for Node.js\u002FTypeScript\n\n## Overview\nSOLID principles adapted for functional and TypeScript-first development.\n\n## S - Single Responsibility Principle\n\nA module\u002Ffunction should have only one reason to change.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Does validation, processing, and notification\nconst processOrder = async (order: Order) => {\n  \u002F\u002F Validation\n  if (!order.items.length) throw new Error('Empty order');\n  if (order.total \u003C 0) throw new Error('Invalid total');\n\n  \u002F\u002F Processing\n  const processed = { ...order, status: 'processed' };\n  await db.orders.save(processed);\n\n  \u002F\u002F Notification\n  await emailService.send(order.userId, 'Order confirmed');\n\n  return processed;\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Separate responsibilities\nconst validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n  if (!order.items.length) return Result.fail(emptyOrderError());\n  if (order.total \u003C 0) return Result.fail(invalidTotalError());\n  return Result.ok(order);\n};\n\nconst saveOrder = (db: Database) =>\n  async (order: Order): Promise\u003COrder> => {\n    const processed = { ...order, status: 'processed' };\n    await db.orders.save(processed);\n    return processed;\n  };\n\nconst notifyUser = (notifier: Notifier) =>\n  async (userId: string, message: string): Promise\u003Cvoid> => {\n    await notifier.send(userId, message);\n  };\n\n\u002F\u002F Compose in orchestrator\nconst processOrder = async (order: Order) => {\n  const validation = validateOrder(order);\n  if (validation.isFailure) return validation;\n\n  const saved = await saveOrder(db)(validation.value);\n  await notifyUser(emailService)(saved.userId, 'Order confirmed');\n\n  return Result.ok(saved);\n};\n```\n\n## O - Open\u002FClosed Principle\n\nOpen for extension, closed for modification.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Must modify function to add new discount types\nconst calculateDiscount = (type: string, amount: number): number => {\n  if (type === 'percentage') return amount * 0.1;\n  if (type === 'fixed') return 10;\n  if (type === 'loyalty') return amount * 0.15;\n  return 0;\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Extend via new strategies without modifying existing code\ntype DiscountStrategy = (amount: number) => number;\n\nconst discountStrategies: Record\u003Cstring, DiscountStrategy> = {\n  percentage: (amount) => amount * 0.1,\n  fixed: () => 10,\n  loyalty: (amount) => amount * 0.15,\n};\n\n\u002F\u002F Easy to extend\ndiscountStrategies.holiday = (amount) => amount * 0.25;\n\nconst calculateDiscount = (type: string, amount: number): number =>\n  discountStrategies[type]?.(amount) ?? 0;\n```\n\n## L - Liskov Substitution Principle\n\nSubtypes must be substitutable for their base types.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Square breaks Rectangle contract\nclass Rectangle {\n  constructor(public width: number, public height: number) {}\n  setWidth(w: number) { this.width = w; }\n  setHeight(h: number) { this.height = h; }\n  area() { return this.width * this.height; }\n}\n\nclass Square extends Rectangle {\n  setWidth(w: number) {\n    this.width = w;\n    this.height = w; \u002F\u002F Breaks expectation!\n  }\n}\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Use composition and explicit types\ntype Shape = {\n  area: () => number;\n};\n\nconst createRectangle = (width: number, height: number): Shape => ({\n  area: () => width * height,\n});\n\nconst createSquare = (side: number): Shape => ({\n  area: () => side * side,\n});\n```\n\n## I - Interface Segregation Principle\n\nClients should not depend on interfaces they don't use.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Fat interface\ninterface DataService {\n  read(id: string): Promise\u003CData>;\n  write(data: Data): Promise\u003Cvoid>;\n  delete(id: string): Promise\u003Cvoid>;\n  backup(): Promise\u003Cvoid>;\n  restore(): Promise\u003Cvoid>;\n  migrate(): Promise\u003Cvoid>;\n}\n\n\u002F\u002F Client only needs read\nconst reportGenerator = (service: DataService) => {\n  \u002F\u002F Only uses service.read(), but depends on entire interface\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Segregated interfaces\ntype Reader\u003CT> = {\n  read: (id: string) => Promise\u003CT>;\n};\n\ntype Writer\u003CT> = {\n  write: (data: T) => Promise\u003Cvoid>;\n};\n\ntype Deletable = {\n  delete: (id: string) => Promise\u003Cvoid>;\n};\n\n\u002F\u002F Client depends only on what it needs\nconst reportGenerator = (reader: Reader\u003CReportData>) => {\n  \u002F\u002F Only depends on read capability\n};\n\n\u002F\u002F Compose interfaces as needed\ntype DataService = Reader\u003CData> & Writer\u003CData> & Deletable;\n```\n\n## D - Dependency Inversion Principle\n\nDepend on abstractions, not concretions.\n\n### Violation\n```typescript\n\u002F\u002F Bad: Direct dependency on implementation\nimport { PrismaClient } from '@prisma\u002Fclient';\n\nconst createUserService = () => {\n  const prisma = new PrismaClient(); \u002F\u002F Hardcoded!\n\n  return {\n    findUser: (id: string) => prisma.user.findFirst({ where: { id } }),\n  };\n};\n```\n\n### Correct\n```typescript\n\u002F\u002F Good: Depend on abstraction\ntype UserRepository = {\n  findById: (id: string) => Promise\u003CUser | null>;\n  save: (user: User) => Promise\u003CUser>;\n};\n\nconst createUserService = (repo: UserRepository) => ({\n  findUser: (id: string) => repo.findById(id),\n  createUser: async (data: CreateUserData) => {\n    const user = { id: generateId(), ...data };\n    return repo.save(user);\n  },\n});\n\n\u002F\u002F Inject implementation\nconst prismaRepo: UserRepository = {\n  findById: (id) => prisma.user.findFirst({ where: { id } }),\n  save: (user) => prisma.user.create({ data: user }),\n};\n\nconst service = createUserService(prismaRepo);\n```\n\n## SOLID in Practice\n\n### Factory Function Pattern\n```typescript\n\u002F\u002F Follows all SOLID principles\ntype Dependencies = {\n  userRepo: UserRepository;\n  orderRepo: OrderRepository;\n  paymentGateway: PaymentGateway;\n  logger: Logger;\n};\n\nconst createOrderProcessor = (deps: Dependencies) => {\n  const validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n    \u002F\u002F Single responsibility: validation only\n  };\n\n  const processPayment = async (order: Order): Promise\u003CResult\u003CPayment, PaymentError>> => {\n    \u002F\u002F Single responsibility: payment only\n  };\n\n  return {\n    process: async (order: Order): Promise\u003CResult\u003CProcessedOrder, OrderError>> => {\n      const validation = validateOrder(order);\n      if (validation.isFailure) return validation;\n\n      const payment = await processPayment(validation.value);\n      if (payment.isFailure) return payment;\n\n      \u002F\u002F Compose results\n      return Result.ok({ order: validation.value, payment: payment.value });\n    },\n  };\n};\n```\n\n### Testing SOLID Code\n```typescript\ndescribe('OrderProcessor', () => {\n  it('should process valid order', async () => {\n    \u002F\u002F Easy to test due to dependency injection\n    const deps = {\n      userRepo: createFakeUserRepo(),\n      orderRepo: createFakeOrderRepo(),\n      paymentGateway: { charge: jest.fn().mockResolvedValue(Result.ok({})) },\n      logger: { info: jest.fn() },\n    };\n\n    const processor = createOrderProcessor(deps);\n    const result = await processor.process(createTestOrder());\n\n    expect(result.isSuccess).toBe(true);\n  });\n});\n```\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Fsolid-principles",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":41,"prompt":51,"zipAvailable":52},[42,45,48],{"tool":43,"command":44},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill solid-principles",{"tool":46,"command":47},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill solid-principles",{"tool":49,"command":50},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill solid-principles","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Fsolid-principles\u002FSKILL.md",true,[54,60],{"path":55,"resourceType":56,"resourceTypeDesc":57,"sizeBytes":58,"sourceHtmlUrl":59},"examples.md","REFERENCE","参考文档",10381,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Fsolid-principles\u002Fexamples.md",{"path":61,"resourceType":56,"resourceTypeDesc":57,"sizeBytes":62,"sourceHtmlUrl":63},"skill-report.json",13990,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Fsolid-principles\u002Fskill-report.json",[65,79,89,98,104,111],{"skillNo":66,"name":67,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":68,"categories":69,"keywords":75,"publishedAt":26},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[70],{"categoryNo":71,"categoryName":72,"taxonomyType":73,"taxonomyTypeDesc":74},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[76,77,78],"model","model hierarchy","model hierarchy skill",{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":85,"publishedAt":26},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[84],{"categoryNo":71,"categoryName":72,"taxonomyType":73,"taxonomyTypeDesc":74},[86,87,88],"MCP","zoom","zoom mcp",{"skillNo":90,"name":91,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":92,"categories":93,"keywords":94,"publishedAt":26},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[95,96,97,87],"sdk","zoom apps sdk","apps",{"skillNo":99,"name":100,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":26},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[100],{"skillNo":105,"name":106,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":110,"publishedAt":26},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[109],{"categoryNo":71,"categoryName":72,"taxonomyType":73,"taxonomyTypeDesc":74},[106],{"skillNo":112,"name":113,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":26},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[113]]