Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript helpers suggestion. #114

Closed
nickmessing opened this issue Apr 19, 2018 · 8 comments

Comments

Projects
None yet
4 participants
@nickmessing
Copy link

commented Apr 19, 2018

Hello,

I have used feathers-vuex with TypeScript in a project and I made a set of helpers that I think could be really useful to other developers, here you can see the source code and below is an example of usage:

import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import { namespace, Action } from 'vuex-class'
import { ActionGet, ActionCreate, ActionPatch } from '../types/feathers'
import { Person } from '../types/models'

const PeopleAction = namespace('people', Action)

@Component
export default class CreateEditPeople extends Vue {
  @PeopleAction('get') getPerson: ActionGet<Person>
  @PeopleAction('create') createPerson: ActionCreate<Person>
  @PeopleAction('patch') patchPerson: ActionPatch<Person>
  // some extra here
}

TypeScript reads it really well and all suggestions and autocomplete helps a lot.

@marshallswain

This comment has been minimized.

Copy link
Collaborator

commented Apr 21, 2018

Cool!

@nickmessing how would one use your feathers-vuex-helpers.ts file in their project? This looks like something that ought to go into the docs in a "Using with TypeScript" section. We can link to your helpers gist.

@nickmessing

This comment has been minimized.

Copy link
Author

commented Apr 22, 2018

@marshallswain, I could finalize the typings and make a PR to make them universal so people can use them with bot class-component definition and classic component definition if you want to support that.

@marshallswain

This comment has been minimized.

Copy link
Collaborator

commented Apr 22, 2018

@marshallswain

This comment has been minimized.

Copy link
Collaborator

commented Jan 15, 2019

@rayfoss is your 👎 reaction a reflection of your dislike for TypeScript? Or is it about the quality of the recommendation?

@rayfoss

This comment has been minimized.

Copy link
Contributor

commented Jan 15, 2019

@marshallswain Features should have a good reason to exist because they take time to add and maintain. My vote is just a reflection of this feature being 99% unlikely to be of use to me. I'm waiting for native types to come to Node. Fun fact, I used to use Typescript in Angular 2.

I think TS support is good for the project, as long as it doesn't get in the way for everybody else with a ton of irrelevant files and dependencies everywhere. Forcing it is definitely a bad idea, as there are many many hold outs and designers using js or flow. Remember coffeescript?

@marshallswain

This comment has been minimized.

Copy link
Collaborator

commented Jan 15, 2019

@rayfoss Thanks for the update. I have similar sentiment. If @nickmessing's suggestions work without requiring modifying the repo, that's the perfect solution, in my opinion.

I've added a link to this issue in the docs. I'm closing this issue, now. Thanks, guys.

@marshallswain

This comment has been minimized.

@NickBolles

This comment has been minimized.

Copy link
Contributor

commented Jan 15, 2019

I have some typings for feathers-vuex too, I'm planning on putting together a PR at some point, but for now here they are.

import feathers, { Application } from "@feathersjs/feathers";
import { StoreOptions, Plugin, Commit, Dispatch } from "vuex";
import { PluginObject } from "vue";
import { Request } from "request";
import { type } from "os";

/**
 * Vue Plugin
 */
export interface FeathersVuexModel<ModelType = any> {
  namespace: string;
  className: string;
  modelName: string;
  options: FeathersVuexOptions;
  new(data?: Partial<ModelType>, options?: FeathersVuexModelOptions)
  reset: () => Promise<FeathersVuexModel<ModelType>>
  clone: () => Promise<FeathersVuexModel<ModelType>>
  create: (params: Partial<ModelType>) => Promise<FeathersVuexModel<ModelType>>
  patch: (params: Partial<ModelType>) => Promise<FeathersVuexModel<ModelType>>
  remove: (params: Partial<ModelType>) => Promise<FeathersVuexModel<ModelType>>
  save: (params: Partial<ModelType>) => Promise<FeathersVuexModel<ModelType>>
  update: (params: Partial<ModelType>) => Promise<FeathersVuexModel<ModelType>>
}

interface FeathersVuexModelOptions {
  isClone?: boolean;
  skipCommit?: boolean;
}

export type FeathersVuexGlobalModelsIndex<T> = {
  [P in keyof T]: FeathersVuexModel<T[P]> | FeathersVuexGlobalModels;
}

// export interface FeathersVuexGlobalModelsByPath<T> {
//   byServicePath: {
//     [P in keyof T]: FeathersVuexModel<T[P]>;
//   };
// }

