(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-5LHNRP9'); Setja upp GraphQL/MongoDB API með Netlify Functions - The Codest
The Codest
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Iðnaðargreinar
    • Fjártæknifyrirtæki og bankastarfsemi
    • E-commerce
    • Adtech
    • Heilbrigðistækni
    • Framleiðsla
    • Flutningar
    • Bifreiða
    • Internet hlutanna
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
  • Um okkur
  • Þjónusta
    • Hugbúnaðarþróun
      • Framhliðþróun
      • Bakendaþróun
    • Staff Augmentation
      • Framhliðaráþrófarar
      • Bakhliðaráþróunaraðilar
      • Gagnaverkfræðingar
      • Skýjaverkfræðingar
      • Gæðatryggingartæknimenn
      • Annað
    • Það er ráðgjafi
      • Endurskoðun og ráðgjöf
  • Gildi fyrir
    • CEO
    • CTO
    • Afhendingarstjóri
  • Teymið okkar
  • Case Studies
  • Vitið hvernig
    • Blogg
    • Fundir
    • Vefnámskeið
    • Auðlindir
Starfsferilmöguleikar Hafðu samband
Aftur ör Farðu aftur
2020-10-02
Hugbúnaðarþróun

Setja upp GraphQL/MongoDB API með Netlify Functions

The Codest

Pawel Rybczynski

Software Engineer

Markmið Upphafleg stilling Settu upp háð kerfi Byrjum Fyrst skaltu bæta tsconfig.json í aðalmöppuna: Nú skulum við búa til src/server.ts fyrir netþjónauppsetningar. Bættu síðan við tveimur fallum: eitt fyrir staðbundinn netþjón og hitt fyrir lambda. OK, við höfum engin resolvers né gerðarskilgreiningar, svo við þurfum að búa til nokkur. Gerum ráð fyrir að við viljum í fyrstu […]

Hér er tómt.

Markmið

  1. Stilla bæði staðbundna og lambda-þjóna.
  2. Tengdu bæði við MongoDB.
  3. Innleiða grunnauðkenningu.
  4. Setja upp serverlausan Apollo GraphQL forritaskil með Netlify.
  5. Notaðu Typescript.

Upphafleg stilling

npm init -yHljóðskrift

Setja upp forsendur

npm install --save týpskrift graphql aws-lambda @types/aws-lambdaHljóðskrift

Skulum byrja

Fyrst, bættu við the tsconfig.json í aðalmöppu:

"compilerOptions": {
 "target": "es5",
 "module": "commonjs",
 "allowJs": true,
 "strict": true,
 "esModuleInterop": true,
 "skipLibCheck": true,
 "forceConsistentCasingInFileNames": true
 },
 "include": ["src/*.ts", "src/**/*.ts", "src/**/*.js"],
 "exclude": ["node_modules"]
 }Hljóðskrift

Nú skulum við búa til uppspretta/þjónn.ts fyrir netþjónauppsetningar. Bættu síðan við tveimur fallum: eitt fyrir staðbundinn netþjón og hitt fyrir lambda.

// src/server.ts
import { ApolloServer as ApolloServerLambda } from "apollo-server-lambda";
import { ApolloServer } from "apollo-server";


const createLambdaServer = () =>
  new ApolloServerLambda({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    },
  });

const createLocalServer = () =>
  new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    },
  });

export { createLambdaServer, createLocalServer };

OK, við höfum engar lausnir né gerðarskilgreiningar, svo við þurfum að búa til nokkrar. Segjum að við viljum fyrst búa til notendur og fá upplýsingar um þá.

// src/schemas.ts
const { gql } = require("apollo-server-lambda");

const userSchema = gql`
  type User {
    id: ID!
    email: String!
    name: String!
  }

  type Mutation {
    createUser(name: String!, email: String!, password: String!): User!
  }
`;

Ef þú ert ekki kunnugur þessu, Apollo undirbjó mjög góða kennsluleiðbeiningu.

Nú skulum við búa til notendauppleysara með einni fyrirspurn og einni mutasjón.

// src/resolvers.ts
const userResolver = {
  Query: {
    user: async (parent, args, context, info) => {
 {...}
    },
  },
};
  Mutation: {
    createUser: async (parent, args, context, info) => {
 {...}
    },
  },
};

En við höfum engin gögn… Látum laga það 😉

Ekki gleyma að flytja inn gerðarskilgreiningu og lausnara á netþjóninn.

// src/server.ts
import { ApolloServer as ApolloServerLambda } from "apollo-server-lambda";
import { ApolloServer } from "apollo-server";

import { typeDefs } from "./schemas";
import { resolvers } from "./resolvers";

{...}

Tengjast MongoDB með mongoose

Nú er góður tími til að tengjast gagnagrunninum okkar. Í þessu tilviki verður það MongoDB. Það er ókeypis og auðvelt í viðhaldi. En áður en við byrjum skulum við setja upp tvær fleiri forsendur:

npm install --save mongoose dotenv

Fyrsta skrefið er að búa til notendalíkan.

// src/model.ts
import mongoose, { Document, Error, Schema } from "mongoose";

export type User = Document & {
  _id: string,
  email: string,
  name: string,
  password: string,
};

delete mongoose.connection.models["User"];

const UserSchema: Schema = new Schema({
  email: {
    type: String,
    required: true,
    unique: true,
  },
  name: {
    type: String,
    required: true,
    minLength: 3,
    maxLength: 32,
  },
  password: {
    type: String,
    required: true,
  },
});

export const userModel = mongoose.model  ("User", UserSchema);

Gerið lykilorð öruggari

Öryggi fyrst! Nú skulum við tryggja öryggi lykilorða okkar með því að haska þau.

npm install --save bcrypt @types/bcryptHljóðskrift

Nú skaltu innleiða lykilorðsvörnina innan pre-middleware callback-sins. Pre-middleware-aðgerðir eru keyrðar hver á eftir annarri þegar hver middleware kallar next. Til að gera lykilorðin örugg notum við aðferð sem býr til salt og skrá á aðskildum fallaköllunum.

// src/model.ts
import bcrypt from "bcrypt";
{...}
const SALT_WORK_FACTOR: number = 10;

UserSchema.pre("save", function (next) {
  const user = this as User;
  if (!this.isModified("password")) return next();

  bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
    if (err) return next(err);

    bcrypt.hash(user.password, salt, function (err, hash) {
 if (err) return next(err);
 user.password = hash;
 next();
    });
  });
});
{...}

Bættu síðan comparePasswords-aðferð við UserSchema:

// src/model.ts
{...}
UserSchema.methods.comparePasswords = function (
  candidatePassword: string,
  cb: (err: Error | null, same: boolean | null) => void)
 {
  const user = this as User;
  bcrypt.compare(candidatePassword, user.password, (err, isMatch) => {
    if (err) {
 return cb(err, null);
    }
    cb(null, isMatch);
  });
};
{...}

Og auðvitað breyta notendagerð.

type comparePasswordFunction = (
  candidatePassword: string,
  cb: (err: Error, isMatch: boolean) => void)
 => void;

export type User = Document & {
  _id: string,
  email: string,
  name: string,
  password: string,
  comparePasswords: comparePasswordFunction,
};

Nú getum við komið á tengingu milli netþjóna og gagnagrunnanna. MONGODB_URI er umhverfisbreyta sem inniheldur tengistreng sem þarf til að stofna tenginguna. Þú getur fengið hana í klústerspjaldinu þínu eftir að þú skráir þig inn í MongoDB Atlas-reikninginn þinn. Settu hana inn í .umhverfi

// .env
MONGODB_URI = ...;

Mundu alltaf að bæta þeirri skrá við .gitignore. Frábært! Nú skulum við bæta við falli sem gerir okkur kleift að tengjast gagnagrunninum.

// src/server.ts
import mongoose, { Connection } from "mongoose";
{...}
let cachedDb: Connection;

const connectToDatabase = async () => {
  if (cachedDb) return;

  await mongoose.connect(process.env.MONGODB_URI || "", {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useCreateIndex: true,
  });
  cachedDb = mongoose.connection;
};
{...}

Samhengi er hlutur sem er sameiginlegur öllum lausnara. Til að útvega það þurfum við bara að bæta við upphafsstillingarfalli fyrir samhengi í smiðinn á ApolloServer. Skulum gera það.