/**
 * @description The type for the $FeathersVuex vue plugin. To type this stronger include the
 * following in a typings.d.ts file
 *
 *
 * @example
 * declare module "vue/types/vue" {
 *   import { FeathersVuexGlobalModels } from "feathers-vuex";
 *   interface Vue {
 *     $FeathersVuex: FeathersVuexGlobalModels<Services>;
 *   }
 * }
 *
 * @description Where services is something like this
 * @example
 * interface Services {
 *   users: User
 *   //...
 * }
 *
 * interface User {
 *   name: string;
 *   rating: number;
 *   //...
 * }
 * @description
 * The second generic is for the "byServicePath" property, and can be used in a similar way, just make a
 * ServicesByPath interface, where the key for the service is the path, not the name
 *
 * @example
 * interface Services {
 *   usersPath: User
 *   //...
 * }
 *
 * declare module "vue/types/vue" {
 *   import { FeathersVuexGlobalModels } from "feathers-vuex";
 *   interface Vue {
 *     $FeathersVuex: FeathersVuexGlobalModels<Services, ServicesByPath>;
 *   }
 * }
 *
 */
type FeathersVuexGlobalModels<T = any, P = any> = FeathersVuexGlobalModelsIndex<T>;//& FeathersVuexGlobalModelsByPath<P>;

/**
 * Init Auth
 */
interface InitAuthOptions {
  commit: Commit;
  dispatch: Dispatch;
  req: Request;
  cookieName: string;
  moduleName: string;
}
export function initAuth(options: InitAuthOptions): Promise<object>;

/**
 * Auth module factory
 */
interface FeathersVuexAuthOptions<State = FeatheresVuexAuthState> extends FeathersVuexStoreOptions<State> {
  userService: string
}

interface FeatheresVuexAuthState<UserType = any> {
  accessToken?: string, // The JWT
  payload: Object, // The JWT payload

  isAuthenticatePending: boolean,
  isLogoutPending: boolean,

  errorOnAuthenticate: Error | undefined,
  errorOnLogout: Error | undefined,
  user: UserType
}

interface FeathersVuexServiceState<ModelType = any, IDType = string> extends FeathersVuexCoreProps {
  ids: IDType[],
  keyedById: {
    [i: string]: ModelType
  }, // A hash map, keyed by id of each item
  currentId?: IDType, // The id of the item marked as current
  copy?: ModelType, // A deep copy of the current item
  servicePath: string // The full service path
  paginate: boolean, // Indicates if pagination is enabled on the Feathers service.

  isFindPending: boolean,
  isGetPending: boolean,
  isCreatePending: boolean,
  isUpdatePending: boolean,
  isPatchPending: boolean,
  isRemovePending: boolean,

  errorOnfind: Error | undefined,
  errorOnGet: Error | undefined,
  errorOnCreate: Error | undefined,
  errorOnUpdate: Error | undefined,
  errorOnPatch: Error | undefined,
  errorOnRemove: Error | undefined
}


interface FeathersVuexCoreProps {
  /**
   * @default 'id'
   */
  idField: string;
  /**
   * @default false
   */
  autoRemove: boolean;
  /**
   * @default true
   */
  enableEvents: boolean;
  /**
   * @default false
   */
  addOnUpsert: boolean;
  /**
   * @default false
   */
  diffOnPatch: boolean;
  /**
   * @default false
   */
  skipRequestIfExists: boolean;
  /**
   * @default false
   */
  preferUpdate: boolean;
  /**
   * @default false
   */
  replaceItems: boolean;
}
interface FeathersVuexStoreOptions<Store> extends Pick<StoreOptions<Store>, 'state' | 'getters' | 'mutations' | 'actions'> { }

interface FeathersVuexOptions<Store = any> extends FeathersVuexStoreOptions<Store>, FeathersVuexCoreProps {

  /**
   * @default 'path'
   */
  nameStyle?: 'short' | 'path';
  namespace: string;
  apiPrefix: string
  modelName: string;
  instanceDefaults?: any;
  /**
   * @debug false
   */
  debug: boolean;
}

/**
 * default export
 */
interface FeathersVuexResult {
  service<ModelType = any, IDType = string>(servicePath: string, options?: Partial<FeathersVuexOptions>): Plugin<FeathersVuexServiceState<ModelType, IDType>>;
  auth<UserType>(options?: FeathersVuexAuthOptions): Plugin<FeatheresVuexAuthState<UserType>>;
  FeathersVuex: PluginObject<any>;
}

export default function (client: Application, options: Partial<FeathersVuexOptions>): FeathersVuexResult;

declare namespace FeathersVuex {
  export interface FeathersVuexPluginType extends FeathersVuexGlobalModels { }
}

declare module "vue/types/vue" {
  interface Vue {
    $FeathersVuex: any;
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.