// src/server.ts
import { userModel } from "./models/user.model";
{...}
const createLambdaServer = async () =>
  new ApolloServerLambda({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async () => {
      await connectToDatabase();

 return {
 models: {
 userModel,
 },
 };
    },
  });

const createLocalServer = () =>
  new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async () => {
 await connectToDatabase();

 return {
 models: {
 userModel,
 },
 };
    }
  });

Eins og þú sérð, erum við líka að ljúka. notendalíkan í gegnum samhengi. Við getum nú uppfært resolverinn:

// resolvers.ts
const userResolver = {
  Query: {
    user: async (_, { email, name, password }, { models: { userModel } }) => {
 const user = await userModel.findById({ _id: id }).exec();
      return user;
    },
  },
};

Lítur vel út! Búðu nú til einfalt netþjónsdæmi:

// src/index.ts
import { createLocalServer } from "./server";
require("dotenv").config();

const port = process.env.PORT || 4000;

const server = createLocalServer();

server.listen(port).then(({ url }) => {
  console.log(`Server ir running at ${url}`);
});

Ræsa staðbundinn netþjón með Nodemon

Síðasta hlutinn áður en hlaupið hefst, bætið við nodemon.json

{
  "watch": ["src"],
  "ext": ".ts,.js",
  "ignore": [],
  "exec": "ts-node --transpile-only ./src/index.ts"
}

Bættu skriftu við package.json

"scripts": {
    "start": "nodemon"
  },

Og hlaupa!

Hafna npm.

Þú ættir að fá slíkar upplýsingar í terminalnum:

Þjónninn er keyrður á http://localhost:4000/

Ef já, opnaðu http://localhost:4000/ innan í vafranum þínum.

GraphQL-leikvöllurinn ætti að birtast. Sköpum nýjan notanda!

búa til notanda.png

Skoðaðu hvernig það lítur út í gagnagrunninum.

gagnagrunnurJohnDoe.png

Frábært! Allt virkar vel!

Reynum að fá nokkrar notendaupplýsingar.

notandiÁnAuðkenningar.png

Og bættu við lykilorðareitnum…

notandiorð.png

Frábært! Við fáum villu Ekki er hægt að fyrirspyrja reitinn "password" á gerðinni "User".". Eins og þú getur séð aftur, bættum við þessu reit ekki inn í skilgreiningu notendategundarinnar. Hann er þar viljandi. Við ættum ekki að gera kleift að fyrirspyrja neitt lykilorð eða aðrar viðkvæmar gögn.

Annað… Við getum fengið notendagögn án nokkurrar auðkenningar… þetta er ekki góð lausn. Við verðum að laga þetta.

En áður en…

Stilla Codegen

Skoðum GraphQL kóði rafall til að fá samhæfa grunntegund, byggða á skema okkar.

npm install --save @graphql-codegen/cli @graphql-codegen/introspection
@graphql-codegen/typescript @graphql-codegen/typescript-resolvers

Búa til kóðagerð.yml

yfirskrift: satt
skema: "http://localhost:4000"
framleiðir:
  ./src/generated/graphql.ts:
    viðbætur:
 - "typescript"
 - "typescript-resolvers"
  ./graphql.schema.json:
    viðbætur:
 - "introspection"

Bæta við kóðagerð handrit til package.json

"scripts": {
    "start": "nodemon",
    "codegen": "graphql-codegen --config ./codegen.yml",
  },

Þá, þegar staðbundni netþjónninn er í gangi, keyrið handritið:

npm run codegen

Ef vel tekst til færðu skilaboðin:

  √ Greina stillingu
  √ Búa til úttak

Ef þú færð þessar upplýsingar, ættu tvær skrár að birtast:

  • graphql.schema.json í aðalmappunni
  • graphql.ts í nýlega búinni leið uppruna/framleitt

Við höfum meiri áhuga á þeim seinni. Ef þú opnar hann, munt þú taka eftir fallegum gerðauppbyggingu.

Nú getum við bætt leysara okkar:

// src/resolvers.ts
import { Resolvers, Token, User } from "./generated/graphql";

const userResolver: Resolvers = {
  Query: {
    user: async (_, { id }, { models: { userModel }, auth }): Promise => {
      const user = await userModel.findById({ _id: id }).exec();
 return user;
    },
  },
  Mutation: {
    createUser: async (
 _,
 { email, name, password },
      { models: { userModel } }
    ): Promise => {
 const user = await userModel.create({
 email,
 name,
 password,
 });
 return user;
    },
  },
};

Auðkenning

Næst skulum við setja upp einfalda auðkenningu byggða á táknum.

npm install --save jsonwebtoken @types/jsonwebtoken

Búa til Athuga auðkenningu Fall til að staðfesta hvort tokenið sé gilt. Við munum bæta niðurstöðunni við samhengi til að við getum nálgast hana innan lausnara.

// src/server.ts
import { IncomingHttpHeaders } from "http";
import {
  APIGatewayProxyEvent,
  APIGatewayProxyEventHeaders,
  Context,
} from "aws-lambda";
import jwt from "jsonwebtoken";
{...}
const checkAuth = async ({ token } : APIGatewayProxyEventHeaders | IncomingHttpHeaders ) => {
  if (typeof token === "string") {
    try {
      return await jwt.verify(token, "riddlemethis");
    } catch (e) {
      throw new AuthenticationError(`Your session expired. Sign in again.`);
    }
  }
};
{...}
const createLambdaServer = async (
  { headers }: APIGatewayProxyEvent,
  context: Context
) => {
  return new ApolloServerLambda({
    typeDefs,
    resolvers,
    context: async () => {
      await connectToDatabase();

      const auth = await checkAuth(headers);

      return {
        auth,
        models: {
          userModel,
        },
      };
    },
  });
};

function createLocalServer() {
  return new ApolloServer({
    typeDefs,
    resolvers,
    introspection: true,
    playground: true,
    context: async ({ req: { headers } = {} }) => {
      const auth = await checkAuth(headers);
      await connectToDatabase();

      return {
         auth,
         models: {
          userModel,
        },
      };
    },
  });
}

Einnig þurfum við leið til að búa til slíkt token. Besta leiðin er að innleiða innskráningarfyrirspurn í lausnara okkar.

// resolvers.ts
import { Resolvers, Token, User } from "./generated/graphql";

const userResolver: Resolvers = {
  Query: {
    user: async (_, { id }, { models: { userModel }, auth }): Promise => {
      if (!auth) throw new AuthenticationError("Þú ert ekki staðfestur");

 const user = await userModel.findById({ _id: id }).exec();
 return user;
    },
    login: async (
 _,
 { email, password },
 { models: { userModel } }
    ): Promise => {
 const user = await userModel.findOne({ email }).exec();

 if (!user) throw new AuthenticationError("Invalid credentials");

 const matchPasswords = bcrypt.compareSync(password, user.password);

 if (!matchPasswords) throw new AuthenticationError("Invalid credentials");

      const token = jwt.sign({ id: user.id }, "riddlemethis", {
 expiresIn: 60,
 });

 return { token };
    },
  },
  Mutation: {
    createUser: async (
 _,
 { email, name, password },
      { models: { userModel } }
    ): Promise => {
 const user = await userModel.create({
 email,
 name,
 password,
 });
 return user;
    },
  },
};

Þú þarft einnig að uppfæra skilgreiningar á notendategundum eftir token-gerð og innskráningar-fyrirspurn.

type Token {
    token: String!
  }

type Query {
    user(id: ID!): User!
    login(email: String!, password: String!): Token!
  }

Reynum nú að fá notanda án token

Ekki innskráð.png

OK, virkar vel! Reyndu að skrá þig inn.

tákni.png

Reynum aftur að fá notandann, en að þessu sinni með token bætt við hausana.

meðToken.png

Frábært! Og hvað ef við sláum inn rangar auðkenningargögn?

rangtNetfang.png

Fínt!

Undirbúa uppsetningu

Síðasta skref: Deildu þjónustulausu API-inu með Netlify!

Búa til möppu lamda Í aðalmappunni og settu tvær skrár inn í hana:

Fyrst inniheldur AWS handler. Hann býr til ApolloServerLambda-þjónsinstans og
Þá skaltu búa til meðhöndlara með createHandler á þeirri instans.

// lambda/graphql.ts
import { APIGatewayProxyEvent, Context } from "aws-lambda";
import { createLambdaServer } from "???";

export const handler = async (
  event: APIGatewayProxyEvent,
  context: Context)
 => {
  const server = await createLambdaServer(event, context);

  return new Promise((res, rej) => {
    const cb = (err: Error, args: any) => (err ? rej(err) : res(args));
    server.createHandler()(event, context, cb);
  });
};

Þú getur lesið meira um það.

Annar er tsconfig. Mikilvægur hluti er útgáfuskrá svið.

// lambda/tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es6",
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "moduleResolution": "hnútur",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "outDir": "./dist"
  },
  "include": ["./*.ts", "./**/*.ts", "./**/*.js"]
}

En það er vandamál. Við getum ekki notað /uppspretta dir vegna þess að Netlify nær ekki utan um lambda-möppuna. Þess vegna verðum við að pakka henni.

npm install --save ncp

Þetta er pakki sem gerir okkur kleift að afrita möppu.

Bæta við pakki handrit til package.json

"scripts": {
    "bundle": "ncp ./src ./lambda/bundle",
    "codegen": "graphql-codegen --config ./codegen.yml",
    "start": "nodemon",
  },

Nú ef þú hleypur npm run bundle, þú sérð, að í nýlega búin lambda/bundle dir við höfum allar skrár frá uppspretta/.

Uppfærðu innflutningsslóðina innan lambda/graphql.ts

// lambda/graphql.ts
import { APIGatewayProxyEvent, Context } from "aws-lambda";
import { createLambdaServer } from "./bundle/server";

{...}

Þú getur nú bætt lambda/bundle dir við .gitignore

Setja upp með Netlify

Við verðum að segja Netlify hvaða byggingarskipun er og hvar fallin okkar eru. Til þess skulum við búa til netlify.toml file:

// netlify.toml
[build]
  command = "npm run build:lambda"
  functions = "lambda/dist"

Eins og þú sérð, er þetta sama möppan sem skilgreind er sem a útgáfuskrá Slá inn lambda/tsconfig.json

Svona ætti uppbygging forritsins þíns að líta út (jæja… hluti af því ;))

app
└───lambda
│ └────bundle
│ │ graphql.ts
│   tsconfig.json.ts
└───src
│ └───generated
│ │    │ graphql.ts
│ │ index.ts
│ │ model.ts
│ │ resolvers.ts
│ │ schemas.ts
│   server.ts
│
│ codegen.yml
│ graphql.schema.json
│ netlify.toml
│ nodemon.json
│ tsconfig.json

Bæta við pakki:lambda handrit til package.json

"scripts": {
    "build:lambda": "npm run bundle && tsc -p lambda/tsconfig.json",
    "bundle": "ncp ./src ./lambda/bundle",
    "codegen": "graphql-codegen --config ./codegen.yml",
    "start": "nodemon",
  },

Setja upp

Reynum að setja forritið okkar upp á Netlify.

  1. Skráðu þig inn á Netlify-reikninginn þinn,
  2. Tengstu við GitHub-reikninginn þinn,
  3. Smelltu á hnappinn ‘Ný vefsíða úr Git’,
  4. Veldu viðeigandi geymslu.,
  5. Settu upp byggingar-skipunina npm run build:lambda,
  6. Bættu við umhverfisbreytu (MONGODB_URI),
  7. Setja upp…

Og tadaaa…

síða ekki fundin.png

Það er vegna þess að endapunkturinn er sjálfgefið ekki http://page/ en http://page/.netlify/functions/graphql.

án endurbeiningar.png

Hvernig á að laga það? Það er mjög einfalt. Bara búa til _redirects með:

/ /.netlify/functions/graphql 200!

Setjið aftur upp og athugið.

Endurbeina.png

Vonandi líkaði þér við það! Endilega endurbættu og breyttu því.

Lesa meira:

Hvernig á ekki að drepa verkefni með slæmum forritunarvenjum?

Öryggi vefumsókna. Veikleiki Target=”_blank”

Öryggi vefumsókna – XSS-veikleiki

Tengdar greinar

Myndskreyting af heilbrigðisforriti fyrir snjallsíma með hjartatákni og hækkandi heilsufarsgrafík, merkt með The Codest-merkinu, sem táknar stafræna heilsu og HealthTech-lausnir.
Hugbúnaðarþróun

Heilbrigðis-hugbúnaður: gerðir og notkunartilvik

Tólin sem heilbrigðisstofnanir treysta á í dag líta ekkert út eins og pappírsskjöl frá fyrri áratugum. Heilbrigðisforrit styðja nú heilbrigðiskerfi, sjúklingameðferð og nútímalega heilbrigðisþjónustu á klínískum og...

THECODEST
Yfirlitsmynd sem sýnir hnignandi súlurit með uppstrekktri ör og gullmynt sem táknar kostnaðarhagkvæmni eða sparnað. The Codest-merkið birtist í efra vinstra horni með slagorðinu "In Code We Trust" á ljósgráum bakgrunni.
Hugbúnaðarþróun

Hvernig á að stækka þróunarteymið án þess að fórna gæðum vörunnar

Ertu að stækka þróunarteymið þitt? Lærðu hvernig á að vaxa án þess að fórna gæðum vörunnar. Þessi leiðarvísir fjallar um merki um að kominn sé tími til að stækka, uppbyggingu teymisins, ráðningar, forystu og verkfæri—og hvernig teymið getur...

THECODEST
Hugbúnaðarþróun

Búðu til vefumsóknir sem þola framtíðina: innsýn frá sérfræðiteymi The Codest

Uppgötvaðu hvernig The Codest skarar fram úr við að búa til stigstækar, gagnvirkar vefumsóknir með nýjustu tækni, sem bjóða upp á hnökralausa notendaupplifun á öllum kerfum. Lærðu hvernig sérfræðiþekking okkar knýr fram stafræna umbreytingu og viðskipti...

THECODEST
Hugbúnaðarþróun

Topp 10 hugbúnaðarþróunarfyrirtæki í Lettlandi

Kynntu þér fremstu hugbúnaðarþróunarfyrirtæki Lettlands og nýstárlegar lausnir þeirra í nýjustu grein okkar. Uppgötvaðu hvernig þessir tækniforingjar geta hjálpað til við að efla fyrirtækið þitt.

thecodest
Lausnir fyrir fyrirtæki og vaxtarfyrirtæki

Grunnatriði í Java hugbúnaðarþróun: Leiðarvísir að árangursríkri útvistun

Kannaðu þessa ómissandi leiðbeiningu um árangursríka outsourcing Java hugbúnaðarþróun til að auka skilvirkni, afla aðgangs að sérfræðiþekkingu og tryggja árangur verkefna með The Codest.

thecodest

Gerðu þig áskrifanda að þekkingargrunni okkar og vertu upplýstur um sérfræðiþekkingu upplýsingatæknigeirans.

    Um okkur

    The Codest – Alþjóðlegt hugbúnaðarþróunarfyrirtæki með tæknimiðstöðvar í Póllandi.

    Bretland - Höfuðstöðvar

    • Skrifstofa 303B, 182-184 High Street North E6 2JA
      Lundúnir, England

    Pólland - staðbundin tæknimiðstöðvar

    • Fabryczna skrifstofugarður, Aleja
      Herbergi 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsjá, Pólland

    The Codest

    • Heim
    • Um okkur
    • Þjónusta
    • Case Studies
    • Vitið hvernig
    • Starfsferilmöguleikar
    • Orðabók

    Þjónusta

    • Það er ráðgjafi
    • Hugbúnaðarþróun
    • Bakendaþróun
    • Framhliðþróun
    • Staff Augmentation
    • Bakhliðaráþróunaraðilar
    • Skýjaverkfræðingar
    • Gagnaverkfræðingar
    • Annað
    • Gæðatryggingartæknimenn

    Auðlindir

    • Staðreyndir og goðsagnir um samstarf við utanaðkomandi hugbúnaðarþróunaraðila
    • Frá Bandaríkjunum til Evrópu: Af hverju ákveða bandarísk sprotafyrirtæki að flytja til Evrópu?
    • Samanburður á tæknifjarkerfisþróunarmiðstöðvum: Tech Offshore Europe (Pólland), ASEAN (Filippseyjar), Eurasia (Tyrkland)
    • Hvert eru helstu áskoranir CTO-a og CIO-a?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Höfundarréttur © 2026 af The Codest. Öll réttindi áskilin.

    is_ISIcelandic
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian es_ESSpanish nl_NLDutch etEstonian elGreek pt_PTPortuguese cs_CZCzech lvLatvian lt_LTLithuanian is_ISIcelandic